親パートを取るストアドプロシージャを記述し、そのパートのBOM(bill-of-materials)レコードを調べ、条件を満たす子レコード(つまり、含まれるパーツ特定の基準(私たちの命名規則、 '。'、 '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カーソルに関するすべての質問は、このコメントとともに1つの形式で終わりますまたは別のもの。私はカーソルに行く前にセットベースのアプローチを使ってみました。 – SpaceAge
これは、ほとんどすべてのカーソルがRBARの代わりにセットベースのアプローチで解決できるためです。 –