2017-02-22 25 views
0

Я пытаюсь прочитать из таблицы столбец varchar, но этот столбец фактически является Xml, поэтому я преобразовываю значение в XML и пытаюсь получить оттуда значение ,Получение null пытается прочитать значение столбца XML SQL

Проблема в том, что я всегда получаю null. Это мой код:

declare @Greeting xml = (select CAST(sg.Greeting as xml) from AnsService.Ans.SiteGroup sg with (nolock) where sg.SiteGroupNum = 2032) 

select 
    sg.AnswerAs, 
    (select xmlData.Col.value('.', 'varchar(max)') from @Greeting.nodes('//Section/Paragraph/Run') xmlData(col)) as Greeting 
from AnsService.Ans.SiteGroup sg with (nolock) 
where sg.SiteGroupNum = 2032 

значение XML после преобразования является:

<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve> 
    <Paragraph> 
    <Run>Thank you for calling Intelli-tec Security Services. This is [OpFirst] speaking, how may I help you?</Run> 
    </Paragraph> 
</Section> 

Любой человек может помочь мне определить мою проблему здесь, благодаря

ответ

1

Есть несколько недостатков:

  • bad habit to kick: NOLOCK everywhere
  • Если XML вы sho w us is complete, нет необходимости в APPLY по телефону .nodes()
  • Не используйте двойной // перед «Разделом». Это вызывает глубокий поиск и ищет любой элемент <Section> в любом месте XML.
  • Ваш XML определяет пространство имен по умолчанию. Вы должны использовать его или использовать подстановочные знаки
  • Вы должны сохранить XML в соответствующем типе. Никаких бросков не требуется (например, здесь select CAST(sg.Greeting as xml)
  • Похоже, что этот XML хранится в той же таблице, из которой вы читаете остальное. Там нет (наверное) нет необходимости читать это в переменную первого

Попробуйте это:

DECLARE @Greeting XML= 
N'<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve"> 
    <Paragraph> 
    <Run>Thank you for calling Intelli-tec Security Services. This is [OpFirst] speaking, how may I help you?</Run> 
    </Paragraph> 
</Section>'; 

--declared namespace 
SELECT 
    @Greeting.value('declare namespace ns1="http://schemas.microsoft.com/winfx/2006/xaml/presentation"; 
        (/ns1:Section/ns1:Paragraph/ns1:Run/text())[1]','nvarchar(max)') Greeting; 

--predefined namespace 
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/winfx/2006/xaml/presentation') 
SELECT 
    @Greeting.value('(/Section/Paragraph/Run/text())[1]','nvarchar(max)') Greeting; 

--no namespace but wildcards 
SELECT 
    @Greeting.value('(/*:Section/*:Paragraph/*:Run/text())[1]','nvarchar(max)') Greeting; 

Если мой магический хрустальный шар работает правильно, то вам нужно что-то вроде этого

select 
    sg.AnswerAs, 
    CAST(sg.Greeting AS XML).value('declare namespace ns1="http://schemas.microsoft.com/winfx/2006/xaml/presentation"; 
            (/ns1:Section/ns1:Paragraph/ns1:Run/text())[1]','nvarchar(max)') AS Greeting 
from AnsService.Ans.SiteGroup sg with (nolock) 
where sg.SiteGroupNum = 2032 
+0

Большое спасибо @ Шнуго, ты лучший, твой ответ абсолютно правильный. Я очень ценю вашу помощь в этом. Все ваши рекомендации правы, что база данных не моя, поэтому я должен использовать ее так, как она реализована. Огромное спасибо. –