Bases de datos SQL

Insertar y consultar

Lección 4 de 8 · 16 min

Meter datos

INSERT es de lo más portátil que hay: se escribe igual en los tres motores. Se nombran las columnas y se dan los valores en el mismo orden.

INSERT, idéntico en los tres
-- Una fila
INSERT INTO clientes (nombre, email, ciudad, saldo)
VALUES ('Julia Gomez', 'julia@correo.com', 'Bogota', 150000);

-- Varias de golpe, que es mucho mas rapido que una a una
INSERT INTO clientes (nombre, email, ciudad, saldo) VALUES
    ('Carlos Ruiz',  'carlos@correo.com', 'Medellin', 0),
    ('Ana Martinez', 'ana@correo.com',    'Bogota',   85000),
    ('Luis Herrera', NULL,                'Cali',     -20000);

No hemos puesto el id ni creado_en: los rellena la base de datos, porque así se declararon en la lección 3. Y fíjate en el NULL del correo de Luis: la columna admitía vacío, así que entra.

Recuperar el id que se acaba de crear

Este es el problema práctico: acabas de insertar un cliente y necesitas su id para insertar su primer pedido. La base de datos lo generó, pero no lo sabes.

Y aquí cada motor lo resuelve de una forma distinta. Es la diferencia que más código rompe al portarlo, precisamente porque el INSERT de arriba sí era idéntico.

PostgreSQL: RETURNING
INSERT INTO clientes (nombre, email, ciudad)
VALUES ('Marta Diaz', 'marta@correo.com', 'Bogota')
RETURNING id;
Resultado
 id
----
  5
MySQL y SQL Server: una consulta aparte
-- MySQL
INSERT INTO clientes (nombre, email, ciudad)
VALUES ('Marta Diaz', 'marta@correo.com', 'Bogota');
SELECT LAST_INSERT_ID();

-- SQL Server
INSERT INTO clientes (nombre, email, ciudad)
VALUES ('Marta Diaz', 'marta@correo.com', 'Bogota');
SELECT SCOPE_IDENTITY();

En SQL Server se usa SCOPE_IDENTITY() y no @@IDENTITY, aunque las dos parezcan hacer lo mismo.

@@IDENTITY devuelve el último id generado en la sesión, incluido el que haya creado un disparador de otra tabla por debajo. Si esa tabla tiene uno, te llevas un id que no es el tuyo, y el fallo no da error: simplemente asocias el pedido al cliente equivocado.

Consultar: SELECT

Es lo que más vas a escribir en tu vida. La estructura básica es siempre la misma: qué columnas quieres, de qué tabla, con qué condición.

Lo esencial de SELECT
-- Todo, para explorar
SELECT * FROM clientes;

-- Solo lo que necesitas: asi va en codigo de verdad
SELECT nombre, ciudad, saldo FROM clientes;

-- Con condicion
SELECT nombre, saldo FROM clientes WHERE ciudad = 'Bogota';

-- Varias condiciones
SELECT nombre, saldo
FROM clientes
WHERE ciudad = 'Bogota' AND saldo > 100000;

-- Renombrar una columna en el resultado
SELECT nombre AS cliente, saldo AS saldo_actual FROM clientes;

SELECT * está perfecto para explorar, y no debería quedar en código de producción: trae columnas que no usas, y el día que alguien añada una columna nueva a la tabla, tu consulta empieza a devolver algo distinto sin que nadie haya tocado el programa.

Buscar dentro de un texto: LIKE

LIKE busca por coincidencia parcial usando dos comodines: % es «cualquier cosa» y _ es «un carácter cualquiera».

Los tres usos habituales
-- Que empiece por
SELECT nombre FROM clientes WHERE nombre LIKE 'Ju%';

-- Que contenga
SELECT nombre FROM clientes WHERE nombre LIKE '%Gomez%';

-- Que termine en
SELECT email FROM clientes WHERE email LIKE '%@correo.com';

La trampa silenciosa de esta lección: con la configuración habitual, en MySQL y SQL Server LIKE NO distingue mayúsculas -buscar gomez encuentra Gomez-, y en PostgreSQL SÍ las distingue: gomez no encuentra Gomez.

La misma consulta devuelve resultados distintos según el motor, y ninguno da error. En PostgreSQL existe ILIKE, que ignora mayúsculas; la forma que funciona en los tres es comparar en minúsculas: WHERE LOWER(nombre) LIKE LOWER('%gomez%').

Los operadores de filtro

Además de la comparación normal, hay cuatro formas de filtrar que evitan escribir condiciones larguísimas.

IN, BETWEEN, NOT y NULL
-- Uno de estos valores
SELECT nombre FROM clientes WHERE ciudad IN ('Bogota', 'Medellin', 'Cali');

-- En un rango, extremos incluidos
SELECT nombre, saldo FROM clientes WHERE saldo BETWEEN 50000 AND 200000;

-- Lo contrario
SELECT nombre FROM clientes WHERE ciudad NOT IN ('Bogota');

-- Sin dato: OJO, se usa IS NULL, no = NULL
SELECT nombre FROM clientes WHERE email IS NULL;

La causa número uno de «la consulta no devuelve nada y no entiendo por qué»: escribir WHERE email = NULL.

NULL significa «no se sabe», así que preguntar si un valor desconocido es igual a otro valor desconocido no da ni verdadero ni falso: no devuelve nada. Y no produce ningún error, solo un resultado vacío. Se usa siempre IS NULL e IS NOT NULL.

Situaciones que aparecen aquí

Un apóstrofo rompe la consulta

Insertar O'Brien falla porque el apóstrofo cierra el texto. Se escapa duplicándolo: 'O''Brien'.

Y esto conecta con algo mayor: cuando el dato viene de un formulario, nunca se pega dentro de la consulta. Se usan consultas parametrizadas, o alguien puede hacer que su «nombre» sea SQL. Es la inyección SQL.

Necesito buscar sin importar mayúsculas ni tildes

Para las mayúsculas, LOWER() en los dos lados funciona en los tres motores.

Las tildes dependen de la intercalación configurada, y cada motor la maneja distinto. Si tus datos llevan tildes, hay que probarlo: no se puede asumir.

La consulta devuelve filas repetidas

SELECT DISTINCT ciudad FROM clientes; devuelve cada valor una sola vez.

Es lo que se usa para responder «¿en qué ciudades tenemos clientes?».

Comillas simples o dobles

Las simples son para textos: 'Bogota'. Las dobles, en el estándar, son para nombres de tablas y columnas.

MySQL es más permisivo y acepta las dobles para texto, y eso enseña una costumbre que se rompe al cambiar de motor. Usa siempre simples para texto.

Compruébalo tú mismo

Escribes WHERE email = NULL y no devuelve nada, aunque sabes que hay clientes sin correo. ¿Por qué?

La misma consulta con LIKE '%gomez%' encuentra resultados en MySQL y ninguno en PostgreSQL. ¿Qué pasa?

Insertas un cliente y necesitas su id para crear su pedido. ¿Cómo lo obtienes en PostgreSQL?

Lo que sigue

Ya metes y sacas datos. En la siguiente lección los ordenas y los paginas -y ahí SQL Server se separa claramente de los otros dos- y aprendes a modificar y borrar sin provocar un desastre.

Siguiente: Ordenar, limitar, actualizar y borrar

Continuar ← Tablas, tipos y el id automático