T-SQL для изменения XML-данных - PullRequest
0 голосов
/ 18 января 2019

Я хочу изменить значение для TransactionAmount, где TransactionAmount> 15000, используя TSQL. Таблица содержит более 50 тысяч строк.

Может ли кто-нибудь помочь мне? У меня проблемы с поиском каких-либо примеров.

<BillingTransactionInfo xmlns="http://xed.com/bc/gx.billsactioninfomodel">
  <AccountingDate>2018-12-07T13:40:44</AccountingDate>
  <AccountingDay>7</AccountingDay>
  <AccountingMonth>12</AccountingMonth>
  <AccountingYear>2018</AccountingYear>
  <AccountNumber>PC:0049207</AccountNumber>
  <AccountType>insured</AccountType>
  <BillingReferenceNumber>50000018100</BillingReferenceNumber>
  <CustomerName>JOHN MCGEE</CustomerName>
  <GLMonth>12</GLMonth>
  <GLYear>2018</GLYear>
  <TransactionSubtypeCode>DirectBillMoneyReceivedTxn</TransactionSubtypeCode>
  <TransactionSubtypeDesc>Direct Bill Money Received</TransactionSubtypeDesc>
  <IssueDate>2018-12-07T13:40:37</IssueDate>
  <PaymentMethod>cash</PaymentMethod>
  <PolicyRiskState>AL</PolicyRiskState>
  <ReasonCode>Direct Bill Money Received</ReasonCode>
  <RecordCreationDate>2018-12-07T13:40:37</RecordCreationDate>
  <Source>BILLING</Source>
  <TransactionAmount>2570.77</TransactionAmount>
  <TransactionCreateDate>2018-12-07T13:40:37</TransactionCreateDate>
</BillingTransactionInfo>
 

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Чтобы найти строки с TransactionAmount более 15000, должно работать что-то вроде этого:

SELECT * 
FROM TableName 
WHERE ColumnWithXml.value('(/BillingTransactionInfo/TransactionAmount)[1]','int') > 15000

Где TableName - это имя таблицы, а ColumnWithXml - это имя столбца XML (необходимобыть типа XML)

Чтобы обновить эти строки, должно сработать что-то вроде этого:

UPDATE TableName
SET ColumnWithXml.modify('replace value of 
(/BillingTransactionInfo/TransactionAmount)[1] with ("25000")')

WHERE ColumnWithXml.value('(/BillingTransactionInfo/TransactionAmount)[1]','int') > 15000

См. здесь (где предложения в столбцах XML): https://www.sqlservercentral.com/Forums/Topic1545273-392-1.aspx

и здесь (обновление данных): https://www.mssqltips.com/sqlservertip/2738/examples-of-using-xquery-to-update-xml-data-in-sql-server/

0 голосов
/ 18 января 2019

Ваш XML имеет пространство имен по умолчанию .Можно использовать подстановочный знак (например, *:ElementName), но рекомендуется объявлять пространства имен.

Кроме того, лучший способ фильтровать значение в тех случаях, когда вам это не нужно.значение является собственным методом XML .exist().

Попробуйте это:

WITH XMLNAMESPACES(DEFAULT('http://xed.com/bc/gx.billsactioninfomodel'))
UPDATE YourTable
SET TheXmlColumn.modify('replace value of (/BillingTransactionInfo/TransactionAmount/text())[1] with "12345"')
WHERE TheXmlColumn.exist('/BillingTransactionInfo[TransactionAmount > 15000]')=1;

Вы можете прочитать это как

  • Использовать указанное пространство имен по умолчаниюкогда нет явного пространства имен
  • Обновите вашу таблицу и измените XML указанным способом
  • Но попадайте только в те строки, где существует <BillingTransactionInfo> с <TransactionAmount> выше, чем 15000.

Внимание : Ваш образец выглядит не так, но вы должны быть уверены, что ваш столбец XML будет содержать только один <BillingTransactionInfo> в качестве состояния в вашем вопросе!

0 голосов
/ 18 января 2019

Добро пожаловать в переполнение стека. Это должно быть довольно просто. Во-первых, давайте сгенерируем 50К строк образцов данных.

IF OBJECT_ID('tempdb..#things') IS NOT NULL DROP TABLE #things;

DECLARE @xml XML =
'<BillingTransactionInfo xmlns="http://xed.com/bc/gx.billsactioninfomodel">
  <AccountingDate>2018-12-07T13:40:44</AccountingDate>
  <AccountingDay>7</AccountingDay>
  <AccountingMonth>12</AccountingMonth>
  <AccountingYear>2018</AccountingYear>
  <AccountNumber>PC:0049207</AccountNumber>
  <AccountType>insured</AccountType>
  <BillingReferenceNumber>50000018100</BillingReferenceNumber>
  <CustomerName>JOHN MCGEE</CustomerName>
  <GLMonth>12</GLMonth>
  <GLYear>2018</GLYear>
  <TransactionSubtypeCode>DirectBillMoneyReceivedTxn</TransactionSubtypeCode>
  <TransactionSubtypeDesc>Direct Bill Money Received</TransactionSubtypeDesc>
  <IssueDate>2018-12-07T13:40:37</IssueDate>
  <PaymentMethod>cash</PaymentMethod>
  <PolicyRiskState>AL</PolicyRiskState>
  <ReasonCode>Direct Bill Money Received</ReasonCode>
  <RecordCreationDate>2018-12-07T13:40:37</RecordCreationDate>
  <Source>BILLING</Source>
  <TransactionAmount>2570.77</TransactionAmount>
  <TransactionCreateDate>2018-12-07T13:40:37</TransactionCreateDate>
</BillingTransactionInfo>';
SELECT TOP (50000)
  id = IDENTITY(INT,1,1),
  X  = CAST(REPLACE(CAST(@xml AS VARCHAR(8000)),
  '<TransactionAmount>2570.77</TransactionAmount>',
  CONCAT('<TransactionAmount>',ABS(CHECKSUM(NEWID())%2250000)*.01,'</TransactionAmount>')) AS XML)
INTO    #things
FROM   sys.all_columns a, sys.all_columns b;

Решение:

SELECT id, tr.amt
FROM #things AS t
CROSS APPLY (VALUES(t.X.value(
  '(/*:BillingTransactionInfo/*:TransactionAmount/text())[1]','DECIMAL(10,2)'))) AS tr(amt)
WHERE tr.amt > 15000;

Возвращает:

id          amt
----------- ------------
201         21876.97
202         21229.64
204         19188.62
209         21680.17
212         18603.47
213         20507.21
216         19536.31
218         19490.95
...

Обновлено, чтобы продемонстрировать, как изменить значения до 10000 согласно запросу OP.

UPDATE t
SET X.modify('
    replace value of (/*:BillingTransactionInfo/*:TransactionAmount/text())[1]
    with "10000"')
FROM #things AS t
CROSS APPLY (VALUES(t.X.value(
  '(/*:BillingTransactionInfo/*:TransactionAmount/text())[1]','DECIMAL(10,2)'))) AS tr(amt)
WHERE tr.amt > 15000;
...