T-SQL修改XML数据

时间:2019-01-17 22:26:45

标签: xml tsql sql-server-2012

我想使用TSQL修改TransactionAmount> 15000的TransactionAmount值。表格有超过5万行。

有人可以帮我吗?我在任何地方都找不到例子。

<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 :(得分:1)

您的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>高于15000的<TransactionAmount>的行。

注意:您的示例看起来不是这样,但是必须确保,您的XML列将仅保留一个<BillingTransactionInfo>作为问题中的陈述!

答案 1 :(得分:0)

欢迎使用堆栈溢出。这应该很简单。首先让我们生成5万行样本数据。

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
...

已更新,以演示如何根据OP的要求将值修改为10000。

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;

答案 2 :(得分:0)

要查找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列的where子句): 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/