2015-09-16 150 views
0

我在SQL Server中的以下触发:SQL Server触发器和批量更新

CREATE TRIGGER Trig_UpdateSearch 
    ON nt_CadProduct 
    FOR UPDATE 
AS 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
BEGIN 
    DECLARE @CodProduct INT 
    SET @CodProduct = (SELECT prdCod FROM INSERTED) 

    DECLARE @DescSearch VARCHAR(500) 
    SET @DescSearch = (SELECT CONVERT(VARCHAR(30),p.prdCod) +' '+ CONVERT(VARCHAR(255),p.prdDesc) +' '+ CONVERT(VARCHAR(255),p.prdCaract) +' '+ CONVERT(VARCHAR(30),p.prdCodFab) +' '+ CONVERT(VARCHAR(255),f.fabname) +' '+ CONVERT(VARCHAR(100),g.grpName) +' '+ CONVERT(VARCHAR(100),a.agrpname) +' '+ CONVERT(VARCHAR(100),t.tpName) 
         FROM nt_CadProduct AS p 
         LEFT JOIN nt_cadFab AS f ON p.prdFab = f.fabcod 
         LEFT JOIN nt_CadGp AS g ON p.prdGp = g.grpCod 
         LEFT JOIN nt_cadagp AS a ON p.prdagp = a.agpcod 
         LEFT JOIN nt_CadT AS t ON p.prdTb = t.tpCod 
         WHERE prdCod = @CodProduct) 

    UPDATE Index_nt_CadProduct 
    SET IndexSearch = @DescSearch 
    WHERE IdProduct = @CodProduct 

    IF @@ROWCOUNT = 0 
     INSERT INTO Index_nt_CadProduct (IdProduct, IndexSearch) 
     VALUES (@CodProduct, @DescSearch) 
END 

这是工作的罚款单更新,但如果我尝试批量更新这是行不通的,因为子查询返回多于1值,我试图使用JOIN INSERTED而不是使用DECLARE,但它也不起作用。

我试图从其他SO回答几个“解决方案”,但没有成功,因为需要我进行@DescSearch查询返回CONCAT结果

我已经改变了列名,因此,如果有是任何拼错只是忽略它。实际触发功能

+2

一个常见的初学者错误。而不是填充变量,您应该使用JOINs插入/删除,以便您的触发器处理所有行。我确定这个问题已经在StackOverflow上重复了好几次。 –

+0

就像我说过的,我已经尝试使用JOINS插入太多,但得到相同的错误。我认为这个问题在DECLARE DescSearch查询中的某处,我使用DECLARE CodProduct来连接列。我试过SELECT i.prdCod FROM INSERTED,而不是在嵌套select中使用DECLARE CodProduct – Alephtus

+0

,你有很多左连接,你的where是'WHERE prdCod = @ CodProduct',但你没有限定'prdCod' ...这是从哪里来的? –

回答

0

你应该能够做到这一点没有一个临时表。我不是百分之百的加入 - 尽我所能全力解析。尽管如此,我认为它应该可以用于多个记录。给它一个测试

BEGIN 
     UPDATE Index_nt_CadProduct 
      SET IndexSearch = CONVERT(VARCHAR(30),nt_CadProduct.prdCod) +' '+ CONVERT(VARCHAR(255),nt_CadProduct.prdDesc) +' '+ CONVERT(VARCHAR(255),nt_CadProduct.prdCaract) +' '+ CONVERT(VARCHAR(30),nt_CadProduct.prdCodFab) +' '+ CONVERT(VARCHAR(255),f.fabname) +' '+ CONVERT(VARCHAR(100),g.grpName) +' '+ CONVERT(VARCHAR(100),a.agrpname) +' '+ CONVERT(VARCHAR(100),t.tpName) 
     FROM INSERTED 
     JOIN Index_nt_CadProduct 
      ON Index_nt_CadProduct.IdProduct = INSERTED.prdCod 
     JOIN nt_CadProduct 
      ON nt_CadProduct.prdCod = Index_nt_CadProduct.IdProduct 
    LEFT JOIN nt_cadFab AS f ON nt_CadProduct.prdFab = f.fabcod 
    LEFT JOIN nt_CadGp AS g ON nt_CadProduct.prdGp = g.grpCod 
    LEFT JOIN nt_cadagp AS a ON nt_CadProduct.prdagp = a.agpcod 
    LEFT JOIN nt_CadT AS t ON nt_CadProduct.prdTb = t.tpCod 

    IF @@ROWCOUNT = 0 
     INSERT INTO Index_nt_CadProduct (IdProduct, IndexSearch) 
     SELECT INSERTED.prdCod 
      , CONVERT(VARCHAR(30),nt_CadProduct.prdCod) +' '+ CONVERT(VARCHAR(255),nt_CadProduct.prdDesc) +' '+ CONVERT(VARCHAR(255),nt_CadProduct.prdCaract) +' '+ CONVERT(VARCHAR(30),nt_CadProduct.prdCodFab) +' '+ CONVERT(VARCHAR(255),f.fabname) +' '+ CONVERT(VARCHAR(100),g.grpName) +' '+ CONVERT(VARCHAR(100),a.agrpname) +' '+ CONVERT(VARCHAR(100),t.tpName) 
     FROM INSERTED 
     JOIN Index_nt_CadProduct 
      ON Index_nt_CadProduct.IdProduct = INSERTED.prdCod 
     JOIN nt_CadProduct 
      ON nt_CadProduct.prdCod = Index_nt_CadProduct.IdProduct 
    LEFT JOIN nt_cadFab AS f ON nt_CadProduct.prdFab = f.fabcod 
    LEFT JOIN nt_CadGp AS g ON nt_CadProduct.prdGp = g.grpCod 
    LEFT JOIN nt_cadagp AS a ON nt_CadProduct.prdagp = a.agpcod 
    LEFT JOIN nt_CadT AS t ON nt_CadProduct.prdTb = t.tpCod 

END 

...虽然它发生,我认为长连接字符串会为空,如果其中任何LEFT JOIN S的都是空。

+0

与临时表的解决方案正在工作,但我担心性能,不真的知道对此的影响,另一方面,您的解决方案抛出一个错误恢复INSERTED.prdCod,我也添加了一些()周围这两个选择自从抛出语法错误太...关于你是正确的零部分,但我解决了使用COALESCE,我很想让它在没有临时表的情况下工作 – Alephtus

+0

哦!插入上的第二个选择是错误的。我会在上面解决它。 .. –

+0

你不应该需要额外的() –

1

没有拥有它是有点硬数据,也许这就是你想要什么:

CREATE TRIGGER Trig_UpdateSearch ON nt_CadProduct 
    FOR UPDATE 
AS 
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
    BEGIN 
    SELECT distinct p.prdCod, 
      CONVERT(VARCHAR(30), p.prdCod) + ' ' + 
      CONVERT(VARCHAR(255), p.prdDesc) + ' ' + 
      CONVERT(VARCHAR(255), p.prdCaract) + ' ' + 
      CONVERT(VARCHAR(30), p.prdCodFab) + ' ' + 
      CONVERT(VARCHAR(255), f.fabname) + ' ' + 
      CONVERT(VARCHAR(100), g.grpName) + ' ' + 
      CONVERT(VARCHAR(100), a.agrpname) + ' ' + 
      CONVERT(VARCHAR(100), t.tpName) AS descSearch 
    INTO #tmp 
    FROM nt_CadProduct AS p 
    LEFT JOIN nt_cadFab AS f ON p.prdFab = f.fabcod 
    LEFT JOIN nt_CadGp AS g ON p.prdGp = g.grpCod 
    LEFT JOIN nt_cadagp AS a ON p.prdagp = a.agpcod 
    LEFT JOIN nt_CadT AS t ON p.prdTb = t.tpCod 
    WHERE prdCod IN (SELECT prdCod 
         FROM inserted); 

    WITH x AS (
       SELECT * 
       FROM [#tmp] AS [t] 
       WHERE EXISTS (SELECT * 
           FROM Index_nt_CadProduct inp 
           WHERE t.prdCod = inp.IdProduct) 
       ) 
     UPDATE Index_nt_CadProduct 
     SET  IndexSearch = x.descSearch 
     FROM x 
     WHERE IdProduct = x.prdCod; 

    INSERT INTO Index_nt_CadProduct (IdProduct, IndexSearch) 
    SELECT prdCod, descSearch 
    FROM [#tmp] AS [t] 
    WHERE NOT EXISTS (SELECT * 
         FROM Index_nt_CadProduct inp 
         WHERE t.prdCod = inp.IdProduct); 
    drop table #tmp; 
    END;