我已經編寫了一個存儲過程,該存儲過程將採用父級部分,通過該部分的物料清單記錄並有條件地連接匹配的子記錄(即包含的部分在這部分的BOM中),但只有滿足特定條件的子記錄(使用我們的命名約定,任何以'。','E'或'ZG'開頭的內容)。在遊標SELECT語句中使用變量
我已經創建了SP,它工作的很好,但只有當我傳入一個[可選]父部件號。我需要爲所有部分運行這個SP,所以我的想法是在遊標內部執行SP,並繼續傳入下一部分,直到沒有剩下的部分處理爲止。我無法解決如何做到這一點,或者甚至可能,因爲在遊標的SELECT語句中(我正在使用存儲過程代碼),我需要傳入一個變量才能使其工作。
這裏是存儲過程的代碼:
CREATE PROCEDURE dbo.usp_BuildBOMLit
@item_no CHAR(8) = NULL
AS
BEGIN
WITH CTE AS (
SELECT DISTINCT
LTRIM(RTRIM(lvl1.item_no)) as item_no, LTRIM(RTRIM(lvl1.comp_item_no)) as comp_item_no,
CASE
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE '.%'
THEN
LTRIM(RTRIM(lvl1.comp_item_no))
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE 'E%'
THEN
(SELECT TOP 1 LTRIM(RTRIM(comp_item_no)) FROM bmprdstr_sql WHERE LTRIM(RTRIM(item_no))=LTRIM(RTRIM(lvl1.comp_item_no)) AND LTRIM(RTRIM(comp_item_no)) LIKE '.%')
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE 'ZG%'
THEN
(SELECT TOP 1 LTRIM(RTRIM(comp_item_no)) FROM bmprdstr_sql WHERE LTRIM(RTRIM(item_no))=LTRIM(RTRIM(lvl1.comp_item_no)) AND LTRIM(RTRIM(comp_item_no)) LIKE '.%')
ELSE
NULL
END as lvl_2_comp_item_no
FROM
bmprdstr_sql as lvl1
LEFT JOIN bmprdstr_sql lvl2 ON lvl1.comp_item_no=lvl2.item_no
WHERE
(lvl1.item_no = @item_no)
AND (lvl1.comp_item_no LIKE '.%' OR lvl1.comp_item_no LIKE 'ZG%' OR lvl1.comp_item_no LIKE 'E%')
)
SELECT DISTINCT
CASE
WHEN LEFT(item_no,1)='.'
THEN STUFF(item_no,1,1,'')
ELSE
item_no
END as item_no,
part_no =
STUFF((SELECT DISTINCT ',' +
CASE
WHEN LEFT(lvl_2_comp_item_no,1)='.'
THEN STUFF(lvl_2_comp_item_no,1,1,'')
ELSE lvl_2_comp_item_no
END
FROM CTE where [email protected]_no FOR XML PATH('')),1,1,'')
FROM
CTE
WHERE
lvl_2_comp_item_no IS NOT NULL AND item_no IS NOT NULL
END
輸出正是我所需要的格式:
ITEM_NO | part_no
JM9027 | GS10702,LB2391,LB2704,LB2834,LB2896,LB6996
當我創建光標,我使用光標的SELECT
聲明相同的代碼,但你可以看到,如果需要父(@itemno
)在傳遞。我已經試過了,無濟於事:
SET NOCOUNT ON;
DECLARE @itemno CHAR(15);
DECLARE @partno VARCHAR(254);
DECLARE @outside_cursor AS CURSOR;
SET @outside_cursor = CURSOR FAST_FORWARD FOR
WITH CTE AS
(SELECT DISTINCT
LTRIM(RTRIM(lvl1.item_no)) AS item_no,
LTRIM(RTRIM(lvl1.comp_item_no)) AS comp_item_no,
CASE
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE '.%'
THEN LTRIM(RTRIM(lvl1.comp_item_no))
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE 'E%'
THEN
(SELECT TOP 1
LTRIM(RTRIM(comp_item_no))
FROM
bmprdstr_sql
WHERE
LTRIM(RTRIM(item_no))=LTRIM(RTRIM(lvl1.comp_item_no))
AND LTRIM(RTRIM(comp_item_no)) LIKE '.%'
)
WHEN LTRIM(RTRIM(lvl1.comp_item_no)) LIKE 'ZG%'
THEN
(SELECT TOP 1
LTRIM(RTRIM(comp_item_no))
FROM
bmprdstr_sql
WHERE
LTRIM(RTRIM(item_no))=LTRIM(RTRIM(lvl1.comp_item_no))
AND LTRIM(RTRIM(comp_item_no)) LIKE '.%'
)
ELSE NULL
END AS lvl_2_comp_item_no
FROM
bmprdstr_sql AS lvl1
LEFT JOIN bmprdstr_sql lvl2 ON lvl1.comp_item_no=lvl2.item_no
WHERE
(lvl1.item_no = @itemno) -- <-- problem
AND (lvl1.comp_item_no LIKE '.%' OR lvl1.comp_item_no LIKE 'ZG%'
OR lvl1.comp_item_no LIKE 'E%')
)
SELECT DISTINCT
CASE
WHEN LEFT(item_no,1)='.'
THEN STUFF(item_no,1,1,'')
ELSE item_no
END AS item_no,
part_no =
STUFF(
(SELECT DISTINCT ',' +
CASE
WHEN LEFT(lvl_2_comp_item_no,1)='.'
THEN STUFF(lvl_2_comp_item_no,1,1,'')
ELSE lvl_2_comp_item_no
END
FROM
CTE
WHERE
[email protected] FOR XML PATH('')),1,1,'')
--^problem
FROM
CTE
WHERE
lvl_2_comp_item_no IS NOT NULL
AND item_no IS NOT NULL
OPEN @outside_cursor;
FETCH NEXT FROM @outside_cursor INTO @itemno, @partno;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO items_parts (item_no, part_no)
VALUES (@itemno, @partno)
FETCH NEXT FROM @outside_cursor INTO @itemno, @partno
END
CLOSE @outside_cursor
DEALLOCATE @outside_cursor
有關如何完成此任務的任何建議?
不確定你爲什麼使用遊標來插入數據。我沒有試圖解析這個大的查詢來真正看到它在做什麼,但是這可以被重寫爲一個基於集合的插入。這裏是一個開始的好地方。 http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –
@SeanLange每個關於SQL遊標的問題都以一種形式結束或其他。我在去光標前嘗試使用基於集合的方法。 – SpaceAge
這是因爲幾乎每個遊標都可以用基於集合的方法而不是RBAR來解決。 –