2015-09-16 197 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;