如何在 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

这应该让您大致了解。您很可能想要稍微调整一下以获得您正在寻找的任何输出,但这应该吐出一个描述,其中包含 10psrid 的所有父描述。