📚 RESUMEN SQL SERVER - BASES DE DATOS II
1️⃣ MODIFICACIÓN DE TABLAS (ALTER TABLE)
Añadir columnas
sql
ALTER TABLE tabla ADD nombre_columna tipo_dato [restricciones];
ALTER TABLE equipo ADD patrocinador VARCHAR(50);
ALTER TABLE equipo ADD presupuesto NUMERIC(10,2);
Modificar columnas existentes
sql
ALTER TABLE tabla ALTER COLUMN columna tipo_dato [NOT NULL];
ALTER TABLE ciclista ALTER COLUMN edad INT NOT NULL;
Añadir restricciones
PRIMARY KEY
sql
ALTER TABLE tabla ADD CONSTRAINT pk_nombre PRIMARY KEY (columna);
ALTER TABLE equipo ADD CONSTRAINT pk_equipo PRIMARY KEY (codequ);
FOREIGN KEY
sql
ALTER TABLE tabla ADD CONSTRAINT fk_nombre
FOREIGN KEY (columna) REFERENCES tabla_ref(columna_ref)
ON DELETE [CASCADE | SET NULL | NO ACTION];
-- Ejemplos:
ALTER TABLE ciclista ADD CONSTRAINT fk_ciclista_equipo
FOREIGN KEY (codequ) REFERENCES equipo(codequ) ON DELETE SET NULL;
ALTER TABLE puerto ADD CONSTRAINT fk_puerto_etapa
FOREIGN KEY (numetapa) REFERENCES etapa(numetapa) ON DELETE CASCADE;
CHECK
sql
ALTER TABLE tabla ADD CONSTRAINT ch_nombre CHECK (condicion);
ALTER TABLE ciclista ADD CONSTRAINT ch_edad CHECK (edad < 65);
ALTER TABLE puerto ADD CONSTRAINT ch_altura CHECK (altura > 0);
ALTER TABLE puerto ADD CONSTRAINT ch_categoria CHECK (categoria IN ('E','1','2','3'));
UNIQUE
sql
ALTER TABLE tabla ADD CONSTRAINT uq_nombre UNIQUE (columna);
ALTER TABLE articulos ADD CONSTRAINT uq_descrip UNIQUE (descrip);
NOT NULL
sql
ALTER TABLE etapa ALTER COLUMN kms INT NOT NULL;
Eliminar restricciones
sql
ALTER TABLE tabla DROP CONSTRAINT nombre_constraint;
ALTER TABLE equipo DROP CONSTRAINT fk_equipo_director;
Eliminar columnas
sql
ALTER TABLE tabla DROP COLUMN nombre_columna;
ALTER TABLE equipo DROP COLUMN patrocinador;
2️⃣ VISTAS (VIEWS)
Crear vista
sql
CREATE OR ALTER VIEW nombre_vista AS
SELECT columnas
FROM tablas
WHERE condiciones;
-- Ejemplo básico:
CREATE OR ALTER VIEW vista_equipos AS
SELECT codequ, nomequipo, director
FROM equipo
WHERE nomequipo LIKE '%A%';
Vistas con JOINs
sql
CREATE OR ALTER VIEW todoterrenos AS
SELECT [Link], [Link], [Link], [Link]
FROM ciclista c
JOIN equipo e ON [Link] = [Link]
JOIN lleva l ON [Link] = [Link]
GROUP BY [Link], [Link], [Link], [Link]
HAVING COUNT(DISTINCT [Link]) = (
SELECT MAX(num_maillots)
FROM (
SELECT COUNT(DISTINCT codigo) AS num_maillots
FROM lleva
GROUP BY dorsal
) AS subconsulta
);
Vistas con agregaciones
sql
CREATE OR ALTER VIEW mediaedad AS
SELECT AVG(CAST([Link] AS FLOAT)) AS edadmedia
FROM ciclista c
JOIN etapa e ON [Link] = [Link];
Usar vistas en consultas
sql
SELECT * FROM vista_equipos;
SELECT dorsal, nombre
FROM todoterrenos
WHERE edad < (SELECT edadmedia FROM mediaedad);
Actualizar definición de vista
sql
CREATE OR ALTER VIEW vista_equipos AS
SELECT codequ, nomequipo, director, patrocinador, presupuesto
FROM equipo
WHERE nomequipo LIKE '%A%';
Eliminar vista
sql
DROP VIEW nombre_vista;
3️⃣ SECUENCIAS (SEQUENCES)
Crear secuencia básica
sql
CREATE SEQUENCE nombre_seq;
-- Valores por defecto: START WITH 1, INCREMENT BY 1
Crear secuencia personalizada
sql
CREATE SEQUENCE nombre_seq
START WITH valor_inicial
INCREMENT BY incremento
MINVALUE valor_minimo
MAXVALUE valor_maximo
CYCLE; -- O NO CYCLE
-- Ejemplos:
CREATE SEQUENCE codequ_seq; -- Por defecto
CREATE SEQUENCE codcic_seq
START WITH 1000
INCREMENT BY -1; -- Decrementar
CREATE SEQUENCE codeta_seq
START WITH 100
INCREMENT BY 10
MAXVALUE 10000
CYCLE; -- Vuelve a empezar al llegar al máximo
CREATE SEQUENCE codpue_seq
START WITH -10
INCREMENT BY -5;
Usar secuencias
sql
-- Obtener siguiente valor
SELECT NEXT VALUE FOR nombre_seq;
-- Usar en INSERT
INSERT INTO equipo (codequ, nomequipo, director)
VALUES (NEXT VALUE FOR codequ_seq, 'Banesto', 'Miguel Echevarria');
-- Usar en SELECT
INSERT INTO ciclista (codcic, dorsal, nombre, edad, codequ)
SELECT NEXT VALUE FOR codcic_seq, dorsal, nombre, edad, codequ
FROM aux_ciclista;
Ver información de secuencias
sql
SELECT * FROM [Link];
Eliminar secuencia
sql
DROP SEQUENCE nombre_seq;
4️⃣ SINÓNIMOS (SYNONYMS)
Crear sinónimo
sql
CREATE SYNONYM nombre_sinonimo FOR [Link];
-- Ejemplos:
CREATE SYNONYM equipos FOR CICLISMO.aux_equipo;
CREATE SYNONYM ciclistas FOR CICLISMO.aux_ciclista;
CREATE SYNONYM etapas FOR CICLISMO.aux_etapa;
Usar sinónimos
sql
-- En lugar de:
SELECT * FROM CICLISMO.aux_equipo;
-- Usamos:
SELECT * FROM equipos;
-- En INSERT:
INSERT INTO equipo (codequ, nomequipo, director)
SELECT NEXT VALUE FOR codequ_seq, nomequipo, director
FROM equipos; -- Usando el sinónimo
Eliminar sinónimo
sql
DROP SYNONYM nombre_sinonimo;
5️⃣ SUBCONSULTAS
Subconsultas escalares (devuelven 1 valor)
sql
-- En WHERE
SELECT nombre, edad
FROM ciclista
WHERE edad > (SELECT AVG(edad) FROM ciclista);
-- En SELECT
SELECT nombre,
(SELECT COUNT(*) FROM etapa WHERE dorsal = [Link]) AS etapas_ganadas
FROM ciclista c;
Subconsultas de múltiples valores
sql
-- Con IN
SELECT nombre
FROM ciclista
WHERE dorsal IN (SELECT dorsal FROM etapa WHERE kms > 200);
-- Con NOT IN
SELECT nombre
FROM ciclista
WHERE dorsal NOT IN (SELECT dorsal FROM lleva);
-- Con EXISTS
SELECT nombre
FROM ciclista c
WHERE EXISTS (SELECT 1 FROM etapa e WHERE [Link] = [Link]);
-- Con NOT EXISTS
SELECT nombre
FROM ciclista c
WHERE NOT EXISTS (SELECT 1 FROM lleva l WHERE [Link] = [Link]);
Subconsultas correlacionadas
sql
SELECT [Link], [Link]
FROM articulos a
WHERE [Link] > ALL (
SELECT [Link]
FROM lineas_fac l
WHERE [Link] = [Link]
);
Subconsultas en FROM (vistas en línea)
sql
SELECT precio_max
FROM (
SELECT MAX(precio) AS precio_max
FROM lineas_fac
) AS subconsulta;
Operadores ALL, ANY, SOME
sql
-- ALL: debe cumplirse para TODOS
SELECT nombre
FROM ciclista
WHERE edad > ALL (SELECT edad FROM ciclista WHERE codequ = 3);
-- ANY/SOME: debe cumplirse para ALGUNO
SELECT nombre
FROM ciclista
WHERE edad > ANY (SELECT edad FROM ciclista WHERE codequ = 3);
6️⃣ OPERADORES CONJUNTISTAS
UNION (une resultados, elimina duplicados)
sql
SELECT nombre FROM clientes
UNION
SELECT nombre FROM vendedores;
UNION ALL (une resultados, mantiene duplicados)
sql
SELECT nombre FROM clientes
UNION ALL
SELECT nombre FROM vendedores;
INTERSECT (elementos comunes)
sql
SELECT nombre, direccion FROM clientes
INTERSECT
SELECT nombre, direccion FROM vendedores;
EXCEPT (elementos en A pero no en B)
sql
SELECT nombre FROM ciclistas
EXCEPT
SELECT nombre FROM ganadores;
7️⃣ JOINS (REUNIONES)
INNER JOIN
sql
SELECT [Link], [Link]
FROM ciclista c
INNER JOIN equipo e ON [Link] = [Link];
LEFT JOIN (todos de la izquierda)
sql
SELECT [Link], [Link]
FROM ciclista c
LEFT JOIN equipo e ON [Link] = [Link];
-- Incluye ciclistas sin equipo (NULL)
RIGHT JOIN (todos de la derecha)
sql
SELECT [Link], [Link]
FROM ciclista c
RIGHT JOIN equipo e ON [Link] = [Link];
-- Incluye equipos sin ciclistas
FULL OUTER JOIN (todos de ambos)
sql
SELECT [Link], [Link]
FROM ciclista c
FULL OUTER JOIN equipo e ON [Link] = [Link];
SELF JOIN (auto-reunión)
sql
SELECT [Link] AS vendedor, [Link] AS jefe
FROM vendedores v1
LEFT JOIN vendedores v2 ON [Link] = [Link];
Múltiples JOINs
sql
SELECT [Link], [Link], [Link], [Link]
FROM ciclista c
JOIN equipo e ON [Link] = [Link]
JOIN etapa et ON [Link] = [Link]
JOIN puerto p ON [Link] = [Link] AND [Link] = [Link];
8️⃣ FUNCIONES DE AGREGACIÓN
COUNT, SUM, AVG, MAX, MIN
sql
SELECT COUNT(*) AS total_ciclistas FROM ciclista;
SELECT COUNT(DISTINCT codequ) AS equipos_con_ciclistas FROM ciclista;
SELECT AVG(edad) AS edad_media FROM ciclista;
SELECT MAX(precio) AS precio_maximo FROM articulos;
SELECT MIN(stock) AS stock_minimo FROM articulos;
SELECT SUM(cant * precio) AS total_factura FROM lineas_fac;
GROUP BY
sql
SELECT codequ, COUNT(*) AS num_ciclistas
FROM ciclista
GROUP BY codequ;
HAVING (filtro después de GROUP BY)
sql
SELECT codequ, COUNT(*) AS num_ciclistas
FROM ciclista
GROUP BY codequ
HAVING COUNT(*) > 5;
9️⃣ FUNCIONES ÚTILES
Funciones de cadena
sql
UPPER(texto) -- Mayúsculas
LOWER(texto) -- Minúsculas
LEN(texto) -- Longitud
SUBSTRING(texto, inicio, longitud)
CHARINDEX(buscar, texto) -- Posición de subcadena
CONCAT(texto1, texto2) -- Concatenar
TRIM(texto) -- Quitar espacios
LEFT(texto, n) -- N caracteres desde izquierda
RIGHT(texto, n) -- N caracteres desde derecha
Funciones de fecha
sql
GETDATE() -- Fecha y hora actual
YEAR(fecha) -- Año
MONTH(fecha) -- Mes
DAY(fecha) -- Día
DATEADD(intervalo, cantidad, fecha) -- Sumar/restar fecha
DATEDIFF(intervalo, fecha1, fecha2) -- Diferencia
FORMAT(fecha, 'formato') -- Formatear
Funciones de conversión
sql
CAST(valor AS tipo) -- Convertir tipo
CONVERT(tipo, valor) -- Convertir tipo
COALESCE(val1, val2, ...) -- Primer valor no NULL
NULLIF(val1, val2) -- NULL si son iguales
ISNULL(valor, reemplazo) -- Reemplazar NULL
Funciones matemáticas
sql
ROUND(numero, decimales) -- Redondear
CEILING(numero) -- Redondear arriba
FLOOR(numero) -- Redondear abajo
ABS(numero) -- Valor absoluto
🔟 CASE WHEN
CASE simple
sql
SELECT nombre,
CASE edad
WHEN 25 THEN 'Joven'
WHEN 30 THEN 'Maduro'
ELSE 'Veterano'
END AS categoria
FROM ciclista;
CASE con condiciones
sql
SELECT nombre,
CASE
WHEN edad < 25 THEN 'Joven'
WHEN edad BETWEEN 25 AND 35 THEN 'Maduro'
ELSE 'Veterano'
END AS categoria
FROM ciclista;
En UPDATE
sql
UPDATE articulos
SET precio = CASE
WHEN precio < 200 THEN precio * 1.07
ELSE precio * 1.05
END;
1️⃣1️⃣ INSERT, UPDATE, DELETE
INSERT simple
sql
INSERT INTO tabla (col1, col2) VALUES (val1, val2);
INSERT múltiple
sql
INSERT INTO tabla (col1, col2) VALUES
(val1, val2),
(val3, val4);
INSERT desde SELECT
sql
INSERT INTO equipo (codequ, nomequipo, director)
SELECT NEXT VALUE FOR codequ_seq, nomequipo, director
FROM equipos; -- tabla o sinónimo
UPDATE simple
sql
UPDATE tabla
SET columna = valor
WHERE condicion;
UPDATE con subconsulta
sql
UPDATE facturas
SET total = (
SELECT SUM(cant * precio)
FROM lineas_fac
WHERE lineas_fac.codfac = [Link]
);
DELETE
sql
DELETE FROM tabla WHERE condicion;
1️⃣2️⃣ CONSULTAS AVANZADAS
DISTINCT (eliminar duplicados)
sql
SELECT DISTINCT codequ FROM ciclista;
ORDER BY
sql
SELECT * FROM ciclista ORDER BY edad DESC, nombre ASC;
TOP
sql
SELECT TOP 10 * FROM ciclista ORDER BY edad DESC;
BETWEEN
sql
SELECT * FROM articulos WHERE precio BETWEEN 100 AND 500;
LIKE (patrones)
sql
WHERE nombre LIKE 'A%' -- Empieza por A
WHERE nombre LIKE '%ez' -- Termina en ez
WHERE nombre LIKE '%Juan%' -- Contiene Juan
WHERE nombre LIKE '_a%' -- Segunda letra es 'a'
IN
sql
WHERE provincia IN ('CASTELLON', 'VALENCIA', 'ALICANTE');
IS NULL / IS NOT NULL
sql
WHERE email IS NULL;
WHERE descuento IS NOT NULL;
1️⃣3️⃣ TIPS PARA EL EXAMEN
1. Orden de ejecución SQL
1. FROM (y JOINs)
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. ORDER BY
2. Cuándo usar LEFT JOIN vs INNER JOIN
INNER JOIN: Solo registros que coinciden en ambas tablas
LEFT JOIN: Todos de la izquierda + coincidencias de la derecha (NULL si no hay)
3. Subconsultas vs JOINs
Subconsultas: Más legibles, para filtros complejos
JOINs: Mejor rendimiento, para combinar datos
4. GROUP BY con HAVING
sql
-- HAVING filtra DESPUÉS de agrupar
SELECT codequ, COUNT(*) AS total
FROM ciclista
GROUP BY codequ
HAVING COUNT(*) > 5; -- Filtro en agregados
5. Manejo de NULL
sql
-- COALESCE: primer valor no NULL
SELECT COALESCE(descuento, 0) FROM facturas;
-- ISNULL: reemplazar NULL
SELECT ISNULL(descuento, 0) FROM facturas;
-- IS NULL / IS NOT NULL
WHERE columna IS NULL;
6. Formato de fechas
sql
FORMAT(fecha, 'dd/MM/yyyy')
FORMAT(fecha, 'yyyy-MM-dd')
YEAR(fecha)
MONTH(fecha)
DAY(fecha)
✅ CHECKLIST PARA EL EXAMEN
Entender la semántica del problema
Identificar claves primarias y foráneas
Conocer ON DELETE CASCADE vs SET NULL
Dominar JOINs (INNER, LEFT, RIGHT, FULL)
Saber usar subconsultas (escalares, múltiples, correlacionadas)
Manejar operadores conjuntistas (UNION, INTERSECT, EXCEPT)
Crear y usar vistas
Crear y usar secuencias
Crear y usar sinónimos
Modificar tablas (ALTER TABLE)
Aplicar restricciones (PK, FK, CHECK, UNIQUE, NOT NULL)
Usar funciones de agregación con GROUP BY y HAVING
Manejar NULL correctamente (COALESCE, ISNULL)
Usar CASE WHEN en SELECT y UPDATE
Formatear salidas correctamente