PostgreSQLのCOPYで「extra data after last expected column」が出る原因は列数不一致

  • PostgreSQL
  • SQL

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

COPYでCSVを取り込もうとすると出る extra data after last expected column。これ、要はファイル側の1行の列数が、テーブル側(またはCOPYで指定した列リスト)が期待する列数より多いときに出るエラー。

原因になりやすいパターン

  • デリミタの指定ミス(CSVなのにデフォルトのタブのままとか、逆にタブ区切りファイルなのにカンマ指定してるとか)
  • クォートされてないフィールドの中に、デリミタと同じ文字が紛れ込んでる
  • ファイルにヘッダー行があるのに HEADER オプションを付け忘れて、ヘッダー行までデータとして読もうとしてる
  • 列リストを指定せずに、ファイルの列数がテーブルの全列数より多い

デフォルトのデリミタは text 形式ならタブ、CSV 形式ならカンマ。ここを間違えると1行がまるごと1列として読まれて、想定より多い列が出てきたように見えることもある。

誤解しやすいポイント

「テーブル側に余分な列があって、そこにNULLやデフォルト値が入らない場合もこのエラーになる」みたいな説明を見かけるけど、これは別のエラー。

  • ファイル側の列 > テーブル側の列 → extra data after last expected column
  • ファイル側の列 < テーブル側の列 → こっちは別のエラー(missing data for column など)になる

原因の方向が逆なので、切り分けるときはまず「ファイルとテーブル、どっちの列数が多いか」を見ること。

構文まわり

このエラーとは直接関係ないけど、調べてる過程で構文の話も出てきたのでついでに。

-- 古い書き方(9.0より前の構文。今も後方互換で動く)
COPY table_name FROM 'file_path' DELIMITER ',' CSV;
-- 現行の書き方
COPY table_name FROM 'file_path' WITH (FORMAT csv, DELIMITER ',');

古い構文はネットの記事だとまだ普通に出てくるけど、今書くなら WITH (...) の方。

切り分け方

行数が多いファイルでどの行が引っかかってるか分からないときは、エラーメッセージの CONTEXT: COPY table_name, line N を見れば該当行が分かる。あとは実際にその行だけ抜き出して、デリミタとクォートの状態を目視で確認するのが早い。