it-swarm.com.de

Wie kann ich in SQL Server Daten gleichzeitig in zwei Tabellen einfügen?

Nehmen wir an, meine Tabellenstruktur sieht ungefähr so ​​aus:

CREATE TABLE [dbo].[table1] (
    [id] [int] IDENTITY(1,1) NOT NULL,
    [data] [varchar](255) NOT NULL,
    CONSTRAINT [PK_table1] PRIMARY KEY CLUSTERED ([id] ASC)
)

CREATE TABLE [dbo].[table2] (
    [id] [int] IDENTITY(1,1) NOT NULL,
    [table1_id] [int] NOT NULL,
    [data] [varchar](255) NOT NULL,
    CONSTRAINT [PK_table2] PRIMARY KEY CLUSTERED ([id] ASC)
)

Das [id] Feld der ersten Tabelle entspricht dem [table1_id] Feld der Sekunde. Ich möchte in einer einzigen Transaktion Daten in beide Tabellen einfügen. Jetzt weiß ich bereits, wie das geht, indem ich INSERT-SELECT-INSERT mache:

BEGIN TRANSACTION;
DECLARE @id [int];
INSERT INTO [table1] ([data]) VALUES ('row 1');
SELECT @id = SCOPE_IDENTITY();
INSERT INTO [table2] ([table1_id], [data]) VALUES (@id, 'more of row 1');
COMMIT TRANSACTION;

Das ist alles gut und in Ordnung für kleine Fälle, in denen Sie nur eine Handvoll Zeilen einfügen. Aber ich muss nur ein paar hunderttausend Zeilen oder möglicherweise sogar eine Million Zeilen auf einmal einfügen. Die Daten stammen aus einer anderen Tabelle. Wenn ich sie also nur in eine einzelne Tabelle einfügen würde, wäre es einfach. Ich müsste nur Folgendes tun:

INSERT INTO [table] ([data])
SELECT [data] FROM [external_table];

Aber wie würde ich das machen und die Daten in [table1] und [table2] und immer noch aktualisieren [table2] mit dem entsprechenden [table1_id] wie mache ich das Ist das überhaupt möglich?

50
soapergem

Versuche dies:

insert into [table] ([data])
output inserted.id, inserted.data into table2
select [data] from [external_table]

PDATE: Re:

Denis - das scheint mir sehr nahe zu sein, aber vielleicht könnten Sie die folgende SQL-Anweisung für mich korrigieren? Grundsätzlich repräsentieren die [Daten] in [Tabelle1] und die [Daten] in [Tabelle2] zwei verschiedene Spalten von [externe_Tabelle]. Die Anweisung, die Sie oben gepostet haben, funktioniert nur, wenn die Spalten [data] identisch sein sollen.

INSERT INTO [table1] ([data]) 
OUTPUT [inserted].[id], [external_table].[col2] 
INTO [table2] SELECT [col1] 
FROM [external_table] 

Es ist unmöglich, externe Spalten in einer insert -Anweisung auszugeben, daher denke ich, dass Sie so etwas tun könnten

merge into [table1] as t
using [external_table] as s
on 1=0 --modify this predicate as necessary
when not matched then insert (data)
values (s.[col1])
output inserted.id, s.[col2] into [table2]
;
30
Denis Valeev

Ich hatte auch Probleme mit diesem Problem und finde, dass der beste Weg ist, einen CURSOR zu verwenden.

Ich habe Denis-Lösung mit OUTPUT ausprobiert, aber wie bereits erwähnt, ist es unmöglich, externe Spalten in einer insert-Anweisung auszugeben, und die MERGE-Funktion funktioniert nicht, wenn mehrere Zeilen durch select eingefügt werden.

Also habe ich einen CURSOR verwendet, für jede Zeile in der äußeren Tabelle habe ich ein INSERT durchgeführt und dann das @@ IDENTITY für ein anderes INSERT verwendet.

DECLARE @OuterID int

DECLARE MY_CURSOR CURSOR 
  LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR 
SELECT  ID FROM   [external_Table]

OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @OuterID

WHILE @@FETCH_STATUS = 0
BEGIN 
INSERT INTO [Table]   (data)
    SELECT data
    FROM     [external_Table] where ID = @OuterID 

    INSERT INTO [second_table] (FK,OuterID)
    VALUES(@OuterID,@@identity)

    FETCH NEXT FROM MY_CURSOR INTO @OuterID
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
4
IFink

Halten Sie Ausschau nach SQL Server, um die Anweisung "INSERT ALL" zu unterstützen. Oracle hat es schon, es sieht so aus ( SQL Cookbook ):

insert all
  when loc in ('NEW YORK', 'BOSTON') THEN
   into dept_east(deptno, dname, loc) values(deptno, dname, loc)
  when loc in ('CHICAGO') THEN
   into dept_mid(deptno, dname, loc) values(deptno, dname, loc)
  else
   into dept_west(deptno, dname, loc) values(deptno, dname, loc)
select deptno, dname, loc
  from dept
1
Brian
BEGIN TRANSACTION;

DECLARE @tblMapping table(sourceid int, destid int)

INSERT INTO [table1] ([data]) 
OUTPUT source.id, new.id
Select [data] from [external_table] source;

INSERT INTO [table2] ([table1_id], [data])
Select map.destid, source.[more data] 
from [external_table] source
    inner join @tblMapping map on source.id=map.sourceid;

COMMIT TRANSACTION;
0
Bill

Eine andere Möglichkeit besteht darin, die beiden Einfügungen getrennt auszuführen, die FK-Spalte null zu lassen und dann eine Aktualisierung auszuführen, um sie korrekt zu poulen.

Wenn in den beiden Tabellen nichts Natürliches gespeichert ist, das von einem Datensatz zum nächsten passt (wahrscheinlich), erstellen Sie eine temporäre GUID) - Spalte, füllen Sie diese in Ihre Daten und fügen Sie sie in beide Felder ein Aktualisieren Sie mit dem richtigen FK und löschen Sie die GUIDs.

Z.B.:

CREATE TABLE [dbo].[table1] ( 
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [data] [varchar](255) NOT NULL, 
    CONSTRAINT [PK_table1] PRIMARY KEY CLUSTERED ([id] ASC),
    JoinGuid UniqueIdentifier NULL
) 

CREATE TABLE [dbo].[table2] ( 
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [table1_id] [int] NULL, 
    [data] [varchar](255) NOT NULL, 
    CONSTRAINT [PK_table2] PRIMARY KEY CLUSTERED ([id] ASC),
    JoinGuid UniqueIdentifier NULL
) 


INSERT INTO Table1....

INSERT INTO Table2....

UPDATE b
SET table1_id = a.id
FROM Table1 a
JOIN Table2 b on a.JoinGuid = b.JoinGuid
WHERE b.table1_id IS NULL

UPDATE Table1 SET JoinGuid = NULL
UPDATE Table2 SET JoinGuid = NULL
0
cjk
Create table #temp1
(
 id int identity(1,1),
 name varchar(50),
 profession varchar(50)
)

Create table #temp2
(
 id int identity(1,1),
 name varchar(50),
 profession varchar(50)
)

----- Hauptabfrage ------

insert into #temp1(name,profession)

output inserted.name,inserted.profession into #temp2

select 'Shekhar','IT'
0
Shekhar Kumar