una txt registros otra insertar importar enviar ejecutar desde datos copiar convertir sql sql-server sql-server-2012 sql-server-2014

sql - txt - mantener una columna personalizada de incremento automático



importar txt a sql server 2012 (3)

Tengo una tabla con ID (identidad) y XID (int) que es mi columna personalizada de incremento automático. Estoy usando un activador en lugar de insertar para mantener XID, pero obtengo duplicados.

mesa

xtable (ID de identidad, XID int)

gatillo - en lugar de insertar

insert into [xtable] (XID) select [x].[NextavailableID] from inserted [i] cross apply ( select coalesce(max([t].[XID]), 0) + 1 [NextavailableID] from [xtable] [t] ) [x];

Suponiendo insertado = 1 fila.

Este disparador no evita duplicados en la columna XID. ¿Alguna idea sobre cómo cambiarla?


El problema es que si tiene varias filas insertadas, está utilizando la misma ID disponible para todas las filas, deberá agregar ROW_NUMBER() para asegurarse de que el xid sea único en la inserción:

insert into [xtable] (XID) select [x].[NextavailableID] + ROW_NUMBER() OVER (ORDER BY i.ID) from inserted [i] cross apply ( select coalesce(max([t].[XID]), 0) [NextavailableID] from [xtable] [t] WITH (TABLOCK, HOLDLOCK) ) [x];

Con respecto a la prevención de duplicados, puede usar sugerencias de tabla para bloquear xtable al obtener el xid máximo.

El inconveniente de usar estos bloqueos es que se bloqueará. Debería tener una restricción / índice único en esta columna ya que esto evitará duplicados, sin embargo, también dará lugar a excepciones cuando se cumpla una condición de carrera. En definitiva, sea cual sea el método que elija, tendrá que hacer algún tipo de sacrificio.


SQL Server 2012+:

Yo usaría secuencias .

Primero crearía una nueva secuencia

CREATE SEQUENCE dbo.XTable_XID START WITH 1 -- You should replace the starting value INCREMENT BY 1 -- CACHE 50; -- Optimization: read documentation first GO

y luego usaría NEXT VALUE FOR para generar nuevos valores así:

-- #1 I would use this function when I insert rows `into dbo.XTable` INSERT INTO [dbo].[XTable] (Col1, Col2, Col3, ..., XID) VALUES (''A'', 123, 1000.50, (NEXT VALUE FOR dbo.XTable_XID));

o

-- #2: Also, you could rewrite the trigger thus: insert into [xtable] (XID) select (NEXT VALUE FOR dbo.XTable_XID) from inserted [i]

Si está utilizando el primer método, podría soltar ese activador si solo se usa para generar estos ID. Usaría la solución n. ° 1.

+

Crearía un índice único:

CREATE UNIQUE INDEX IUN_XTable_XID ON dbo.XTable (XID);


Terminé creando otra tabla para almacenar el último incremento. En el desencadenador, dentro de una transacción, selecciono de la nueva tabla con sugerencias ( ROWLOCK , ROWLOCK ).

mesa

Info (LastId int)

gatillo - en lugar de insertar

declare @nextId int; begin tran t1 set @nextId = (select top 1 LastId from Info with (UPDLOCK, ROWLOCK)) + 1; update Info set LastId = nextId; commit tran t1 insert into [xtable] (XID) select @nextId from inserted [i]