Обработать строку с неизвестной структурой в курсоре - PullRequest
0 голосов
/ 08 мая 2019

Я новичок в использовании курсоров для циклического прохождения набора строк. Но до сих пор я знал, какие столбцы я собираюсь прочитать.

* 1003 Е.Г. *

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 ]

1 голос
/ 08 мая 2019

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-список.
1 голос
/ 08 мая 2019

TSQL-курсоры на самом деле не предназначены для чтения данных из таблиц неизвестной структуры. Я могу придумать две возможности для достижения чего-либо в этом направлении:

  • Сначала прочитайте имена столбцов неизвестной таблицы из представлений информационной схемы (см. Представления схемы системной информации (Transact-SQL) ). Затем используйте динамический SQL для создания курсора.
  • Если вы просто хотите получить какие-либо столбцы в виде большого строкового значения, вы также можете попробовать простой SELECT * FROM TABLE_NAME FOR XML AUTO и дополнительно обработать полученные данные для ваших целей (см. FOR XML (SQL Server) ) .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...