处理游标中结构未知的行

时间:2019-05-08 08:26:15

标签: tsql cursor

我不熟悉使用游标在一组行之间循环。但是到目前为止,我已经对要阅读的专栏有所了解。

例如

DECLARE db_cursor FOR 
SELECT Column1, Column2
FROM MyTable

DECLARE @ColumnOne VARCHAR(50), @ColumnTwo VARCHAR(50)

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @ColumnOne, @ColumnTwo
...

但是我要读入键/值表的表没有特定的结构,我应该能够一次处理它们。如何使用嵌套游标遍历提取行的所有列并根据其类型和名称对其进行处理?

2 个答案:

答案 0 :(得分:1)

TSQL游标并不是真正为从结构未知的表中读取数据而设计的。我可以想到的朝着这个方向发展的两种可能性是:

  • 首先从信息架构视图中读取未知表的列名(请参见System Information Schema Views (Transact-SQL))。然后使用动态SQL创建游标。
  • 如果您只是想将任何列作为大字符串值获取,则还可以尝试使用简单的SELECT * FROM TABLE_NAME FOR XML AUTO并根据您的目的进一步处理检索到的数据(请参见FOR XML (SQL Server))。

答案 1 :(得分:1)

SQL在处理集合方面不是很好。在大多数情况下,您必须事先知道列名,数据类型等等。但是有XQuery。您可以轻松地将任何SELECT转换为XML,并使用强大的功能来处理那里的通用结构。我不建议这样做,但可能值得尝试:

CREATE PROCEDURE dbo.Get_EAV_FROM_SELECT
(
     @SELECT NVARCHAR(MAX)
)
AS
BEGIN
    DECLARE @tmptbl TABLE(TheContent XML);
    DECLARE @cmd NVARCHAR(MAX)= N'SELECT (' + @SELECT + N' FOR XML RAW, ELEMENTS XSINIL);';
    INSERT INTO @tmptbl EXEC(@cmd);

    SELECT r.value('*[1]/text()[1]','nvarchar(max)') AS RowID
          ,c.value('local-name(.)','nvarchar(max)') AS ColumnKey
          ,c.value('text()[1]','nvarchar(max)') AS ColumnValue
    FROM @tmptbl t
    CROSS APPLY t.TheContent.nodes('/row') A(r)
    CROSS APPLY A.r.nodes('*[position()>1]') B(c)
END;
GO

EXEC Get_EAV_FROM_SELECT @SELECT='SELECT TOP 10 o.object_id,o.* FROM sys.objects o';
GO
--Clean-Up for test purpose
DROP PROCEDURE Get_EAV_FROM_SELECT;

简而言之

  • 选择将作为字符串传递到过程中。使用SP,我们可以动态创建一条语句并从中创建XML。
  • 第一列被视为行的ID ,如果不是(例如sys.objects),我们可以编写SELECT并以这种方式强制执行。
  • 内部SELECT将读取每一行并返回经典的EAV列表。