Альтернативные узлы в пути SQL Server XQuery?

#sql-server #xml #xquery

#sql-сервер #xml #xquery

Вопрос:

Есть ли какой-либо способ создать своего рода «альтернативную группу», как в регулярных выражениях, в пути XQuery в SQL Server?

У меня есть этот запрос…

 SELECT Q.ROWID QUEUEID, Q.DOCUMENTPACKAGETYPE, 
    B.R.value('@_ID', 'NAME') PARTYID,
    B.R.value('@_BorrowerID', 'NAME') BORROWERID,
    B.R.value('@_Name', 'NAME') NAME,
    B.R.value('@_EmailAddress', 'NAME') EMAILADDRESS
FROM docutech.QUEUE_EX Q 
CROSS APPLY Q.DATA.nodes('LOAN_PUSHBACK_PACKAGE/EVENT_DATA/ESIGN/PARTY') AS B(R)
WHERE Q.REASONFORPUSHBACK = 'DocumentDistribution' AND B.R.value('@_Type', 'NAME') = 'Borrower'
  

Но что мне нужно, так это то, что CROSS APPLY узел ESIGN в пути на самом деле может быть либо ESIGN, либо ECLOSE. Итак, я хочу сделать что-то вроде следующего (думая в терминах регулярных выражений)…

 CROSS APPLY Q.DATA.nodes('LOAN_PUSHBACK_PACKAGE/EVENT_DATA/(ESIGN)|(ECLOSE)/PARTY') AS B(R)
  

Есть ли какой-либо способ сделать что-то подобное? Мне бы очень не хотелось повторять один и тот же запрос дважды, просто из-за этого простого различия, хотя, возможно, XQuery не поддерживает подобные параметры?

На самом деле, я только что обнаружил, что могу использовать звездочку, которая будет соответствовать обоим, но я ХОТЕЛ бы иметь возможность ограничить ее этими известными значениями узла, если это возможно. Если нет, я думаю, это подойдет.

Комментарии:

1. Было бы здорово, если бы вы могли предоставить минимально воспроизводимый пример: (1) DDL и выборку данных, т.Е. Создать таблицу (ы) плюс инструкции INSERT, T-SQL. (2) Что вам нужно сделать, т.Е. логика, и ваша попытка реализовать ее в T-SQL. (3) Желаемый результат на основе образца данных в # 1 выше. (4) Ваша версия SQL Server (ВЫБЕРИТЕ @@version;)

Ответ №1:

Думаю, я понял, что вам нужно. Вот концептуальный пример для вас.

Выражение предиката XPath проверяет, принадлежат ли имена элементов на определенном уровне последовательности указанных имен. <SomethingElse> Элемент не является членом последовательности, поэтому его данные не извлекаются.

SQL

 -- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<LOAN_PUSHBACK_PACKAGE>
    <EVENT_DATA>
        <ESIGN>
            <PARTY _Name="one"/>
        </ESIGN>
        <ECLOSE>
            <PARTY _Name="two"/>
        </ECLOSE>
        <SomethingElse>
            <PARTY _Name="three"/>
        </SomethingElse>
    </EVENT_DATA>
</LOAN_PUSHBACK_PACKAGE>');
-- DDL and sample data population, end

SELECT c.value('@_Name','VARCHAR(20)') AS [Name] 
FROM @tbl
    CROSS APPLY xmldata.nodes('/LOAN_PUSHBACK_PACKAGE/EVENT_DATA/*[local-name(.)=("ESIGN","ECLOSE")]/PARTY') AS t(c);
  

Вывод

  ------ 
| Name |
 ------ 
| one  |
| two  |
 ------ 
  

Комментарии:

1. Это сделало это! И бонус, он исключил несколько строк из * , которые отображали другие типы записей, которые мы получаем из стороннего источника данных. (Они предоставляют очень мало документации!) … На что ссылается этот синтаксис в мире XQuery? Я пробовал поискать в Google reg ex , options , alternates optional groups и несколько других, но не смог этого понять. Знание правильных имен в области XQuery может помочь разобраться в любых дальнейших вопросах, которые у меня могут возникнуть.

2. Хех … выяснил, как определить, чему он соответствует, добавив следующее поле в мой SELECT список полей: B.R.value('local-name(..)', 'NAME') PARENT , которое возвращает либо ESIGN , либо ECLOSE .

3. @eidylon, рад слышать, что предложенное решение работает для вас. «… На что ссылается этот синтаксис в мире XQuery?..» На языке XQuery это последовательность. Пожалуйста, свяжитесь со мной в LinkedIn.