将两个字符串转换并合并为 table

Convert and merge two string as a table

假设我们有以下两个字符串:

DECLARE @AllowedCardBoardIds NVARCHAR(MAX) = '1,2,3,4,5,6'
DECLARE @AllowedCardBoardIdsAccessTypes NVARCHAR(MAX) = '11,22,33,44,55,66'

此外,假设我们有一个函数可以将字符串拆分为 table。
它returns一个序列值

Select * FROM dbo.SplitString(',', @AllowedCardBoardIds)
-- result:
Value
------
1
2
3
4
5
6

现在我想将两个字符串转换为 table 并按如下方式合并它们:

Id     | AccessType
--------------------
1      | 11
2      | 22
3      | 33
4      | 44
5      | 55
6      | 66

我应该怎么做?

我写了一个查询如下:

DECLARE  @AllowedCardBoardsTable TABLE(
    Id INT NOT NULL,
    AccessType INT NOT NULL
)

INSERT INTO @AllowedCardBoardsTable
(
    Id, AccessType
)
SELECT id.[Value], accessType.[Value]
FROM dbo.SplitString(',', @AllowedCardBoardIds) AS id

但我不知道如何填写 AccessType 列!

请尝试以下解决方案。

SQL

DECLARE @AllowedCardBoardsTable TABLE(
    Id INT NOT NULL,
    AccessType INT NOT NULL
);

DECLARE @AllowedCardBoardIds NVARCHAR(MAX) = '1,2,3,4,5,6';
DECLARE @AllowedCardBoardIdsAccessTypes NVARCHAR(MAX) = '11,22,33,44,55,66';

DECLARE @separator CHAR(1) = ',';

;WITH rs AS
(
    SELECT CardBoardIds = CAST('<root><r><![CDATA[' + 
          REPLACE(@AllowedCardBoardIds, @separator, ']]></r><r><![CDATA[') + 
          ']]></r></root>' AS XML)
        , CardBoardIdsAccessTypes = CAST('<root><r><![CDATA[' + 
          REPLACE(@AllowedCardBoardIdsAccessTypes, @separator, ']]></r><r><![CDATA[') + 
          ']]></r></root>' AS XML)
)
, rs2 AS 
(
    SELECT rn = ROW_NUMBER() OVER(ORDER BY (t.c))
        , Id = c.value('.', 'INT') 
    FROM rs
    CROSS APPLY CardBoardIds.nodes('/root/r/text()') AS t(c)
)
, rs3 AS 
(
    SELECT rn = ROW_NUMBER() OVER(ORDER BY (t.c))
        , Id = c.value('.', 'INT') 
    FROM rs
    CROSS APPLY CardBoardIdsAccessTypes.nodes('/root/r/text()') AS t(c)
)
INSERT INTO @AllowedCardBoardsTable (Id, AccessType)
SELECT rs2.id, rs3.Id 
FROM rs2 INNER JOIN rs3 ON rs3.rn = rs2.rn;

-- test
SELECT * FROM @AllowedCardBoardsTable;

输出

+----+------------+
| Id | AccessType |
+----+------------+
|  1 |         11 |
|  2 |         22 |
|  3 |         33 |
|  4 |         44 |
|  5 |         55 |
|  6 |         66 |
+----+------------+

我建议您使用 built-in string-splitting 方法之一,而不是尝试自己动手。

不幸的是,SQL 服务器的当前版本不支持带有 ordinal 列的 STRING_SPLIT。但在这种情况下,你可以用 OPENJSON

破解它
DECLARE @AllowedCardBoardIds NVARCHAR(MAX) = '1,2,3,4,5,6';
DECLARE @AllowedCardBoardIdsAccessTypes NVARCHAR(MAX) = '11,22,33,44,55,66';

SELECT
  id = acb.value,
  AccessType = at.value
FROM OPENJSON('[' + @AllowedCardBoardIds + ']') acb
JOIN OPENJSON('[' + @AllowedCardBoardIdsAccessTypes + ']') at
  ON at.[key] = acb.[key];

db<>fiddle

我强烈建议您首先存储正确规范化的数据,例如 table 变量、温度 table 或正常 table.