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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?