0

SQLServer2000とSQLServer2005の両方で提供されるDBを(現在)使用する必要があるアプリケーションがあります。

DBをプログラムで1つのサーバーから別のサーバーに移動しようとしています。私が使用するすべてのテーブルには、自動インクリメントされる主キーがあります。これらの自動インクリメントキーは他のテーブルで外部キーとして使用されるため、テーブルをコピーするための攻撃の計画は、宛先テーブルの自動インクリメントを一時的にオフにし、レコードを逐語的に(元の主キーで)挿入してから自動にすることでした。 -インクリメントし直します。

正しく理解していれば、実行することで一度に1つのテーブルで「自動インクリメントのオン/オフを切り替える」ことができます。

SET IDENTITY_INSERT tbl_Test ON;
...
SET IDENTITY_INSERT tbl_Test OFF;

私の実装はVB2005で、System.Data.SqlClientを使用しています。

簡潔にするために、SQLクエリの構築に関連するコード行のみを示します。

テーブルを作成するには:

    Dim createTableStatement As String = _
        "CREATE TABLE tbl_Test (" & _
            "ID_Test INTEGER PRIMARY KEY IDENTITY," & _
            "TestData INTEGER" & _
            ")"
    Dim createTableCommand As New SqlCommand(createTableStatement, connection)

    createTableCommand.ExecuteNonQuery()

IDENTITY_INSERTをオンまたはオフにするには:

    Dim turnOffIdentInsertStatement As String = _
        "SET IDENTITY_INSERT tbl_Test OFF;"
    Dim turnOffIdentInsertCommand As New SqlCommand(turnOffIdentInsert, connection)
    turnOffIdentInsertCommand.ExecuteNonQuery()

    Dim turnOnIdentInsertStatement As String = _
        "SET IDENTITY_INSERT tbl_Test ON;"
    Dim turnOnIdentInsertCommand As New SqlCommand(turnOnIdentInsert, connection)
    turnOnIdentInsertCommand.ExecuteNonQuery()

主キーを指定せずに、通常どおりに新しいレコードを挿入するには、次の手順に従います。

    Dim insertRegularStatement As String = _
        "INSERT INTO tbl_Test (TestData) VALUES (42);"
    Dim insertRegularCommand As New SqlCommand(insertRegularStatement, connection)
    insertRegularCommand.ExecuteNonQuery()

明示的な主キーを使用して新しいレコードを挿入するには、次の手順に従います。

    Dim insertWithIDStatement As String = _
        "INSERT INTO tbl_Test (ID_Test, TestData) VALUES (20, 42);"
    Dim insertWithIDCommand As New SqlCommand(insertWithIDStatement, connection)
    insertWithIDCommand.ExecuteNonQuery()

したがって、私の計画では、IDENTITY_ INSERTをオンにするコードを呼び出し、明示的な主キーを使用してレコードを追加してから、IDENTITY_INSERTをオフにします。

このメソッドは、SQL Server 2000と通信しているときは正常に機能しているように見えますが、SQL Server 2005に対してまったく同じコードを試してみると、例外が発生します。

"Cannot insert explicit value for identity column in table 'tbl_Test' when IDENTITY_INSERT is set to OFF."

ヒントはありますか?いつものように事前に感謝します。

4

3 に答える 3

2

バルクデータのインポートで最適化されているため、 SqlBulkCopyを確認する価値があります。

また、シナリオに応じて検討する価値があるのは、SSISタスクを使用してデータを一括コピーする(一括コピーAPIも使用する)か、BULK INSERTステートメントを使用してサーバーをリンクする(これも一括コピーAPIを使用する)ことです。

IDの設定に関しては、set identity_insertステートメントは挿入と同じ接続で実行されますか?SQL Server 2005は、現在の接続でその設定のみを保持するためです。

SQL Server 2008 Expressでは、次のように問題なく機能しました。

using (var conn = CreateConnection())
{
    conn.Open();
    new SqlCommand("SET IDENTITY_INSERT Foo ON", conn).ExecuteNonQuery();
    new SqlCommand("INSERT INTO Foo(id) VALUES (1)", conn).ExecuteNonQuery();
    new SqlCommand("SET IDENTITY_INSERT Foo OFF", conn).ExecuteNonQuery();
}
于 2009-09-08T21:36:20.723 に答える
1

ステートメントの後にGOステートメントを挿入する必要がある場合がありますSET IDENTITY ... ON

于 2009-09-08T21:16:38.713 に答える
1

SQLクエリアナライザセッションでは、IDENTITY_INSERTの後、実際の挿入の前にGOを発行します。多分これはコードからそれを呼び出すことにも当てはまりますか?

于 2009-09-08T21:17:09.770 に答える