Take a look at GW

【SqlServer】解析INSERT,DELETE 和 UPDATE语句中的OUTPUT从句

sql server 支持在INSERT, DELTE, UPDATE后使用output [into]从句,output是直接输出到结果中,如果想要改变输出终端,比如想要输出到临时表中,这时候就需要使用 output into, 并且在into后指定要输出到的临时表。

INSERT OUTPUT

我们常常会遇见往一个表中插入数据,另一个表中需要插入的数据依赖于我们之前插入的数据。

比如:

学生和班级

--班级
declare @classroom table(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [classname] nvarchar(20) not null
);

--学生
declare @student table(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [classid] [int] not null,
    [studentname] nvarchar(20) not null
);

现在需要添加一个班级,并且在这个班级上添加两个学生。

 

student表中有一个classid字段,表示该学生的所在班级的id。classroom表也就是班级表的id是自增长的,那么怎么获得这个班级id呢?我们可以先给classroom表中插入数据,然后查询最大的id,就可以获得我们刚刚插入进去数据的id。

--1.先往班级表中插入数据
insert into classroom(classname) values('5班');
GO

--2.获得刚刚插入的id
declare @classid int
select @classid = max(id) from classroom;

--3.往学生表中插入数据
insert into student(classid,studentname) values(@classid,'张三');
GO

这样会有一个问题,就是你获得的classid不一定是你想要的id, 万一在你执行第二条sql语句之前,又有一个班级的插入操作,那么数据就不正确了。 

 

这时候可以使用Insert output into语句。

insert classroom
    output 
        INSERTED.id,'张三'
    into 
        student(classid,studentname)
values('5班');

 INSERTED  就是你插入到classroom表的那条数据, INSERTED.id  就是获得你插入的数据生成的id.

 

insert output into 只能插入一条数据,比如你想在添加了一个班级后,再在这个班级下添加两个学生,那么insert output into直接往student里插入数据就不正确了。但可以先把id保存下来,后面再拿着这个保存下来的id进行其他的操作。

--定义一个临时表,用于保存id
declare @temp table(id int)

--将插入生成的classid,保存到@temp临时表中。
insert @classroom
    output inserted.id
    into @temp(id)
values('5班');

--把classid从临时表@temp中取出来
declare @classid int;
select top 1 @classid = id from @temp;

insert into @student values(@classid,'张三');
insert into @student values(@classid,'李四');

select * from @classroom;
select * from @student;

也可以用@@identity,来实现这个功能。

--插入班级数据
insert @classroom values('5班');
insert @classroom values('6班');
insert @classroom values('7班');

--把classid 保存下来
declare @classid int;
select @classid = @@IDENTITY;

--往学生表中插入数据
insert into @student values(@classid,'张三');
insert into @student values(@classid,'李四');

select * from @classroom;
select * from @student;

因为@@identity只能获取主键值,而INSERT OUTPUT可以获取插了的那条数据的完整相关数据。比如,student表还依赖于classroom表的其他自动生成的字段(非主键字段),那么这时候就要用INSERT OUTPUT。

 

update output

 

update output into可以使用 INSERTED 也可以使用 DELETED ,INSERTED代表改变之后的数据,DELETED代表改变之前的数据。

update @student
set studentname = '王五'
output INSERTED.*,DELETED.*

因为有DELETED,所以我们可以给任何改变的数据,进行日志记录。

--创建student日志表
declare @student_log table(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [classid] [int] not null,
    [studentname] nvarchar(20) not null,
    [action] nvarchar(30) null
);
--每次update后都需要把改变之前的数据,记录到日志表中
update @student
set studentname = '王五'
output deleted.classid,deleted.studentname,'update'
into @student_log(classid,studentname,action)

select * from @student_log;

触发器也有INSERTED,UPLDATED,触发器和OUTPUT之间有一定的相通性。

 

delete output

 

delete output into和update比较相似。只不过它就没有INSERTED的了。因为是删除操作,所以只有deleted变量,有DELTED变量我们也可以对任何删除操作进行日志记录。

--创建student日志表
declare @student_log table(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [classid] [int] not null,
    [studentname] nvarchar(20) not null,
    [action] nvarchar(30) null
);
--每次delete后都把删除掉的数据,记录到日志中
delete from @student
output deleted.classid,deleted.studentname,'delete'
into @student_log(classid,studentname,action)
where id = 1;

select * from @student_log;

 

posted @ 2020-07-01 15:03  HDWK  阅读(1796)  评论(0编辑  收藏  举报