2

私はMSAccessバックエンドデータベースのスイートをSQLServerにアップサイジングすることに取り組んでいます。SQLのスクリプトを作成して、SQLServerでテーブルスキーマを作成しました。今、私はテーブルにデータを入力しようとしています。ほとんどのテーブルには自動番号付けの主キーがあります。これが私の一般的なアプローチです:

For each TblName in LinkedTableNames
    'Create linked table "temp_From" that links to the existing mdb'
    'Create linked table "temp_To" that links to the new SQL server table
    ExecutePassThru "SET IDENTITY_INSERT " & TblName & " ON"
    db.Execute "INSERT INTO temp_To SELECT * FROM temp_From", dbFailOnError
    ExecutePassThru "SET IDENTITY_INSERT " & TblName & " OFF"
Next TblName

最初の挿入はすぐに行われます。その後の挿入試行は、「IDENTITY_INSERTがOFFに設定されている場合、テーブル'TblName'のID列に明示的な値を挿入できません。」というエラーで失敗します。

その特定のエラーとタイマーのResumeステートメントを追加しました。エラーが正確に600秒(10分)続くことがわかり、その後、挿入は正常に続行されます。

MS AccessはODBCセッションを10分ごとに自動的に更新しますか?それをより速く発生させる方法はありますか? 明らかな何かが欠けていますか?

「アップサイジングウィザードを使用する」とすぐに言いたい人のための背景情報:
操作全体を最初から最後までスクリプト化できる必要があるため、組み込みのアップサイジングウィザードを使用していません。目標は、クライアントの場所でスイッチを実行する前に、これをテスト環境で実行することです。

4

3 に答える 3

2

最初の質問に対する答えを見つけました。10分は、Jetエンジンキーの下のレジストリに埋め込まれた設定です。

'Jet WinXP/ Win7 32-bit:'
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\ODBC\ConnectionTimeout

'Jet Win7 64-bit:'
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\ODBC\ConnectionTimeout

'ACE WinXP/ Win7 32-bit:'
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Access Connectivity Engine\Engines\ODBC\ConnectionTimeout

'ACE Win7 64-bit:'
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MicrosoftAccess Connectivity Engine\Engines\ODBC\ConnectionTimeout

ACEについては、ここに文書化されています。

ConnectionTimeout:キャッシュされた接続がタイムアウトする前にアイドル状態を維持できる秒数。デフォルトは600です(値のタイプはREG_DWORDです)。

このキーはデフォルトの600に設定されています。これは600秒または10分です。これを10秒に短縮すると、それに応じてコードが高速化されました。

デフォルトをlowに設定すると、他の場所で問題が発生する可能性があるため、これは完全な解決策ではありません。実際、Tony Toewsはかつて、 DSNなしの接続を使用する場合は、デフォルトを増やす方がよいと推奨していました。

私はまだ私の質問の2番目の部分への答えを見つけることを望んでいます。つまり、更新をより速く実行するように強制する方法があります。


更新:これが必要な理由は、リンクされたテーブルがADOパススルークエリとは異なるセッションを使用するためです。SQLプロファイラーを使用してテストを実行しました。ここにいくつかの簡単な結果があります:

TextData                               SPID
-------------------------------------------
SET IDENTITY_INSERT dbo.TblName ON       50
SET IDENTITY_INSERT "dbo"."TblName" ON   49
exec sp_executesql N'INSERT INTO "d...   49
SET IDENTITY_INSERT dbo.TblName OFF      50
SET IDENTITY_INSERT dbo.NextTbl ON       50
SET IDENTITY_INSERT "dbo"."NextTbl" ON   49
exec sp_executesql N'INSERT INTO "d...   49

ここで起こっていることは、私のADOコマンドがリンクされたテーブル(#50)とは異なるセッション(#49)で実行されていることです。Accessは、ID列の値を設定していることを確認したため、そのテーブルのIDENTITY_INSERTONを設定すると便利です。ただし、IDENTITY_INSERTOFFを設定することはありません。手動でオフにしますが、それは別のセッションで発生しています。

これは、ODBCセッションタイムアウトを低く設定することが機能する理由を説明しています。これは、AccessがテーブルのIDENTITY_INSERTをオンにすると、オフにしないという事実に対する醜い回避策にすぎません。IDENTITY_INSERTはセッション固有であるため、新しいセッションを作成することは、IDENTITY_INSERTのリセットボタンを押すようなものです。その後、Accessは次のテーブルでそれをオンにすることができ、これはまったく新しいセッションであるため、設定が有効になります。

于 2011-08-08T21:11:20.083 に答える
1

これは私にとってなじみのない領域であるため、どちらが役立つかはわかりませんが、2つの考えがあります。

MSAccessは10分ごとにODBCセッションを自動的に更新しますか?それをより速く実行するように強制する方法はありますか?明らかな何かが欠けていますか?

[Access 2003オプション]ダイアログの[詳細設定]タブには、[ODBC更新間隔]の設定と再試行の設定があります。それらを調整することは助けになりますか...またはまったく効果がありますか?

SQL Serverの列を自動番号ではなくプレーンな数値として作成し、データを挿入してから、ALTER TABLE ... ALTER COLUMNを作成して、データの挿入後に列を変更することで、この問題を回避できるでしょうか。

テーブルにデータが含まれている場合、Accessでは数値列を自動番号に変換できませんが、ISTRSQLServerはそのスコアに対してより柔軟です。

于 2011-08-08T20:13:29.987 に答える
0

多くのアクセステーブルをSQLサーバーにエクスポートし、identity_insertの問題を回避するための、便利でありながらそれほど美しくないソリューションを見つけました。

  1. エクスポートするすべてのテーブルを一覧表示するローカルテーブルレコードセットを開き、レコード(各テーブル)をループします。各ループで私は...

  2. アクセスアプリケーションオブジェクトを作成する

  3. アプリケーションオブジェクトでデータベース転送メソッドを使用する

  4. アプリケーションオブジェクトを終了/終了し、再度ループします

サンプルコードは次のとおりです。

Public Sub exporttables()
Dim rst As Recordset
Dim access_object

'First create a local access table which lists all tables to be exported'
Set rst = CurrentDb.OpenRecordset("Select txt_tbl from ####your_table_of_tables####")

 With rst
 While Not .EOF
    'generate a new object to avoid identity insert problem'
    Set access_object = CreateObject("Access.Application")
    'with access object open the database which holds the tables to be exported'
    access_object.OpenCurrentDatabase "####C:\yoursourceaccessdb####.accdb"
    access_object.DoCmd.TransferDatabase acExport, "ODBC Database", "ODBC;DSN=####your connection string to target SQL DB;", acTable, .Fields("txt_tbl"), .Fields("txt_tbl"), False, False
    Debug.Print .Fields("txt_tbl") & " exported"
    access_object.CloseCurrentDatabase
    access_object.Application.Quit
    Set access_object = Nothing
    .MoveNext
Wend
End With

Set rst = Nothing
End Sub
于 2022-01-31T16:25:22.653 に答える