1

5万行のSQLServer2008テーブルがあり、それぞれのvarchar列に次のようなXMLフラグメントがあります。

<infoElems>
        <infoElem id="1" Name="somename" money="3399.3984939" />
</infoElems>

列を選択し、money属性を選択varcharして、実際のmoneyタイプ(私の例では3399.40)に変更してから、フラグメント全体を元に戻す必要があります。

誰かが私にこれを乗り越える方法を教えてもらえますか?ある種のXMLインデックスを作成する必要があると思いますか?混乱している。

ありがとう。

4

3 に答える 3

2
-- Table with xml fragment
declare @YourTable table(SomeID int identity, YourColumn varchar(max))

-- Add 2 rows of test data
insert into @YourTable values(
'<infoElems>
        <infoElem id="1" Name="somename" money="3399.3984939" />
</infoElems>')

insert into @YourTable values(
'<infoElems>
        <infoElem id="1" Name="somename" money="4399.3584939" />
</infoElems>')

-- Declare a table variable with a xml column
declare @TempTable table(SomeID int, YourColumn xml)

-- Copy rows that should be modified (ID and xml is enough)
insert into @TempTable
select SomeID, YourColumn
from @YourTable

--Modify the money attribute in TempTable
;with cte as
(
  select YourColumn.value('(infoElems/infoElem/@money)[1]', 'money') as MoneyCol,
         YourColumn
  from @TempTable
)
update cte set
  YourColumn.modify('replace value of (infoElems/infoElem/@money)[1] with sql:column("MoneyCol")')  

-- Write the changes back to the source table
update Y set
  Y.YourColumn = cast(T.YourColumn as varchar(max))
from @YourTable as Y
  inner join @TempTable as T
    on Y.SomeID = T.SomeID

-- Look at the result  
select *
from @YourTable  

結果:

SomeID  YourColumn
------  ---------------------------------------------------------------------------
1       <infoElems><infoElem id="1" Name="somename" money="3399.3985"/></infoElems>
2       <infoElems><infoElem id="1" Name="somename" money="4399.3585"/></infoElems>

SQLServerのお金には小数点以下4桁があります。小数点以下2桁が必要な場合は、代わりにこの更新ステートメントを使用する必要があります。

--Modify the money attribute in TempTable
;with cte as
(
  select YourColumn.value('(infoElems/infoElem/@money)[1]', 'numeric(15,2)') as MoneyCol,
         YourColumn
  from @TempTable
)
update cte set
  YourColumn.modify('replace value of (infoElems/infoElem/@money)[1] with sql:column("MoneyCol")')  
于 2011-06-10T20:34:37.537 に答える
1

関係するデータ型は、特に列のXMLが価格以外に変化する場合、これを醜くします。これはSQL2008で機能するものです。多くの行を更新する必要がある場合は、これを。で使用する必要がありますCURSOR

DECLARE @orig VARCHAR(20), @new money
DECLARE @origXml XML, @newXml VARCHAR(100)

// first you have to cast to xml
SELECT @origXml = CAST(myColunm AS XML) 
FROM dbo.Tbl1
WHERE ...

// then extract the value as a string
SET @orig = @origXml.value('(//infoElem/@money)[1]','varchar(20)') 

// then get the new value to the right percision - MONEY is accurate to the ten-thousandth hence the ROUND
SET @new = ROUND(CAST(@orig AS MONEY),2)  

SET @newXml = REPLACE(CAST(@origXml AS VARCHAR(100)),  
  'money="'+CAST(@orig AS VARCHAR)+'"',
  'money="'+CAST(@new AS VARCHAR)+'"') // then replace - this can be combined with the update 

UPDATE dbo.Tbl1 SET myColunm = @newXml // then update

状況によっては、これを行うための外部スクリプトを作成する方が簡単な場合があります。正規表現の使用を検討することもできます-この投稿を参照してください、しかしそれは本当に醜くなる可能性があります。

于 2011-06-10T17:16:21.833 に答える
1

基本的に、次のようなことができます。

SELECT
   SomeID,
   CAST(YourColumn AS XML).value('(/infoElems/infoElem/@money)[1]', 'money') AS 'MoneyValue'
FROM 
   dbo.YourTable
WHERE
   ....

moneyXMLから行と属性のリストを取得します。

その列(XMLのみを含む)が実際にタイプである場合は、はるかに簡単になりますXMLCAST(....AS XML)

于 2011-06-10T16:30:10.487 に答える