4

C# で小さなコンソール アプリを作成して、XML ファイルの内容に従って SQL Server 2008 の製品 (ITEMS) のテーブルに挿入を実行しようとしています。SQL テーブルへの適切なマッピングを含む .XSD ファイルが既にあります (以下に概説するアプローチでは必要ない場合があります)。

これが私のアプローチの高レベルです:

  1. XML を読み取り、それを使用してテーブルを作成します。
  2. XML ファイルから作成されたテーブルを使用して、ITEMS テーブルに対して MERGE を実行します。
    2a. アイテムが存在する場合は、それを更新します。
    2b. アイテムが存在しない場合は、挿入します。
  3. XML に挿入されたレコードのみのログを作成します。

次の ITEMS テーブルと XML ファイルについて考えてみましょう。

アイテム

  Item_Id    Name    Price  
     1       Coke     5.00  
     2       Pepsi    3.00  
     3       Sprite   2.00   

アイテム.XML

   <?xml version="1.0" encoding="ISO-8859-1"?>
   <Item>
    <Id>5</Id>
    <Name>Mountain Dew</Name>
    <Price>4.50</Price>
   </Item>
   <Item>
    <Id>3</Id>
    <Name>Sprite Zero</Name>
    <Price>1.75</Price>
   </Item>

インポート後、ITEMS テーブルは次のようになります。

アイテム

  Item_Id    Name         Price  
     1       Coke          5.00  
     2       Pepsi         3.00  
     3       Sprite Zero   1.75  
     5       Mountain Dew  4.50

それが完了したら、テーブルに挿入された「新しい」レコード (ITEMS_LOG.XML) を含む XML 形式のログ ファイルも生成する必要があります。

ITEMS_LOG.XML

   <?xml version="1.0" encoding="ISO-8859-1"?>
   <Item>
    <Id>5</Id>
    <Name>Mountain Dew</Name>
    <Price>4.50</Price>
   </Item>

SQLXMLBulkLoad を使用してこれを実装しようとしましたが、残念ながら、必要なログが提供されず、SQL Server から返されたメッセージ (つまり、挿入/更新されたもの) にアクセスすることもできません。私は中級レベルの SQL の専門知識を持っていますが、特にこのコンテキストで XML を扱うのはかなり初めてです。ヘルプ/ガイダンスをいただければ幸いです。

4

3 に答える 3

4

テーブル変数に対してwithを使用mergeしてoutputから、テーブル変数をクエリしてログXMLを作成できます。

アイテムXMLをinパラメーターとして、ログXMLをoutパラメーターとして持つストアード・プロシージャーに入れてください。

create procedure AddItemXML
  @ItemsXML xml,
  @ItemsLogXML xml out
as

declare @Changes table
(
  Item_Id int,
  Name nvarchar(20),
  Price money,
  Action nvarchar(10)
);

merge Items as T
using
  (
    select T.N.value('Id[1]', 'int') as Item_Id,
           T.N.value('Name[1]', 'varchar(20)') as Name,
           T.N.value('Price[1]', 'money') as Price
    from @ItemsXML.nodes('/Item') T(N)
  ) as S
on T.Item_Id = S.Item_Id
when matched then
  update set Name = S.Name, Price = S.Price
when not matched then
  insert (Item_Id, Name, Price) values (S.Item_Id, S.Name, S.Price)
output inserted.Item_Id,
       inserted.Name,
       inserted.Price,
       $action 
  into @Changes;

set @ItemsLogXML = 
  (
    select Item_Id as ID,
           Name,
           Price
    from @Changes
    where Action = 'INSERT'
    for xml path('Item'), type
  );

SE-Dataの作業サンプル

于 2012-05-02T09:03:38.493 に答える
2

これが役に立てば幸いです。私がしたことは、以下のストアド プロシージャを作成することでした。基本的に、ストアド プロシージャは xml 値を受け取り、コードから渡されたフラグをチェックして、それが挿入か更新かを判断します。

DECLARE @xml xml
SET @xml = @xmlCredentials

SELECT
      item.value('@Id', 'int') As ID,
      item.value('@AgentID', 'int') As AgentID,
      item.value('@Username', 'varchar (50)') As Username,
      item.value('@Password', 'varchar (50)') As [Password],
      item.value('@IsDirty', 'bit') As IsDirty,
      item.value('@IsDeleted', 'bit') As IsDeleted
INTO #tmp
FROM @xml.nodes('Credentials/Credential') x(item)

BEGIN TRY
BEGIN TRAN
      INSERT INTO Credentials (AgentID, Username, [Password])
          SELECT
              AgentID, Username, [Password]
          FROM
              #tmp
          WHERE
              ID = 0 AND IsDirty = 1
      UPDATE c
      SET c.[AgentID] = t.AgentID,
          c.[Username] = t.Username,
          c.[Password] = t.[Password]
      FROM
          [dbo].[Credentials] c
      JOIN 
          #tmp t ON t.Id = c.ID
      WHERE
          t.IsDirty = 1 AND t.IsDeleted = 0

      DELETE FROM [dbo].[Credentials]
      FROM [dbo].[Credentials] c
      JOIN #tmp t ON t.Id = c.ID
      WHERE 
          t.IsDirty = 1 AND t.IsDeleted = 1

      COMMIT TRAN
END TRY
BEGIN CATCH

      IF @@TRANCOUNT > 0
            ROLLBACK TRAN

      DECLARE @errorMSG varchar(4000)
      DECLARE @errorSeverity int
      DECLARE @errorState int

      SET @errorMSG = ERROR_MESSAGE()
      SET @errorSeverity = ERROR_SEVERITY()
      SET @errorState = ERROR_STATE()

      RAISERROR (@errorMSG,
                        @errorSeverity, @errorState);

END CATCH

SELECT [ID], [AgentID], [Username], [Password]
FROM [dbo].[Credentials]

コード ビハインドでは、xml があり、xml をパラメーターとしてストアド プロシージャに渡します。

// read xml and assign it to string variable
string xml = readxml();

try
{
    string command = "EXEC SaveCredentails '" + xml + "'";
}
catch(Exception e)
{
}
于 2012-05-02T08:27:50.713 に答える