レコードが作成された日付を常に含む新しいDATETIMEフィールドをMS-SQLで作成する必要があり、レコードが変更されるたびに自動的に更新する必要があります。トリガーが必要だと言われているのを聞いたことがありますが、それは問題ありませんが、その書き方がわかりません。誰かがこれを達成するためのトリガーの構文を手伝うことができますか?
MySQLの用語では、このMySQLステートメントとまったく同じことを行う必要があります。
ADD `modstamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
以下にいくつかの要件を示します。
実際、MSSQLにはUPDATEのデフォルト値を定義する方法がありません。
そのため、挿入するためのデフォルト値を持つ列を追加する必要があります。
ADD modstamp DATETIME2 NULL DEFAULT GETDATE()
そして、テーブルにトリガーを追加します。
CREATE TRIGGER tgr_modstamp
ON **TABLENAME**
AFTER UPDATE AS
UPDATE **TABLENAME**
SET ModStamp = GETDATE()
WHERE **ID** IN (SELECT DISTINCT **ID** FROM Inserted)
はい、トリガーごとにID列を指定する必要があります。
注意:アプリケーションのコードがわからないテーブルに列を挿入するときは注意してください。アプリにフィールド定義のないINSERT VALUESコマンドがある場合、新しい列のデフォルト値でもエラーが発生します。
さて、私はいつも何かが起こったときだけでなく、誰がそれをしたのかを常に追跡したいです!
[dwarfs]という名前の[tempdb]にテストテーブルを作成します。金融機関である以前の仕事では、挿入(作成)日付と更新(変更)日付を追跡します。
-- just playing
use tempdb;
go
-- drop table
if object_id('dwarfs') > 0
drop table dwarfs
go
-- create table
create table dwarfs
(
asigned_id int identity(1,1),
full_name varchar(16),
ins_date datetime,
ins_name sysname,
upd_date datetime,
upd_name sysname,
);
go
-- insert/update dates
alter table dwarfs
add constraint [df_ins_date] default (getdate()) for ins_date;
alter table dwarfs
add constraint [df_upd_date] default (getdate()) for upd_date;
-- insert/update names
alter table dwarfs
add constraint [df_ins_name] default (coalesce(suser_sname(),'?')) for ins_name;
alter table dwarfs
add constraint [df_upd_name] default (coalesce(suser_sname(),'?')) for upd_name;
go
更新用ですが、挿入および削除されたテーブルは存在します。更新のために挿入されたものに参加することを選択します。
-- create the update trigger
create trigger trg_changed_info on dbo.dwarfs
for update
as
begin
-- nothing to do?
if (@@rowcount = 0)
return;
update d
set
upd_date = getdate(),
upd_name = (coalesce(suser_sname(),'?'))
from
dwarfs d join inserted i
on
d.asigned_id = i.asigned_id;
end
go
最後になりましたが、コードをテストしてみましょう。誰でも未テストのTSQLステートメントを入力できます。しかし、チームには常にテストを強調しています!
-- remove data
truncate table dwarfs;
go
-- add data
insert into dwarfs (full_name) values
('bilbo baggins'),
('gandalf the grey');
go
-- show the data
select * from dwarfs;
-- update data
update dwarfs
set full_name = 'gandalf'
where asigned_id = 2;
-- show the data
select * from dwarfs;
出力。挿入と削除の間は10秒しか待ちませんでした。良いことは、誰といつがキャプチャされることです。
Create trigger tr_somename
On table_name
For update
As
Begin
Set nocount on;
Update t
Set t.field_name = getdate()
From table_name t inner join inserted I
On t.pk_column = I.pk_column
End
これは、SQL Server 2016以降のPERIOD FOR SYSTEM_TIME
。
これはテンポラルテーブル用に導入されたものですが、これを使用するためにテンポラルテーブルを使用する必要はありません。
以下に例を示します
CREATE TABLE dbo.YourTable
(
FooId INT PRIMARY KEY CLUSTERED,
FooName VARCHAR(50) NOT NULL,
modstamp DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
MaxDateTime2 DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
PERIOD FOR SYSTEM_TIME (modstamp,MaxDateTime2)
)
INSERT INTO dbo.YourTable (FooId, FooName)
VALUES (1,'abc');
SELECT *
FROM dbo.YourTable;
WAITFOR DELAY '00:00:05'
UPDATE dbo.YourTable
SET FooName = 'xyz'
WHERE FooId = 1;
SELECT *
FROM dbo.YourTable;
DROP TABLE dbo.YourTable;
いくつかの制限があります。
MaxDateTime2
上記)これは、このユースケースにはまったく不要です。ただし、非表示としてマークすると、無視しやすくなります。ALTER TRIGGER [trg_table_name_Modified]
ON [table_name]
AFTER UPDATE
AS
Begin
UPDATE table_name
SET modified_dt_tm = GETDATE() -- or use SYSDATETIME() for 2008 and newer
FROM Inserted i
WHERE i.ID = table_name.id
end