1

DAO を使用して、Access データベースに対して一連のクエリを実行したいと考えています。"Database.Execute()" メソッドは、結果セットを返さないクエリである "アクション クエリ" のみを実行できるという点で、これに適しているようです ( MSDN リファレンス)。レコードを返すクエリには、「Database.OpenRecordset()」を使用できます。間違ったタイプのクエリが渡されると、どちらのメソッドも例外をスローします。

リストにアクション クエリと選択クエリの両方がある場合、レコードを返すものと返さないものを事前に決定するにはどうすればよいですか?

4

5 に答える 5

1

ADO Execute メソッドは、クエリが結果セットを返すかどうかに関係なく使用できることに注意してください。

しかし、本当にすべての「クエリ」を実行しますか? それらに SQL DDL が含まれている場合はどうなりますか? PROCEDURE次のSQL DDL コードを使用してを作成したとします。

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

于 2009-09-09T15:33:33.593 に答える
1

アクセスは、クエリの種類を示す値を格納するフィールド (Flags) を含む MSysObjects と呼ばれる非表示のシステム テーブルを保持します。リストの各クエリ名で次の関数を試し、戻り値を使用して Database.Execute() または Database.OpenRecordset() のどちらを使用するかを決定できます。

関数には、MSysObjects の読み取り権限が必要です。一部の Access 2007 ユーザーが MSysObject の読み取り権限を拒否されているという報告を聞きました。ただし、Access 2007 ではその問題は発生していません。

Flags 値を決定するために、いくつかのクエリ タイプをテストしました。クエリの 1 つが私がテストしていない型である場合、関数はフラグ値を認識できないものとして返します。関数を変更して、そのフラグ型を含めることができます。

テストした唯一の DDL クエリは DROP TABLE (Flags = 96) でした。

また、すべての "SELECT ... FROM ..." クエリが目的 (レコードセットを返す) の選択クエリであるとは限らないことに注意してください。「SELECT fields INTO newtable FROM oldtable;」などのクエリ はレコードを返さず、Access UI はそれをテーブル作成クエリとして分類します。

Public Function QueryType(ByVal pQueryName As String) As String
    Dim lngFlags As Long
    Dim strType As String
    Dim strCriteria As String

    strCriteria = "[Name] = """ & pQueryName & """ And [Type] = 5"
    lngFlags = DLookup("Flags", "MSysObjects", strCriteria)

    Select Case lngFlags
    Case 0
        strType = "Select"
    Case 16
        strType = "Crosstab"
    Case 32
        strType = "Delete"
    Case 48
        strType = "Update"
    Case 64
        strType = "Append"
    Case 80
        strType = "Make Table"
    Case 96
        strType = "Drop Table"
    Case 128
        strType = "Union"
    Case Else
        strType = "Flags " & CStr(lngFlags) & " unrecognized"
    End Select

    QueryType = strType
End Function
于 2009-09-09T18:41:41.673 に答える
1

@HansUp の回答に触発されて、DAO インターフェイスによって提供される QueryDef 構造をもう少し調査しました。構造には、さまざまなクエリの種類 ( MSDN )を区別するために使用できる "Type" プロパティがあります。私は次の実装で終わった:

function TAccessDatabase.SQLExec(AName, AQuery: String): Integer;
var
  I: Integer;
  QDef: QueryDef;
  QDefExists: Boolean;
begin
  Result := 0;

  // Lookup querydef in the database
  QDefExists := False;
  for I := 0 to DB.QueryDefs.Count - 1 do
  begin
    QDef := DB.QueryDefs[I];
    if QDef.Name = AName then
    begin
      QDefExists := True;
      break; //-->
    end;
  end;

  // Create query def if it doesn't exists
  if not QDefExists then
  begin
    QDef := DB.CreateQueryDef(AName, AQuery);
    // Refresh is required to get the correct QDef.Type_
    DB.QueryDefs.Refresh;
  end;

  // Execute the query only if it is not a SELECT
  if QDef.Type_ <> dbQSelect then
  begin
    db.Execute(AQuery, dbInconsistent);
    Result := DB.RecordsAffected;
  end;
end;

参考になる回答とコメントをありがとうございました。

于 2009-09-10T08:21:14.837 に答える
0

スローされた例外をキャッチして分析してみませんか?

beginTrans/Rollback 命令を使用する方法はありますか? その後、SQL コマンドを送信し、エラーを収集してから、データベースを変更せずにトランザクションをロールバックすることができます。

接続が「エラー」コレクションを保持し、影響を受けたレコードの数などの他のデータを返す、ADO 接続よりもいくらかスマートな ADO 接続を使用するのはどうですか?

于 2009-09-10T04:51:26.777 に答える
-1

この情報は、クエリのタイプに適用されます。それで:

  • SELECT ...FROM...を実行するすべてのクエリはselectクエリです
  • すべてのINSERTUPDATEDELETEアクションクエリです

query sqlコマンドテキストを調べて、上記のキーワードのいずれかで始まっているかどうかを確認し、それに応じて動作する必要があります。

于 2009-09-09T15:27:43.747 に答える