#「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);
要点: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"