トリガー内で、挿入および削除されたテーブルにあるデータを格納できる一意のテーブル名(NEWID()
を使用)を作成しようとしています。
Declare @NewID varchar(50) = Replace(convert(Varchar(50),NEWID()),'-','')
Declare @SQLStr varchar(8000)
Set @SQLStr= 'Select * into [TMPIns' + @newID + '] from inserted'
Exec (@SQLStr)
次のエラーが表示されます:無効なオブジェクト名 '挿入'
私はできることを知っています:
Select * into #inserted from inserted
Set @SQLStr= 'Select * into [TMPIns' + @newID + '] from #inserted'
Exec (@SQLStr)
ただし、これらのテーブルが大きくなる可能性があるため、TempDBを使用したくありません。また、冗長であると感じています。 #insertedの作成を回避する方法はありますか?
このリクエストの意図された目標に対する洞察がなければ、確かにこの差し迫った問題が解決されたとしても、作業コードは本当に有用なものを提供しないかもしれません。いくつかの懸念があります:
UpdatedDate
または日付フィールドがありますか?そうでない場合は、テーブルの作成日を確認しないと年表がわかりません。UPDATE
の「before」と「after」の値を追跡する場合は、inserted
とdeleted
の両方のテーブルをキャプチャする必要があります。ただし、GUIDベースの名前がある場合、特定のUPDATE操作の「挿入」コピーテーブルと「削除」コピーテーブルを相互に関連付けることはできません。同じGUID=値を再利用し、テーブル名の接頭辞に「挿入」または「削除」を示す必要があります。テーブルを動的に作成していない場合は、 DMLアクションを指定する列、inserted
とdeleted
の両方のテーブルを既存のテーブルにダンプし、GUIDまたはシーケンスのINTを使用して相関させる同じUPDATE
操作の2行の間。ただし、言われていることはすべて、動的SQLを介してinserted
およびdeleted
テーブルを操作する問題は興味深い問題です。残念ながら、T-SQLでは実行できません。だから今はまた挑戦です:-)。幸いなことに、これは実際に行うことができます。どうして?私たちの友人、SQLCLR氏の少しの助けを借りて。
現在、SQLCLRトリガーを実際に要求したり、SQLCLRトリガーから利益を得たりするような状況はそれほど多くないようです。それらは、SQLCLRで作成できる最も有用でないもののようです。ただし、ここでは、これらが最適なシナリオを示します。 SQLCLRコードから送信されたSQLは動的SQLです。また、SQLCLRトリガーはinserted
およびdeleted
テーブルにアクセスできるため、SQLCLRトリガーは動的SQLのinserted
およびdeleted
テーブルにアクセスできるようです。以下は、この要求を実行するために正確に実行するコードです(DB接続はインプロセスの「コンテキスト接続」を使用しているため、アセンブリにPERMISSION_SET = SAFE
を付けることができます。非対称キーまたはデータベースをTRUSTWORTHY ON
)に設定するには:
トリガーを作成するためのテストテーブル(Visual Studio/SSDTを使用している場合は、テーブル定義をプロジェクトに含める必要があります):
CREATE TABLE TableThatHasTriggers
(
TableThatHasTriggersID INT IDENTITY(1, 1) NOT NULL
CONSTRAINT [PK_TableThatHasTriggers] PRIMARY KEY,
InsertTime DATETIME NOT NULL
CONSTRAINT [DF_TableThatHasTriggers_InsertTime] DEFAULT (GETDATE()),
SomeValue NVARCHAR(50) COLLATE Latin1_General_100_CI_AS NULL
);
SQLCLR C#コード:
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
public class Triggers
{
[SqlTrigger(Target = "TableThatHasTriggers", Event = "FOR INSERT, UPDATE")]
public static void tr_TableThatHasTriggers_audit()
{
string _AuditSQL = @"
SELECT ins.*
INTO dbo.[TMPIns_" + Guid.NewGuid().ToString().Replace("-", "") + @"]
FROM INSERTED ins;
";
SqlConnection _Connection = new SqlConnection("Context Connection = true");
SqlCommand _Command = _Connection.CreateCommand();
_Command.CommandText = _AuditSQL;
// SqlContext.Pipe.Send(_AuditSQL); // display query for debugging purposes ONLY
try
{
_Connection.Open();
_Command.ExecuteNonQuery();
}
finally
{
_Command.Dispose();
_Connection.Dispose();
}
}
}
SQLCLRトリガーをテーブルに配置するT-SQLラッパーオブジェクト:
CREATE TRIGGER [dbo].[tr_TableThatHasTriggers_SQLCLRaudit]
ON [dbo].[TableThatHasTriggers]
AFTER INSERT, UPDATE
AS EXTERNAL NAME
[InsertedTableViaDynamicSQL].[Triggers].[tr_TableThatHasTriggers_SQLCLRaudit];