Альтернативным решением будет создание дополнительного поля в вашей целевой таблице, которое принимает строковое значение. После заполнения таблицы данными XML выполните инструкцию, чтобы обновить целочисленное поле, установив его в NULL, если строковое поле пустое.
Например, вот моя строка XML.
'<xml>
<d MetricID="1" Days="15" Sort="1" />
<d MetricID="2" Days="45" Sort="2" />
<d MetricID="3" Days="29" Sort="3" />
<d MetricID="4" Days="119" Sort="4" />
<d MetricID="5" Days="59" Sort="5" />
<d MetricID="6" Days="179" Sort="6" />
<d MetricID="7" Days="0" Sort="7" />
<d MetricID="8" Days="" Sort="8" />
<d MetricID="9" Days="60" Sort="9" />
</xml>'
Узлы 7 и 8 имеют соответствующие значения Дней 0 и Пусто. Ноль должен быть сохранен, а пробел должен быть сохранен как NULL. Вот мое решение для достижения этой цели.
DECLARE @idoc INT
EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlDeadline
CREATE TABLE #Deadline
( TimeframeMetricID INT
, DeadlineDays INT NULL
, DaysString VARCHAR(5) -- Hack for identifying DeadlineDays that were blank (null).
, SortOrder INT
)
INSERT INTO #Deadline
(TimeframeMetricID
, DeadlineDays
, DaysString
, SortOrder
)
SELECT MetricID
, Days
, DaysString
, Sort
FROM OPENXML
( @iDoc -- Handle to the XML doc.
, 'xml/d' -- Map to the node that contains the attributes.
, 1 -- Attribute centric mapping (1), instead of Element centric mapping (2).
)
WITH
( MetricID INT '@MetricID' -- Select attribute. When selecting element remove @ sign.
, Days INT '@Days'
, DaysString VARCHAR(5) '@Days' -- Hack for identifying DeadlineDays that were blank (null).
, Sort INT '@Sort'
) a
-- Release the XML parser
EXEC sp_xml_removedocument @idoc
-- Now convert Days that arrived as blank (i.e. Days="") from zero to NULL
-- to accurately reflect the supplied values.
UPDATE #Deadline
SET DeadlineDays = NULL
WHERE (DaysString = '')
SELECT * FROM #Deadline
Чтобы вспомнить, что происходит выше. Код захватывает атрибут Days дважды. Поместите один в столбец INT и один в столбец VARCHAR. После выполнения оператора XML INSERT запустите инструкцию UPDATE, чтобы преобразовать целевое поле INT в NULL, когда соответствующий столбец VARCHAR пуст.
Этот подход может предлагать лучшую производительность, чем XQuery. Я оставлю это кому-то еще в этой теме.