web-dev-qa-db-ja.com

SQL Serverテーブルに「最終変更」および「作成」列を追加するにはどうすればよいですか?

SQL Server 2012データベース用の新しいdbスキーマを設計しています。

各テーブルには、modifiedおよびcreatedという2つの追加の列が必要です。これらの列は、行が挿入または更新されるとすぐに自動的に変更されます。

どうやってそこにたどり着くのがベストかわからない。

トリガーはそれを処理するための最良の方法だと思います。

私はトリガーを使用して例を見つけようとしていました。

私はそれが非常に一般的なシナリオであると想定しましたが、まだ答えが見つかりませんでした。

30
stevo

created列は単純です-新しい行が挿入されたときに設定されるデフォルトの制約を持つDATETIME2(3)列だけです:

Created DATETIME2(3) 
   CONSTRAINT DF_YourTable_Created DEFAULT (SYSDATETIME())

したがって、YourTableに行を挿入し、Createdの値を指定しない場合、現在の日付と時刻に設定されます。

modifiedは、AFTER UPDATEケースのトリガーを作成して更新する必要があるため、もう少し作業が必要です。これをSQL Serverに宣言することはできません。

Modified DATETIME2(3)

その後

CREATE TRIGGER updateModified
ON dbo.YourTable
AFTER UPDATE 
AS
   UPDATE dbo.YourTable
   SET modified = SYSDATETIME()
   FROM Inserted i
   WHERE dbo.YourTable.PrimaryKey = i.PrimaryKey

そのテーブルの主キーのベーステーブルで更新されたすべての行を含むInserted擬似テーブルを結合する必要があります。

そして、modified列を持ちたい各テーブルに対して、このAFTER UPDATEトリガーを作成する必要があります。

43
marc_s

通常、次の列を使用できます。

  • LastModifiedBy
  • LastModifiedOn
  • によって作成された
  • 作成日

LastModifiedByCreatedByusersテーブル(UserID)への参照であり、LastModifiedOnCreatetOn列は日付と時刻の列。

次のオプションがあります。

  1. トリガーを使用しないソリューション-「トリガーを作成する最良の方法は、トリガーを作成しないことです。」と読んでいますが、一般的にそれらが痛いことを知っている必要がありますパフォーマンス。そのため、それらを回避できる場合は、回避する方が良い場合があります。トリガーを使用することでさえ、場合によっては最も簡単なことのように見えるかもしれません。

    したがって、すべてのINSERTおよびUPDATEステートメントを編集して、現在のUserIDおよび現在の日時を含めるだけです。そのようなuser IDを定義できない場合(匿名ユーザー)、代わりに0を使用でき、列のデフォルト値(user IDが指定されていない場合はNULLになります)。 NULL値が挿入されているのを見ると、「有罪」ステートメントを見つけて編集する必要があります。

  2. トリガーを使用したソリューション-AFTER INSERT, UPDATEトリガーを作成し、そこにユーザー列を追加できます。トリガーのコンテキストで現在の日付と時刻を取得するのは簡単です(たとえば、GETUTCDATE()を使用します)。ここでの問題は、トリガーがパラメーターの受け渡しを許可しないことです。したがって、user ID値を挿入しておらず、トリガーに渡すことができないためです。現在のユーザーを見つける方法は?

    SET CONTEXT_INFO および CONTEXT_INFO を使用できます。すべてのinsertおよびupdateステートメントの前に、SET CONTEXT_INFOを使用してcurrent user IDを現在のコンテキストに追加し、トリガーでCONTEXT_INFO関数を使用して抽出する必要があります。

そのため、トリガーを使用する場合は、すべてのINSERT節とUPDATE節を再度編集する必要があります。そのため、これらを使用しない方がよいのです。

とにかく、日付と時刻の列のみが必要で、列によって作成/変更する必要がない場合、現在および将来、他のステートメントを編集しないため、トリガーの使用はより耐久性があり、簡単です。


SQL Server 2016を使用して、セッションの詳細を読み取るために SESSION_CONTEXT 関数を使用できるようになりました。詳細は sp_set_session_contextread-onlyまたはread and writeとして)を使用して設定されます。物事は少しユーザーフレンドリーです:

EXEC sp_set_session_context 'user_id', 4;  
SELECT SESSION_CONTEXT(N'user_id');  

すてきな

8
gotqn

注意、上記では正常に動作しますが、すべての場合でなく、私は多くの時間を失い、これが役立つことがわかりました:

create TRIGGER yourtable_update_insert
ON yourtable
AFTER UPDATE 
as
begin
   set nocount on;
   update yourtable set modified=getdate(), modifiedby = suser_sname()
   from  yourtable t 
   inner join inserted i on t.uniqueid=i.uniqueid 
end
go

set nocount on;が必要です。それ以外の場合、エラーが発生します。


Microsoft SQL Server Management Studio


行は更新されませんでした。

行5のデータはコミットされませんでした。エラーソース:Microsoft.SqlServer.Management.DataTools。エラーメッセージ:更新または削除された行の値は、行を一意にしないか、複数の行(2行)を変更します。

エラーを修正して再試行するか、ESCを押して変更をキャンセルします。


OKヘルプ


1
pietervnk
CREATE TRIGGER [dbo].[updateModified]
   ON  [dbo].[Transaction_details] 
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Transaction_details
    SET ModifedDate = GETDATE() FROM dbo.Transaction_details t JOIN inserted i ON 
    t.TransactionID = i.TransactionID--SYSDATETIME()
END
0
G.Protocol