sql - relacionadas - insertar en dos tablas con el mismo id
SQL Server: ¿es posible insertar en dos tablas al mismo tiempo? (11)
// si quieres insertar lo mismo que la primera mesa
$qry = "INSERT INTO table (one, two, three) VALUES(''$one'',''$two'',''$three'')";
$result = @mysql_query($qry);
$qry2 = "INSERT INTO table2 (one,two, three) VVALUES(''$one'',''$two'',''$three'')";
$result = @mysql_query($qry2);
// o si quiere insertar ciertas partes de la tabla uno
$qry = "INSERT INTO table (one, two, three) VALUES(''$one'',''$two'',''$three'')";
$result = @mysql_query($qry);
$qry2 = "INSERT INTO table2 (two) VALUES(''$two'')";
$result = @mysql_query($qry2);
// Sé que parece demasiado bueno para estar bien, pero funciona y puedes seguir agregando consultas, solo cambia el
"$qry"-number and number in @mysql_query($qry"")
Tengo 17 mesas en las que esto ha funcionado.
Mi base de datos contiene tres tablas llamadas Object_Table
, Data_Table
y Link_Table
. La tabla de enlace solo contiene dos columnas, la identidad de un registro de objeto y una identidad de un registro de datos.
Quiero copiar los datos de DATA_TABLE
donde está vinculado a una identidad de objeto dado e insertar los registros correspondientes en Data_Table
y Link_Table
para una identidad de objeto dada diferente.
Puedo hacer esto seleccionando en una variable de tabla y haciendo un bucle haciendo dos inserciones para cada iteración.
¿Es esta la mejor manera de hacerlo?
Editar : quiero evitar un bucle por dos razones, la primera es que soy flojo y una tabla de bucle / temp requiere más código, más código significa más lugares para cometer un error y la segunda razón es una preocupación sobre el rendimiento.
Puedo copiar todos los datos en una sola inserción, pero ¿cómo puedo obtener la tabla de enlaces para vincular a los nuevos registros de datos donde cada registro tiene una nueva identificación?
A continuación, configuro 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 answer que me señaló 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 en ninguno de los lados de una relación (clave principal, clave externa)
Todavía puedo OUTPUT INTO
una tabla temporal y luego terminar con inserción normal. Así que puedo evitar mi ciclo pero no puedo evitar la tabla temporal.
Antes de poder hacer una inserción múltiple en Oracle, podría usar un truco que involucre una inserción en una vista que tenía un desencadenador INSTEAD OF definido en ella para realizar las inserciones. ¿Se puede hacer esto en SQL Server?
En una declaración : No.
En una 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 el código anterior también está garantizado que es atómico , y puede enviarse al servidor desde una aplicación cliente con una cadena sql en una sola llamada a función como si fuera una sola 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, sigue siendo dos afirmaciones y es probable que no desee ejecutar el desencadenador para cada inserción.
Insert solo puede operar en una tabla a la vez. Las inserciones múltiples deben tener múltiples declaraciones.
No sé si necesitas hacer un bucle a través de una variable de tabla, ¿no puedes simplemente usar una inserción masiva en una tabla, y luego insertar la masa en la otra?
Por cierto, supongo que quieres copiar los datos de Object_Table; de lo contrario, la pregunta no tiene sentido.
Parece que la tabla Enlace captura la relación muchos: muchos entre la tabla Objeto y la Tabla de datos.
Mi sugerencia es utilizar un procedimiento almacenado para administrar las transacciones. Cuando desee insertar en el objeto o la tabla de datos, realice sus inserciones, obtenga los nuevos ID e insértelos en la tabla de enlaces.
Esto permite que toda su lógica permanezca encapsulada en un sproc fácil de llamar.
Puede crear una vista seleccionando los nombres de columna requeridos por su instrucción de inserción, agregar un desencadenador INSTEAD OF INSERT e insertar en esta vista.
Quiero hacer hincapié en el uso
SET XACT_ABORT ON;
para la transacción MSSQL con múltiples sentencias sql.
Ver: https://msdn.microsoft.com/en-us/library/ms188792.aspx Proporcionan un muy buen ejemplo.
Por lo tanto, el código final debería ser similar al siguiente:
SET XACT_ABORT ON;
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
Si desea que las acciones sean más o menos atómicas, me aseguraré de envolverlas en una transacción. De esa manera, puede estar seguro de que ambos sucedieron o que ambos no sucedieron según sea necesario.
Todavía necesita dos INSERT
, pero parece que desea obtener la IDENTITY
de la primera inserción y usarla en la segunda, en cuyo caso, es posible que desee buscar en OUTPUT
o OUTPUT INTO
: http://msdn.microsoft.com/en-us/library/ms177564.aspx
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE InsetIntoTwoTable
(
@name nvarchar(50),
@Email nvarchar(50)
)
AS
BEGIN
SET NOCOUNT ON;
insert into dbo.info(name) values (@name)
insert into dbo.login(Email) values (@Email)
END
GO