SQL Server: Ist es möglich, in zwei Tabellen zur gleichen Zeit einfügen?
-
05-07-2019 - |
Frage
Meine Datenbank enthält drei Tabellen genannt Object_Table
, Data_Table
und Link_Table
. Die Verknüpfungstabelle enthält nur zwei Spalten, um die Identität eines Objektdatensatzes und eine Identität eines Datensatzes.
Ich mag die Daten von DATA_TABLE
kopieren, in dem es zu einer bestimmten Objektidentität verknüpft ist, und fügen Sie Datensätze in Data_Table
und Link_Table
für eine andere bestimmte Objektidentität entspricht.
I können Dies geschieht, indem in eine Tabelle Variable auswählen und das Durchschleifen für jede Iteration zwei Einsätze zu tun.
Ist dies der beste Weg, es zu tun?
Bearbeiten : Ich habe eine Schleife aus zwei Gründen vermeiden will, die erste ist, dass ich faul bin und eine Schleife / temp Tabelle mehr Code erfordert, mehr Code mehr Orte bedeutet einen Fehler zu machen und der zweite Grund ist die Sorge über die Leistung.
kann ich alle Daten in einem Einsatz kopieren, sondern, wie die Link-Tabelle auf die neuen Datensätze zu verknüpfen erhalte, wo jeder Datensatz eine neue ID hat?
Lösung 3
Die folgenden Sätze auf die Situation, die ich hatte, Tabellenvariablen verwendet wird.
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
Durch eine andere Antwort , die mich auf die OUTPUT-Klausel habe ich darauf hingewiesen, eine Lösung nachweisen kann:
-- 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
Es stellt sich heraus jedoch, dass es wegen des folgenden Fehlers
im wirklichen Leben ist nicht so einfachder OUTPUT INTO-Klausel kann nicht auf seine auf beiden Seiten eines (Primärschlüssel, Fremd key) Beziehung
Ich kann immer noch eine temporäre Tabelle und dann fertig mit normalen Einsatz OUTPUT INTO
. So kann ich meine Schleife vermeiden, aber ich kann die temporäre Tabelle nicht vermeiden.
Andere Tipps
In einer Anweisung . Nein
In einer Transaktion : Ja
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
Die gute Nachricht ist, dass der oben genannte Code auch sein garantiert Atom , und kann in einem einzigen Funktionsaufruf mit einer SQL-Zeichenfolge von einer Client-Anwendung an den Server gesendet werden, als ob es ein waren Aussage. Sie könnten auch einen Trigger auf eine Tabelle gelten die Wirkung eines einzelnen Einsatz zu bekommen. Allerdings ist es letztlich noch zwei Aussagen und Sie wahrscheinlich nicht wollen, den Auslöser für alle einfügen.
laufen Sie müssen noch zwei INSERT
Aussagen, aber es klingt wie Sie die IDENTITY
aus dem ersten Einsatz zu bekommen und es in den zweiten verwenden, wobei in diesem Fall, Sie könnten in OUTPUT
oder OUTPUT INTO
aussehen wollen: http://msdn.microsoft.com/en-us/library/ms177564.aspx
Es klingt wie die Link-Tabelle, die die vielen einfängt. Beziehung zwischen der Objekttabelle und Datentabelle
Mein Vorschlag ist, eine gespeicherte Prozedur zu verwenden, um die Transaktionen zu verwalten. Wenn Sie zum Objekt oder Datentabelle einfügen mögen Ihre Einsätze durchführen, um die neue IDs erhalten und sie an die Link-Tabelle einfügen.
Auf diese Weise können alle Ihre Logik in Frage zu nennen sproc leicht eingekapselt bleiben.
Wenn Sie die Aktionen wollen mehr oder weniger Atom sein, würde ich sicherstellen, dass sie in einer Transaktion wickeln. Auf diese Weise können beide sicher sein, passiert oder beide nicht nach Bedarf geschehen.
Sie können eine Ansicht der Auswahl der Spaltennamen durch Ihre Insert-Anweisung erforderlich erstellen, fügen Sie ein STATT INSERT-Trigger, und legen Sie in dieser Ansicht.
Ich möchte auf mit
StressSET XACT_ABORT ON;
für die MSSQL-Transaktion mit mehreren SQL-Anweisungen.
Siehe auch: https://msdn.microsoft.com/en-us/ Bibliothek / ms188792.aspx Sie bieten ein sehr gutes Beispiel.
So sollte der endgültige Code wie folgt aussehen:
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
Einfügen kann nur auf einem Tisch zu einem Zeitpunkt, betreiben. Mehrere Einsätze haben mehrere Anweisungen haben.
Ich weiß nicht, dass Sie die Schleife durch eine Tabelle Variable tun müssen - können Sie nicht nur eine Masse in eine Tabelle einfügen verwenden, dann legen Sie die Masse in die anderen
Übrigens - ich vermute, Sie die Daten aus Object_Table kopieren bedeuten; sonst wird die Frage nicht sinnvoll ist.
Bevor man ein Multitable Einsatz in Oracle tun, könnten Sie einen Trick verwenden, um einen Einsatz in eine Ansicht, die Beteiligung definiert auf sie ein INSTEAD OF-Trigger musste die Einsätze durchzuführen. Kann dies in SQL Server durchgeführt werden?
-- ================================================
-- 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
// Wenn Sie das gleiche wie erste Tabelle einfügen möchten
$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);
// oder wenn Sie wollen bestimmte Teile Tabelle ein
einfügen $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);
// Ich weiß es zu gut aussieht richtig zu sein, aber es funktioniert und Sie halten Abfrage Hinzufügen ist nur das ändern
"$qry"-number and number in @mysql_query($qry"")
Ich habe 17 Tabellen dies in gearbeitet hat.