1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本語を扱うDBはSQL_ASCIIに要注意!

Last updated at Posted at 2025-02-01

遭遇した問題

PostgreSQLを使って従業員のデータを管理するテーブルを作成しようと以下のSQLを実行しました

crate.sql
CREATE TABLE employee (
  id SERIAL PRIMARY KEY,
  family_name VARCHAR(20) NOT NULL,
  first_name VARCHAR(20) NOT NULL,
  name_kana VARCHAR(20) NOT NULL,
);
insert.sql
INSERT INTO
  employee (
    id,
    family_name,
    first_name,
    name_kana,
  )
VALUES
  (
    1,
    '佐藤',
    '一子',
    'サトウ イチコ',
  ) ON CONFLICT (id) DO NOTHING;

しかし、あるエラーにより処理に失敗している…

ERROR: value too long for type character varying(20)

このエラーを見た私は

VARCHAR(20)の最大文字数エラーかぁ😏

エラーが出ているのは文字数的に'サトウ イチコ'だろうな
VARCHAR(50)ぐらいにするか、データ型をTEXTすれば治るだろう…

とたいした調査をせずにそう決めつけて解決しようとしてました
(日本語文字数すら数えず直そうとしてました。よくないですね)

ちょっと待った!

この問題を上司に報告したところ、

「PostgreのVACHAR(n)はバイト数ではなく単純に文字数でカウントされるはずなのでいけるはずだけど?🤔」

とアドバイスをいただきました

PostgreSQLのVARCHAR(n)

ということでPostgreSQLの最大文字数カウントのルールを調査しました

SQL では、character varying(n)character(n)という2 つの主要な文字型が定義されています。nは正の整数です。これらの型は両方とも、最大 文字数 (バイト数ではありません) の文字列を格納できます。

たしかにバイト数ではなく文字数でカウントされるらしい

ちなみにcharacter varying(n)varcahr(n)の別名とのこと。

じゃあなぜエラーになっていたのか?

結論から言うと、DBのエンコードがSQL_ASCIIに設定されていたことが原因でした😅

SQL_ASCIIに設定している場合は、文字エンコードが無視されて日本語データもバイト数で扱うようです

設定がSQL_ASCIIの場合は、符号化は実行されません。よって、この設定は特定の符号化を使用している場合には、その符号化を無視するようになってしまいます。

バイト数でカウントされるなら、

全角文字(サトウイチコ): 6文字 × 3バイト = 18バイト
全角スペース: 1文字 × 3バイト = 3バイト
合計: 21バイト

でエラーになるのは頷けますね

対応策

エンコードをUTF-8に変更すれば解決OK

日本語文字列に対応しているエンコードを設定することで、最大数のカウントをバイトから文字数にすることができます

ちなみに一度作成したDBのエンコード設定は変えられないそうです…
新しくDBを作り直してSQLを実行したら無事通りました😮‍💨

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?