AccScan
技術

Accessエラー3061「パラメータが少なすぎます」の原因と直し方

エラー3061「Too few parameters. Expected N.」の原因は、クエリ内のフィールド名の綴り誤り・角括弧の欠落・フォームコントロールへの参照解決失敗の3類型。DAOのOpenRecordset前にQueryDef.Parametersへ値をセットする修正コードも解説します。

まずは、自社のAccessが「解析できるか」を無料で確認できます。

約2分・ファイル送信不要・発注義務なし

結論:クエリに「値が渡されなかったパラメータ」があるのが原因

実行時エラー3061「パラメータが少なすぎます。N を指定してください。」(英語メッセージ: "Too few parameters. Expected N.")が出るのは、クエリが要求したパラメータのうちN個分の値が実行時に渡されなかったときです。「N個」は、値が来なかったパラメータの数です。

パラメータになる経緯は2種類あります。一つは、クエリ内でフィールド名を綴り間違えたり角括弧を付け忘れたりして、Accessがその名前をフィールドとして認識できずパラメータとみなすケース(暗黙パラメータ)。もう一つは、意図的にパラメータクエリを使っているのにVBAからパラメータ値を渡さずに開こうとするケースです。

Microsoft公式ドキュメントには「フィールド名に空白や句読点が含まれる場合は角括弧 [ ] で囲むこと、未知のフィールド名や式がパラメータとして解釈される場合がある」と明記されています(Too few parameters. Expected <number>. (Error 3061) — Microsoft Learn)。まず「SQLの中に解決できない名前がないか」「パラメータ値を渡しているか」の2点を確認します。

エラー3061が起きる主な原因

同じエラー番号でも、背景によって原因が違います。次の表で自分の状況に近いものを確認してください。

原因典型的な状況確認ポイント
フィールド名の綴り誤り(暗黙パラメータ)SQLを手書きしたとき、コピーして修正したときクエリをデザインビューで開き、各フィールドの綴りをテーブルの列名と目視確認する
フィールド名に空白・記号が含まれるのに [ ] がない(暗黙パラメータ)「注文 番号」「売上-合計」など空白やハイフンを含む列名を使っている該当フィールドを [注文 番号] のように角括弧で囲む
VBAからクエリを開く際にパラメータ値を渡していないCurrentDb.OpenRecordset("クエリ名") だけで開こうとしている(パラメータクエリ・フォーム参照クエリ問わず)QueryDefオブジェクト経由でParametersに値をセットしてからOpenRecordsetを呼ぶ
フォームのコントロールを参照しているがDAOからは解決されないクエリが Forms!フォーム名!コントロール名 を参照している。DAOで開く場合、フォームが開いていても自動評価されないQueryDefのParametersにEvalで値をセットするか、SQL文に値を埋め込む形に変更する
削除・変更したフィールド名がクエリにまだ残っているテーブルのフィールド名を変更したが、そのテーブルを参照するクエリを修正し忘れたクエリをSQLビューで開き、テーブルに実在するフィールド名と照合する

原因ごとの対処

フィールド名の綴りを確認する

エラーが出たクエリをデザインビューまたはSQLビューで開いてください。テーブルに存在しない名前があると、その名前がパラメータ欄に表示されます。デザインビューでは、テーブル欄が空欄になるケースがあります。SQLビューで確認するほうが判断しやすい場面も多いです。

フィールド名に空白や記号が含まれる場合は [フィールド名] のように角括弧で囲まないと、Accessがそれをフィールドとして正しく解釈できず、構文エラーや未解決パラメータの原因になります。SELECT [注文 番号] FROM 受注台帳 のように角括弧で囲むのが正しい形です。

フォーム参照の問題を解決する

クエリのWHERE句に Forms!フォーム名!コントロール名 という参照が含まれているとき、AccessのGUI経由でクエリを開けば参照先フォームの値を自動的に評価してくれます。ところがVBAから CurrentDb.OpenRecordset("クエリ名") で直接開くと、フォームが開いていてもGUIが介在しないため、データベースエンジン(ACE)がフォーム参照式を解決できずエラー3061になります。これはVBAのバグや設定の問題ではなく、DAOを使う場合の仕組み上の動作です。

パラメータ名がフォームのコントロール参照式(Forms!frmOrders!txtCustomerID のような形式)になっている場合は、QueryDefのParametersコレクションで Eval を使って式を評価してから開く方法が使えます。

' この方法はパラメータ名がフォームのコントロール参照式である場合に有効
' パラメータ名が "Enter a value" のような入力プロンプト文字列の場合は Eval では解決しない
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim prm As DAO.Parameter
Dim rst As DAO.Recordset

Set dbs = CurrentDb
Set qdf = dbs.QueryDefs("qryOrdersByCustomer")

For Each prm In qdf.Parameters
    prm = Eval(prm.Name)   ' 参照先のフォームが開いていることが前提
Next prm

Set rst = qdf.OpenRecordset

' 処理...
rst.Close
qdf.Close

Eval(prm.Name) はパラメータ名として格納されている式を評価して値に変換します。ただしこの方法が使えるのは、パラメータ名がAccessが評価できる式(フォームコントロール参照など)になっている場合に限ります。パラメータ名が「Enter a value」のような入力プロンプト文字列の場合は Eval で解決できないため、後述の名前指定方式で直接値をセットしてください。

クエリをデザインビューで直接開いて確認する

VBAから呼んでいるクエリをいったんナビゲーションウィンドウから直接実行してみてください(ダブルクリック、またはデザインビューで「実行」ボタンをクリック)。パラメータが未解決の名前に起因する場合は、Accessがパラメータ入力を求めるダイアログを表示します。ダイアログに表示されるパラメータ名を手がかりに、SQLの中のどの名前が解決できていないかを特定できます。

特定したら、クエリのSQLビューで該当箇所を確認し、テーブル側のフィールド名と一致させます。Accessクエリの基礎で解説しているように、クエリはテーブルのフィールド名を正確に参照する必要があります。

DAOのOpenRecordsetでよく出る理由

GUIからクエリを開く場合は、Accessの層がフォーム参照を評価してからデータベースエンジンに渡してくれます。ところが DAO.Database.OpenRecordset ではアプリケーション層を通らず、ACEエンジンに直接クエリが渡ります。エンジンはフォームの存在を知らないので、[Forms]![フォーム名]![コントロール名] を見ても解決できず「パラメータが足りない」と判断します。

VBAのエラー処理の観点からは、エラー3061が出た場合の On Error GoTo ハンドラで握りつぶすのではなく、原因のクエリとSQL自体を直すことを優先してください。握りつぶすと、取得できていないレコードセットをそのまま処理して別のエラーや不正データにつながります。

エラー番号とメッセージの一覧についてはAccessエラーメッセージ早見表もあわせて参照してください。

DAOでパラメータを渡すコードパターン

パラメータを名前で参照する書き方は、フォーム参照式かどうかに関わらず使えます。

Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset

Set dbs = CurrentDb
Set qdf = dbs.QueryDefs("qryOrdersByDateAndCustomer")

' パラメータ名はクエリのSQL内で [ ] で囲んだ名前と一致させる
qdf.Parameters("開始日") = #2025/04/01#
qdf.Parameters("顧客ID") = 101

Set rst = qdf.OpenRecordset

Do Until rst.EOF
    Debug.Print rst!受注番号
    rst.MoveNext
Loop

rst.Close
qdf.Close

パラメータ名はクエリのSQL内で定義している名前(角括弧の中の文字列)と一致させます。Parametersコレクションはゼロ基点なので、qdf.Parameters(0)qdf.Parameters(1) のようにインデックスでも参照できますが、順番が変わったときに気づきにくいので名前指定のほうが保守しやすいです。

フォーム参照を使わずVBAでSQLを組み立てる場合は、参照式をSQLに埋め込まずVBA変数として取り出してから連結する方法もあります。ただし文字列型や日付型の値を連結する場合はクォートや書式の処理が必要で、誤りやすいです。整数の主キーのような単純な数値条件以外では、パラメータクエリ+QueryDefのParametersへの値セットのほうが確実です。

クエリ実行が遅い場合は、クエリ高速化の観点でインデックスやクエリ構造も確認してみてください。

現在のAccessの状態が解析対象になるかどうか確認したい場合は、無料の解析可否チェックで目安を確認できます(ファイル送信不要です)。

よくある質問

Q. エラーメッセージの「Expected 2」の数字は何を意味しますか。

クエリが要求したものの値が渡されなかったパラメータの数です。「Expected 2」なら、値が来なかったパラメータが2つあります。綴り誤りによる暗黙パラメータの場合も、意図的に宣言したパラメータに値が渡されなかった場合も、同じ3061が出ます。エラーが出たクエリをナビゲーションウィンドウから実行するとパラメータ入力ダイアログが表示されるので、そこで表示される名前をSQLと照合すると特定しやすいです。

Q. クエリをデザインビューで開くと正常に動くのに、VBAから呼ぶとエラー3061になります。なぜですか。

フォームのコントロールを参照しているクエリが原因である可能性が高いです。デザインビューから開くとAccessがフォーム参照を評価してくれますが、VBAのDAOからはフォームが開いていてもGUIを経由しないためフォーム参照が解決されません。QueryDefのParametersコレクションに値を渡してからOpenRecordsetを呼ぶか、SQL文内の参照式をVBA変数に置き換える形に変更してください。

Q. フィールド名に間違いはないはずなのにエラー3061が出ます。

スペースや全角文字が混入しているケースがあります。フィールド名を角括弧 [ ] で囲んでみてください。また、クエリが参照しているテーブルそのものが変更・削除されている場合は、テーブルが見つからない別のエラー(3078など)が出ることがあります。リンクテーブル経由で参照している場合はリンクが切れていないか確認してください。Accessファイルが開かないときの確認手順も参考になります。

Q. エラー3061はAccess 2019と2021で同じ動作ですか。

3061の基本的な意味(パラメータ値が渡されなかった)とDAOでの対処方針は2019・2021でも一般に共通です。ただしクエリの種類や更新チャネルによる細かい差異までは当社では保証できないため、不明な場合はMicrosoft公式のドキュメントも合わせて参照してください(Error 3061 — Microsoft Learn)。

触れないAccessが「診断できるか」だけ、確かめませんか。

顧客データは送信不要。発注の義務もありません。

約2分・ファイル送信不要・発注義務なし/説明はオンライン・売り込みはしません