Функция SQL REPLACE внутри Xml.modify 'заменить значение'

Я пытаюсь обновить некоторые данные XML в SQL Server. XML содержит данные, которые выглядят следующим образом:

<root> <id>1</id> <timestamp>16-10-2017 19:24:55</timestamp> </root> 

Предположим, что этот XML существует в столбце Data в таблице TestTable . Я хотел бы иметь возможность изменить дефисы в метке времени на косые черты.

Я надеялся, что смогу сделать что-то вроде:

 update TestTable set Data.modify('replace value of (/root/timestamp/text())[1] with REPLACE((/root/timestamp/text())[1], "-", "/")') 

Я получаю следующую ошибку:

XQuery [TestTable]: нет функции '{ http://www.w3.org/2004/07/xpath-functions }: REPLACE ()'

Когда я думаю об этом, это имеет смысл. Но мне интересно, есть ли способ сделать это в одном обновлении? Или мне сначала нужно запросить значение временной метки и сохранить его как переменную, а затем обновить XML с помощью переменной?

Примечание: этот ответ предполагает, что вы хотите, чтобы этот формат был отформатирован с целью отображения этого в виде строки, а не для разбора содержимого как xs: dateTime. Если вы хотите последнего, ответ Shungo будет отформатировать его как таковой.


Похоже, что replace не является поддерживаемой функцией XQuery в SQL Server на момент написания этой статьи. Вы можете использовать функцию substring вместе с функцией concat в «замещающем значении (XML DML)» .

 CREATE TABLE #t(x XML); INSERT INTO #t(x)VALUES(N'<root><id>1</id><timestamp>16-10-2017 19:24:55</timestamp></root>'); UPDATE #t SET x.modify('replace value of (/root/timestamp/text())[1] with concat(substring((/root/timestamp/text())[1],1,2), "/", substring((/root/timestamp/text())[1],4,2), "/", substring((/root/timestamp/text())[1],7) ) ') SELECT*FROM #t; 

В результате:

 <root><id>1</id><timestamp>16/10/2017 19:24:55</timestamp></root> 

Если вам не нужна внешняя необходимость , вы должны использовать строки даты / времени ISO8601 в XML.

Строка dateTime связана с культурой. Чтение этого в разных системах с различными языковыми настройками или настройками даты приведет к ошибкам или – еще хуже !!! – к неправильным результатам.

Датой типа «08-10-2017» может быть 8 октября или 10 августа …

Хуже всего то, что это может успешно пройти все ваши тесты, но будет ломаться на машине клиента со странными сообщениями об ошибках или плохими результатами вплоть до реального повреждения данных!

Переключение дефиса на косые черты просто косметическое! XML – это строго определенный контейнер данных . Любые нестроковые данные должны быть представлены как безопасная конвертируемая строка.

Это то, что вы должны делать:

 DECLARE @tbl TABLE(ID INT IDENTITY,YourXML XML); INSERT INTO @tbl VALUES (N'<root> <id>1</id> <timestamp>16-10-2017 19:24:55</timestamp> </root>'); UPDATE @tbl SET YourXml.modify(N'replace value of (/root/timestamp/text())[1] with concat( substring((/root/timestamp/text())[1],7,4), "-" ,substring((/root/timestamp/text())[1],4,2), "-" ,substring((/root/timestamp/text())[1],1,2), "T" ,substring((/root/timestamp/text())[1],12,8) ) cast as xs:dateTime?'); SELECT * FROM @tbl; 

Результат

 <root> <id>1</id> <timestamp>2017-10-16T19:24:55</timestamp> </root> 

вы можете попробовать замену строки, как показано ниже.

 update testtable set data= cast( concat( left(cast(data as varchar(max)),charindex('<timestamp>',cast(data as varchar(max)))+len('<timestamp>')-1), replace( substring( cast(data as varchar(max)), len('<timestamp>') + charindex( '<timestamp>', cast(data as varchar(max))) , charindex('</timestamp>',cast(data as varchar(max))) -charindex('<timestamp>',cast(data as varchar(max))) -len('<timestamp>') ), '-','/'), right(cast(data as varchar(max)),len(cast(data as varchar(max)))-charindex('</timestamp>',cast(data as varchar(max)))+1) ) as xml) select * from testtable 

рабочая демонстрация

  • Получение имени элемента XML с помощью t-SQL
  • XPath в запросе T-SQL
  • Использование XPATH / XQUERY для выбора всех значений для элементов с атрибутом X
  • Итерация Sql по XML
  • Создание XML из таблицы SQL (уникальное форматирование XML)
  • Перенос данных T-sql из xml в столбцы
  • Запрос столбца xml SQL Server с предоставленным пользователем XPath через Entity Framework
  • SQL Использование OpenXML для извлечения нескольких элементов
  • Запрос Xpath SQL Server
  • Преобразование всех дочерних тегов в одну колонку с несколькими разделителями -SQL Server (3)
  • Использование Convert Style Option 2 для большого количества XML-файлов одновременно в Microsoft SQL Server
  • Interesting Posts

    Entity Framework фильтрует данные по строке sql

    Проблема с SQL Cursor

    SQL Server: возвращает наиболее часто встречающиеся значения (и числа) из 9 столбцов в одной таблице

    Как перечислить сообщения из одной таблицы и в то же время суммировать сумму из другой таблицы?

    Отобразить обозначение, основанное на их достижениях в SQL Server

    Запрос, который работал в течение нескольких месяцев

    использование MERGE для инкрементной вставки

    Попытка удалить пробелы между инициалами в sql

    Есть ли способ установить сравнительное значение в предложении WHERE равным IS NULL или IS NOT NULL на основе переменной

    В SQL-сервере, как я могу запросить столбец Timestamp Oracle через соединение Linked Server?

    Как я могу рассчитывать результат запроса

    Как перенести базу данных MS SQL, запущенную на удаленном компьютере, в мою локальную базу данных MySQL, работающую на Linux, сохраняя кодировку

    Несколько PIVOTS? Необходимо подсчитывать по часам в месяц

    Объедините таблицу таблицы, чтобы они были применены

    «Аргумент« sql »не может быть нулевым» при включении «Go» в EF DbMigration

    Давайте будем гением компьютера.