【T-SQL】利用OUTPUT子句,將資料寫入兩個不同資料表。

  • 7818
  • 0
  • SQL
  • 2019-09-04

摘要:SQL 利用OUTPUT子句,將資料寫入兩個不同資料表。

最近遇到要將某些資料表做一下LOG記錄。

作法有很多,利用資料庫進行Tigger,將變更的資料內容記錄到另一個資料表。

例如:

CREATE Trigger (trigger_Name)  ON (Table_Name)
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
--當 SET NOCOUNT 爲 ON 時,不返回計數(表示受 Transact-SQL 語句影響的行數)。當 SET NOCOUNT 爲 OFF 時,返回計數。
SET NOCOUNT ON;
    if (Select Count(*) From inserted) > 0 and (Select Count(*) From deleted) = 0
    begin
--如果有新增資料要做的事情!!
  print ('新增')
    end

    if (Select Count(*) From inserted) = 0 and (Select Count(*) From deleted) > 0
    begin
  print ('刪除')
    end
 
    if (Select Count(*) From inserted) > 0 and (Select Count(*) From deleted) > 0
    begin
  print ('修改')
    end

或是利用C# 程式將資料直接寫到兩個不同的資料表(這裡不研究.....)

也或是利用預存程序,將資料分別寫到不同資料表。

最近意外發現,利用OUTPUT 子句,也可以做到相關的事情,直接用SQL語法直接寫入兩各資料表(不過是不是會影響效能??,這裡我們也不探討)

例如:

--新增資料表
CREATE  TABLE dbo.ATABLE 
(
	[Event_ID] int IDENTITY(1,1)  NOT NULL,
	[title] [nvarchar](100) NULL,
	[CusName] [nvarchar](100) NULL,
	[description] [nvarchar](200) NULL
);
GO
-- 建立初始資料

DECLARE @counter int
SET @counter = 10;

WHILE @counter >0
BEGIN
INSERT INTO [dbo].[ATABLE] (
	[title],
	[CusName] ,
	[description])
VALUES
	('測試'+ convert(VARCHAR(2),@counter), '都都強'+ + convert(VARCHAR(2),@counter), '測試標題' + convert(VARCHAR, getdate(),9))
SELECT @counter = @counter - 1;
END

SELECT *
FROM
	dbo.[ATABLE]
GO		

--建立暫存表存放記錄
DECLARE @outputtable table
(
  Event_ID int,
  OldData nvarchar(200),	
  NewData nvarchar(200),
  [DateTime] datetime
)

DECLARE @title nvarchar(100)
DECLARE @description nvarchar(200)
DECLARE @CusName nvarchar(50)
DECLARE @event_id int
SET @title = '來猛的' 
SET @description = '在改過' 
SET @CusName = '好像是真的'
--隨機選取資料行
SET @event_id = ( SELECT top 1 Event_ID from dbo.[ATABLE] order by NEWID()) 

UPDATE [ATABLE] SET title=@title, description=@description ,CusName=@CusName  
OUTPUT 
INSERTED.Event_ID, 
DELETED.title + ',' + DELETED.[description] +','+ DELETED.CusName , 
INSERTED.title + ',' + INSERTED.[description] +','+ INSERTED.CusName ,
GETDATE()
 INTO  @outputtable ( Event_ID,OldData,NewData,[DateTime])
WHERE event_id=@event_id

--查詢結果

SELECT * fROM [ATABLE]
SELECT * FROM @outputtable

在實做中,遇到一點問題,出現『資料行名稱或提供的數值數量與資料表定義不相符』。

原先設計是寫入實體Table,然後DateTime  欄位  使用預設值為  Getdate(),因此在寫入資料時,想讓DB自動產生日期。

卻出現上述的錯誤訊息。

查詢 OUTPUT 子句 http://msdn.microsoft.com/zh-tw/library/ms177564.aspx

重新確認 output_table  的用法

指定資料表,讓傳回的資料列插入其中,而不要傳回給呼叫者。 output_table 可能是暫存資料表。

如果未指定 column_list,資料表必須有與 OUTPUT 結果集數目相同的資料行。

識別和計算資料行例外。 它們必須被略過。

如果指定 column_list,任何省略的資料行都必須允許 Null 值或已指派預設值。

也就是說可以指定寫入的 column_list 寫在 INTO (table Name) (column_list)。

 

雖然暫時解決工作上問題,順便記錄一下,但是寫到這裡,其實很想知道使用  Tigger  與  sql command  作法之間的效能問題@@。

希望有時間可以研究一下,或是有好心人可以指導一下。謝謝!!

 

水滴可成涓流,涓流可成湖泊大海。
汲取累積知識,將知識堆積成常識;將常識探究成學識;將學識簡化為知識;授人自省。