0

更新と挿入を処理する 1 つのトリガーが必要です。トリガー内の SQL アクションのほとんどは、両方を対象としています。唯一の例外は、挿入と更新の日付とユーザー名を記録するために使用しているフィールドです。これは私が持っているものですが、更新と挿入を追跡するために使用されるフィールドの更新が正しく実行されません。新しいレコードを挿入すると、CreatedBy、CreatedOn、LastEditedBy、LastEditedOn が入力され、LastEditedOn は CreatedOn の 1 秒後 (発生したくない) になります。レコードを更新すると、LastEditedBy と LastEditedOn のみが変更されます (これは正しいです)。参照用に完全なトリガーを含めています。

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
-- =================================================================================
-- Author:  Paul J. Scipione
-- Create date: 2/15/2012
-- Update date: 6/5/2012
-- Description: To concatenate several fields into a set formatted UnitDescription,
--              to total Span & Loop footages, to set appropriate AcctCode, & track
--              user inserts
-- =================================================================================
IF OBJECT_ID('ProcessCable', 'TR') IS NOT NULL
  DROP TRIGGER ProcessCable
GO
CREATE TRIGGER ProcessCable
ON Cable
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;

-- IF TRIGGER_NESTLEVEL() > 1 RETURN

IF ((SELECT TRIGGER_NESTLEVEL()) > 1 )
  RETURN
ELSE
  BEGIN
  -- record user and date of insert or update
  IF EXISTS (SELECT * FROM DELETED)
    UPDATE Cable SET LastEditedOn = getdate(), LastEditedBy = REPLACE(user_name(), 'GRTINET\', '')
  ELSE IF NOT EXISTS (SELECT * FROM DELETED)
    UPDATE Cable SET CreatedOn = getdate(), CreatedBy = REPLACE(user_name(), 'GRTINET\', '')

  -- reset Suffix if applicable
  UPDATE Cable SET Suffix = NULL WHERE Suffix = 'n/a'

  -- create UnitDescription value
  UPDATE Cable SET UnitDescription =
    isnull (Type, '') +
    isnull (CONVERT (NVARCHAR (10), Size), '') +
    '-' +
    isnull (CONVERT (NVARCHAR (10), Gauge), '') +
    CASE
      WHEN ExtraTrench IS NOT NULL AND ExtraTrench > 0 THEN
        CASE
          WHEN Suffix IS NULL THEN 'TE' + '(' + CONVERT (NVARCHAR (10), ExtraTrench) + ')'
          ELSE 'TE' + '(' + CONVERT (NVARCHAR (10), ExtraTrench) + ')' + Suffix
        END
      ELSE isnull (Suffix, '')
    END

  -- convert any accidental negative numbers entered
  UPDATE Cable SET Length = ABS(Length)

  -- sum Length with LoopFootage into TotalFootage
  UPDATE Cable SET TotalFootage = isnull(Length, 0) + isnull(LoopFootage, 0)

  -- set proper AcctCode based on Type
  UPDATE Cable SET AcctCode =
    CASE
      WHEN Type IN ('SEA', 'CW', 'CJ') THEN '32.2421.2'
      WHEN Type IN ('BFC', 'BJ', 'SEB') THEN '32.2423.2'
      WHEN Type IN ('TIP','UF') THEN '32.2422.2'
      WHEN Type = 'unknown' OR Type IS NULL THEN 'unknown'
    END
  WHERE AcctCode IS NULL OR AcctCode = ' '

END

END
GO
4

1 に答える 1

0

私があなたの引き金を見るとき、いくつかのことが私に飛び出します:

  • 単一の更新ではなく、いくつかの追加の更新を実行しています(パフォーマンスに関しては、単一の更新の方が適しています)。
  • 更新ステートメントには制約がありません(これらの追加の更新を実行するレコードの数を制限するために、挿入/削除されたテーブルに結合することはありません)。
  • このロジックのほとんどは、データベースではなくアプリケーション層にあるべきだと感じています。または、場合によっては、実装が異なる場合もあります。

いくつかの簡単な例:

  • 「n/a」のサフィックスは、挿入する前に削除する必要があります。
  • ケーブル長の絶対値は、挿入する前に行う必要があります(不正なデータを挿入できないことを確認するためのチェック制約を使用して)。
  • TotalFootageは計算列である必要があるため、常に正しくなります。
  • Type / ActtCodeの関係は、外部キー参照の列値である必要があるようです。

しかし、最終的には、予期しない日付が表示されるのは、制約のない更新が原因だと思います。上記で取り上げた他の懸念事項に対処しないと、監査フィールドを設定するステートメントは次のようになります。

UPDATE Cable SET LastEditedOn = getdate(), LastEditedBy = REPLACE(user_name(), 'GRTINET\', '')
FROM Cable
    JOIN deleted on Cable.PrimaryKeyColumn = deleted.PrimaryKeyColumn

UPDATE Cable SET CreatedOn = getdate(), CreatedBy = REPLACE(user_name(), 'GRTINET\', '')
FROM Cable
    JOIN inserted on Cable.PrimaryKeyColumn = inserted.PrimaryKeyColumn
    LEFT JOIN deleted on Cable.PrimaryKeyColumn = deleted.PrimaryKeyColumn
WHERE deleted.PrimaryKeyColumn IS NULL
于 2012-06-06T18:42:06.293 に答える