development

SQL Server : 두 테이블에 동시에 삽입 할 수 있습니까?

big-blog 2020. 6. 29. 07:29
반응형

SQL Server : 두 테이블에 동시에 삽입 할 수 있습니까?


내 데이터베이스라는 세 개의 테이블을 포함하고 Object_Table, Data_Table하고 Link_Table. 연결 테이블에는 개체 레코드의 ID와 데이터 레코드의 ID라는 두 개의 열만 포함됩니다.

나는의 데이터를 복사 할 DATA_TABLE이 하나 개의 지정된 객체의 정체성과에 기록을 해당 삽입 연결되는 경우 Data_TableLink_Table다른 지정된 객체 정체성을.

내가 할 수 있는 테이블 변수로 선택하고 각 반복 두 삽입하고 통해 반복하여이 작업을 수행.

이것이 최선의 방법입니까?

편집 : 두 가지 이유로 루프를 피하고 싶습니다. 첫 번째는 게으르고 루프 / 온도 테이블에 더 많은 코드가 필요하다는 것입니다. 더 많은 코드는 실수를하기 위해 더 많은 장소를 의미하며 두 번째 이유는 성능에 대한 우려입니다.

한 번의 삽입으로 모든 데이터를 복사 할 수 있지만 각 레코드에 새 ID가있는 새 데이터 레코드에 링크 테이블을 링크하려면 어떻게해야합니까?


진술에서 : 아니오.

한 번의 거래에서 : 예

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

좋은 소식은 위의 코드도 원 자성으로 보장되며 단일 함수 호출에서 하나의 명령문 인 것처럼 하나의 SQL 문자열로 클라이언트 애플리케이션에서 서버로 전송 될 수 있다는 것입니다. 단일 삽입의 효과를 얻기 위해 하나의 테이블에 트리거를 적용 할 수도 있습니다. 그러나 궁극적으로 여전히 두 개의 명령문이므로 모든 삽입에 대해 트리거를 실행하지 않을 것입니다 .


여전히 두 개의 INSERT구문이 필요 하지만 IDENTITY첫 번째 삽입물 을 가져 오고 두 번째 삽입물에서 사용 하려는 것처럼 들립니다 .이 경우 다음을 살펴 OUTPUT보거나 싶을 수 있습니다 OUTPUT INTO. http://msdn.microsoft.com/en- us / library / ms177564.aspx


다음은 테이블 변수를 사용하여 내가 가진 상황을 설정합니다.

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

Thanks to another answer that pointed me towards the OUTPUT clause I can demonstrate a solution:

-- 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

It turns out however that it is not that simple in real life because of the following error

the OUTPUT INTO clause cannot be on either side of a (primary key, foreign key) relationship

I can still OUTPUT INTO a temp table and then finish with normal insert. So I can avoid my loop but I cannot avoid the temp table.


It sounds like the Link table captures the many:many relationship between the Object table and Data table.

My suggestion is to use a stored procedure to manage the transactions. When you want to insert to the Object or Data table perform your inserts, get the new IDs and insert them to the Link table.

This allows all of your logic to remain encapsulated in one easy to call sproc.


If you want the actions to be more or less atomic, I would make sure to wrap them in a transaction. That way you can be sure both happened or both didn't happen as needed.


You might create a View selecting the column names required by your insert statement, add an INSTEAD OF INSERT Trigger, and insert into this view.


I want to stress on using

SET XACT_ABORT ON;

for the MSSQL transaction with multiple sql statements.

See: https://msdn.microsoft.com/en-us/library/ms188792.aspx They provide a very good example.

So, the final code should look like the following:

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

Insert can only operate on one table at a time. Multiple Inserts have to have multiple statements.

I don't know that you need to do the looping through a table variable - can't you just use a mass insert into one table, then the mass insert into the other?

By the way - I am guessing you mean copy the data from Object_Table; otherwise the question does not make sense.


Before being able to do a multitable insert in Oracle, you could use a trick involving an insert into a view that had an INSTEAD OF trigger defined on it to perform the inserts. Can this be done in SQL Server?


-- ================================================
-- 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

//if you want to insert the same as first table

$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);

//or if you want to insert certain parts of table one

 $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);

//i know it looks too good to be right, but it works and you can keep adding query's just change the

    "$qry"-number and number in @mysql_query($qry"")

I have 17 tables this has worked in.

참고URL : https://stackoverflow.com/questions/175066/sql-server-is-it-possible-to-insert-into-two-tables-at-the-same-time

반응형