我无法让TSQL触发器正常工作。我已经通过调试器运行它,并且它没有根据SQL Server Management Studio设置任何变量。最糟糕的事情是触发器本身正确执行,执行时没有错误(只是说'执行成功')。
代码如下(这是一项正在进行的工作......只是让我自己熟悉):
USE TestDb
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'OfficeSalesQuotaUpdate' AND type = 'TR')
DROP TRIGGER OfficeSalesQuotaUpdate
GO
CREATE TRIGGER OfficeSalesQuotaUpdate
ON SalesReps
AFTER UPDATE, DELETE, INSERT
AS
DECLARE @sales_difference int, @quota_difference int
DECLARE @sales_original int, @quota_original int
DECLARE @sales_new int, @quota_new int
DECLARE @officeid int
DECLARE @salesrepid int
--UPDATE(Sales) returns true for INSERT and UPDATE.
--Not for DELETE though.
IF ((SELECT COUNT(*) FROM inserted) = 0)
SET @salesrepid = (SELECT SalesRep FROM deleted)
ELSE
SET @salesrepid = (SELECT SalesRep FROM inserted)
--If you address the @salesrepid variable, it does not work. Doesn't even
--print out the 'this should work line.
PRINT 'This should work...' --+ convert(char(30), @salesrepid)
IF (@salesrepid = NULL)
PRINT 'SalesRepId is null'
ELSE
PRINT 'SalesRepId is not null'
PRINT convert(char(50), @salesrepid)
SET @officeid = (SELECT RepOffice
FROM SalesReps
WHERE SalesRep = @salesrepid)
SELECT @sales_original = (SELECT Sales FROM deleted)
SELECT @sales_new = (SELECT Sales FROM inserted)
--Sales can not be null, so we'll remove this later.
--Use this as a template for quota though, since that can be null.
IF (@sales_new = null)
BEGIN
SET @sales_new = 0
END
IF (@sales_original = 0)
BEGIN
SET @sales_original = 0
END
SET @sales_difference = @sales_new - @sales_original
UPDATE Offices
SET Sales = Sales + @sales_difference
WHERE Offices.Office = @officeid
GO
那么,有什么提示吗?我完全不知道这个。提前谢谢。
答案 0 :(得分:2)
您的主要问题似乎是@foo = NULL
和@foo IS NULL
之间存在差异:
declare @i int
set @i = null -- redundant, but explicit
if @i = null print 'equals'
if @i is null print 'is'
'This should working'PRINT语句不起作用,因为将NULL与字符串连接会产生NULL,而PRINT NULL
不会打印任何内容。
至于实际设置@salerepid的值,似乎很可能插入和/或删除的表实际上是空的。您使用什么语句来测试触发器?你打印出COUNT(*)值吗?
如果有人一次更改多行,您还应该考虑(如果您还没有)。您当前的代码假定一次只更改一行,这在您的环境中可能是合理的假设,但如果有人批量加载数据或进行其他“批处理”,则很容易中断。
最后,你应该经常提到你的MSSQL版本和版本;它可能与某些语法问题有关。
答案 1 :(得分:2)
你应该用这样的东西替换触发器的主体:
;WITH Totals AS (
SELECT RepOffice,SUM(Sales) as Sales FROM inserted GROUP BY RepOffice
UNION ALL
SELECT RepOffice,-SUM(Sales) FROM deleted GROUP BY RepOffice
), SalesDelta AS (
SELECT RepOffice,SUM(Sales) as Delta FROM Totals GROUP BY RepOffice
)
UPDATE o
SET Sales = Sales + sd.Delta
FROM
Offices o
inner join
SalesDelta sd
on
o.Office = sd.RepOffice
这将充分应对插入和删除的多行。我假设SalesRep是SalesReps表的主键。
上面更新,以应对UPDATE更改特定销售代表的RepOffice(原始版本没有,可以推测,也是正确的)
答案 2 :(得分:0)
只是一个建议......您是否尝试过将BEGIN和END封装到触发器的“AS”部分?