web-dev-qa-db-ja.com

XMLをSQL Serverテーブルにインポートするにはどうすればよいですか?

私のソリューションを修正してXMLデータをSQL Serverテーブルにインポートする作業を手伝ってくれる人はいますか?私は研究をしましたが、この仕事は達成するのが非常に困難でした。私が見つけたものはすべて単純なデータで機能しましたが、私の名前と値は「website_details」セクションで別々になっています。これが私のスクリプトが機能していない理由です。約200のXMLファイルがあり、それぞれにインポートするレコードが1,000を超えるため、構造を変更できません。私が使用しているデータは機密情報と見なされるため、値の名前と値を変更して、これを投稿できるようにしました。

Websitesテーブルの最初の挿入コマンドは完全に機能し、すべてのデータをインポートします。私が抱えている問題は、2番目の挿入コマンドにあります。 @ xmlData.nodes定義は、問題があると私が思うところです。 "website_details"セクションでは、他の情報とは異なり、名前と値が分かれているため、構造を定義するのに苦労しています。

現時点で私のデータベースの概要を説明するために、2つのテーブルで構成されています。それらはwebsitesおよびwebsite_detailsです。 Web_ID列は両方のテーブルに含まれており、website_detailsをWebサイトに接続する外部キーです。私はwebsite_viewというデータを結合するために使用しているビューも持っています。

これは私のXMLファイルから抜粋したサンプルデータです:

<WEBSITES>
    <WEBSITE>
        <WEBSITE_ID>sta001</WEBSITE_ID>
        <WEBSITE_ALTERNATE_ID/>
        <WEBSITE_VERSION>4</WEBSITE_VERSION>
        <TYPE>DYNAMIC</TYPE>
        <NAME>TEST WEBSITE</NAME>
        <WEBSITE_DETAILS>
            <WEBSITE_DETAIL>
                <NAME>COST</NAME>
                <VALUE>500</VALUE>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
            <WEBSITE_DETAIL>
                <NAME>LANGUAGE</NAME>
                <VALUE>EN</VALUE>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
            <WEBSITE_DETAIL>
                <NAME>DATABASE</NAME>
                <VALUE/>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
        </WEBSITE_DETAILS>
    </WEBSITE>
    <WEBSITE>
        <WEBSITE_ID>mmn023</WEBSITE_ID>
        <WEBSITE_ALTERNATE_ID/>
        <WEBSITE_VERSION>3</WEBSITE_VERSION>
        <TYPE>DYNAMIC</TYPE>
        <NAME>TEST WEBSITE 2</NAME>
        <WEBSITE_DETAILS>
            <WEBSITE_DETAIL>
                <NAME>COST</NAME>
                <VALUE>750</VALUE>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
            <WEBSITE_DETAIL>
                <NAME>LANGUAGE</NAME>
                <VALUE>RU</VALUE>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
            <WEBSITE_DETAIL>
                <NAME>DATABASE</NAME>
                <VALUE>TRUE</VALUE>
                <INHERITED>false</INHERITED>
            </WEBSITE_DETAIL>
        </WEBSITE_DETAILS>
    </WEBSITE>
</WEBSITES>

これは私が使用しているストアドプロシージャです:

USE [websitesDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_website_import] (
 @xmlData XML ,
 @retValue varchar(100) OUTPUT
)

AS
BEGIN
SET @retValue='Failed';



INSERT INTO  [websites](
[Web_ID],
[Web_Version],
[Web_Type],
[Web_Name]
)

SELECT
[Table].[Column].value('WEBSITE_ID [1]', 'nvarchar(100)'),
[Table].[Column].value('WEBSITE_VERSION [1]', 'nvarchar(100)'),
[Table].[Column].value('TYPE [1]', 'nvarchar(100)'),
[Table].[Column].value('NAME [1]', 'nvarchar(100)')

 FROM @xmlData.nodes('/ WEBSITES / WEBSITE') as [Table]([Column])
IF(@@ROWCOUNT > 0 )
  SET @retValue='SUCCESS';


INSERT INTO  [website_details](
[Web_ID],
[cost],
[language],
[database]
)

SELECT
[Table].[Column].value('WEBSITE_ID [1]', 'nvarchar(100)'),
[Table].[Column].value('COST [1]', 'nvarchar(100)'),
[Table].[Column].value('LANGUAGE [1]', 'nvarchar(100)'),
[Table].[Column].value('DATABASE [1]', 'nvarchar(100)')

 FROM @xmlData.nodes('/ WEBSITES / WEBSITE / WEBSITE_DETAILS') as [Table]([Column])
IF(@@ROWCOUNT > 0 )
  SET @retValue='SUCCESS'

;

5
Austin

/WEBSITES/WEBSITEを2番目のクエリでも使用し、values句のNAMEノードに対して述語を使用して、VALUEノードから値を取得します。

select S.X.value('(WEBSITE_ID/text())[1]', 'nvarchar(100)') as WEBSITE_ID,
       S.X.value('(WEBSITE_DETAILS/WEBSITE_DETAIL[(NAME/text())[1] eq "COST"]/VALUE/text())[1]', 'nvarchar(100)'),
       S.X.value('(WEBSITE_DETAILS/WEBSITE_DETAIL[(NAME/text())[1] eq "LANGUAGE"]/VALUE/text())[1]', 'nvarchar(100)'),
       S.X.value('(WEBSITE_DETAILS/WEBSITE_DETAIL[(NAME/text())[1] eq "DATABASE"]/VALUE/text())[1]', 'nvarchar(100)')
from @xmlData.nodes('/WEBSITES/WEBSITE') as S(X)

結果:

sta001  500  EN  NULL
mmn023  750  RU  TRUE
11
Mikael Eriksson

ネクロマンシング。
誰かがそれをファイルおよび変数なしにする必要がある場合(テーブル値関数に適しています):

SELECT 
    --myTempTable.XmlCol.value('.', 'varchar(36)') AS val 
     myTempTable.XmlCol.query('./ID').value('.', 'varchar(36)') AS ID 
    ,myTempTable.XmlCol.query('./Name').value('.', 'nvarchar(MAX)') AS Name 
    ,myTempTable.XmlCol.query('./RFC').value('.', 'nvarchar(MAX)') AS RFC 
    ,myTempTable.XmlCol.query('./Text').value('.', 'nvarchar(MAX)') AS Text 
    ,myTempTable.XmlCol.query('./Desc').value('.', 'nvarchar(MAX)') AS Description 

    --,myTempTable.XmlCol.value('(Desc)[1]', 'nvarchar(MAX)') AS DescMeth2
FROM 
(
    SELECT  
        CAST('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <data-set>
            <record>
                <ID>1</ID>
                <Name>A</Name>
                <RFC>RFC 1035[1]</RFC>
                <Text>Address record</Text>
                <Desc>Returns a 32-bit IPv4 address, most commonly used to map hostnames to an IP address of the Host, but it is also used for DNSBLs, storing subnet masks in RFC 1101, etc.</Desc>
            </record>
            <record>
                <ID>2</ID>
                <Name>NS</Name>
                <RFC>RFC 1035[1]</RFC>
                <Text>Name server record</Text>
                <Desc>Delegates a DNS zone to use the given authoritative name servers</Desc>
            </record>
        </data-set>
        ' AS xml) AS RawXml
) AS b 
--CROSS APPLY b.RawXml.nodes('//record/ID') myTempTable(XmlCol);
CROSS APPLY b.RawXml.nodes('//record') myTempTable(XmlCol);

またはファイルから直接(テーブル値関数)

SELECT 
    --myTempTable.XmlCol.value('.', 'varchar(36)') AS val 
     myTempTable.XmlCol.query('./ID').value('.', 'varchar(36)') AS ID 
    ,myTempTable.XmlCol.query('./Name').value('.', 'nvarchar(MAX)') AS Name 
    ,myTempTable.XmlCol.query('./RFC').value('.', 'nvarchar(MAX)') AS RFC 
    ,myTempTable.XmlCol.query('./Text').value('.', 'nvarchar(MAX)') AS Text 
    ,myTempTable.XmlCol.query('./Desc').value('.', 'nvarchar(MAX)') AS Description 
FROM 
(
    SELECT CONVERT(XML, BulkColumn) AS RawXml 
    FROM OPENROWSET(BULK 'D:\username\Desktop\MyData.xml', SINGLE_BLOB) AS RowSetName 
) AS b 
CROSS APPLY b.RawXml.nodes('//record') myTempTable(XmlCol)

例えば.

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tfu_RPT_SEL_XmlData]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[tfu_RPT_SEL_XmlData]
GO




CREATE FUNCTION [dbo].[tfu_RPT_SEL_XmlData]
(
     @in_language varchar(10) 
    ,@in_reportingDate datetime 
)
RETURNS TABLE
AS
RETURN 
(   

    SELECT 
        --myTempTable.XmlCol.value('.', 'varchar(36)') AS val 
         myTempTable.XmlCol.query('./ID').value('.', 'varchar(36)') AS ID 
        ,myTempTable.XmlCol.query('./Name').value('.', 'nvarchar(MAX)') AS Name 
        ,myTempTable.XmlCol.query('./RFC').value('.', 'nvarchar(MAX)') AS RFC 
        ,myTempTable.XmlCol.query('./Text').value('.', 'nvarchar(MAX)') AS Text 
        ,myTempTable.XmlCol.query('./Desc').value('.', 'nvarchar(MAX)') AS Description 
    FROM 
    (
        SELECT CONVERT(XML, BulkColumn) AS RawXml 
        FROM OPENROWSET(BULK 'D:\username\Desktop\MyData.xml', SINGLE_BLOB) AS RowSetName 
    ) AS b 
    CROSS APPLY b.RawXml.nodes('//record') myTempTable(XmlCol)

)


GO

SELECT * FROM tfu_RPT_SEL_XmlData('DE', CURRENT_TIMESTAMP)
3
Quandary