質問

DAOを使用してAccessデータベースに対してクエリのリストを実行したい。 " Database.Execute()"メソッドは、「アクションクエリ」、つまり結果セットを返さないクエリ( MSDNリファレンス)。レコードを返すクエリの場合" Database.OpenRecordset()"に使える。間違ったタイプのクエリが渡されると、両方のメソッドは例外をスローします。

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

役に立ちましたか?

解決 3

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

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;

有益な回答と発言をありがとうございました。

他のヒント

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

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

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

;)

Accessは、クエリタイプを示す値を格納するフィールド(フラグ)を含むMSysObjectsと呼ばれる非表示のシステムテーブルを保持します。リストの各クエリ名で次の関数を試し、戻り値を使用してDatabase.Execute()またはDatabase.OpenRecordset()を使用するかどうかを判断できます

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

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

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

また、すべての&quot; SELECT ... FROM ...&quot;クエリは、目的(レコードセットを返す)の選択クエリです。 &quot; SELECT fields INTO newtable FROM oldtable;&quot;などのクエリレコードを返さず、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

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

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

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

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

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top