SQL XPath сравнивает переменную с пустым XML узлом - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть следующий код:

declare @mydoc xml
declare @myPhone nvarchar(12) = '2223334445'
declare @lastName nvarchar(100) = 'John'
declare @myEmail nvarchar(100) = null
set @mydoc = '<details>
                    <phone />
                    <email />
                    <lastname>John</lastname>
              </details>'


select @mydoc.exist('/details[fn:lower-case(lastname[1])=fn:lower-case(sql:variable("@lastName"))
                            and (phone[1]=sql:variable("@myPhone") 
                                 or phone[1]=fn:concat(fn:substring(sql:variable("@myPhone") ,1,3),"-",fn:substring(sql:variable("@myPhone") ,4,3), "-", fn:substring(sql:variable("@myPhone") ,7,4))
                                 or (fn:lower-case(email[1])=fn:lower-case(sql:variable("@myEmail")) and not(fn:lower-case(sql:variable("@myEmail"))="null"))
                                 )]')

В основном я хочу вернуть узел сведений, если он содержит заданную фамилию И либо адрес электронной почты, либо телефон (при условии, что они не пусты или не равны нулю). Я ожидаю, что приведенный выше код вернет 0, потому что даже если фамилия = Джон, телефон пуст и не равен @myPhone, а адрес электронной почты равен нулю. Тем не менее, он возвращает 1.

Если я изменяю свой код, как показано ниже (удалил часть электронной почты), он работает нормально, возвращает 0.

declare @mydoc xml
declare @myPhone nvarchar(12) = null --'2223334445'
declare @lastName nvarchar(100) = 'John'
declare @myEmail nvarchar(100) = null
set @mydoc = '<lead>
                    <phone />
                    <email />
                    <lastname>John</lastname>
              </lead>'


select @mydoc.exist('/lead[fn:lower-case(lastname[1])=fn:lower-case(sql:variable("@lastName"))
                            and (phone[1]=sql:variable("@myPhone") 
                                 or phone[1]=fn:concat(fn:substring(sql:variable("@myPhone") ,1,3),"-",fn:substring(sql:variable("@myPhone") ,4,3), "-", fn:substring(sql:variable("@myPhone") ,7,4)))]')

Чего мне не хватает в части электронной почты ? В первом примере я проверил, что электронная почта не является нулевой, потому что изначально я думал, что это проблема, но, как видно из второго примера, запрос отлично работает при отсутствии проверки на ноль для телефонного узла.

1 Ответ

0 голосов
/ 28 апреля 2020
declare @mydoc xml;
declare @myPhone nvarchar(12) = '2223334445';
declare @lastName nvarchar(100) = 'JOHN';
declare @myEmail nvarchar(100)= 'TESTmail@mail.org';

set @mydoc = '<details>
                    <phone>123456</phone>
                    <email>testmail@mail.org</email>
                    <lastname>John</lastname>
              </details>';
select @mydoc.exist('
/details[lastname[lower-case(.)=lower-case(sql:variable("@lastName"))]][phone[lower-case(.)=lower-case(sql:variable("@myPhone"))] or email[lower-case(.)=lower-case(sql:variable("@myEmail"))]]');  
go


declare @mydoc xml
declare @myPhone nvarchar(12) = '2223334445'
declare @lastName nvarchar(100) = 'John'
declare @myEmail nvarchar(100) = null
set @mydoc = '<details>
                    <phone />
                    <email />
                    <lastname>John</lastname>
              </details>';


select @mydoc.exist('/details[lastname=sql:variable("@lastName")][phone=sql:variable("@myPhone") or email=sql:variable("@myEmail")]');
---------
set @mydoc = '<details>
                    <phone>2223334445</phone>
                    <email />
                    <lastname>John</lastname>
              </details>'
select @mydoc.exist('/details[lastname=sql:variable("@lastName")][phone=sql:variable("@myPhone") or email=sql:variable("@myEmail")]');
---------
set @myEmail = 'testmail@mail.org'
set @mydoc = '<details>
                    <phone>123456</phone>
                    <email>testmail@mail.org</email>
                    <lastname>John</lastname>
              </details>';
select @mydoc.exist('/details[lastname=sql:variable("@lastName")][phone=sql:variable("@myPhone") or email=sql:variable("@myEmail")]');  
...