将两个字符串转换并合并为 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];
我强烈建议您首先存储正确规范化的数据,例如 table 变量、温度 table 或正常 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];
我强烈建议您首先存储正确规范化的数据,例如 table 变量、温度 table 或正常 table.