В наборе результатов SQL XQuery есть ли способ заставить оператор «value» возвращать ноль для отсутствующих элементов? - PullRequest
4 голосов
/ 10 мая 2011

При получении значений из атрибутов xml с помощью оператора значения xquery отсутствующие атрибуты возвращаются как нулевые. Есть ли способ сделать то же самое, не прибегая к CASE WHEN N.exists('path')=0 THEN NULL ELSE n.value('path') END?

Этот SQL:

DECLARE @val xml
SET @val = '<records>
  <record attrval="attrval">
    <stringvalue>some value</stringvalue>
    <intvalue>1</intvalue>
  </record>
  <record>
    <intvalue>1</intvalue>
  </record>
  <record>
    <stringvalue>another value</stringvalue>
  </record>
</records>'

SELECT N.query('stringvalue').value('/', 'varchar(100)') AS stringvalue,
       N.query('intvalue').value('/', 'int') AS intvalue,
       N.value('@attrval', 'varchar(100)') AS attrval
FROM @val.nodes('//record') as T(N)

Результат:

[stringvalue]       [intvalue]  [attrval]
some value          1           attrval
                    1           NULL
another value       0           NULL

И я бы хотел получить:

[stringvalue]       [intvalue]  [attrval]
some value          1           attrval
NULL                1           NULL
another value       NULL        NULL

Без выполнения:

SELECT CASE WHEN N.exists('stringvalue')=1 THEN N.query('stringvalue').value('/', 'varchar(100)') ELSE NULL END AS stringvalue,
       CASE WHEN N.exists('intvalue')=1 THEN N.query('intvalue').value('/', 'int') ELSE NULL END AS intvalue,
       N.value('@attrval', 'varchar(100)') AS attrval
FROM @val.nodes('//record') as T(N)

Обратите внимание, что в этом случае я не могу просто использовать значения атрибутов, поскольку существует ограничение на длину атрибутов, наложенных SQL Server, и некоторые из моих данных превышают это значение.

Кроме того, есть связанный вопрос, но ответ не применим, потому что мне нужно различать пустое и отсутствующее: SQL Server xQuery возвращает NULL вместо пустого

Ответы [ 2 ]

2 голосов
/ 22 мая 2011
SELECT N.value('stringvalue[1]', 'varchar(100)') AS stringvalue,
       N.value('intvalue[1]', 'int') AS intvalue,
       N.value('@attrval', 'varchar(100)') AS attrval
FROM @val.nodes('//record') as T(N)
1 голос
/ 13 мая 2011

Это то, что вы ищете:

   SELECT NULLIF(N.query('stringvalue').value('/', 'varchar(100)'),'') AS stringvalue,
       N.query('intvalue').value('/', 'int') AS intvalue,
       N.value('@attrval', 'varchar(100)') AS attrval
   FROM @val.nodes('//record') as T(N)

Использование NULLIF (выражение, выражение), где первое выражение - это выражение, возвращаемое из данных, а второе - выражение, с которым его можно сравнить иравно, он вернет NULL.

...