Я написал триггер для одной из таблиц нашей компании в SQL Server, который выполняется в UPDATE или INSERT. При работе с INSERT мне нужно вставить две строки в отдельную таблицу. Каждая часть триггера работает нормально, за исключением инструкции INSERT в самом конце. Он не бросает никаких ошибок, SQL Profiler говорит, что 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 Profiler) без возникновения ошибки, но все же ничего не делать?
SQL Profiler говорит, что INSERT выполнен? Вы уверены, что он проинформирует о вставке в '[DLIDEMO3]. [Dbo]. [USER_DEF_FIELDS]'. вероятно, у вас будет одна из проблем. 1. Профилировщик рассказывает о некоторой вставке, которая встречается в процедуре 'msdb.dbo.sp_send_dbmail @ recipients', или если профайлер действительно говорит о вставке в' DLIDEMO3 '. [Dbo]. [USER_DEF_FIELDS] 'тогда это не должно было бы говорить ложь , вы можете ошибаться при проверке вставки (может быть, смотрите другую таблицу или базу данных) Убедитесь, что ваш взгляд верен – Sami
У вашего триггера есть главный недостаток дизайна. Кажется, вы предполагаете, что только одна строка будет вставлена или обновлена. Это не тот случай. Вы должны сделать этот набор основанным и избавиться от этих скалярных переменных. Я также предлагаю вам не отправлять электронные письма прямо из вашего триггера. Вместо этого создайте промежуточную таблицу и запланированную задачу для сбора данных и отправки электронных писем. –
@Sami, это то, что сказал Профайлер: 'INSERT INTO [DLIDEMO3]. [Dbo].[USER_DEF_FIELDS] \t \t (PROGRAM_ID, удостоверение личности, document_id, DATE_VAL, STRING_VAL) \t \t ЗНАЧЕНИЯ \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 ЧАСТЬ СОЗДАННАЯ' + SYSTEM_USER); ' Я дважды проверил таблицу я ищу в, это тот самый. – 7Nate9