摘要: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 作法之間的效能問題@@。
希望有時間可以研究一下,或是有好心人可以指導一下。謝謝!!
水滴可成涓流,涓流可成湖泊大海。
汲取累積知識,將知識堆積成常識;將常識探究成學識;將學識簡化為知識;授人自省。