3

つまり、SQL Server (2008) データベースに XML 一括読み込みを実行し、子で使用できる親の自動インクリメント ID を生成したいと考えています。これはスコープによって制限されているようです: 親ノードは完成していないため、まだ挿入されていません。誰もこれを回避する方法を知っていますか?

詳細な説明(申し訳ありませんが、非常に長いですが、私は完全にしようとしています):

顧客から、テスト DB を生成するための類似した構造を持つ XML ドキュメントをたくさん受け取りました。それらは別のツールで使用するためにエクスポートされます。私の顧客には、構造や内容に影響を与える権限も連絡先もありません。(ツールは別の関係者が親会社のために作成したものです。) また、エクスポート元の XML やデータベースの正式な説明もありません。

「トップ」の XML ノード<Registration>には ID がありますが、これらはドキュメント全体で一意ではないことがわかります。(トップ ノードは相対的であり、ルート ノードとリスト ノードがありますが、XML ではデータベースに到達する最上位の要素です。) ID は他の XML ドキュメントで使用される場合があります。<Case>エクスポートに含まれていない別のオブジェクトに。<Registration>したがって、ファイル間でもすべての要素を一意に保つために、auto-increment-id を生成する必要があります。

私の<Registration>-node には、 -node などの多くの娘がい<Activity>ます。これらのノードは親を参照する必要があるため、生成された auto-increment-id を使用する必要があります。ただし、これらは未完成の親ノードの一部であるため、親ノードはまだスコープ内にあり、 msdnおよびtechnetの「レコード サブセットとキーの順序付け規則」で説明されているように、まだテーブルに挿入されていません。ただし、これらのサイトの例にCustomerIdは、自動生成された ID ではなく、明示的な unique があります。

「キーの順序付けルール」に関するこのドキュメントでは、これを行うことができないように見えますが、(一意の) ID がない XML ファイルに対してこれを回避する方法がないとは信じられません。さらに奇妙なのは、子に親 ID を挿入することですが、その数は 1 つ小さいことです。したがって、これは前のスコープの auto-increment-id であると想定しています (ここで、0 はまだ何も挿入されていないデフォルトであり、NULL を想定していました)。したがって、回避策が 1 つあります。その後、子テーブルの親キーをインクリメントします ( UPDATE Activity SET RegistrationId = RegistrationId + 1)。ただし、これには制限 ( ) を維持する必要がありWHERE TimeStamp > ...、他の (手動またはスクリプトによる) 介入は必要ありません。

私は多くの異なるリレーションシップと VB スクリプトを試しました (たとえば、テーブルの自動生成を好みます) が、最新の試みを投稿します。これは、前のスコープからの auto-increment-id の挿入を説明するのにも役立ちます。

私の主な問題は次のとおりです。

  • 自動インクリメントされた正しい親 ID を取得することは可能ですか?

ただし、次のような他のヒントは大歓迎です。

  • CREATE TABLESQLで明示的なステートメントなしで自動インクリメントIDを自動生成するために使用する設定は何ですか?

テーブルを生成します。

CREATE TABLE [dbo].[Registration](
  [Id] INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Registration PRIMARY KEY,
  [XmlId] [nvarchar](40) NULL,
)
CREATE TABLE [dbo].[Activity](
  [Id] INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Activity PRIMARY KEY,
  [RegistrationId] INT CONSTRAINT FK_Activity_Registration FOREIGN KEY (RegistrationId) REFERENCES Registration (Id),
  [XmlId] [nvarchar](1000) NULL,
)

インポートする XML ファイル:

<Updates>
  <Registrations>
    <Registration ID="NonUniqCaseId-123">
      <Activities>
        <Activity ID="UniqActId-1234" />
        <Activity ID="UniqActId-1235" />
      </Activities>
    </Registration>
    <Registration ID="NonUniqCaseId-124">
      <Activities>
        <Activity ID="UniqActId-1241" />
        <Activity ID="UniqActId-1242" />
      </Activities>
    </Registration>
  </Registrations>
</Updates>

アップロードをテストする VB スクリプト (複数のファイルを処理するために、後でプログラムにループを含めたい):

    Dim objBL 
Set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkload.4.0")
objBL.ConnectionString = "provider=SQLOLEDB;data source=localhost;database=Test;integrated security=SSPI"
objBL.ErrorLogFile = "error.log"

objBL.CheckConstraints = False
objBL.XMLFragment = False
objBL.SchemaGen = True
objBL.SGDropTables = False
objBL.KeepIdentity = False

objBL.Execute "BulkTestMapping.xsd", "BulkTestContents.xml"
Set objBL = Nothing

XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
    attributeFormDefault="qualified"
    elementFormDefault="qualified"
    xmlns:sql="urn:schemas-microsoft-com:mapping-schema">

  <xs:annotation>
    <xs:appinfo>
      <sql:relationship name="Registration_Activity"
            parent="Registration"
            parent-key="Id"
            child="Activity"
            child-key="RegistrationId"
            inverse="true"
            />
    </xs:appinfo>
  </xs:annotation>

  <xs:element name="Registration"
              sql:relation="Registration"
              sql:key-fields="Id" 
            >
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Activities" minOccurs="0" maxOccurs="unbounded" sql:is-constant="true">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Activity" minOccurs="0" maxOccurs="unbounded"
                     sql:relation="Activity" 
                     sql:key-fields="RegistrationId"
                     sql:relationship="Registration_Activity"
              >
                <xs:complexType>
                  <xs:attribute name="ID" sql:field="XmlId" form="unqualified" type="xs:string" />
                  <xs:attribute name="DbId" sql:identity="ignore" sql:field="Id" msdata:AutoIncrement="true" msdata:ReadOnly="true" type="xs:int" /> 
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="ID" form="unqualified" sql:field="XmlId" />
      <xs:attribute name="DbId" sql:identity="ignore" sql:field="Id" msdata:AutoIncrement="true" type="xs:int" /> 
    </xs:complexType>
  </xs:element>
</xs:schema>

結果のテーブル (1 つずれていることに注意してくださいRegistrationId):

[Registration]
Id  XmlId
1   NonUniqCaseId-123
2   NonUniqCaseId-124

[Activity]
Id  RegistrationId  XmlId
1   0   UniqActId-1234
2   0   UniqActId-1235
3   1   UniqActId-1241
4   1   UniqActId-1242

編集:思ったよりも悪いです。再度レコードを追加すると、外部キー (子キー) は再び 0 から始まります。したがって、(テーブルごとに) どのような修正を行うべきかを判断するのは、困難から不可能になるでしょう。

[Registration]
Id  XmlId
1   NonUniqCaseId-123
2   NonUniqCaseId-124
3   NonUniqCaseId-123
4   NonUniqCaseId-124

[Activity]
Id  RegistrationId  XmlId
1   0   UniqActId-1234
2   0   UniqActId-1235
3   1   UniqActId-1241
4   1   UniqActId-1242
5   0   UniqActId-1234
6   0   UniqActId-1235
7   1   UniqActId-1241
8   1   UniqActId-1242
4

2 に答える 2

0

XMLでの一括読み込みがわからないので、代わりにTSQLを使用してこれを行うための答えを次に示します。

SQL Server 2008では、マージを出力と組み合わせて使用​​して、ソースデータとターゲットの自動生成ID間のマッピングを作成できます。

merge..outputを使用して、source.idとtarget.idの間のマッピングを取得します

Dr. OUTPUTまたは:心配をやめてMERGEを愛することをどのように学んだか

この場合Registration、生成されたIDを持つ子XMLノードを一時テーブルまたはテーブルvariablにマージして出力し、そのテーブルをへの挿入に使用できますActivity

SQLフィドル

MS SQL Server 2008スキーマのセットアップ

CREATE TABLE [dbo].[Registration](
  [Id] INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Registration PRIMARY KEY,
  [XmlId] [nvarchar](40) NULL,
);

CREATE TABLE [dbo].[Activity](
  [Id] INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Activity PRIMARY KEY,
  [RegistrationId] INT CONSTRAINT FK_Activity_Registration FOREIGN KEY (RegistrationId) REFERENCES Registration (Id),
  [XmlId] [nvarchar](1000) NULL,
);

クエリ1

declare @XML xml = '
<Updates>
  <Registrations>
    <Registration ID="NonUniqCaseId-123">
      <Activities>
        <Activity ID="UniqActId-1234" />
        <Activity ID="UniqActId-1235" />
      </Activities>
    </Registration>
    <Registration ID="NonUniqCaseId-124">
      <Activities>
        <Activity ID="UniqActId-1241" />
        <Activity ID="UniqActId-1242" />
      </Activities>
    </Registration>
  </Registrations>
</Updates>';

declare @T table
(
  RegistrationId nvarchar(40),
  Activities xml
);

merge Registration as T
using
  (
  select R.N.value('@ID', 'nvarchar(40)') as XmlId,
         R.N.query('Activities') as Activities
  from @XML.nodes('/Updates/Registrations/Registration')  as R(N)
  ) as S
on 0 = 1
when not matched then
  insert(XmlId) values (S.XmlId)
output inserted.Id, S.Activities into  @T(RegistrationId, Activities);

insert into Activity(RegistrationId, XmlId)
select T.RegistrationId,
       A.N.value('@ID', 'nvarchar(1000)')
from @T as T
  cross apply T.Activities.nodes('Activities/Activity') as A(N);

クエリ2

select *
from Registration;

結果

| ID |             XMLID |
--------------------------
|  1 | NonUniqCaseId-123 |
|  2 | NonUniqCaseId-124 |

クエリ3

select *
from Activity;

結果

| ID | REGISTRATIONID |          XMLID |
----------------------------------------
|  5 |              1 | UniqActId-1234 |
|  6 |              1 | UniqActId-1235 |
|  7 |              2 | UniqActId-1241 |
|  8 |              2 | UniqActId-1242 |
于 2012-11-26T16:35:39.873 に答える
0

答えは非常に単純であることがわかります。 の を省略して、inverse次のXSD行を削除します。

inverse="true"

私は多対多の関係をたくさん持っているので、これを紹介しました。(私の例は、問題を再現するための非常に短い抜粋です。)しかし、あまりにも多くの場所で導入したようです。

憶測: (残念ながら、この次の仮説を調査/確認する時間がありません。)

私は今、それは母親である側ではなく、関係の娘である側にのみ使用されるべきであると仮定していますinverse. たとえば、A と B に多対多の関係 A_B があり、XML は次のようになります。

<ListOfA>
  <A ID="Uniq_A123">
    <A_B>
      <B ID="NonUniq_B234" />
    </A_B>
    <A_B>
      <B ID="NonUniq_B235" />
    </A_B>
  </A>
  <A ID="Uniq_A124">
    <A_B>
      <B ID="NonUniq_B234" />
    </A_B>
  </A>
</ListOfA>

A は、XML の母であることにより、暗黙的に A_B の関係の「親」であり、B は、指定することにより、子から親に明示的に反転する必要がありますinverse。ただし、A と B の独自の ID を生成しているため、これが機能するかどうかは疑問であり、後で修復クエリを実行するだけです。

于 2012-11-28T14:31:50.353 に答える