我希望这对任何SQL人员来说都是一个简单的问题......
我们有一个包含系统配置数据的表,它通过触发器与历史表绑定,因此我们可以跟踪谁更改了什么,何时更改。
我需要在此表中添加另一个值,但它会经常从代码中更改,并且要求我们不跟踪它的历史记录(我们不希望阻塞该表每天有数千个更新。
目前,我们的触发器有点像这样......
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
如果Attribute colum值以特定字符串作为前缀(例如“NoHist _”),我希望能够添加一些逻辑来阻止它创建记录
鉴于我几乎没有使用触发器的经验,我想知道如何最好地实现这个...我已经尝试过如下的where子句
where I.Attribute NOT LIKE 'NoHist_%'
但它似乎不起作用。该值仍会复制到历史记录表中。
您可以提供任何帮助。
好的 - 正如Cade Roux预测的那样,这次失败引起了多次更新。我将不得不对此采取新方法。有人有任何其他建议吗?
伙计们 - 请在这里教育我......为什么LEFT()在这种情况下会优于LIKE?我知道我接受了答案,但我想知道我自己的教育。
答案 0 :(得分:39)
鉴于WHERE子句不起作用,可能会这样:
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
If (SELECT Attribute FROM INSERTED) LIKE 'NoHist_%'
Begin
Return
End
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
答案 1 :(得分:6)
这个怎么样?
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
IF (LEFT((SELECT Attribute FROM INSERTED), 7) <> 'NoHist_')
BEGIN
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
END
答案 2 :(得分:5)
你的where子句应该有效。我不知道为什么没有。让我告诉你我如何通过where子句找出问题,因为它可能对你的未来有所帮助。
当我创建触发器时,我从查询窗口开始,创建一个名为#inserted(和/或#leleted)的临时表,其中包含表的所有列。然后我用典型值(总是多个记录,我尝试在值中点击测试用例)来播放它
然后我编写了我的触发器逻辑,我可以在没有实际处于触发器中的情况下进行测试。在你的where子句没有做到预期的情况下,我可以通过注释插入来轻松测试,看看select返回了什么。那么我可能很容易就能看出问题所在。我向你保证,如果正确写入,那么clasues在触发器中的作用是什么。
一旦我知道代码适用于所有情况,我将全局替换为插入的#inserted并在其周围添加创建触发器代码,并且这是一个经过测试的触发器。
正如我在评论中所说,我担心您选择的解决方案在多记录插入或更新中无法正常工作。应该始终写入触发器,因为您无法预测它们是否以及何时发生(并且它们最终会在每个表中发生。)
答案 3 :(得分:5)
_
字符也是一个通配符,BTW,但我不确定为什么这不适合你:
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM Inserted AS I
WHERE I.Attribute NOT LIKE 'NoHist[_]%'
END
答案 4 :(得分:1)
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @StartRow int
DECLARE @EndRow int
DECLARE @CurrentRow int
SET @StartRow = 1
SET @EndRow = (SELECT count(*) FROM inserted)
SET @CurrentRow = @StartRow
WHILE @CurrentRow <= @EndRow BEGIN
IF (SELECT Attribute FROM (SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', Attribute FROM inserted) AS INS WHERE RowNum = @CurrentRow) LIKE 'NoHist_%' BEGIN
INSERT INTO SystemParameterHistory(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM
(SELECT Attribute, ParameterValue, ParameterDescription, ChangeDate FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', *
FROM inserted)
AS I
WHERE RowNum = @CurrentRow
END --END IF
SET @CurrentRow = @CurrentRow + 1
END --END WHILE
END --END TRIGGER
答案 5 :(得分:-1)
使用LIKE将为您提供定义字符串其余内容的选项,但如果规则只是以“NoHist_”开头,则无关紧要。
答案 6 :(得分:-1)
对于通常的触发器,您需要使用游标来处理多行的插入或更新。例如:
DECLARE @Attribute;
DECLARE @ParameterValue;
DECLARE mycursor CURSOR FOR SELECT Attribute, ParameterValue FROM inserted;
OPEN mycursor;
FETCH NEXT FROM mycursor into @Attribute, @ParameterValue;
WHILE @@FETCH_STATUS = 0
BEGIN
If @Attribute LIKE 'NoHist_%'
Begin
Return
End
etc.
FETCH NEXT FROM mycursor into @Attribute, @ParameterValue;
END
触发器,至少在SQL Server中,是一个巨大的痛苦,我完全避免使用它们。