Guía rápida de comandos SQL

SELECT, joins, agrupaciones, INSERT, UPDATE, DELETE, upserts, CREATE TABLE, índices, transacciones y funciones de ventana, ejecutados en SQLite, más las diferencias entre dialectos.

Última revisión:

AdSense Placeholder
Slot: header_reference_page
En esta página

SQL es el lenguaje para consultar y modificar bases de datos relacionales. Todas las sentencias de esta página se ejecutaron en SQLite 3.46 con el pequeño esquema customers / orders creado en la primera sección; donde MySQL, PostgreSQL o SQL Server difieren, la última sección lo indica. Ordene las consultas largas con el formateador de SQL.

Crear tablas

CREATE TABLE customers (
  id         INTEGER PRIMARY KEY,
  name       TEXT NOT NULL,
  email      TEXT UNIQUE,
  country    TEXT DEFAULT 'US',
  created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
  id          INTEGER PRIMARY KEY,
  customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
  total       NUMERIC NOT NULL CHECK (total >= 0),
  status      TEXT NOT NULL DEFAULT 'new'
);

SQLite solo aplica REFERENCES (y, por tanto, ON DELETE CASCADE) tras ejecutar PRAGMA foreign_keys = ON; en cada conexión; las demás bases de datos siempre lo aplican.

Sentencia Qué hace
ALTER TABLE customers ADD COLUMN phone TEXT; Añade una columna
ALTER TABLE customers RENAME COLUMN phone TO mobile; Renombra una columna
ALTER TABLE customers DROP COLUMN mobile; Elimina una columna
CREATE INDEX idx_orders_customer ON orders(customer_id); Acelera las búsquedas y los joins por esa columna
CREATE UNIQUE INDEX idx_email ON customers(email); Además impone unicidad
DROP TABLE IF EXISTS old_orders; Elimina una tabla y sus datos
CREATE VIEW big_orders AS SELECT * FROM orders WHERE total > 100; Guarda una consulta como tabla virtual

Insertar, actualizar y eliminar

Sentencia Qué hace
INSERT INTO customers (name, email) VALUES ('Ana', '[email protected]'); Añade una fila
INSERT INTO orders (customer_id, total) VALUES (1, 40), (1, 120), (2, 75); Añade varias filas
INSERT INTO archive SELECT * FROM orders WHERE status = 'done'; Copia filas desde una consulta
UPDATE orders SET status = 'paid' WHERE id = 2; Modifica las filas que coinciden
DELETE FROM orders WHERE status = 'cancelled'; Elimina las filas que coinciden
INSERT INTO customers (id, name, email) VALUES (1, 'Ana B.', '[email protected]') ON CONFLICT(id) DO UPDATE SET name = excluded.name; Upsert: inserta o, si la clave existe, actualiza
INSERT INTO customers (name) VALUES ('Di') RETURNING id; Devuelve los valores de la fila nueva (SQLite 3.35 y posteriores)

Un UPDATE o DELETE sin WHERE modifica todas las filas. Ejecute antes el mismo WHERE en un SELECT. Convierta la exportación de una hoja de cálculo en sentencias INSERT con el conversor de CSV a SQL.

Consultar

Cláusula Ejemplo Notas
SELECT SELECT name, email FROM customers; SELECT * devuelve todas las columnas
WHERE WHERE country = 'US' AND total > 50 Filtra las filas antes de agrupar
IN, BETWEEN WHERE status IN ('new','paid'), WHERE total BETWEEN 50 AND 100 BETWEEN incluye ambos extremos
LIKE WHERE email LIKE '%@example.com' % cualquier texto, _ un carácter
IS NULL WHERE email IS NULL = NULL nunca coincide
ORDER BY ORDER BY total DESC, id Por defecto es ascendente
LIMIT / OFFSET LIMIT 10 OFFSET 20 Filas 21 a 30
DISTINCT SELECT DISTINCT country FROM customers; Elimina las filas duplicadas
AS SELECT total * 1.2 AS gross FROM orders; Alias de columna o de tabla
CASE CASE WHEN total >= 100 THEN 'large' ELSE 'small' END Valor condicional
COALESCE COALESCE(email, 'none') Primer argumento no NULL

Las cláusulas aparecen siempre en este orden: SELECT ... FROM ... JOIN ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT.

Joins

Join Devuelve
INNER JOIN Solo las filas con coincidencia en ambos lados
LEFT JOIN Todas las filas de la izquierda, con NULL donde la derecha no coincide
RIGHT JOIN Todas las filas de la derecha (SQLite 3.39 y posteriores)
FULL OUTER JOIN Todas las filas de ambos lados (SQLite 3.39 y posteriores; no existe en MySQL)
CROSS JOIN Todas las combinaciones de filas
-- Customers with no orders
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

Agrupaciones y agregados

Función Devuelve
COUNT(*) Número de filas
COUNT(col) Número de valores no NULL
SUM(col), AVG(col) Total y media (los NULL se ignoran)
MIN(col), MAX(col) Valor menor y mayor
-- Revenue per customer, only customers above 100
SELECT customer_id, COUNT(*) AS orders, SUM(total) AS revenue
FROM orders
GROUP BY customer_id
HAVING SUM(total) > 100
ORDER BY revenue DESC;

WHERE filtra las filas antes de agrupar; HAVING filtra los grupos después.

Subconsultas, CTE y funciones de ventana

-- Orders above the average
SELECT * FROM orders WHERE total > (SELECT AVG(total) FROM orders);

-- Common table expression
WITH revenue AS (
  SELECT customer_id, SUM(total) AS amount FROM orders GROUP BY customer_id
)
SELECT c.name, r.amount FROM revenue r JOIN customers c ON c.id = r.customer_id;

-- Rank each customer's orders and keep a running total
SELECT customer_id, id, total,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY total DESC) AS rank_in_customer,
       SUM(total)   OVER (ORDER BY id) AS running_total
FROM orders;

Transacciones

Sentencia Qué hace
BEGIN; Inicia una transacción (START TRANSACTION en MySQL, BEGIN TRANSACTION en SQL Server)
COMMIT; Hace permanentes los cambios
ROLLBACK; Deshace todo desde el BEGIN
SAVEPOINT s1; / ROLLBACK TO s1; Deshacer parcial dentro de una transacción

Diferencias entre dialectos

Tarea SQLite PostgreSQL MySQL / MariaDB SQL Server
Primeras 10 filas LIMIT 10 LIMIT 10 LIMIT 10 SELECT TOP 10 ... o OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
Clave autoincremental INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY o SERIAL AUTO_INCREMENT IDENTITY(1,1)
Concatenar cadenas a || b a || b CONCAT(a, b) a + b o CONCAT(a, b)
Upsert ON CONFLICT ... DO UPDATE ON CONFLICT ... DO UPDATE ON DUPLICATE KEY UPDATE MERGE
Devolver la fila insertada RETURNING RETURNING no admitido (MariaDB: RETURNING) OUTPUT inserted.*
Hora actual CURRENT_TIMESTAMP, datetime('now') CURRENT_TIMESTAMP, now() CURRENT_TIMESTAMP, NOW() CURRENT_TIMESTAMP, GETDATE()
Entrecomillar un identificador "name" "name" `name` [name]
Comparación sin distinguir mayúsculas LIKE (solo ASCII) ILIKE LIKE (con las intercalaciones por defecto) LIKE (con las intercalaciones por defecto)
Tipo booleano ninguno: 0 y 1 BOOLEAN BOOLEAN (alias de TINYINT(1)) BIT

Seguridad

No construya nunca SQL pegando entradas del usuario en una cadena: así ocurre la inyección SQL. Use marcadores de posición (?, $1, :name o %s, según el controlador) y pase los valores por separado.

Pruebe estas herramientas

Véase también

  • Glosario SQLite
    SQLite es una base de datos ligera guardada en un solo archivo, usada por navegadores.
  • Glosario Inyección SQL
    La inyección SQL es un ataque en el que una entrada manipulada se ejecuta en parte como comandos de base de datos.
  • Glosario CSV
    CSV (valores separados por comas) es un formato de texto plano para tablas, con una fila por línea y los valores separados por comas.

Preguntas frecuentes

NULL significa desconocido, así que compararlo con cualquier valor da desconocido, nunca verdadero. Use WHERE x IS NULL o IS NOT NULL.

AdSense Placeholder
Slot: footer_leaderboard