7

SQL Server バックエンドを使用する Microsoft Access 2007 では、通常、SQL Server からリンクされたテーブルを、単一のテーブル データ変更用の編集可能なフォームの Form.RecordSource として取得します。ローカル クエリは、複数のリンクされたテーブルのフィールドを結合するクロス テーブル エディションに使用されます。編集フォームでデータを変更するには、ローカル クエリ自体が更新可能である必要があります。

現在、ネイティブ SQL Server テーブルを直接使用するために、すべてのローカル クエリをパススルー クエリに置き換えることを計画しています。

次の SQL 文字列を使用して、qrySelProductsPassThroughEditable という名前の非常に単純なパススルー クエリを作成しようとしました。

SELECT dbo.Products.ID, dbo.Products.Name FROM dbo.Products;

ID フィールドは、定義として SQL Server でプライマリ キーとして定義されている IDENTITY フィールドです。

CREATE TABLE [dbo].[Products](
    [ID] [int] IDENTITY(1,1) NOT NULL,
        ....
)

ただし、Access パススルー クエリによって返されるデータシートはまったく編集できません。したがって、編集フォームの .RecordSource としても使用できません。

これは、パススルー クエリに関連するすべてのテーブルのすべての主キーが含まれている場合、クエリが編集可能になるというリンクとは対照的です。

結論 事後論を追加

以下の説明では、Microsoft Access 2007 の .accdb、.accde、または .accdr (Access ランタイム) のパススルー クエリは常に読み取り専用であり、編集することはできません。これは、リンク テーブルを使用する必要があるフォームや、データ IO 用のリンク テーブルを含む書き込み可能な通常のクエリではなく、最終的なリストとして、またはレポートの .RecordSource として使用する必要があります。

4

4 に答える 4

6

上記の私のコメントと Yawar の回答に沿って、パス スルー クエリが編集可能/更新可能であることを認識していません。保存された Pass Through Query オブジェクトを編集できるという意味では編集可能ですが、Pass Through Query で編集可能なレコードセットを作成できるとは思えません。

Access を Access 以外のデータ ソースに接続するには、基本的に 2 つの方法があります。

最初の最も一般的な方法は、何らかの形式のリンク テーブル (通常は ODBC リンク テーブル) を使用する方法です。MS Access で ODBC リンク テーブルを使用するにはさまざまな方法がありますが、ほとんどの開発者は、アプリケーションの起動時に更新または再構築 (削除および再接続) される DSN レス接続を使用することを好みます。ODBC を使用するときは、DAO も使用していることに注意してください。DAO は MS Access に組み込まれている既定のデータ アクセス オブジェクトであり、特に DAO コードを記述しなくても、MS Access は内部で DAO を使用して、フォーム、レポート、およびクエリをデータ ソースにリンクしています。ODBC の場合、実際には、DAO と ODBC という 2 つのデータ アクセス層が機能することになります。ただし、ODBC/DAO はかなりまともなパフォーマンスで、コードを書かなくても (ODBC リンク テーブルを維持する以外は) 使用できます。

2 番目の方法は、ADO を使用することです。一般に信じられていることとは反対に、これはバインドされていないフォームを使用する必要があるという意味ではありません。ただし、JET/DAO/MSAccess または DAO/ODBC/SSQL Server を使用するよりも多くのコードを記述する必要があることを意味します。データベースから ADO Recordset にレコードを取り込むコードを記述し、コードを使用してフォームをその Recordset にバインドする必要があります。子フォームを親フォームと同期させたり、新しいレコードが作成されたときに外部キーを子フォームに挿入したり、フォームの組み込みのフィルタリングや並べ替えとしてのフィルタリングや並べ替えなど、さまざまなことのために、より多くのコードを記述する必要があります。オプションは通常、ADO レコードセットでは機能しません。ADO は、実際に多くの制御を提供するため、SQL Server と対話するための優れた方法ですが、コードが集中的であり、ODBC リンク テーブルが非常にうまく機能するため、ほとんどの開発者は、やりたいことを実行する方法が他にない場合を除き、ADO の使用をお勧めしません。この 1 つの例は、ストアド プロシージャの呼び出しです。パススルークエリを使用してストアドプロシージャを呼び出すことができると思いますが、いくつかの制限があると思います (パラメーターの使用など)。ほとんどの場合、開発者は ADO を使用してストアド プロシージャを呼び出すと思います。私は ADO をよく使用しますが、ストアド プロシージャはあまり (まだ) 使用していないため、それに関する情報はあまりありません。

言及する価値のあるもう 1 つのことは、ODBC を使用する DAO は「遅延読み込み」を使用しますが、ADO はすべてのデータをプルすることを強制するため、数百万行を超える場合、非常に時間がかかり、大量のメモリを消費する可能性があります。そうしないと、何らかのページングを実装する必要があります。

単一の DSN レス ODBC リンク テーブルを作成する独自の関数を以下に示します。Access と VBA を初めて使用する場合、これはおそらくあまり意味がありません。このコードは、リンクしようとしているテーブルに対して既に存在するテーブル定義をすべて削除します。これは、ローカルのリンクされていないテーブルを削除する可能性があるため、少し危険です。ここでのエラー処理もあまり高速ではありませんが、オンラインのサンプル コードのほとんどは、複雑な問題が発生するため、適切なエラー処理を行っていません。リンク テーブルでの主キー インデックスの作成は、必ずしも必要ではありません。特定のプロジェクトで一度必要だったので、機能に組み込みましたが、今はそこに残して、良くも悪くも使用しています。

このコードを適切に使用するには、リンクされたすべてのテーブルのリストをどこかに用意し、そのリストを繰り返し処理して、テーブルごとにこの関数を呼び出す必要があります。この関数を使用すると、SQL Server での実際の名前とは異なる名前を使用してテーブルをリンクできます。また、この関数に渡す必要がある有効な ODBC 接続文字列を作成する方法も必要です。

Private Sub LinkODBCTable(sSourceTableName As String, _
                        sLocalTableName As String, _
                        sPrimaryKeyField As String, _
                        sConString As String)

    Dim dbCurrent As DAO.Database
    Dim tdfCurrent As DAO.TableDef
    Set dbCurrent = DBEngine.Workspaces(0).Databases(0)

    On Error Resume Next
    'Be Careful, this could delete a local, non-linked table.
    dbCurrent.TableDefs.Delete sLocalTableName
    If Err.Number <> 0 Then
        If Err.Number = 3011 Then
            'Table does not exist
        Else
            MsgBox "Error in LinkODBCTable" & vbCrLf & vbCrLf & Err.Number & " " & Err.Description
        End If
        Err.Clear
    End If

    On Error GoTo 0

    Set tdfCurrent = dbCurrent.CreateTableDef(sLocalTableName)
    tdfCurrent.Connect = sConString
    tdfCurrent.sourceTableName = sSourceTableName
    dbCurrent.TableDefs.Append tdfCurrent

    On Error Resume Next
    If sPrimaryKeyField <> "" Then
        dbCurrent.Execute "CREATE INDEX __UniqueIndex ON [" & sLocalTableName & "] (" & sPrimaryKeyField & ")", dbFailOnError
        If Err.Number <> 0 Then
            If Err.Number = 3283 Then
                'Primary Key Already Exists
            Else
                MsgBox "Error in LinkODBCTable" & vbCrLf & vbCrLf & Err.Number & " " & Err.Description
            End If
            Err.Clear
        End If
    End If

    Set tdfCurrent = Nothing
    Set dbCurrent = Nothing
End Sub

DAO、ADO、パス スルー クエリ、SQL Server などに関して、チェックすべき非常に優れたリソースがいくつかあります。

http://technet.microsoft.com/en-us/library/bb188204%28v=sql.90%29.aspx
http://www.utteraccess.com/wiki/Choosing_between_DAO_and_ADO

フォームを ADO レコードセットにバインドする例を次に示します。ただし、アプリケーションの実行時に開いたままのグローバル接続オブジェクトを使用するのが最善であるため、少し誤解を招く可能性があります。これにより、自動的に更新可能な ADO レコードセットを使用できます。この方法を使用すると、レコードセットがフォーム レベル オブジェクトになる場合もあります。

http://msdn.microsoft.com/en-us/library/office/bb243828%28v=office.12%29.aspx

于 2013-09-19T21:43:58.053 に答える
5

MsAccess クエリ ウィンドウで任意の SQL Server Select ステートメント (テーブル、ビュー、または多くの結合されたテーブルを含む sql-select) を開き、編集可能/更新可能にする、十分に文書化されていない簡単な方法があります。

Access クエリ ウィンドウを開き、SQL ステートメントを入力します。次の例のように、テーブル名を角かっこ内の SQL Server への完全な ODBC 文字列に置き換え、その後にドットとスキーマおよびテーブル名を続けます。

前:

SELECT SOH.SalesOrderID, SOH.OrderDate
FROM   Sales.SalesOrderHeader as SOH 

後:

SELECT SOH.SalesOrderID, SOH.OrderDate
FROM   [ODBC;Driver=SQL Server;Server=myServer;Database=AdventureWorks2012;Trusted_Connection=Yes;MarsConn=yes;].Sales.SalesOrderHeader as SOH 

クエリが更新可能になりました。 Access Query ウィンドウには、SQL Select ステートメントに従って SQL Server からのデータが表示されます。

備考:

  • すべての SQL ステートメントがテーブルまたはビューを更新可能にするわけではありません。制限事項については、CREATE VIEW (Transact-SQL) ( https://msdn.microsoft.com/en-us/library/ms187956.aspx ) の「更新可能なビュー」セクションを参照してください。
  • Access で更新可能にする基になるテーブルには、タイムスタンプまたは RowVersion 列が必要です。
于 2015-09-03T11:18:21.873 に答える
1

パススルー クエリの結果セットは編集できませんが、リンク テーブルに基づく Access クエリは編集できます。

于 2013-09-19T19:05:34.480 に答える
0

はい、「2番目の方法はADOを使用することです」と、LinkMasterFieldsおよびLinkChildFieldsプロパティがマルチフォームで機能せず、ADOレコードセットがAccess 2013レポートで機能しないため、パススルークエリを使用しています。ADP+ ADPX.accde を使用して、複数フォームおよび複数レポートで LinkMasterFields および LinkChildFields プロパティをシミュレートしています。

于 2014-09-14T13:50:03.780 に答える