遍历T-SQL中的字符列表

时间:2018-09-27 07:10:59

标签: sql loops tsql for-loop

我正在寻找任何有效的方法来解决T-SQL中的以下问题:

for i in L = ['A', 'B',..., 'N'] 
INSERT INTO MyTable1 (SomeCol1, SomeCol2)
SELECT SomeCol1, SomeCol2 FROM SomeTable1 WHERE <conditions>
UPDATE MyTable1 SET MyCol1 = i WHERE MyCol1 = 'the default value of MyCol1'

鉴于我的字符列表L很长,我不想对每个元素分别执行一次。因此,如果有比使用循环更好的解决方案,我对此也很感兴趣,只要它可以解决问题。请注意,我没有在上面尝试使用正确的语法-我还想知道如何处理T-SQL中的for i in L = ['A', 'B',..., 'N']部分。

谢谢!

2 个答案:

答案 0 :(得分:3)

您的问题还不清楚...

SQL-Server是基于 set 的工具。每当您觉得需要遍历集合的循环/迭代时,您都可能从错误的角度来解决问题。

第一个问题:如何提供字符列表?是表格,JSON,XML,CSV字符串吗?

无论如何,您的目标都必须是将其作为设置

仅显示原理:如果您提供字符,例如作为简单列表,您可以使用递归CTE

DECLARE @L VARCHAR(100)='ACFHJTZJ'; --add as many as you need

WITH recCTE AS
(
    SELECT 1 AS Pos,SUBSTRING(@L,1,1) AS OneChar
    UNION ALL
    SELECT r.Pos+1, SUBSTRING(@L,r.Pos+1,1)
    FROM recCTE r
    WHERE r.Pos<LEN(@L)
)
SELECT /*add DISTINCT if you want to surpress repeating characters*/ 
       Pos,OneChar 
FROM recCTE;

这将返回所有字母作为派生表。

您可以在基于集合的语句中使用这样的集合(无论如何创建):

DECLARE @L VARCHAR(100)='ACFHJTZJ'; --add as many as you need
DECLARE @tbl TABLE(SomeColumn CHAR(1));

WITH recCTE AS
(
    SELECT 1 AS Pos,SUBSTRING(@L,1,1) AS OneChar
    UNION ALL
    SELECT r.Pos+1, SUBSTRING(@L,r.Pos+1,1)
    FROM recCTE r
    WHERE r.Pos<LEN(@L)
)
INSERT INTO @tbl(SomeColumn)
SELECT DISTINCT OneChar 
FROM recCTE;

SELECT * FROM @tbl;

这会将每个单独的char插入表@tbl中。当然,您也可以在任何其他上下文(例如WHERE条件)中使用它。

无论如何,无论您的列表包含1、10还是一千个元素,该语句都不必更改。

如果您需要更多帮助,您确实应该提供更多背景信息。最好的方法是像上面一样创建一个独立方案。您可能想了解有关XY问题的信息...

答案 1 :(得分:0)

这解决了我的问题,我想这离实现它的最佳方式还很远。

CREATE TABLE MyTable2 (MyCol2 VARCHAR(5))
INSERT INTO MyTable2 (MyCol2) VALUES ('A')
INSERT INTO MyTable2 (MyCol2) VALUES ('B')
.
.
.
INSERT INTO MyTable2 (MyCol2) VALUES ('N')
ALTER TABLE MyTable2 ADD ID INT IDENTITY

WHILE (SELECT COUNT(*) FROM MyTable2) > 0
BEGIN
  INSERT INTO MyTable1 (SomeCol1, SomeCol2)
  SELECT SomeCol1, SomeCol2 FROM SomeTable1 WHERE <conditions>
  UPDATE MyTable1 
  SET MyCol1 = (SELECT MyCol2 FROM MyTable2 HAVING ID = MIN(ID)) 
  WHERE MyCol1 = 'the default value of MyCol1'
  DELETE FROM MyTable2 WHERE MyCol2 = (SELECT MyCol2 FROM MyTable2 HAVING ID = MIN(ID))
END