xml.exist - sql: столбец для последовательности - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь создать запрос с xml.exist с помощью функции sql: column-, где значение столбца должно быть преобразовано в пригодную для использования последовательность XQuery.

Это запрос со статическимпоследовательность, которая работает.

SELECT
    FieldA
    , FieldB
FROM
    MyTable
WHERE
    FieldC.exist('DSAuth/role[@id=("195", "267", "350")')

Чтобы получить динамическую последовательность, я бы использовал табличную функцию с возвращаемой таблицей со столбцом «IDsequence», у которого все идентификаторы представлены в виде строки.например, «195», «267», «350».

Табличная функция должна возвращать только одну строку!С несколькими строками это работает, но мне, наконец, нужно сгруппировать результат, что плохо для производительности.

SELECT
    FieldA
    , FieldB
FROM
    MyTable
CROSS APPLY
    dbo.MyFunc(0) AS f
WHERE
    FieldC.exist('DSAuth/role[@id=sql:column("f.IDsequence")]')

Есть ли способ получить пригодную для XQuery последовательность из sql: column ("f.IDsequence ")?

Спасибо за помощь.

Редактировать:

Проблема в производительности заключается в том, что FieldB (и еще несколько полей) является столбцом XML, поэтому у меня естьчтобы преобразовать его в группу по.

SELECT
    FieldA
    , CAST(CAST(FieldB AS nvarchar(max)) AS xml) AS FieldB
FROM
    MyTable
CROSS APPLY
    dbo.MyFunc(0) AS f
WHERE
    FieldC.exist('DSAuth/role[@id=sql:column("f.IDsequence")]')
GROUP BY
    FieldA
    , CAST(FieldB AS nvarchar(max))

1 Ответ

0 голосов
/ 03 марта 2019

Я не знаю, является ли это самым простым подходом, но вы можете попытаться включить свой список в XML и использовать его в предикате, как здесь:

- A таблица макетов, чтобы показать принципы

DECLARE @tbl TABLE(TheXml XML)
INSERT INTO @tbl VALUES
(
    N'<root>
        <a>1</a>
        <a>2</a>
      </root>'
)
,(
    N'<root>
        <a>1</a>
      </root>'
)
,(
    N'<root>
        <a>3</a>
        <a>4</a>
      </root>'
);

- Это легко: просто одно значение

SELECT * FROM @tbl WHERE TheXml.exist('/root/a[. cast as xs:int?=1]')=1;

- Это ваша последовательность .
- Но вы не можете ввести список значений с помощью sql:column() или sql:variable().

SELECT * FROM @tbl WHERE TheXml.exist('/root/a[. cast as xs:int?=(2,3)]')=1;

- Но вы можете добавить значения в свой XML до , как в этом cte

DECLARE @values TABLE(val INT);
INSERT INTO @values VALUES(2),(3);

WITH cte(NewXml) AS
(
    SELECT (SELECT (SELECT val AS [@val] FROM @values FOR XML PATH('values'),TYPE)
                  ,TheXml AS [*] 
            FOR XML PATH(''),TYPE
           )
    FROM @tbl t 
)
SELECT NewXml.query('/root') TheXml
FROM cte
WHERE NewXml.exist('/root/a[. cast as xs:int?=/values/@val]')=1;

Промежуточный XML выглядит следующим образом:

<values val="2" />
<values val="3" />
<root>
  <a>1</a>
  <a>2</a>
</root>

Финальный .query('/root') вернет предыдущий XML без изменений.

UPDATE

То же самое будет работать с введением на основе строк, как здесь:

WITH cte(NewXml) AS
(
    SELECT (SELECT CAST(N'<values val="2" /><values val="3" />' AS XML)
                  ,TheXml AS [*] 
            FOR XML PATH(''),TYPE
           )
    FROM @tbl t 
)
SELECT NewXml.query('/root') TheXml
FROM cte
WHERE NewXml.exist('/root/a[. cast as xs:int?=/values/@val]')=1
...