🗄️ Contenido

SQL Engineering: Guía Definitiva

Estrategias avanzadas, diseño de esquemas y optimización extrema de consultas para Bases de Datos Relacionales (SQL Server y PostgreSQL) en Devlinks.

1. RDBMS e Introducción

SQL es el estándar mundial de gestión de datos. El objetivo principal como Data Engineer en Devlinks es escribir consultas que eviten bloqueos innecesarios (Table Scans), respetando las estructuras estructuradas y relacionales de los BD.
Diseño Normalizado: Siempre procura cumplir la 3ra Forma Normal (3FN) para evitar redundancias de datos. No dupliques información a menos que estés desarrollando un Data Warehouse donde uses esquemas Desnormalizados (Estrella).

2. Tipos de Datos y Comandos DDL

El Data Definition Language rige la estructura física de los datos.

Tipos Fundamentales

-- INT: Usado para IDs. (Identidades de Autoincremento) -- VARCHAR / NVARCHAR: Usa NVARCHAR para soportar codificación Unicode (Emoticones/Kanji) -- DECIMAL(18,2): OBLIGATORIO para cálculos monetarios. Nunca uses FLOAT. -- UUID / UNIQUEIDENTIFIER: Global Unique Identifiers, geniales para sistemas distribuidos, pero lentos como Primary Keys Clustered. -- DATETIME2: En SQL Server, se prefiere sobre DATETIME por mayor precisión y rango.

Creación de Tablas (DDL)

CREATE TABLE Users ( Id INT IDENTITY(1,1) PRIMARY KEY, GlobalId UNIQUEIDENTIFIER DEFAULT NEWID(), Email NVARCHAR(100) NOT NULL UNIQUE, Balance DECIMAL(18,2) DEFAULT 0.00, CreatedAt DATETIME2 DEFAULT GETUTCDATE() );

3. Filtrado y DML Moderno

Proyección y Paginación (OFFSET/FETCH)

-- Anti-Patrón: SELECT * FROM Users; (Trae cargas pesadas de red) -- Mejor Práctica (Proyección Estricta con Paginación Segura): SELECT Id, Email, Balance FROM Users WHERE Balance > 0 ORDER BY CreatedAt DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY;

Actualizaciones Condicionadas Seguras (DML)

-- Uso avanzado de UPDATE con EXISTS y JOIN implícito UPDATE a SET a.Status = 'Suspended' FROM Accounts a WHERE EXISTS ( SELECT 1 FROM FraudLogs f WHERE f.AccountId = a.Id AND f.RiskLevel >= 90 );

4. Uniones (Joins)

Los Joins cruzan los conjuntos matemáticos de manera optimizada. Evita cadenas de subqueries dentro del SELECT evaluadas fila por fila cuando un JOIN resolvería todo en una exploración simple.

Inner vs Left Join

-- INNER JOIN: Exige que el registro exista en AMBAS tablas SELECT O.Id, C.Name, O.Total FROM Orders O INNER JOIN Customers C ON O.CustomerId = C.Id; -- LEFT JOIN: Trae TODOS los Customers, incluso si no tienen Orders (retorna NULL) SELECT C.Name, O.Id FROM Customers C LEFT JOIN Orders O ON C.Id = O.CustomerId WHERE O.Id IS NULL; -- Excelente forma de encontrar Usuarios inactivos

5. Agrupación y Agregación

GROUP BY vs HAVING

-- WHERE filtra antes de agrupar. HAVING filtra DESPUÉS de agrupar. SELECT CategoryId, SUM(Price * Quantity) AS TotalSales FROM OrderDetails WHERE Discount = 0 -- Quita detalles con descuento antes de agrupar GROUP BY CategoryId HAVING SUM(Price * Quantity) > 10000; -- Filtra los grupos matemáticos sumados

6. Common Table Expressions y Windows Functions

SQL Moderno permite generar tablas virtuales nombradas al vuelo (CTEs) y manipular datos en el aire con Window Functions sin arruinar la cardinalidad.

Over, Partition By, y Row_Number()

WITH RankingCTE AS ( SELECT DepartmentId, EmployeeName, Salary, ROW_NUMBER() OVER( PARTITION BY DepartmentId ORDER BY Salary DESC ) AS SalaryRank FROM Employees ) -- Este CTE permite filtrar fácilmente al Mejor pagado de cada departamento SELECT * FROM RankingCTE WHERE SalaryRank = 1;

7. Índices y Rendimiento B-Tree

Clustered vs Non-Clustered

-- ÍNDICE CLUSTERIZADO: Determina el orden físico en el Disco Duro. -- Solo puede haber UNO por tabla (Casi siempre el ID Autoincremental). -- ÍNDICES NO CLUSTERIZADOS: Crea una copia referencial tipo Directorio Telefónico. CREATE NONCLUSTERED INDEX IX_Users_LastName ON Users (LastName ASC); -- Covering Index: Incluye las columnas del SELECT evitando buscar en el disco la fila completa. CREATE NONCLUSTERED INDEX IX_Orders_Performance ON Orders (Status) INCLUDE (TotalAmount, CreatedAt);

8. Transacciones ACID

Atomicidad (Rollbacks Automáticos)

Siempre encierra cualquier movimiento bancario o lógica de transferencia en una transacción Try-Catch.
BEGIN TRY BEGIN TRAN; UPDATE Accounts SET Balance = Balance - 100 WHERE Id = 1; UPDATE Accounts SET Balance = Balance + 100 WHERE Id = 2; COMMIT TRAN; -- Si ambos updates pasaron, se materializa. END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRAN; -- Si un update falló (Constraint), revierte ambas operaciones. -- Levanta el error original THROW; END CATCH;