INSERT: agregar filas de forma explícita

Cuando registramos un cliente, un pedido o un movimiento de inventario necesitamos crear filas nuevas. INSERT indica la tabla de destino, las columnas que recibiremos y los valores que se almacenarán.

La lista explícita de columnas es importante: hace visible la intención y evita depender del orden físico de la tabla.

Sintaxis

INSERT INTO dbo.Tabla
    (Columna1, Columna2, Columna3)
VALUES
    (Valor1, Valor2, Valor3);

La correspondencia es posicional: Columna1 recibe Valor1, Columna2 recibe Valor2 y así sucesivamente. La cantidad de valores debe coincidir con la cantidad de columnas indicadas.

Ejemplo: insertar una fila

INSERT INTO dbo.Categoria (Nombre)
VALUES (N'Audio');

No incluimos IdCategoria porque es una columna IDENTITY: SQL Server genera automáticamente un número nuevo para cada fila. Tampoco necesitamos escribir todas las columnas cuando las omitidas aceptan NULL —un valor ausente o desconocido— o tienen un valor predeterminado definido por la tabla.

Insertar varias filas

Una sola instrucción puede contener varios grupos de valores:

INSERT INTO dbo.Categoria (Nombre)
VALUES
    (N'Redes'),
    (N'Impresión'),
    (N'Energía');

Todas las filas deben proporcionar los valores en el mismo orden que la lista de columnas.

Insertar el resultado de una consulta

También podemos copiar o transformar datos provenientes de otro conjunto:

En el ejemplo, SUM reúne los importes de las partidas y GROUP BY produce una fila por pedido. El resultado de esa consulta debe tener la misma cantidad y el mismo orden de columnas que la lista del INSERT.

INSERT INTO dbo.PedidoHistorico
    (IdPedidoOriginal, IdCliente, FechaPedido, Estado, Total)
SELECT
    p.IdPedido,
    p.IdCliente,
    p.FechaPedido,
    p.Estado,
    SUM(pd.Cantidad * pd.PrecioUnitario * (1 - pd.Descuento / 100.0))
FROM dbo.Pedido AS p
INNER JOIN dbo.PedidoDetalle AS pd
    ON pd.IdPedido = p.IdPedido
WHERE p.Estado IN ('Enviado', 'Cancelado')
GROUP BY
    p.IdPedido,
    p.IdCliente,
    p.FechaPedido,
    p.Estado;

Conviene ejecutar primero únicamente la consulta para comprobar qué filas insertará.

Confirmar lo insertado

OUTPUT permite recuperar valores generados y filas afectadas sin realizar una búsqueda posterior:

INSERT INTO dbo.Categoria (Nombre)
OUTPUT inserted.IdCategoria, inserted.Nombre
VALUES (N'Seguridad');

Para capturar un único identificador IDENTITY también existe SCOPE_IDENTITY(), que devuelve el último valor generado dentro del mismo alcance de ejecución. OUTPUT devuelve datos de las filas afectadas y resulta más flexible cuando la instrucción inserta varias filas.

Qué conviene comprobar

Antes de insertar revisamos restricciones, tipos, longitudes y duplicados. Una restricción es una regla que la tabla hace cumplir. UNIQUE impide valores repetidos; una llave foránea exige una fila relacionada y CHECK valida una condición escrita en la definición.

Cuando la operación involucra varias tablas relacionadas, una transacción agrupa los cambios para confirmarlos o revertirlos como una unidad. Así evitamos conservar solo una parte. También debemos decidir qué debería ocurrir si ejecutamos el mismo proceso dos veces: insertar duplicados, actualizar lo existente o ignorar filas ya procesadas.

Relacionado con