Исправление SQL Update с использованием XQuery modify для работы на SQL 2005 - PullRequest
2 голосов
/ 12 октября 2011

Я пытаюсь переместить группу полей из таблицы в блоб xml, содержащийся в той же таблице. После того, как это успешно, я буду удалять столбец из таблицы. Ниже приведена очень простая версия (без столбца удаления) того, что я придумал, и это прекрасно работает в SQL 2008 - однако я обнаружил, что это не будет работать в SQL 2005. Я получаю сообщение об ошибке XQuery: SQL type 'datetime' is not supported in XQuery. На самом деле я делаю это с помощью выполнения построенного оператора SQL в SP из-за количества полей, но для простоты я использовал обычный пример в примере:

if OBJECT_ID('tempdb..#Case') is not null
 DROP Table #Case;

CREATE TABLE #Case 
( 
    id INT, 
    DecisionDate DateTime,
    CaseBlob xml
)

INSERT INTO #Case Values(1, '10-OCT-2011 10:10:00', '<CaseBlob></CaseBlob>')
INSERT INTO #Case Values(2, '20-OCT-2011 10:10:00', '<CaseBlob></CaseBlob>')
INSERT INTO #Case Values(3, null, '<CaseBlob></CaseBlob>')
INSERT INTO #Case Values(4, '21-OCT-2011 10:10:00', '<CaseBlob></CaseBlob>')
INSERT INTO #Case Values(5, null, '<CaseBlob></CaseBlob>')


UPDATE #Case
   SET CaseBlob.modify('insert <DecisionDate>{sql:column("#Case.DecisionDate")}</DecisionDate>
   as last into (/CaseBlob)[1]')
   WHERE #Case.DecisionDate is not null
   AND CaseBlob.exist('(/CaseBlob/DecisionDate)') = 0

SELECT * FROM #CASE

Я пытался обернуть sql:column("#Case.DecisionDate") с xs:string(sql:column("#Case.DecisionDate")), но это, похоже, не помогает. @Marc_s указал, что использование sql:column( в операторе .modify(insert не было введено до SQL 2008 - так что я думаю, что это красная сельдь.

В связи с тем, что это сценарий однократной миграции и его нужно запускать только один раз, я думаю, что мне следует отойти от методов Set и перейти к методу процедурного цикла, чтобы удовлетворить мои требования. Похоже ли это на правильный подход из-за ограничения версии сервера и чего я пытаюсь достичь? Любые указатели очень ценятся.

1 Ответ

0 голосов
/ 12 октября 2011

Первая часть:

Вы можете использовать CTE для запроса части даты, преобразованной в строку, используя стиль даты и времени 126.

;with C as
(
  select CaseBlob,
         convert(varchar(23), DecisionDate, 126) as DecisionDate
  from #Case
  where DecisionDate is not null and
        CaseBlob.exist('(/CaseBlob/DecisionDate)') = 0
)
update C
set CaseBlob.modify('insert <DecisionDate>{sql:column("DecisionDate")}</DecisionDate>
                     as last into (/CaseBlob)[1]')

Существует небольшая разница в выводе с использованием этого по сравнению с вашим оператором обновления. Он пропустит миллисекунды, если они равны .000. Если они действительно имеют значение, оно будет включено, чтобы вы не пропустили никаких данных. Это просто другое.

Вторая часть:

Я не очень понимаю, как это достаточно хорошо соединяется с вышеперечисленным, чтобы дать вам пример кода. Но если вам нужно добавить больше материала из других таблиц, вы можете присоединиться к этим таблицам в CTE и сделать столбцы как выходные данные из CTE для использования в операторе изменения, вставляя значения.

...