Comment puis-je INSÉRER des données dans deux tables en même temps dans SQL Server?
Disons que mon tableau de structure ressemble à quelque chose comme ceci:
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)
)
La [id]
champ de la première table correspond à la [table1_id]
champ de la seconde. Ce que je voudrais faire est d'insérer des données dans deux tables en une seule transaction. Maintenant, je sais déjà comment faire cela en faisant INSÉRER-SÉLECTIONNEZ-INSÉRER, comme ceci:
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;
C'est tout bon et très bien pour de petites affaires comme celle où vous êtes seule l'insertion, peut-être une poignée de lignes. Mais ce dont j'ai besoin pour faire est d'insérer un couple de centaines de milliers de lignes, ou peut-être même un million de lignes, tout à la fois. Les données proviennent d'une autre table, donc si je n'avais que de l'insérer dans une table unique, il serait facile, que je venais de faire ceci:
INSERT INTO [table] ([data])
SELECT [data] FROM [external_table];
Mais comment pourrais-je faire cela et de diviser les données en [table1]
et [table2]
, et de toujours mettre à jour [table2]
avec le [table1_id]
que je suis en train de faire? Est-il même possible?
- Belle question beaucoup de débutants de SQL demandent souvent.
Vous devez vous connecter pour publier un commentaire.
Essayez ceci:
Mise à JOUR: Re:
Il est impossible à la sortie des colonnes externes dans un
insert
déclaration, donc je pense que vous pourriez faire quelque chose comme cebegin tran... commit tran
états, comme c'est manifestement va être exécuté en une seule transaction.INSERT INTO [table1] ([data]) OUTPUT [inserted].[id], [external_table].[col2] INTO [table2] SELECT [col1] FROM [external_table]
col2
colonne dans latable1
. Alors vous seriez en mesure de produire l'inserted.col2
dans letable2
.J'ai aussi été aux prises avec ce problème, et de trouver que le meilleur moyen est d'utiliser un CURSEUR.
J'ai essayé Denis solution de SORTIE, mais comme il mentiond, il est impossible à la sortie des colonnes externes dans une instruction insert, et que la FUSION ne peut pas travailler quand insérer plusieurs lignes en sélectionner.
Donc, j'ai utilisé un CURSEUR, pour chaque ligne de la table externe, j'ai fait INSÉRER, puis utilisez le @@IDENTITY pour INSÉRER un autre.
Garder un oeil sur pour SQL Server pour prendre en charge le 'INSÉRER' Instruction. Oracle a déjà, il ressemble à ceci (SQL livre de recettes):
source.id, new.id
dans leoutput
clause. Vous êtes uniquement autorisé à utiliserinserted.*
là pourinsert
. Pourdelete
,update
etmerge
il est possible d'inclure une colonne de la table spécifiée.Une autre option consiste à exécuter les deux inserts séparément, laissant le FK colonne nulle, alors l'exécution d'une mise à jour de poulate correctement.
Si il n'y a rien de naturel stocké dans les deux tableaux qui correspondent à partir d'un enregistrement à l'autre (probablement) puis créer un temporaire GUID de la colonne et le remplir de vos données et de les insérer des deux domaines. Ensuite, vous pouvez mettre à jour avec le bon FK et null le Guid.
E. g.:
JoinGuid
pour les deux tableaux? C'est simple si vous avez un enregistrement dansTable1
et un enregistrement dansTable2
, mais je ne peux pas imaginer comment l'implémenter dans le cas d'un grand nombre de lignes.Vous pourriez écrire une procédure stockée qui effectue une itération sur l'opération que vous avez proposé. L'itérateur serait le curseur de la table qui contient la source de données.