Parámetros de tabla: una interfaz por lotes para SQL Server
Envía conjuntos tipados con reglas claras de validación, duplicados y orden y considera estadísticas ausentes y configuración del cliente.
Enviar una llamada por cada línea de pedido desperdicia viajes de red y complica errores. Usar texto separado por comas traslada el problema al análisis y escape. Un parámetro de tabla, o TVP, permite enviar un conjunto tipado a un procedimiento en una llamada.
Define primero el contrato: productos únicos, líneas donde se permite repetir producto u operaciones independientes. Esa elección determina claves, validación, correlación y significado de los reintentos.
Expresar la entrada mediante un tipo
La interfaz de práctica acepta una cantidad positiva por producto y muestra identificadores desconocidos.
-- Disposable practice database. Send GO-separated batches separately.
CREATE TYPE dbo.RequestLinesDemo AS TABLE (
ProductId int NOT NULL PRIMARY KEY,
Quantity int NOT NULL CHECK (Quantity > 0)
);
GO
CREATE TABLE dbo.ProductsTvpDemo(ProductId int PRIMARY KEY, UnitPrice decimal(12,2));
INSERT dbo.ProductsTvpDemo VALUES (1,10.00),(2,15.00);
GO
CREATE PROCEDURE dbo.ValidateLinesDemo @Lines dbo.RequestLinesDemo READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT l.ProductId, l.Quantity, p.UnitPrice,
CONVERT(bit, CASE WHEN p.ProductId IS NULL THEN 0 ELSE 1 END) AS IsValid
FROM @Lines AS l
LEFT JOIN dbo.ProductsTvpDemo AS p ON p.ProductId = l.ProductId
ORDER BY l.ProductId;
END;
GO
La clave primaria rechaza ProductId duplicados. Si un mismo producto puede aparecer en líneas diferentes, utiliza LineId como clave. No elimines líneas reales solo porque una interfaz de conjuntos resulte cómoda.
CHECK exige cantidades positivas y NOT NULL impide aceptar una cantidad desconocida. Esas restricciones validan forma e invariantes sencillos. No sustituyen comprobaciones contra estado, disponibilidad o catálogo actuales.
READONLY es obligatorio en un TVP. El procedimiento puede consultar y unir sus filas, pero no modificar el parámetro como una tabla temporal. Si necesitas transformaciones, crea otra tabla de trabajo y contabiliza su coste.
La llamada incluye un producto inexistente.
DECLARE @Input dbo.RequestLinesDemo;
INSERT @Input VALUES (1,2),(2,3),(99,1);
EXEC dbo.ValidateLinesDemo @Lines = @Input;
Los productos 1 y 2 son válidos y 99 queda marcado. LEFT JOIN conserva la entrada incorrecta para informar. Un INNER JOIN la ocultaría y podría presentar una respuesta parcial como validación completa.
Mantener consistente la operación
El procedimiento demuestra validación, no una transacción de creación de pedidos. Decide si una línea incorrecta rechaza toda la solicitud o si aceptas resultados parciales. Correlaciona cada respuesta con su entrada y deja claro el estado global.
Validar correctamente no congela los productos para otra llamada. Precios, disponibilidad y permisos pueden cambiar. Revalida condiciones dentro de la transacción real o utiliza un contrato de versiones apropiado. La consulta previa no garantiza concurrencia segura.
Los TVP no tienen orden inherente. Incluye una columna de secuencia cuando importe y ordena la salida. Para claves generadas, devuelve LineId junto al identificador de destino en vez de relacionarlos según el orden de llegada.
En .NET, enlaza un parámetro estructurado con el nombre de tipo correcto y su esquema. Puedes usar DataTable o una secuencia de filas. Ajusta tipos, precisión, escala, longitudes y nulabilidad. El nombre correcto no compensa una estructura incompatible.
Medir tamaños realistas
SQL Server no mantiene estadísticas de columnas para TVP. Una ejecución con cinco filas y otra con cincuenta mil pueden necesitar planes distintos. La clave primaria aporta unicidad y acceso, pero no histogramas de distribución.
Para entradas grandes y variables, copiar a una tabla temporal con índices y estadísticas puede mejorar las uniones. Añade copia y carga de tempdb, por lo que debes medir toda la llamada. Recompilar puede ayudar en ciertos casos de cardinalidad sin producir las estadísticas ausentes.
Define un máximo práctico y considera lotes acotados para importaciones enormes. Un TVP no supera a la carga bulk en todos los tamaños. Compara serialización, transferencia, compilación y ejecución conjuntamente.
El llamador necesita permisos del procedimiento y del tipo, incluido REFERENCES cuando corresponda. Separa despliegue y uso normal. Cambiar la estructura de un tipo de tabla suele requerir despliegue versionado de objetos dependientes y compatibilidad con clientes antiguos.
Prueba entradas vacías, duplicados, cantidades inválidas, productos desconocidos, tamaño máximo y reintentos tras una respuesta incierta. La interfaz debe reducir llamadas sin perder el comportamiento preciso de cada fila ni del conjunto completo.
Referencias técnicas: Microsoft Learn: Table-valued parameters · Microsoft Learn: CREATE TYPE.