0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ACCESS NULLの使い方

Last updated at Posted at 2025-10-19

#「NULLの使い方が不正です。」

原因

Kintone用CData ODBCは“空欄”をNULLで返す項目が多く、SQL Server時代に空文字/0として扱っていた処理(文字列連結・CInt/CDate/CStr・非Variant変数への代入等)がNULLに当たり、VBA実行時エラー94「NULL の使い方が不正です。」を起こしています。

さらに、Access側テーブルで「必須」「空文字列の許可=いいえ」の列にNULLを入れようとしても落ちます(副次要因)。

改善策(優先順)

取得直後に必ずNULLガード:文字列は Nz(x,"")、数値は Nz(x,0)、日付は Nz(x,#1899/12/30#);型変換前(CInt/CDate/CStr等)にもNz/IsNullを噛ませ、代入先はVariantに。

挿入クエリでもNULL対策:INSERT … SELECT Nz([Col],'') AS Col …/パラメータはNULL許容列なら .Value = Null を明示。

テーブル定義の見直し:文字列列は「空文字列の許可=はい」、必要に応じて既定値(0,"",日付)を設定。

ドライバ側設定の確認:Kintone ODBCの公開プロパティ一覧(v25.0.9376)に“空文字⇄NULL自動変換”の項目は見当たりません(他ドライバには PushEmptyValuesAsNull 等が存在)。DSNの[Other]/最新ドキュメントで該当が無ければ、アプリ側のNzで吸収が堅実です。

切り分け:SELECT COUNT(*) FROM [Kintoneリンク表] WHERE [Col] IS NULL; でNULLになる列を特定し、そこだけNzや既定値を適用。

ポイント

“SQL Serverでは空文字、KintoneではNULL”という差を潰すのが肝です。まずはエラー箇所直前の値を Debug.Print VarType(…) で確認→該当列にNzを入れる、で解消します。

①「ACCESS で JOIN 式をサポートしていません」の主な原因(網羅的に把握して対策可能な範囲)

Memo/Long Text(長いテキスト)/OLE/Hyperlink列で結合している(ODBCリンクでVARCHAR(>255)がLong Textに昇格しやすい)。これらは結合キーに不可。
Microsoft Learn
+2
Oracle Docs
+2

結合キーのデータ型不一致(文字列×数値/日付など)。Accessは「類似のデータ型」同士の結合が前提。
Microsoft Learn

ON句に“定数条件”を混在(例:... ON A.ID=B.ID AND B.Flg=True)。Accessはこの形をしばしば不許可と解釈するため、定数条件はWHEREへ退避が安全。
Stack Overflow

複数JOINや複合ON条件での括弧不足/括弧配置不正。AccessはJOIN/ONのかたまりを括弧で明示する必要がある。
Microsoft Learn
+2
Stack Overflow
+2

JOINの入れ子制約:LEFT/RIGHTの中にINNERはOKだが、INNERの中にLEFT/RIGHTは不可。書き換え(JOIN順や種類の調整)が必要。
Database Administrators Stack Exchange

**不等号結合(非等値JOIN)**をONで直接書くと不サポート扱い。クロス結合+WHEREなどに分解して表現。
マイクロソフトサポート

予約語/スペース/記号を含むオブジェクト名(例:Eventsや空白入りのテーブル名)で角括弧未使用。[Events Table]のように角括弧で明示。
Microsoft Learn
+1

JOINの省略形(JOIN単独)を使用。AccessはINNER JOIN表記が必須
Database Administrators Stack Exchange

ODBC越しの結合でドライバが列をMemo化/制限し、結果的に上記制約に該当(特にCData等)。結合用に長文列を255文字へ落とす下位クエリが必要。
community.cdata.com

② ON句のCSTR・NZが原因か?(結論と安全策)

結論:CStr/Nzだから即NGではない。Accessは関数を含むON句自体は許容するが、括弧不足や定数条件混在、外部結合の順序制約、Long Textが絡むと**「JOIN式をサポートしていません」**になりやすい。
Stack Overflow
+1

OKにするコツ

ON全体を括弧で包む:... JOIN T ON (CStr(A.X)=B.Y AND Nz(B.Z,0)=0) のように。
Stack Overflow

定数条件はWHEREへ移す(外部結合なら WHERE B.条件 OR B.キー IS NULL などで外部結合の意味を保持)。
Stack Overflow

型合わせは下位クエリで事前に:
例)SELECT LEFT(LongTextCol,255) AS KeyTxt, ... FROM Src を作り、その結果にJOIN。Long Textを直接ONに置かない。
Microsoft Learn
+1

LEFT/RIGHTとINNERの入れ子を守る(必要ならJOINの順序・種類を組み替え)。
Database Administrators Stack Exchange

悪い例(定数混在):
... INNER JOIN T2 ON A.ID=T2.ID AND T2.Flg=True → エラー化しやすい。
Stack Overflow

良い例(定数はWHERE、ONは等値のみ):

... INNER JOIN T2 ON (A.ID = T2.ID)
WHERE T2.Flg=True
``` (LEFT JOINなら WHERE T2.Flg=True OR T2.ID IS NULL などで保持)。:contentReference[oaicite:15]{index=15}

型変換を下位で:

SELECT *
FROM A
INNER JOIN (SELECT LEFT(KeyLong,255) AS KeyTxt, ... FROM B) AS Bx
ON (CStr(A.Key)=Bx.KeyTxt);

contentReference[oaicite:16]{index=16}


要点:Long Text等の**“結合不可型”の排除**、ON句は等値+括弧で明示、定数条件はWHEREへ、JOIN入れ子規則の順守。この順で直せば再現性高く解消できます。

# 結論(原因)

* **ON句に `CStr(Nz(...))` の“式”を置いた多段の外部結合(LEFT JOIN→LEFT JOIN)を Access/ACE が正しく表現できず、**「JOIN 式をサポートしていません」**が発生しています。ACE は**JOIN の ON は“フィールド=フィールド”の単純比較**を強く想定し、**関数や複雑条件を含むON**、特に**外部結合で複数回使う**と失敗しやすい仕様です。([Stack Overflow][1])

# 補足(なぜ素のJOINは通るのに CStr+Nz で落ちるのか)

* 素の式は **[Table1].[Key] = [Table2].[Key]** の単純比較で、ACE最適化が可能。
* `CStr(Nz(...))` を**両辺**に置くと **「式と式の比較」**となり、**多段LEFT JOINの評価順**や**最適化**が崩れやすく、ACE が **JOIN を内部表現に落とせず**にエラー化します(類例:ONに定数条件や関数を混ぜると同エラー)。([Stack Overflow][1])
* さらに**ODBCリンク**(CData/Kintone等)では、**JOINをサーバー側にパススルーできないON**(関数入り)はAccess側評価に回り、**外部結合×式**の組合せでコケやすくなります。([Access developer][2])

# 改善策(安全で再現性高い順)

1. **下位クエリで“型揃え済みキー”を作ってからJOIN(ONはフィールド=フィールド)**

   * 例:
   * Q1:`SELECT CStr(Nz([テーブル1].[フィールド],'')) AS K1, * FROM テーブル1;`
   * Q2:`SELECT CStr(Nz([テーブル2].[フィールド],'')) AS K2, * FROM テーブル2;`
   * Q3:`SELECT CStr(Nz([テーブル3].[フィールド],'')) AS K3, * FROM テーブル3;`
   * 本体:

     ```
     FROM (Q1 LEFT JOIN Q2 ON Q1.K1 = Q2.K2)
          LEFT JOIN Q3 ON Q1.K1 = Q3.K3;
     ```

   → **ONは“列=列”のみ**になるため通ります。Accessでは**関数はONに直書きせず下位で済ませる**のが定石。([Stack Overflow][3])

2. **ONに定数や追加条件を混ぜない**(混ぜると同エラー誘発。条件はWHEREへ)

   * 悪例:`... LEFT JOIN T2 ON A.ID=T2.ID AND T2.Flg=True`
   * 良例:`... LEFT JOIN T2 ON (A.ID=T2.ID)  WHERE T2.Flg=True OR T2.ID IS NULL`(外部結合の意味を保持)。([Stack Overflow][1])

3. **括弧の徹底**(AccessはON部全体を括弧で囲うと安定)

   * 例:`... JOIN T ON (A.K=B.K)`(多段JOINでも各ONを括弧で)。([Stack Overflow][1])

4. **二段構成に分ける**(まず T1↔T2 を作成 → その結果に T3 をJOIN)

   * 多段外部結合でエラーが出る場合は**クエリを分割**すると解消するケースが多い。([Microsoft Learn][4])

5. **結合に不適な型の混入チェック**

   * ODBCリンク由来で**Long Text/Memo**に見なされた列がONに入ると失敗(該当なら 255 文字へ切り詰めた下位列を作ってJOIN)。([Stack Overflow][5])

# そのまま書き換えるなら(最小修正例)

* **ダメな形(現状)**

FROM (テ1 LEFT JOIN テ2
ON CStr(Nz(テ1.フィールド)) = CStr(Nz(テ2.フィールド)))
LEFT JOIN テ3
ON CStr(Nz(テ1.フィールド)) = CStr(Nz(テ3.フィールド));

* **通る形(推奨)**

FROM (SELECT CStr(Nz(フィールド,'')) AS K1, * FROM テ1) AS A
LEFT JOIN (SELECT CStr(Nz(フィールド,'')) AS K2, * FROM テ2) AS B
ON (A.K1 = B.K2)
LEFT JOIN (SELECT CStr(Nz(フィールド,'')) AS K3, * FROM テ3) AS C
ON (A.K1 = C.K3);


※ONは**常に“列=列”**、関数は**下位で完結**。([Stack Overflow][3])

# チェックリスト(念のため)

* **ONに定数条件が紛れていないか** → あればWHEREへ。([Stack Overflow][1])
* **各ONを括弧で明示**。([Stack Overflow][1])
* **LEFT/RIGHT と INNER の入れ子順が適正か**(ルール違反は同系エラーに波及)。([Microsoft サポート][6])
* **長文型(Memo/Long Text)がJOINキーに混入していないか**。([Microsoft Learn][7])

――
要点:**“ONに関数を置かない”=下位クエリで型揃え→ONは列=列**。これで提示のケースは安定して解消します。([Stack Overflow][3])

[1]: https://stackoverflow.com/questions/16608313/join-expression-not-supported-in-access "\"join expression not supported\" in Access - Stack Overflow"
[2]: https://accessexperts.com/blog/2021/12/20/access-odbc-data-sources-part-6/?utm_source=chatgpt.com "How does Access talk to ODBC data sources? Part 6"
[3]: https://stackoverflow.com/questions/11142458/execute-cstr-expression-inside-join-statement "ms access - Execute CStr() expression inside JOIN statement - Stack Overflow"
[4]: https://learn.microsoft.com/en-us/answers/questions/5135482/access-join-expression-not-supported-nested-sql-pr "Access \"Join expression not supported\" nested SQL problem - Microsoft Q&A"
[5]: https://stackoverflow.com/questions/30921450/cannot-join-on-memo-ole-or-hyperlink-object?utm_source=chatgpt.com "Cannot join on Memo, OLE, or Hyperlink Object"
[6]: https://support.microsoft.com/en-us/office/join-tables-and-queries-3f5838bd-24a0-4832-9bc1-07061a1478f6 "Join tables and queries - Microsoft Support"
[7]: https://learn.microsoft.com/en-us/answers/questions/5001062/joining-tables?utm_source=chatgpt.com "Joining Tables - Microsoft Q&A"
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?