Запрос с CROSS APPLY, пытаясь получить поле на основе значения атрибута - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь получить все имена полей из формы, хранящейся в виде XML в SQL Server, на основе значения атрибута (культура).На самом деле, я могу получить текстовое значение, но они объединяются в столбец FieldName.

Структура XML выглядит следующим образом:

<Form>
  <Field>
    <Field Name="email" Type="text" ColumnSize="6">
      <Localizations>
        <Localization Culture="fr">
          <Text>Adresse couriel</Text>
          <Placeholder>Entrez votre adresse courriel</Placeholder>
        </Localization>
        <Localization Culture="fr">
          <Text>Email</Text>
          <Placeholder>Enter your email</Placeholder>
        </Localization>
      </Localizations>
    </Field>
  </Fields>
</Form>

SQL-запрос:

DECLARE @language VARCHAR(2)
SET @language = 'en'
SELECT 
    c.query('data(@Name)') AS FieldUniqueName, 
    c.query('data(./Localizations/Localization/Text)') AS FieldName, 
    c.query('data(@Type)') AS FieldType
FROM dbo.Form Form CROSS APPLY FormContent.nodes('/Form/Fields/Field') x(c)
WHERE Id = @formId
AND FormContent.exist('/Form/Fields/Field/Localizations/Localization[@Culture=sql:variable("@language")]') = 1

Результат выглядит следующим образом:

FieldUniqueName  |  FieldName             | FieldType
name             |  Nom Name              | text
email            |  Adresse couriel Email | text
phone            |  Téléphone Phone Number| text

Оба языка находятся в столбце FieldName!

Я пробовал также с:

...
c.value('data(./Localizations/Localization/Text)[1]', 'VARCHAR(100)') AS FieldName,
...

Но мне нужно выбрать между [1] или [2], чтобы получить правильный язык ...

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Помимо того, что в предоставленном вами XML были некоторые ошибки (структура и «fr» для обоих), вы можете попробовать это:

DECLARE @tbl TABLE(ID INT IDENTITY, FormContent XML);
INSERT INTO @tbl VALUES
(N'<Form>
  <Fields>
    <Field Name="email" Type="text" ColumnSize="6">
      <Localizations>
        <Localization Culture="fr">
          <Text>Adresse couriel</Text>
          <Placeholder>Entrez votre adresse courriel</Placeholder>
        </Localization>
        <Localization Culture="en">
          <Text>Email</Text>
          <Placeholder>Enter your email</Placeholder>
        </Localization>
      </Localizations>
    </Field>
  </Fields>
</Form>');

Запрос вернет значения loc в зависимости от вашегопеременная.

DECLARE @language VARCHAR(2)
SET @language = 'en'
SELECT 
    fld.value(N'@Name',N'nvarchar(max)') AS FieldUniqueName, 
    fld.value(N'@Type',N'nvarchar(max)') AS FieldType, 
    loc.value(N'(Text/text())[1]','nvarchar(max)') AS LocalText, 
    loc.value(N'(Placeholder/text())[1]','nvarchar(max)') AS LocalPlaceholder
FROM @tbl Form 
CROSS APPLY FormContent.nodes(N'/Form/Fields/Field') AS A(fld)
CROSS APPLY A.fld.nodes(N'Localizations/Localization[@Culture=sql:variable("@language")]') B(loc)
WHERE Id = 1
0 голосов
/ 25 апреля 2018

Хорошо, я нашел ответ на мою проблему!Вместо предложения where я изменяю XPath моего FieldName.Работает как шарм:

DECLARE @language VARCHAR(2)
SET @language = 'en'
SELECT 
    c.query('data(@Name)') AS FieldUniqueName, 
    c.query('data(./Localizations/Localization[@Culture=sql:variable("@language")]/Text)') AS FieldName, 
    c.query('data(@Type)') AS FieldType
FROM dbo.Form Form CROSS APPLY FormContent.nodes('/Form/Fields/Field') x(c)
WHERE Id = @formId
...