SQL Server 2012的触发

SQL Server 2012的触发

问题描述:

嗨预先感谢您的任何帮助, 我有这个触发器在我的SQL Server 2012数据库SQL Server 2012的触发

USE Teste_TextMining 
CREATE TRIGGER Noticia07032016 ON dbo.textos 
AFTER INSERT 
AS 
DECLARE @ID INT 
SET @ID = ( SELECT MAX(ID_texto) FROM dbo.textos) 
DECLARE @tag NVARCHAR(MAX) 
SET @tag = ( SELECT TOP 1 keyphrase 
       FROM semantickeyphrasetable(textos, *) 
       WHERE [email protected]) 
BEGIN 
    UPDATE dbo.textos 
    SET tag = UPPER(@tag) 
    WHERE ID_texto = @ID 
END 
BEGIN 
    UPDATE dbo.textos 
    SET data = GETDATE() 
    WHERE ID_texto = @ID 
END 
GO 

正如你可以看到它应该更新2个值的“标签”行和“数据”行,一旦某个东西被插入表中,但它只更新“数据”行。

如果我只是选择这段代码并运行/调试它,它实际上更新两行,任何想法为什么这是hapening?

DECLARE @ID INT 
    SET @ID = ( SELECT MAX(ID_texto) FROM dbo.textos) 
    DECLARE @tag NVARCHAR(MAX) 
    SET @tag = ( SELECT TOP 1 keyphrase 
        FROM semantickeyphrasetable(textos, *) 
        WHERE [email protected]) 
    BEGIN 
     UPDATE dbo.textos 
     SET tag = UPPER(@tag) 
     WHERE ID_texto = @ID 
    END 
    BEGIN 
     UPDATE dbo.textos 
     SET data = GETDATE() 
     WHERE ID_texto = @ID 
    END 

再次感谢您的帮助和时间。

+1

插入后,您正在使用触发器更新触发器所在的同一张表。我会用Default约束和/或计算列代替它。 –

+0

我同意@TabAlleman在这里。你的触发逻辑在这里也完全被打破了。如果你插入多于一行的话,你的逻辑如果不能正常工作的话。你应该避免标量变量,你也应该在触发器中引用插入和/或删除的表。 –

使用下面的代码。在你的情况下,我认为触发器在semantickeyphrasetable TABLE插入完成之前触发。因此,第一次开始时没有任何更新,因为@tag是空的。

其更好地把扳机子表(如果我们需要更新与子表数据父表。)

USE Teste_TextMining 

    CREATE TRIGGER Noticia07032016 ON dbo.textos 
    AFTER INSERT 
    AS 
    DECLARE @ID INT 
     ,@tag NVARCHAR(MAX) 

    SELECT @ID = ID_texto 
    FROM INSERTED 

    SET @tag = (
      SELECT TOP 1 keyphrase 
      FROM semantickeyphrasetable(textos, *) 
      WHERE document_key = @ID 
      ) 

    UPDATE dbo.textos 
    SET tag = UPPER(@tag) 
     , 

    SET data = GETDATE() 
    WHERE ID_texto = @ID 
    GO 

注意:当多个插入完成,它就会失败。

+0

同样的问题,标记行仍然返回null – XinkZ

+0

是的,这是因为您在标记值被插入之前获取标记值@XinkZ –

+0

既然您知道此代码不会正常工作,为什么不修复它以便它可以处理多行操作? –

触发器基本上会为每个批处理操作触发一次,所以您应该根据这个现实来执行您的逻辑。这也是SQL精神,它支持基于集合的操作(表现更好)。

所有插入的项目被存储到一个特殊的表,称为inserted,所以你应该与此表一起知道什么是受到触摸的确切记录:

CREATE TRIGGER Noticia07032016 ON dbo.textos 
AFTER INSERT 
AS 
BEGIN 
    DECLARE @ID INT 
    SET @ID = ( SELECT MAX(ID_texto) FROM dbo.textos) 

    DECLARE @tag NVARCHAR(MAX) 
    SET @tag = ( SELECT TOP 1 keyphrase 
        FROM semantickeyphrasetable(textos, *) 
        WHERE [email protected]) 

    BEGIN 
     UPDATE Dest 
     SET tag = UPPER(@tag) 
     FROM dbo.textos Dest 
      JOIN inserted I ON I.ID_texto = Dest.ID_texto 
     WHERE ID_texto = @ID 
    END 
    BEGIN 
     UPDATE Dest 
     SET data = GETDATE() 
     FROM dbo.textos Dest 
      JOIN inserted I ON I.ID_texto = Dest.ID_texto 
     WHERE ID_texto = @ID 
    END 
END 

上面没有测试,但是应该帮助您了解如何着手实际更新插入的记录。

我假设你正在执行下面的查询仅仅是为了获取插入的行:

SELECT MAX(ID_texto) FROM dbo.textos 

这是行不通的,正如其他人指出。如果一次插入多行,则只有该集合中的最后一个将被触发器修改。

在INSERTED表上执行JOIN以获取新行,然后在semantickeyphrasetable(textos, *)上执行另一个JOIN以获取标记值。类似这样的:

USE Teste_TextMining 
CREATE TRIGGER Noticia07032016 ON dbo.textos 
AFTER INSERT 
AS 
BEGIN 
    UPDATE T 
    SET tag = UPPER(K.keyphrase), data = GETDATE() 
    FROM dbo.textos T 
    JOIN INSERTED ON INSERTED.ID_texto = T.ID_texto 
    LEFT JOIN (
     SELECT TOP 1 document_key, keyphrase 
     FROM semantickeyphrasetable(textos, *) 
    ) K ON K.document_key=T.ID_texto 
END 
GO 

这个答案有没有解决?

如果没有,为什么不直接在一行中添加两个更新而不是有2个BEGIN ... END块?

CREATE TRIGGER Noticia07032016 ON dbo.textos 
AFTER INSERT 
AS 
BEGIN 
    DECLARE @ID INT 
    SET @ID = ( SELECT MAX(ID_texto) FROM dbo.textos) 

    DECLARE @tag NVARCHAR(MAX) 
    SET @tag = ( SELECT TOP 1 keyphrase 
       FROM semantickeyphrasetable(textos, *) 
       WHERE [email protected]) 

    BEGIN 
     UPDATE Dest 
     SET tag = UPPER(@tag), data = GETDATE() 
     FROM dbo.textos Dest 
     JOIN inserted I ON I.ID_texto = Dest.ID_texto 
     WHERE ID_texto = @ID 
    END 
END