如何在 SQL 中使用游标循环、搜索和连接字符串?
How to loop, search and concatenate string in with cursor in TSQL?
我有这组数据
psrid parent_psrid description
1 NULL Work Management
2 1 Asset Maintenance
3 2 Code
4 3 asset type code
5 3 asset class code
6 3 asset class code - common rate type code
7 3 asset type code - asset status code
8 3 asset material class code - common rate type code
9 3 external interface code
10 2 Asset
11 10 asset
12 10 asset attachment
13 10 asset - common rate type code
14 2 Warranty
15 14 asset warranty attachment
16 1 CRM
17 16 Request
18 17 request
19 16 Code
20 19 crm request type code - crm task type code
21 19 task category code
22 19 request category code
23 19 request type code
24 19 task type code
我想创建一个存储过程,将所选 psrid
的描述与具有 parent_psrid
的所有其他行的描述连接起来,这些行与上一行的 psrid
相匹配,依此类推依此类推,直到父 psrid
为空。请注意,它只会查找描述并将其与其上方的行连接起来(psrid
是主键并已排序)。
这就像 zic-zac 映射。例如,如果我们从 psrid 10 开始并且 parent_psrid 是 2,如下图所示,那么最终连接的字符串将是 Work Management > Asset Maintenance > Asset
我已经走到这一步了,但我不知道下一步该做什么。
-- Declare a variables
DECLARE @in_psrid int = 10,
@psrid nvarchar(255),
@spsone_datasecurity_model_parent_psrid nvarchar(255),
@object_description nvarchar(255)
-- Declare a variable of type TABLE. It will be used as a temporary table.
DECLARE @myTable TABLE (
[psrid] int,
[spsone_datasecurity_model_parent_psrid] int,
[object_description] nvarchar(255)
)
-- Insert required data in the variable of type TABLE
INSERT INTO @myTable
SELECT [psrid], [spsone_datasecurity_model_parent_psrid], [object_description]
FROM [IcjisTest].[dbo].[Book2]
-- Declare cursor
DECLARE cur_psrid CURSOR
FOR SELECT [psrid], [spsone_datasecurity_model_parent_psrid], [object_description]
FROM @myTable
WHERE [psrid] = @in_psrid;
OPEN cur_psrid;
FETCH NEXT FROM cur_psrid INTO
@psrid,
@spsone_datasecurity_model_parent_psrid,
@object_description;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @psrid + @spsone_datasecurity_model_parent_psrid + @object_description;
FETCH NEXT FROM cur_psrid INTO
@psrid,
@spsone_datasecurity_model_parent_psrid,
@object_description;
END;
CLOSE cur_psrid;
DEALLOCATE cur_psrid;
请帮忙!谢谢。
每当您想到“我应该在数据库中循环”时,您应该立即想到“但必须有更好的”设置“方法来解决这个问题”。
A recursive CTE 是解决此问题的更好的“集合”方法。查看页面“示例”部分中 link 中的示例 D。
WITH buildstring As
(
/*
* Recursive Seed - Starting point of recursive lookup
*/
SELECT psrid, parent_psrid, description, 1 as depth
FROM yourtable
WHERE psrid = 10
UNION ALL
/*
* Recursive Member - The part that loops until the join(s) fail
* Note that we refer to the CTE itself (buildstring) in the
* FROM clause, which is what causes the recursiveness.
*/
SELECT
yourtable.psrid,
yourtable.parent_psrid,
buildstring.description + " " + yourtable.description,
buildstring.depth + 1
FROM buildstring
INNER JOIN yourtable
ON buildstring.parent_psrid = yourtable.psrid
WHERE depth < 20 --Just in case you get into an infinite cycle
)
SELECT *
FROM (SELECT description, row_number() OVER (ORDER BY depth DESC) as rn FROM buildstring) depth
WHERE rn = 1 --Get the last record created by the recursive CTE
这应该让您大致了解。您很可能想要稍微调整一下以获得您正在寻找的任何输出,但这应该吐出一个描述,其中包含 10
的 psrid
的所有父描述。
我有这组数据
psrid parent_psrid description
1 NULL Work Management
2 1 Asset Maintenance
3 2 Code
4 3 asset type code
5 3 asset class code
6 3 asset class code - common rate type code
7 3 asset type code - asset status code
8 3 asset material class code - common rate type code
9 3 external interface code
10 2 Asset
11 10 asset
12 10 asset attachment
13 10 asset - common rate type code
14 2 Warranty
15 14 asset warranty attachment
16 1 CRM
17 16 Request
18 17 request
19 16 Code
20 19 crm request type code - crm task type code
21 19 task category code
22 19 request category code
23 19 request type code
24 19 task type code
我想创建一个存储过程,将所选 psrid
的描述与具有 parent_psrid
的所有其他行的描述连接起来,这些行与上一行的 psrid
相匹配,依此类推依此类推,直到父 psrid
为空。请注意,它只会查找描述并将其与其上方的行连接起来(psrid
是主键并已排序)。
这就像 zic-zac 映射。例如,如果我们从 psrid 10 开始并且 parent_psrid 是 2,如下图所示,那么最终连接的字符串将是 Work Management > Asset Maintenance > Asset
我已经走到这一步了,但我不知道下一步该做什么。
-- Declare a variables
DECLARE @in_psrid int = 10,
@psrid nvarchar(255),
@spsone_datasecurity_model_parent_psrid nvarchar(255),
@object_description nvarchar(255)
-- Declare a variable of type TABLE. It will be used as a temporary table.
DECLARE @myTable TABLE (
[psrid] int,
[spsone_datasecurity_model_parent_psrid] int,
[object_description] nvarchar(255)
)
-- Insert required data in the variable of type TABLE
INSERT INTO @myTable
SELECT [psrid], [spsone_datasecurity_model_parent_psrid], [object_description]
FROM [IcjisTest].[dbo].[Book2]
-- Declare cursor
DECLARE cur_psrid CURSOR
FOR SELECT [psrid], [spsone_datasecurity_model_parent_psrid], [object_description]
FROM @myTable
WHERE [psrid] = @in_psrid;
OPEN cur_psrid;
FETCH NEXT FROM cur_psrid INTO
@psrid,
@spsone_datasecurity_model_parent_psrid,
@object_description;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @psrid + @spsone_datasecurity_model_parent_psrid + @object_description;
FETCH NEXT FROM cur_psrid INTO
@psrid,
@spsone_datasecurity_model_parent_psrid,
@object_description;
END;
CLOSE cur_psrid;
DEALLOCATE cur_psrid;
请帮忙!谢谢。
每当您想到“我应该在数据库中循环”时,您应该立即想到“但必须有更好的”设置“方法来解决这个问题”。
A recursive CTE 是解决此问题的更好的“集合”方法。查看页面“示例”部分中 link 中的示例 D。
WITH buildstring As
(
/*
* Recursive Seed - Starting point of recursive lookup
*/
SELECT psrid, parent_psrid, description, 1 as depth
FROM yourtable
WHERE psrid = 10
UNION ALL
/*
* Recursive Member - The part that loops until the join(s) fail
* Note that we refer to the CTE itself (buildstring) in the
* FROM clause, which is what causes the recursiveness.
*/
SELECT
yourtable.psrid,
yourtable.parent_psrid,
buildstring.description + " " + yourtable.description,
buildstring.depth + 1
FROM buildstring
INNER JOIN yourtable
ON buildstring.parent_psrid = yourtable.psrid
WHERE depth < 20 --Just in case you get into an infinite cycle
)
SELECT *
FROM (SELECT description, row_number() OVER (ORDER BY depth DESC) as rn FROM buildstring) depth
WHERE rn = 1 --Get the last record created by the recursive CTE
这应该让您大致了解。您很可能想要稍微调整一下以获得您正在寻找的任何输出,但这应该吐出一个描述,其中包含 10
的 psrid
的所有父描述。