【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;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM