【Oracle】ORA-00932 完全ガイド|inconsistent datatypes(データ型不一致)の原因と解決方法

ORA-00932: inconsistent datatypes: expected %s got %s は、SQL の中で互換性のないデータ型を比較・結合・代入しようとしたときに発生するエラーです。たとえば VARCHAR2 の列と CLOB の列を = で比較したり、UNION の上下で列のデータ型が一致しない場合に発生します。

エラーメッセージの expected %s got %s の部分には「期待したデータ型」と「実際に渡されたデータ型」が表示されます。たとえば expected CHAR got CLOB なら、CHAR/VARCHAR2 を期待している箇所に CLOB が渡されたことが分かります。

この記事でわかること

  • ORA-00932 が発生する主なパターン(7つ)と解決方法
  • CLOB と VARCHAR2 の比較・結合で発生する場合の対処法
  • DECODE / NVL / CASE で型不一致が起きる仕組みと回避方法
  • UNION / UNION ALL で列の型が合わない場合の対処法
  • DISTINCT / GROUP BY / ORDER BY で CLOB を使う方法
  • 暗黙の型変換と明示的な型変換の使い分け
スポンサーリンク

CLOB と VARCHAR2 の比較で発生する場合

最も多い ORA-00932 の原因が CLOB 列と VARCHAR2 の比較です。CLOB はラージオブジェクトのため、= 演算子や IN で直接比較できません。

NG: CLOB 列を = で比較するとエラー
-- CLOB 列を = で比較 → ORA-00932: inconsistent datatypes: expected CHAR got CLOB
SELECT * FROM documents
WHERE content = 'テスト';  -- content が CLOB 型の場合にエラー

-- CLOB 列を IN で比較 → 同じエラー
SELECT * FROM documents
WHERE content IN ('テスト', '本番');
OK: CLOB 列の比較を正しく行う方法
-- ① DBMS_LOB.SUBSTR で先頭 N 文字を VARCHAR2 に変換して比較する
SELECT * FROM documents
WHERE DBMS_LOB.SUBSTR(content, 4000, 1) = 'テスト';
-- DBMS_LOB.SUBSTR(lob, 取得文字数, 開始位置)
-- 4000 バイト以内であれば VARCHAR2 として比較できる

-- ② TO_CHAR で変換する(4000 バイト以内の CLOB に使える)
SELECT * FROM documents
WHERE TO_CHAR(content) = 'テスト';

-- ③ LIKE で部分一致検索する(CLOB でも LIKE は使える)
SELECT * FROM documents
WHERE content LIKE '%テスト%';

-- ④ DBMS_LOB.INSTR で文字列の位置を検索する
SELECT * FROM documents
WHERE DBMS_LOB.INSTR(content, 'テスト') > 0;

-- ⑤ DBMS_LOB.COMPARE で比較する(完全一致)
SELECT * FROM documents d1
WHERE DBMS_LOB.COMPARE(d1.content, TO_CLOB('テスト')) = 0;
-- COMPARE の戻り値: 0=一致, -1=第1引数が小さい, 1=第1引数が大きい

DECODE / NVL / CASE で型不一致が起きる場合

DECODENVL は最初の引数(または戻り値)のデータ型を基準にして後続の値を暗黙変換しようとします。型が異なると ORA-00932 が発生します。

NG: DECODE の戻り値で型が不一致
-- DECODE の第3引数(最初の戻り値)が基準型になる
-- 第3引数が VARCHAR2 なら、以降の戻り値もすべて VARCHAR2 に変換される
SELECT DECODE(status, 1, '有効', 2, '無効', NULL)
FROM settings;
-- ↑ これは OK(すべて VARCHAR2)

-- 第3引数が NUMBER で第5引数が VARCHAR2 → ORA-00932
SELECT DECODE(status, 1, 100, 2, 'なし', NULL)
FROM settings;
-- expected NUMBER got CHAR(第3引数の 100 が NUMBER なので 'なし' を NUMBER に変換しようとする)
OK: DECODE / NVL の型を統一する
-- ① すべての戻り値を VARCHAR2 に統一する
SELECT DECODE(status, 1, '100', 2, 'なし', NULL)
FROM settings;
-- 100 を文字列 '100' にすれば全引数が VARCHAR2 で統一される

-- ② TO_CHAR で明示的に変換する
SELECT DECODE(status, 1, TO_CHAR(100), 2, 'なし', NULL)
FROM settings;

-- ③ NVL の型不一致(第1引数と第2引数の型が異なる場合)
-- NG: salary は NUMBER だが 'なし' は VARCHAR2
-- SELECT NVL(salary, 'なし') FROM employees;  -- ORA-00932

-- OK: 両方を VARCHAR2 に統一する
SELECT NVL(TO_CHAR(salary), 'なし') FROM employees;

-- ④ CASE 式でも同じルールが適用される
-- NG:
-- SELECT CASE status WHEN 1 THEN 100 WHEN 2 THEN 'なし' END FROM settings;

-- OK: 型を統一する
SELECT CASE status WHEN 1 THEN '100' WHEN 2 THEN 'なし' END FROM settings;

UNION / UNION ALL で列の型が不一致の場合

UNION / UNION ALL は上下の SELECT の列数と型が一致している必要があります。型が異なると ORA-00932 が発生します。

NG: UNION の列型が不一致
-- 上の SELECT の第2列が NUMBER、下の SELECT の第2列が VARCHAR2 → エラー
SELECT employee_id, salary       FROM employees   -- salary: NUMBER
UNION ALL
SELECT department_id, department_name FROM departments;  -- department_name: VARCHAR2
-- ORA-00932: inconsistent datatypes: expected NUMBER got CHAR

-- CLOB と VARCHAR2 の UNION もエラー
SELECT doc_id, content FROM documents     -- content: CLOB
UNION ALL
SELECT log_id, message FROM audit_logs;  -- message: VARCHAR2
-- ORA-00932: inconsistent datatypes: expected CLOB got CHAR
OK: UNION の列型を統一する
-- ① TO_CHAR で NUMBER を VARCHAR2 に変換する
SELECT employee_id, TO_CHAR(salary) AS col2 FROM employees
UNION ALL
SELECT department_id, department_name FROM departments;

-- ② CLOB と VARCHAR2 を統一する(TO_CLOB で VARCHAR2 を CLOB に変換)
SELECT doc_id, content FROM documents
UNION ALL
SELECT log_id, TO_CLOB(message) FROM audit_logs;

-- ③ CAST で型を明示的に合わせる
SELECT employee_id, CAST(salary AS VARCHAR2(100)) AS col2 FROM employees
UNION ALL
SELECT department_id, department_name FROM departments;

-- ④ NULL 列の型を明示する(NULL はデフォルトで CHAR 型と解釈される)
SELECT employee_id, salary FROM employees
UNION ALL
SELECT department_id, CAST(NULL AS NUMBER) FROM departments;
-- NULL を NUMBER 列の位置に置く場合は CAST(NULL AS NUMBER) で型を明示する

DISTINCT / GROUP BY / ORDER BY で CLOB を使う場合

CLOB 列は DISTINCTGROUP BYORDER BY に直接使えません。これらの操作は値の比較が必要ですが、CLOB は比較演算子を直接サポートしないためです。

NG: CLOB 列に DISTINCT / GROUP BY を使うとエラー
-- ORA-00932: inconsistent datatypes: expected - got CLOB
SELECT DISTINCT content FROM documents;

-- ORA-00932
SELECT content, COUNT(*) FROM documents GROUP BY content;

-- ORA-00932(ORDER BY でも)
SELECT doc_id, content FROM documents ORDER BY content;
OK: CLOB を DISTINCT / GROUP BY / ORDER BY で扱う方法
-- ① DBMS_LOB.SUBSTR で先頭 N 文字に切り詰めて DISTINCT する
SELECT DISTINCT DBMS_LOB.SUBSTR(content, 4000, 1) AS content_short
FROM documents;

-- ② DBMS_LOB.GETLENGTH でソートする(内容ではなく長さでソート)
SELECT doc_id, content
FROM documents
ORDER BY DBMS_LOB.GETLENGTH(content) DESC;

-- ③ ORA_HASH で CLOB のハッシュ値を使って GROUP BY する(重複判定)
SELECT ORA_HASH(content) AS content_hash, COUNT(*)
FROM documents
GROUP BY ORA_HASH(content);

-- ④ CLOB を含むテーブルで重複行を検出する
SELECT doc_id, doc_name
FROM documents d1
WHERE EXISTS (
    SELECT 1 FROM documents d2
    WHERE d1.doc_id != d2.doc_id
      AND DBMS_LOB.COMPARE(d1.content, d2.content) = 0
);

INSERT / UPDATE で型不一致が起きる場合

INSERT / UPDATE での ORA-00932 と解決方法
-- NG: VARCHAR2 列に CLOB を直接 INSERT する(4000 バイト超の場合)
-- INSERT INTO log_table (message) SELECT content FROM documents;
-- → content が 4000 バイト超の CLOB なら ORA-00932

-- OK: DBMS_LOB.SUBSTR で切り詰める
INSERT INTO log_table (message)
SELECT DBMS_LOB.SUBSTR(content, 4000, 1) FROM documents;

-- OK: ターゲット列を CLOB に変更する
ALTER TABLE log_table MODIFY message CLOB;
INSERT INTO log_table (message) SELECT content FROM documents;

-- NG: DATE 列に文字列を直接 INSERT する(NLS_DATE_FORMAT に依存して失敗する場合)
-- INSERT INTO events (event_date) VALUES ('2026-04-10');
-- → NLS_DATE_FORMAT が 'DD-MON-RR' の場合は ORA-01843 や ORA-00932

-- OK: TO_DATE で明示的に変換する
INSERT INTO events (event_date) VALUES (TO_DATE('2026-04-10', 'YYYY-MM-DD'));

バインド変数の型不一致で発生する場合

バインド変数での ORA-00932 と解決方法
-- PL/SQL でのバインド変数型不一致
-- NG: NUMBER 型の変数を CLOB 列と比較
DECLARE
    v_id NUMBER := 100;
BEGIN
    -- CLOB 型の列に NUMBER を比較 → ORA-00932
    -- SELECT ... WHERE clob_column = v_id;
    NULL;
END;
/

-- JDBC / Python などアプリケーション側でのバインド変数型指定
-- Java:
-- PreparedStatement ps = conn.prepareStatement("SELECT * FROM t WHERE clob_col = ?");
-- ps.setString(1, "test");  -- CLOB 列に setString → ORA-00932 の場合がある
--
-- 解決策: SQL 側で DBMS_LOB.SUBSTR で VARCHAR2 に変換するか、
-- ps.setCharacterStream() を使う

-- Python (python-oracledb):
-- cursor.execute("SELECT * FROM t WHERE clob_col = :val", val="test")
-- → ORA-00932 になる場合がある
--
-- 解決策:
-- cursor.execute(
--     "SELECT * FROM t WHERE DBMS_LOB.SUBSTR(clob_col,4000,1) = :val",
--     val="test"
-- )
-- または TO_CLOB(:val) でバインド変数側を CLOB にする

暗黙の型変換が効くケースと効かないケース

Oracle は一部の型の組み合わせで暗黙変換(自動的な型変換)を行います。暗黙変換が効く場合はエラーにならないため、「なぜこの SQL はエラーにならないのに別の SQL ではエラーになるのか」という混乱が起きることがあります。

比較 暗黙変換 結果
VARCHAR2 = NUMBER VARCHAR2 → NUMBER に変換 暗黙変換が効く(ただし変換不能な値は ORA-01722)
VARCHAR2 = DATE VARCHAR2 → DATE に変換(NLS_DATE_FORMAT 依存) 暗黙変換が効くが環境依存で危険
NUMBER = DATE 変換不可 ORA-00932
VARCHAR2 = CLOB 変換不可(= 演算子では) ORA-00932
CLOB = CLOB 変換不可(= 演算子では) ORA-00932(DBMS_LOB.COMPARE を使う)
VARCHAR2 || CLOB VARCHAR2 → CLOB に変換 暗黙変換が効く(結果は CLOB)
BLOB = VARCHAR2 変換不可 ORA-00932
暗黙変換に頼るのは危険

暗黙変換は NLS 設定や Oracle バージョンによって挙動が変わる場合があります。本番コードでは必ず TO_CHAR / TO_NUMBER / TO_DATE / CAST で明示的に型変換するべきです。暗黙変換に頼ると、開発環境では動くが本番環境ではエラーになるという事態が起きます。

まとめ

  • CLOB と VARCHAR2 の比較= は使えない。DBMS_LOB.SUBSTR(clob, 4000, 1) で VARCHAR2 に変換するか、LIKE / DBMS_LOB.INSTR で検索する
  • DECODE / NVL / CASE:最初の戻り値の型が基準になる。すべての戻り値の型を統一するか、TO_CHAR で明示的に変換する
  • UNION / UNION ALL:上下の SELECT の対応する列の型を一致させる。TO_CHARTO_CLOBCAST で統一する。NULL は CAST(NULL AS 型) で型を明示する
  • DISTINCT / GROUP BY と CLOB:CLOB は直接使えない。DBMS_LOB.SUBSTR で切り詰めるか、ORA_HASH でハッシュ化する
  • 暗黙変換:VARCHAR2 ↔ NUMBER・VARCHAR2 ↔ DATE は暗黙変換が効くが、環境依存で危険。本番コードでは明示的に型変換すること

データ型の詳細については Oracle データ型完全ガイドを参照してください。CLOB / BLOB の操作全般については Oracle LOB 完全ガイドも参照してください。