2016-07-13 4 views
0

私は、UPDATEまたはINSERTで実行されるSQL Serverの社内テーブルのいずれかのトリガーを作成しました。 INSERTを扱うときは、2つの行を別々のテーブルに挿入する必要があります。最後のINSERT文を除いて、トリガのすべての部分が正しく動作しています。 SQLプロファイラでは、エラーは発生していませんが、INSERTが実行され、SQL Serverの独自のクエリにコピーして貼り付け、ローカル変数を定数に置き換えても問題なく動作します。しかし、トリガーは、それが挿入されるはずのテーブルに新しい行を作成していません。INSERT文は実行されますが、新しい行は作成されませんか?

私のコードは以下の通りです:私が間違って何をやっている

USE [DLIDEMO3] 
GO 
/****** Object: Trigger [dbo].[EMAIL_ON_UPDATE] Script Date: 7/13/2016 9:36:40 AM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER TRIGGER [dbo].[EMAIL_ON_UPDATE] 
    ON [dbo].[PART] 
    AFTER INSERT, UPDATE 

AS 
BEGIN 
    SET NOCOUNT ON; 

DECLARE @old_part_id nvarchar(30); -- The value of the ID field from before the change (Used to determine if the part existed before the change). 
DECLARE @old_description nvarchar(40); -- The value of the DESCRIPTION field before the change. 
DECLARE @old_drawing_id nvarchar(30); -- The value of the DRAWING_ID field before the change. 
DECLARE @old_drawing_rev_no nvarchar(8); -- The value of the DRAWING_REV_NO field before the change. 
DECLARE @old_cust_num nvarchar(80); -- The value of the USER_2 field before the change. 

DECLARE @new_description nvarchar(40); -- The value of the DESCRIPTION field after the change. 
DECLARE @new_drawing_id nvarchar(30); -- The value of the DRAWING_ID field after the change. 
DECLARE @new_drawing_rev_no nvarchar(8); -- The value of the DRAWING_REV_NO field after the change. 
DECLARE @new_cust_num nvarchar(80); -- The value of the USER_2 field after the change. 

DECLARE @stock_um nvarchar(15); -- The value of the STOCK_UM field after the change. 
DECLARE @part_id nvarchar(30); -- The value of the ID field. 
DECLARE @product_code nvarchar(15); -- The value of the PRODUCT_CODE field. 
DECLARE @status nchar(1); -- The value of the STATUS field. 

SELECT 
@old_part_id = ID, 
@old_description = DESCRIPTION, 
@old_drawing_id = DRAWING_ID, 
@old_drawing_rev_no = DRAWING_REV_NO, 
@old_cust_num = USER_2 
FROM deleted; 

SELECT 
@part_id = ID, 
@stock_um = STOCK_UM, 
@product_code = PRODUCT_CODE, 
@status = STATUS, 
@new_description = DESCRIPTION, 
@new_drawing_id = DRAWING_ID, 
@new_drawing_rev_no = DRAWING_REV_NO, 
@new_cust_num = USER_2 
FROM inserted; 

DECLARE @change_type nvarchar(10) -- Keeps track of what kind of email needs to be sent: UPDATED, INSERTED, or NONE. 

SET @change_type = N'NONE'; 

-- Determines if any of these fields have changed since before the statement executed, and if so, assigns 'UPDATED' to @change_type. 
IF ISNULL(@old_description, 'ISNULL') <> ISNULL(@new_description, 'ISNULL') 
    SET @change_type = N'UPDATED'; 
IF ISNULL(@old_drawing_id, 'ISNULL') <> ISNULL(@new_drawing_id, 'ISNULL') 
    SET @change_type = N'UPDATED'; 
IF ISNULL(@old_drawing_rev_no, 'ISNULL') <> ISNULL(@new_drawing_rev_no, 'ISNULL') 
    SET @change_type = N'UPDATED'; 
IF ISNULL(@old_cust_num, 'ISNULL') <> ISNULL(@new_cust_num, 'ISNULL') 
    SET @change_type = N'UPDATED'; 

-- Determines if the part ID existed before the statement, and if not, assigns 'INSERTED' to @change_type. 
IF ISNULL(@old_part_id, 'ISNULL') = 'ISNULL' 
    SET @change_type = N'INSERTED'; 

-- Determines if the part is a raw material, and if not, assigns 'NONE' to @change_type. 
IF NOT((@product_code = N'raw' OR @product_code = N'rawotc')) 
    SET @change_type = N'NONE'; 

DECLARE @msg varchar(MAX); -- The HTML body of the email to be sent. 
DECLARE @subject_line varchar(200); -- The subject line of the email. 
DECLARE @title varchar(50); -- The title to be displayed at the top of the table in the email. 
DECLARE @bg_color varchar(6); -- The background color of the email. 
DECLARE @colspan varchar(1); -- The number of columns in the table in the email. 

-- Uses the @change_type to determine @bg_color, resulting in different-colored emails for different kinds of statements. 
SET @bg_color = 
CASE @change_type 
    WHEN 'UPDATED' THEN 'FEFFB5' 
    WHEN 'INSERTED' THEN 'C5E7FF' 
    ELSE 'FFFFFF' 
END; 

-- Uses the @change_type to determine @title. 
SET @title = 
CASE @change_type 
    WHEN 'UPDATED' THEN 'PART UPDATED: '[email protected]_id 
    WHEN 'INSERTED' THEN 'NEW PART CREATED: '[email protected]_id 
    ELSE @change_type 
END; 

-- Uses the @change_type to determine @colspan, since an UPDATED email requires one more column than an INSERTED email does. 
SET @colspan = 
CASE @change_type 
    WHEN 'UPDATED' THEN '6' 
    WHEN 'INSERTED' THEN '5' 
    ELSE '5' 
END; 

SET @subject_line = @title; 

SET @msg = 
'<!doctype html> 
<html> 
    <head> 
     <meta charset="utf-8"> 
     <title></title> 
     <style type="text/css"> 
      body 
       { 
       margin-left: 10px; 
       margin-top: 10px; 
       margin-right: 10px; 
       margin-bottom: 10px; 
       text-align: center; 
       } 

     </style> 
    </head> 

    <body> 
     <div style="font-size: 20px; font-weight: strong; text-align: center;">PART '[email protected]_id+' '[email protected]_type+' ON '+CAST(GETDATE() AS varchar(30))+' BY '+SYSTEM_USER+'.<br>'; 
IF ISNULL(@status, '') = N'O' -- Adds a note stating that the part is obsolete, but only if the part is actually obsolete. 
    SET @msg = @msg + '<br>***NOTE: THIS PART IS OBSOLETE.***<br>'; 
SET @msg = @msg + 
     '</div> 
     <table width="100%" border="2" cellspacing="5" cellpadding="5" bgcolor="#'[email protected]_color+'"> 
      <tbody> 
       <tr> 
        <td colspan="'[email protected]+'" align="center" valign="middle" style="font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace; font-weight: bold; font-size: 36px;"><p><!--<img src="/Images/DESLABLGtag3d.png" width="52" height="53" alt=""/>--><span style="font-size: 24px">'[email protected]+'</span></p></td> 
       </tr> 
       <tr>'; 

IF @change_type = 'UPDATED' -- Adds a column on the left for the 'OLD' and 'NEW' row titles. 
    SET @msg = @msg + '<td width="10%"></td>'; 

SET @msg = @msg +     
        '<td width="30%" height="40" align="middle" valign="middle" style="font-weight: bold;">DESCRIPTION</td> 
        <td width="15%" height="40" align="middle" valign="middle" style="font-weight: bold;">UoM</td> 
        <td width="15%" height="40" align="middle" valign="middle" style="font-weight: bold;">CUST #</td> 
        <td width="15%" height="40" align="middle" valign="middle" style="font-weight: bold;">DRAWING</td> 
        <td width="15%" height="40" align="middle" valign="middle" style="font-weight: bold;">DRAWING REV #</td> 
       </tr> 
       <tr>'; 

IF @change_type = 'UPDATED' 
    SET @msg = @msg + '<td width="10%" height="40" align="middle" valign="middle" style="font-weight: bold;">NEW</td>'; 

SET @msg = @msg + 
        '<td width="30%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@new_description,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@stock_um,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@new_cust_num,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@new_drawing_id,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@new_drawing_rev_no,'')+'</td> 
       </tr>'; 
IF @change_type = 'UPDATED' 
    SET @msg = @msg + 
       '<tr> 
        <td width="10%" height="40" align="middle" valign="middle" style="font-weight: bold;">OLD</td> 
        <td width="30%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@old_description,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@stock_um,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@old_cust_num,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@old_drawing_id,'')+'</td> 
        <td width="15%" height="40" align="left" valign="middle" bgcolor="#E5E5E5" style="font-size: 16px; font-family: Consolas, ''Andale Mono'', ''Lucida Console'', ''Lucida Sans Typewriter'', Monaco, ''Courier New'', monospace;">'+ISNULL(@old_drawing_rev_no,'')+'</td> 
       </tr>'; 

SET @msg = @msg +  
      '</tbody> 
     </table> 
    </body> 
</html>'; 

-- Sends an email only if @change_type is 'INSERTED' or 'UPDATED'. 
IF @change_type <> 'NONE' 
    EXEC msdb.dbo.sp_send_dbmail @recipients = '[email protected]', @body = @msg, @body_format = 'HTML', @subject = @subject_line, @blind_copy_recipients = '[email protected]', @profile_name = 'SQLProfile'; 

IF @change_type = 'INSERTED' 
    INSERT INTO [DLIDEMO3].[dbo].[USER_DEF_FIELDS] 
    (PROGRAM_ID, ID, DOCUMENT_ID, DATE_VAL, STRING_VAL) 
    VALUES 
     (N'VMPRTMNT', N'UDF-0000023', @part_id, GETDATE(), NULL), 
     (N'VMPRTMNT', N'UDF-0000024', @part_id, NULL, N'NEW PART CREATED BY '+SYSTEM_USER); 
END 

?どのようにしてINSERTが(SQLプロファイラによれば)エラーを出さずに実行されますが、まだ何もしていませんか?

+0

SQLプロファイラではINSERTが実行されていますか? '[DLIDEMO3]。[dbo]。[USER_DEF_FIELDS]'の挿入を通知していますか?おそらくあなたは問題の1つを持っているでしょう。 1.プロファイラは、 'msdb.dbo.sp_send_dbmail @ recipients'プロシージャで発生している挿入や、プロファイラが実際に' DLIDEMO3]。[dbo]。[USER_DEF_FIELDS] 'に挿入を伝えていることを伝えています。挿入を確認する際に間違いをしている可能性があります(テーブルやデータベースが異なる可能性があります)。外観が正確であることを確認してください。 – Sami

+1

トリガーには大きな設計上の欠陥があります。 1行しか挿入または更新されないと仮定しているようです。これはそうではありません。これを基にしてスカラー変数を取り除くべきです。あなたのトリガーから直接メールを送信しないことをお勧めします。代わりに、ステージングテーブルとスケジュールされたタスクを作成してデータを収集し、電子メールを送信します。 –

+0

@Sami、これはプロファイラが実行したことです: 'INSERT INTO [DLIDEMO3]。[dbo]。【USER_DEF_FIELDS] \t \t(PROGRAM_ID、ID、DOCUMENT_ID、DATE_VAL、STRING_VAL) \t \t VALUES \t \t \t(N'VMPRTMNT」、N'UDF-0000023' 、@part_id、GETDATE()、NULL)、 \t \t \t(N'VMPRTMNT '、N'UDF-0000024'、@ part_id、NULL、N'NEW PARTで作成された+ SYSTEM_USER); 私が探しているテーブルをダブルチェックしました。同じもの – 7Nate9

答えて

0

いくつかの技術サポートの助けを借りて、私は実用的な解決策を見つけ出すことができました。

このトリガーを有効にしたステートメントのバッチには、INSERTステートメントによって加えられた変更が取り消されたUPDATEステートメントが含まれていたので、ステージングテーブルとスケジュールされたジョブを使用して、ステートメント。

私は新しいテーブルを作成:

USE [DLIDEMO3] 
GO 

CREATE TABLE [dbo].[DLI_STAGING_RAWS](
    [PROGRAM_ID] [nvarchar](30) NOT NULL, 
    [ID] [nvarchar](30) NOT NULL, 
    [DOCUMENT_ID] [nvarchar](128) NULL, 
    [DATE_VAL] [datetime] NULL, 
    [STRING_VAL] [nvarchar](128) NULL, 
    [CREATE_DATETIME] [datetime] NOT NULL 
) ON [PRIMARY] 

GO 

私は私のトリガーでINSERTステートメントを変更:

INSERT INTO [DLIDEMO3].[dbo].[DLI_STAGING_RAWS] 
     (PROGRAM_ID, ID, DOCUMENT_ID, DATE_VAL, STRING_VAL, CREATE_DATETIME) 
     VALUES 
      (N'VMPRTMNT', N'UDF-0000023', @part_id, GETDATE(), NULL, GETDATE()), 
      (N'VMPRTMNT', N'UDF-0000024', @part_id, NULL, N'NEW PART CREATED BY '+SYSTEM_USER, GETDATE()); 

そして、私は、これらのコマンドに続いて、1時間に1回実行するようにスケジュールされたジョブを作成しました:

WHILE EXISTS (SELECT * FROM [DLIDEMO3].[dbo].[DLI_STAGING_RAWS]) 
BEGIN 
    DECLARE 
    @program_id nvarchar(30), 
    @id nvarchar(30), 
    @document_id nvarchar(128), 
    @date_val datetime, 
    @string_val nvarchar(250), 
    @create_datetime datetime; 

    SELECT TOP 1 
    @program_id = PROGRAM_ID, 
    @id = ID, 
    @document_id = DOCUMENT_ID, 
    @date_val = DATE_VAL, 
    @string_val = STRING_VAL, 
    @create_datetime = CREATE_DATETIME 
    FROM [DLIDEMO3].[dbo].[DLI_STAGING_RAWS] 
    ORDER BY ID ASC; 

    IF DATEDIFF(mi, @create_datetime, GETDATE()) >= 15 
    BEGIN 

     INSERT INTO [DLIDEMO3].[dbo].[USER_DEF_FIELDS] 
     (PROGRAM_ID, ID, DOCUMENT_ID, DATE_VAL, STRING_VAL) 
     VALUES 
     (@program_id, @id, @document_id, @date_val, @string_val); 

     DELETE FROM [DLIDEMO3].[dbo].[DLI_STAGING_RAWS] 
     WHERE PROGRAM_ID = @program_id AND ID = @id AND DOCUMENT_ID = @document_id; 
    END; 
END; 

(条件DATEDIFF

このソリューションは、私が前のINSERTのステートメントでやってみたことは本質的に何もしていませんが、それは1時間でずれています(これは時間単位ではありません)。特にこの場合の問題)。

すべての建設的な入力をありがとう。 :)

関連する問題