如何将值插入具有外键关系的两个表中?

时间:2016-06-19 16:19:46

标签: sql sql-server database sql-server-2014

我创建了两个表:

  • 表格tblStaff包含id列(主键,自动增量),nameageaddress

  • tblRoleOfStaff,列id(主键,自动增量),StaffIdtblStaff的外键),RoleId

我有表格来创建具有现有角色的新员工。要插入的数据样本:

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

我想在SQL Server 2014中编写一个存储过程,以便将新员工插入tblStaff并将新记录插入tbleRoleOfStaff,并插入staffId

我该怎么办?

如果我的问题与其他问题重复,我很抱歉。我对SQL更新。 谢谢你的帮助。

6 个答案:

答案 0 :(得分:12)

tblRoleOfStuff的地方StaffId使用SCOPE_IDENTITY()秒插入。像:

insert into tblStaff values
(@name, @age, @address)

insert into tblRoleOfStuff values
(scope_identity(), @roleid)

修改

这个答案有太多评论,所以我想解释一下。

如果OP保证他不会使用任何触发器,他可能会使用@@IDENTITY(不良做法),这足以满足他的需求,但最佳做法是使用SCOPE_IDENTITY()

  

SCOPE_IDENTITY()与@@ IDENTITY一样,将返回在当前会话中创建的最后一个标识值,但它也会将其限制为当前范围。换句话说,它将返回您显式创建的最后一个标识值,而不是由触发器或用户定义函数创建的任何标识。

SCOPE_IDENTITY()将保证您从当前操作中获取身份,而不是从其他连接或最后一个连接获得身份。

为什么不IDENT_CURRENT?因为

  

IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表格。 IDENT_CURRENT返回在任何会话和任何范围内为特定表生成的标识值。

所以你制作最后一个范围,但不是当前范围。是的,OP也可以使用它,但在这种情况下这是一种不好的做法(比如仅使用@@IDENTITY

使用OUTPUT确实是一种很好的做法,但对于一个身份来说过于复杂。如果OP需要在一段时间内处理多行 - 是的,他需要OUTPUT

答案 1 :(得分:3)

因为您似乎一次讨论一行,有些人可能会告诉您使用可@@IDENTITY或其他一些系统可用的系统,但为了确保更加确定,我建议使用OUTPUT insert语句的子句。这种方法的好处是它可以很容易地适应一次处理超过1行。

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)

如果执行与您的链接相关的其他操作,则不使用@@IDENTITY的原因。例如。触发器将另一行插入另一个表,或更新数据库中的另一个记录。SCOPE_IDENTITY在触发器修改同一个表时有类似的缺陷。 IDENT_CURRENT也有短暂的进展。进行互联网搜索,了解更多关于这些的大量资源。

答案 2 :(得分:2)

您可以使用第一个插入语句中的output

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

您也可以同时插入多个角色。

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

答案 3 :(得分:0)

如果一次只插入一个员工行,则可以执行以下操作:

begin try
 begin tran
  insert into tblStaff (name, age, address) values('my name',20,'San Jose');
  insert into tbleRoleOfStaff (StaffId, RoleId) values (SCOPE_IDENTITY(), 1); 
 commit
end try
begin catch
  IF @@trancount > 0 ROLLBACK;
end catch

答案 4 :(得分:-1)

插入第一个表后使用类似

的内容
DECLARE @staffId INT
SET @staffId = (SELECT TOP 1 id from tblStaff order by id desc)

INSERT INTO tblRoleOfStaff (staffId,roleId) VALUES (@staffId, 2)

答案 5 :(得分:-1)

试试这个:

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

请注意IDENT_CURRENTSCOPE_IDENTITY@@IDENTITY之间的差异。阅读它Here