Si hallas algún problema con tu código o proyecto, recuerda probar siempre en un ambiente de testing antes aplicar el código al trabajo final.
Solución:
En uno declaración: No.
En uno transacción: Sí
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
La buena noticia es que también se garantiza que el código anterior será atómicoy se puede enviar al servidor desde una aplicación cliente con un sql string en una sola llamada de función como si fuera una declaración. También puede aplicar un disparador a una tabla para obtener el efecto de una sola inserción. Sin embargo, en última instancia, todavía son dos declaraciones y probablemente no desee ejecutar el disparador para cada insertar.
Todavía necesitas dos INSERT
declaraciones, pero parece que quiere obtener el IDENTITY
desde el primer inserto y utilícelo en el segundo, en cuyo caso, es posible que desee investigar OUTPUT
o OUTPUT INTO
: http://msdn.microsoft.com/en-us/library/ms177564.aspx
Lo siguiente configura la situación que tenía, usando variables de tabla.
DECLARE @Object_Table TABLE
(
Id INT NOT NULL PRIMARY KEY
)
DECLARE @Link_Table TABLE
(
ObjectId INT NOT NULL,
DataId INT NOT NULL
)
DECLARE @Data_Table TABLE
(
Id INT NOT NULL Identity(1,1),
Data VARCHAR(50) NOT NULL
)
-- create two objects '1' and '2'
INSERT INTO @Object_Table (Id) VALUES (1)
INSERT INTO @Object_Table (Id) VALUES (2)
-- create some data
INSERT INTO @Data_Table (Data) VALUES ('Data One')
INSERT INTO @Data_Table (Data) VALUES ('Data Two')
-- link all data to first object
INSERT INTO @Link_Table (ObjectId, DataId)
SELECT Objects.Id, Data.Id
FROM @Object_Table AS Objects, @Data_Table AS Data
WHERE Objects.Id = 1
Gracias a otra respuesta que me indicó la cláusula OUTPUT, puedo demostrar una solución:
-- now I want to copy the data from from object 1 to object 2 without looping
INSERT INTO @Data_Table (Data)
OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId)
SELECT Data.Data
FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId
INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id
WHERE Objects.Id = 1
Sin embargo, resulta que no es tan simple en la vida real debido al siguiente error
la cláusula OUTPUT INTO no puede estar a ningún lado de un (principal keyextranjero
key) relación
todavía puedo OUTPUT INTO
una tabla temporal y luego termine con una inserción normal. Entonces puedo evitar mi ciclo pero no puedo evitar la tabla temporal.