これが、SQLの人々にとって十分に単純な質問であることを願っています...
システム構成データを保持するテーブルがあり、これはトリガーを介して履歴テーブルに関連付けられているため、誰が何をいつ変更したかを追跡できます。
このテーブルに別の値を追加する必要がありますが、コードから頻繁に変更されるものであり、その履歴を追跡しないという要件があります(何千ものテーブルを詰まらせたくない1日あたりの更新。
現在、私たちのトリガーはこのようなものです...
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
属性列の値に特定の文字列(「NoHist_」など)が付いている場合、レコードの作成を停止するロジックを追加できるようにしたい
トリガーを使用した経験がほとんどないことを考えると、これを実装するのが最善かどうか疑問に思っていました...次のようなwhere句を試しました
where I.Attribute NOT LIKE 'NoHist_%'
しかし、うまくいかないようです。値は引き続き履歴テーブルにコピーされます。
あなたが提供できるどんな助けもありがたいです。
OK-Cade Rouxが予測したように、これは複数の更新で見事に失敗します。これに対して新しいアプローチをとる必要があります。誰か他の提案がありますか?
みんな-ここで教えてください...なぜこのシナリオでLEFT()がLIKEよりも望ましいのでしょうか?私は答えを受け入れましたが、私自身の教育について知りたいです。
WHERE句が機能しなかった場合、おそらく次のようになります。
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
If (SELECT Attribute FROM INSERTED) LIKE 'NoHist_%'
Begin
Return
End
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
これはどう?
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
IF (LEFT((SELECT Attribute FROM INSERTED), 7) <> 'NoHist_')
BEGIN
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
END
あなたのwhere句は機能するはずです。なぜそうしなかったのか、私は途方に暮れています。 where句の問題を将来どのように解決できるかを理解する方法を説明します。
トリガーを作成するときは、テーブルのすべての列で#inserted(または#deleted)という一時テーブルを作成して、クエリウィンドウから開始します。次に、典型的な値を入力します(常に複数のレコードがあり、値のテストケースをヒットしようとします)
その後、トリガーロジックを記述し、実際にトリガーに入らずにテストできます。あなたのwhere節のようなケースが期待したことをしていない場合、挿入がコメントアウトされてselectが何を返しているかを簡単にテストできます。そうすれば、問題が何であるかを簡単に確認できるでしょう。正しく書かれていれば、クラスのどこでトリガーが機能するかを保証します。
コードがすべての場合に適切に機能することを確認したら、#insertedをinsertにグローバルに置き換え、テストトリガーであるvoilaの周りにcreateトリガーコードを追加します。
コメントで述べたように、複数のレコードの挿入または更新では、選択したソリューションが適切に機能しないことが心配です。トリガーは、発生するかどうか、いつ発生するかを予測できないため、常に説明する必要があります(最終的にはほとんどすべてのテーブルで発生します)。
_
文字もワイルドカード、BTWですが、なぜこれがうまくいかなかったのかはわかりません。
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM Inserted AS I
WHERE I.Attribute NOT LIKE 'NoHist[_]%'
END
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @StartRow int
DECLARE @EndRow int
DECLARE @CurrentRow int
SET @StartRow = 1
SET @EndRow = (SELECT count(*) FROM inserted)
SET @CurrentRow = @StartRow
WHILE @CurrentRow <= @EndRow BEGIN
IF (SELECT Attribute FROM (SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', Attribute FROM inserted) AS INS WHERE RowNum = @CurrentRow) LIKE 'NoHist_%' BEGIN
INSERT INTO SystemParameterHistory(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM
(SELECT Attribute, ParameterValue, ParameterDescription, ChangeDate FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', *
FROM inserted)
AS I
WHERE RowNum = @CurrentRow
END --END IF
SET @CurrentRow = @CurrentRow + 1
END --END WHILE
END --END TRIGGER