Saltar a contenido

Diferencias entre motores

SQL es un estándar, pero cada motor lo implementa a su manera y añade extensiones. El SQL básico (SELECT, WHERE, JOIN, GROUP BY, INSERT, UPDATE, DELETE) funciona casi igual en todos. Lo que cambia son los detalles, y es lo que más tropiezos causa al pasar de un motor a otro.

Qué está comprobado y qué no

En esta web solo se ha ejecutado SQLite. La columna de SQLite de las tablas de abajo se ha comprobado en este equipo; las de MySQL, PostgreSQL y Oracle proceden de la documentación de cada motor y pueden variar entre versiones. Ante la duda, consulta el manual del motor que uses.

Lo más habitual

Quiero... SQLite MySQL PostgreSQL Oracle
Limitar filas LIMIT 3 LIMIT 3 LIMIT 3 FETCH FIRST 3 ROWS ONLY
Concatenar texto a \|\| b CONCAT(a, b) a \|\| b a \|\| b
Clave autonumérica INTEGER PRIMARY KEY AUTOINCREMENT INT AUTO_INCREMENT GENERATED ... AS IDENTITY / SERIAL GENERATED ... AS IDENTITY
Fecha de hoy date('now') CURDATE() CURRENT_DATE SYSDATE
Año de una fecha strftime('%Y', f) YEAR(f) EXTRACT(YEAR FROM f) EXTRACT(YEAR FROM f)
Verdadero/falso 0 y 1 BOOLEAN (= TINYINT) BOOLEAN NUMBER(1)
Texto con comillas 'texto' 'texto' 'texto' 'texto'
Nombre con caracteres especiales "nombre" `nombre` "nombre" "nombre"
Vaciar una tabla DELETE FROM t TRUNCATE TABLE t TRUNCATE TABLE t TRUNCATE TABLE t
Ver las tablas .tables o sqlite_master SHOW TABLES \dt o information_schema SELECT * FROM user_tables
Ver las columnas PRAGMA table_info(t) DESCRIBE t \d t DESCRIBE t

Operaciones de conjuntos y uniones

SQLite MySQL PostgreSQL Oracle
UNION, UNION ALL Sí Sí Sí Sí
INTERSECT Sí Desde 8.0.31 Sí Sí
EXCEPT Sí Desde 8.0.31 Sí Se llama MINUS
RIGHT JOIN Desde 3.39 Sí Sí Sí
FULL JOIN Desde 3.39 No Sí Sí

Funciones modernas

SQLite MySQL PostgreSQL Oracle
WITH (CTE) Sí Desde 8.0 Sí Sí
Funciones de ventana Desde 3.25 Desde 8.0 Sí Sí
Vistas materializadas No No Sí Sí
Procedimientos almacenados No Sí Sí Sí (PL/SQL)
RETURNING Sí No (usa LAST_INSERT_ID()) Sí Sí (RETURNING ... INTO)

Insertar o actualizar («upsert»)

Una operación muy común: insertar una fila y, si ya existe, actualizarla. Cada motor lo escribe distinto. En SQLite (comprobado) y PostgreSQL:

INSERT INTO profesores (id, nombre) VALUES (1, 'Marta Ruiz Pérez')
ON CONFLICT (id) DO UPDATE SET nombre = excluded.nombre;
Motor Escritura
SQLite y PostgreSQL INSERT ... ON CONFLICT (columna) DO UPDATE SET ...
MySQL INSERT ... ON DUPLICATE KEY UPDATE ...
Oracle MERGE INTO ... USING ... WHEN MATCHED THEN UPDATE ... WHEN NOT MATCHED THEN INSERT ...

Cómo se comportan distinto

Aspecto Qué cambia
Tipos SQLite no los comprueba estrictamente; los demás sí
Mayúsculas en LIKE En SQLite y MySQL no distingue; en PostgreSQL sí (ILIKE para ignorarlas)
Ordenar los NULL SQLite y MySQL los ponen primero en orden ascendente; PostgreSQL y Oracle, los últimos
División de enteros 7 / 2 da 3 en SQLite y PostgreSQL, pero 3.5 en MySQL
División entre 0 NULL en SQLite y MySQL; error en PostgreSQL y Oracle
Columna sin agrupar en GROUP BY SQLite la acepta (valor cualquiera); los demás la rechazan
Claves foráneas SQLite las ignora salvo PRAGMA foreign_keys = ON; los demás las comprueban siempre
Transacciones La mayoría empieza en autocommit; en Oracle una transacción empieza con la primera sentencia y hay que confirmar con COMMIT

Cómo escribir SQL que cambie lo menos posible

  • Usa el SQL estándar siempre que puedas (JOIN ... ON, CASE, COALESCE, CAST).
  • Aísla lo específico de un motor (fechas, paginación, autonumerados) en un solo sitio.
  • Prueba el SQL en el motor real donde se va a usar.
  • Los programas (Java, Python...) usan capas de acceso a datos (DAO, ORM como Hibernate o SQLAlchemy) que ocultan buena parte de estas diferencias, como se ve en la unidad de bases de datos de los lenguajes.