- データベース
operator does not existの直し方|PostgreSQL
ERROR: operator does not exist: integer = character varying は、型の違う値どうしを =・>=・LIKE などで比べたときのエラーです。 PostgreSQL は、整数と文字列のように型が違う値を、自動では変換して比べません。MySQL では動いていた SQL が、PostgreSQL に移すと止まる代表的なエラーです。
エラー文の integer = character varying は「左が integer、右が varchar」という意味です。どちらかに型を合わせます。
| エラー文 | よくある原因 | 直し方 |
|---|---|---|
integer = character varying |
数値の列と、文字列の列・パラメーターを比べた(JDBC の setString) |
setInt を使う、CAST(? AS int) |
boolean = integer |
WHERE active = 1(MySQL の TINYINT の書き方) |
WHERE active = true |
date ~~ unknown |
日付の列に LIKE(joined LIKE '2026%') |
範囲の条件(>= と <)にする |
integer ~~ unknown |
数値の列に LIKE | 文字列にしてから LIKE(id::text LIKE) |
date >= character varying |
日付の列と、文字列のパラメーター | setObject(LocalDate) |
確認環境:PostgreSQL 16.15、PostgreSQL JDBC Driver 42.7.2(Java 21)、MySQL 8.0.46(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「operator does not existの直し方|PostgreSQL」
再現
=> SELECT c.name, o.amount FROM op_c c JOIN op_o o ON o.customer_code = c.id;
ERROR: operator does not exist: character varying = integer
LINE 1: ... o.amount FROM op_c c JOIN op_o o ON o.customer_code = c.id;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
顧客の id は integer、注文の customer_code は varchar('1'・'2'・'002')でした。 以前のシステムから移したテーブルで、コードを文字列で持っている形です。HINT のとおり、型を明示的に変換(キャスト)します。
文字の定数('1')はエラーにならない
=> SELECT name FROM op_c WHERE id = '1';
name
------
佐藤
SQL に直接書いた '1' は、型がまだ決まっていない(unknown)値として扱われ、相手の列(integer)に合わせて変換されました(PostgreSQL の公式ドキュメント)。エラーになるのは、型が varchar・text と決まっている値(列、または型付きのパラメーター)と比べたときです。そのため、psql で試すと動くのに、アプリから実行すると止まることがあります。
MySQL ではなぜ動くのか
| SQL | MySQL 8.0 | PostgreSQL 16 |
|---|---|---|
varchar の列 = int の列 |
動く(数値に変換して比べる) | operator does not exist |
WHERE active = 1 |
動く(TINYINT(1) の場合) | boolean = integer |
WHERE joined LIKE '2026%' |
動く | date ~~ unknown |
'1abc' = 1 |
1(真)(警告 Truncated incorrect DOUBLE value) |
型が違えばエラー |
'abc' = 0 |
1(真) | — |
MySQL は、文字列と数値を比べるとき、両方を浮動小数点の数に変換して比べます(公式マニュアル)。そのため、'1abc' = 1 や 'abc' = 0 まで「一致」になりました。PostgreSQL のエラーは、こうした思わぬ一致を防ぐための動きです。
直し方:キャストの向きで、結果が変わる
-- 文字列のほうを数値に
SELECT c.name, o.amount FROM op_c c JOIN op_o o ON o.customer_code::int = c.id;
-- 数値のほうを文字列に
SELECT c.name, o.amount FROM op_c c JOIN op_o o ON o.customer_code = c.id::text;
| 書き方 | 結果(確認環境) |
|---|---|
o.customer_code::int = c.id |
3 件('002' も顧客 2 に一致) |
o.customer_code = c.id::text |
2 件('002' は '2' と一致しない) |
どちらに合わせるかで、件数が変わりました。 '002' を顧客 2 と同じとみなすかは、業務の決まりで決めます。::int は、数字以外の値('A01' など)が1行でもあるとエラー(invalid input syntax for type integer)になります。
| 書き方 | 意味 |
|---|---|
CAST(x AS int) |
標準 SQL の書き方 |
x::int |
PostgreSQL の書き方(同じ意味) |
根本的には、列の型をそろえる
ALTER TABLE op_o ALTER COLUMN customer_code TYPE int USING customer_code::int;
確認環境では、'A01' の行があると invalid input syntax for type integer: "A01" で止まり、その行を直してから実行すると変更できました。結合に使う列は、同じ型にそろえると、毎回キャストを書かずに済みます。
boolean・日付の比べ方
-- boolean
SELECT name FROM op_c WHERE active = true; -- active = 1 はエラー
SELECT name FROM op_c WHERE active; -- これでも同じ
-- 日付:LIKE ではなく範囲で
SELECT name FROM op_c WHERE joined >= '2026-01-01' AND joined < '2027-01-01';
日付は、LIKE の代わりに範囲の条件で探します。 to_char(joined, 'YYYY') = '2026' でも結果は同じでした。範囲の条件なら、列を加工せずに比べられます。
Java(JDBC)で出る形
PreparedStatement で setString を使うと、PostgreSQL の JDBC ドライバーは、その値を varchar 型のパラメーターとして送ります。
| Java のコード | 結果(確認環境) |
|---|---|
WHERE id = ? に setString(1, "1") |
operator does not exist: integer = character varying |
INSERT ... VALUES (?)(int の列)に setString |
column "id" is of type integer but expression is of type character varying |
WHERE active = ? に setInt(1, 1) |
operator does not exist: boolean = integer |
WHERE joined >= ? に setString(1, "2026-01-01") |
operator does not exist: date >= character varying |
setInt・setBoolean・setObject(LocalDate) |
動いた(列の型に合わせる) |
WHERE id = CAST(? AS int) に setString |
動いた |
INSERT・UPDATE では、operator does not exist ではなく column ... is of type integer but expression is of type character varying という別の文になります。 原因は同じです。
stringtype=unspecified
jdbc:postgresql://localhost:5432/reldemo?stringtype=unspecified
接続 URL に stringtype=unspecified を付けると、setString の値を「型が決まっていない値」として送り、サーバーが列の型に合わせて変換します(PostgreSQL JDBC の公式ドキュメント)。確認環境でも、setString のまま WHERE・INSERT ともに動きました。
| 方法 | 向いている場面 |
|---|---|
setInt・setObject など、列の型に合わせる |
通常はこれ(型の間違いに早く気づける) |
stringtype=unspecified |
MySQL から移したアプリで、setString を一度に直せないとき |
stringtype=unspecified でも、setString(1, "abc") を int の列と比べると、invalid input syntax for type integer: "abc" になりました。値が正しくない問題は残るので、移行の間の手当てと考えるのが安全です。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | どの型とどの型か | エラー文の integer = character varying(左と右) |
| 2 | どこか | ^ の位置、JDBC なら Position |
| 3 | psql では動くか | 動くなら、アプリのパラメーターの型(setString) |
| 4 | どちらに合わせるか | ::int と ::text で結果が変わることがある |
| 5 | boolean・日付 | = true、範囲の条件 |
| 6 | 根本 | 列の型をそろえる(ALTER ... TYPE ... USING) |
よくある質問
Q. SQLSTATE は何ですか。
A. 42883(undefined_function)です。演算子も関数の一種として扱われるためです。
Q. Hibernate・MyBatis でも出ますか。 A. フレームワークがパラメーターを文字列として渡すと、同じエラーになります。エンティティの項目の型と、DB の列の型を合わせるのが根本の直し方です(各フレームワークでの動きは、確認環境では試していません)。
まとめ
- 型の違う値どうしを比べたエラー。PostgreSQL は数値と文字列を自動で変換しない
- MySQL は文字列と数値を数として比べるので動いていた(
'1abc' = 1も真) - SQL に直接書いた
'1'は動く。型が決まった値(列・setString)で出る ::intと::textで結果が変わることがある('002')active = 1は= true、日付の LIKE は範囲の条件に- Java は
setInt・setObject。移行の間はstringtype=unspecifiedも使える
参考・出典
確認日はいずれも 2026年10月11日です。
- PostgreSQL 16 Documentation「Operators」(Type Conversion):https://www.postgresql.org/docs/16/typeconv-oper.html
- PostgreSQL JDBC Driver「Initializing the Driver」(stringtype):https://jdbc.postgresql.org/documentation/use/
- MySQL 8.0 Reference Manual「Type Conversion in Expression Evaluation」:https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「operator does not existの直し方|PostgreSQL」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。