質問
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コマンドテキストを調べて、上記のキーワードのいずれかで始まるかどうかを確認し、それに応じて行動する必要があります。