Comment insert des valeurs dans deux tables avec une relation de key étrangère?

J'ai créé deux tables:

  • Table tblStaff avec les colonnes id (key primaire, incrément automatique), name , age , address

  • Table tblRoleOfStaff avec les colonnes id (key primaire, auto increment), StaffId (key étrangère to tblStaff ), RoleId

J'ai la forme pour créer un nouveau personnel avec un rôle existant. Échantillon de données à insert:

 (name, age, address, roleId) = ('my name',20,'San Jose', 1) 

Je veux écrire une procédure stockée dans SQL Server 2014 pour insert du nouveau personnel dans tblStaff et insert un nouvel logging dans tbleRoleOfStaff avec staffId je viens d'insert.

Que devrais-je faire?

Je suis tellement désolé si ma question est en double avec d'autres. Je suis plus frais en SQL. Merci pour toute aide.

Utilisez la seconde insertion SCOPE_IDENTITY () dans tblRoleOfStuff sur une place de StaffId . Comme:

 insert into tblStaff values (@name, @age, @address) insert into tblRoleOfStuff values (scope_identity(), @roleid) 

MODIFIER

Il y a trop de commentaires sur cette réponse, alors je veux donner une explication.

Si OP garantit qu'il n'utilisera aucun triggersur, il peut utiliser @@IDENTITY (mauvaise pratique), il est suffisant pour ses besoins, mais il est préférable d'utiliser SCOPE_IDENTITY() .

SCOPE_IDENTITY (), comme @@ IDENTITY, renvoie la dernière valeur d'identité créée dans la session en cours, mais elle la limite également à votre scope actuelle. En d'autres termes, il renvoie la dernière valeur d'identité que vous avez explicitement créée, plutôt que toute identité créée par un triggersur ou une fonction définie par l'user.

SCOPE_IDENTITY() garantira que vous obtenez l'identité de l'opération en cours, pas d'une autre connection ou du dernier traité.

Pourquoi pas IDENT_CURRENT ? Car

IDENT_CURRENT n'est pas limité par la scope et la session; il est limité à une table spécifiée. IDENT_CURRENT renvoie la valeur d'identité générée pour une table spécifique dans toute session et toute scope.

Donc vous faites prendre la dernière scope mais pas celle en cours. Oui, OP peut aussi l'utiliser, mais c'est une mauvaise pratique dans cette situation (comme utiliser seulement @@IDENTITY )

Utiliser OUTPUT est en effet une bonne pratique, mais trop complexe pour une seule identité. Si OP doit traiter plus d'une ligne à la fois – oui, il a besoin de OUTPUT .

Parce qu'il semble que vous discutez 1 ligne à la fois, certaines personnes peuvent vous dire d'utiliser un système vairable comme @@IDENTITY ou certains des autres, mais pour assurer avec plus de certitude, je recommand la clause OUTPUT de l'instruction d'insertion. La bonne chose à propos de cette méthode est qu'elle peut facilement être adaptée pour gérer plus de 1 rangée à la fois.

 DECLARE @Output AS TABLE (StaffId INT) INSERT INTO tblStaff (name, age, address) OUTPUT inserted.Id INTO @Output (StaffId) VALUES (@name, @age, @address) DECLARE @StaffId INT SELECT @StaffId = StaffId FROM @Output INSERT INTO tblRoleOfStaff (StaffId, RoleId) VALUES (@StaffId,@RoleId) 

Raisons de ne pas utiliser @@IDENTITY dans le cas où une autre opération liée à la vôtre est effectuée. Par exemple, un triggersur insère une autre ligne dans une autre table ou met à jour un autre logging dans votre database. SCOPE_IDENTITY présente un déficit similaire lorsqu'un triggersur modifie la même table. IDENT_CURRENT a aussi une courte date d'arrivée. Faire une search sur Internet pour en savoir plus, il ya des tonnes de ressources sur ces.

Vous pouvez utiliser la output de votre première instruction d'insertion.

 declare @tmp table(id int) insert tblStaff (name, age, address) OUTPUT inserted.Id INTO @tmp (id) values (@name, @age, @address) declare @roleId int = 1 --or whatever insert tblRoleOfStaff (staffId,roleId) select id, @roleId from @tmp 

Vous pouvez également insert plusieurs rôles à la fois.

 create table Roles (roleId int identity(1,1) primary key, RoleName varchar(50), isDefaultRole bit default 0 ) --mark some roles as default (`isDefaultRole = 1`) --the 2nd insert will be insert tblRoleOfStaff (staffId,roleId) select id, roleId from @tmp cross join Roles where isDefaultRole = 1 

Après l'insertion dans la première table, utilisez quelque chose comme

 DECLARE @staffId INT SET @staffId = (SELECT TOP 1 id from tblStaff order by id desc) INSERT INTO tblRoleOfStaff (staffId,roleId) VALUES (@staffId, 2) 

Essaye ça:

 Create Procedure Pro_XXX() AS BEGIN INSERT INTO tblStaff (name, age, address, roleId) VALUES ('my name',20,'San Jose', 1); INSERT INTO tbleRoleOfStaff VALUES (staffId, roleId) VALUES (IDENT_CURRENT('tblStaff'),0) END 

Veuillez noter les différences entre IDENT_CURRENT , SCOPE_IDENTITY et @@IDENTITY . Lisez à ce sujet ici