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;