我创建了两个表:
表格tblStaff
包含id
列(主键,自动增量),name
,age
,address
表tblRoleOfStaff
,列id
(主键,自动增量),StaffId
(tblStaff
的外键),RoleId
我有表格来创建具有现有角色的新员工。要插入的数据样本:
(name, age, address, roleId) = ('my name',20,'San Jose', 1)
我想在SQL Server 2014中编写一个存储过程,以便将新员工插入tblStaff
并将新记录插入tbleRoleOfStaff
,并插入staffId
。
我该怎么办?
如果我的问题与其他问题重复,我很抱歉。我对SQL更新。 谢谢你的帮助。
答案 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_CURRENT
,SCOPE_IDENTITY
和@@IDENTITY
之间的差异。阅读它Here