0

以下のようなSQLトリガーがあります

GO
create trigger ExpDateCheckCard
On Card 
FOR Insert, Update
As
Declare @expDate as DateTime
Select @expDate = inserted.ExpirationDate from inserted
if (YEAR(@expDate) < 1971 )
BEGIN
     UPdate Card set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
                                where inserted.RecordID = Card.RecordID
END

トリガーの実行時に挿入/更新されたすべてのレコードのトリガーに従って正しい場合、そのレコードの ExpirationDate 列の YEAR がチェックされ、値が 1971 未満の場合は、更新クエリの日付で更新されます.

奇妙なことに、期待どおりに機能していません。

if 条件が機能していないようです。

この特定のトリガーに何か問題がありますか。

4

3 に答える 3

3

はい- このトリガーの書き方には根本的な問題があることは間違いありません。

SQL Server(それがあなたが使用していると仮定して)は、行ごとに1回ではなくトリガーを起動します(あなた自身を含む多くの人々が考えているように)-トリガーはバッチごとに1回起動され、一度に10、20、50行を更新または挿入する可能性があります.

したがって、Insertedトリガー内の疑似テーブルには複数の行を含めることができます (そしてそうします! )。その場合、ここでのステ​​ートメントは正確に何を選択するのでしょうか?

Select @expDate = inserted.ExpirationDate from inserted

ランダムな 1 行 (50 行のうち) を取得してそれを処理する (他の 49 行はすべて無視する) か、エラーが発生するかのいずれかです....

そのことを念頭に置いてトリガーを作成する必要があります - (and ) には複数の行が含まれることを常に想定する必要があります。InsertedDeleted

したがって、トリガーを次のように変更する必要があります。

CREATE TRIGGER ExpDateCheckCard
ON dbo.Card 
FOR Insert, Update
AS
  UPDATE dbo.Card 
  SET ExpirationDate = '1900-01-01 00:00:00' 
  FROM dbo.Card c
  INNER JOIN inserted i ON i.RecordID = c.RecordID
  WHERE YEAR(i.ExpirationDate) < 1971

(また、古いスタイルの JOIN 構文 (テーブルのコンマ区切りリスト) を、1992 年から導入されている ANSI 標準に変更しました。テーブルのコンマ区切りリストは使用しないでください!適切なANSI JOINを使用してください。これを参照してください。背景情報の詳細については、ブログ投稿:キックする悪い習慣: 古いスタイルの JOIN を使用する)

于 2013-02-14T06:02:47.860 に答える
0

これで試してください:

create trigger ExpDateCheckCard
    On Card 
    FOR Insert, Update
    As
    BEGIN
    Declare @expDate as DateTime
    Select @expDate = inserted.ExpirationDate from inserted
    if (YEAR(@expDate) < 1971 ) Begin

         UPdate Card set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
                                    where inserted.RecordID = Card.RecordID
    end
    END
于 2013-02-14T05:14:00.140 に答える
0

このコードを試す必要があります

CREATE TRIGGER ExpDateCheckCard AFTER INSERT,Update ON Card
   FOR EACH ROW

   Declare @expDate as DateTime
   Select @expDate = inserted.ExpirationDate from inserted
   if (YEAR(@expDate) < 1971 )
   BEGIN
      update Card 
      set ExpirationDate = '1900-01-01 00:00:00' FROM Card, inserted
      where inserted.RecordID = Card.RecordID
   END
于 2013-02-14T06:26:21.927 に答える