3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CharとVarcharについて復習

Last updated at Posted at 2018-10-31

アプリの開発の時はMySQLを使っているのだが、文字列型の適切な選択や、判断方法についてはあやふやだったので、まずはcharとvarcharについて復習してみた

MySQLの文字列型の種類

MySQLには大きく分けて、以下の8つの型が存在する。

  • CHAR
  • VARCHAR
  • BINARY
  • VARBINARY
  • BLOB
  • TEXT
  • ENUM
  • SET

CHAR型(M)

  • 固定長文字列
  • Mで文字数を指定
  • 0から255文字まで可能
  • 取得する時に末尾についた空白は削除された上で取得される

[補足] 固定長文字列

指定した文字数以下の文字を格納した場合には文字列の末尾に空白を必要なだけ付け加えて指定の長さの文字列として格納する

consoleで確認(Rails)
childテーブルにはchar型のcharカラムが存在するとする

irb(main):005:0> a.char = "a"*254
irb(main):006:0> a.save! #=> 成功

irb(main):005:0> a.char = "a"*255
irb(main):006:0> a.save! #=> 失敗

irb(main):007:0> a.char = "あ"*254
irb(main):006:0> a.save! #=> 成功

irb(main):009:0> a.char = "あ"*255
irb(main):006:0> a.save! #=> 失敗

文字数に依存していることがわかる

VARCHAR型(M)

  • 可変長文字列
  • Mはバイト数を指定する
  • 0~65535バイト

[補足] 可変長文字列

末尾に空白を付けるようなことはしません。また現行のバージョンでは末尾に空白がある文字列であっても空白が付いたまま格納される

consoleで確認(Rails)
aモデルにはvarchar型のvarcharカラムが存在するとする
varchar(21800) DEFAULT NULLで設定した

irb(main):024:0> child.varchar = 'b'*21800
irb(main):025:0> child.varchar.bytesize #=> 21800
irb(main):027:0> child.save! #=> 成功


irb(main):024:0> child.varchar = 'b'*21801
irb(main):028:0> child.varchar.bytesize #=> 21801
irb(main):027:0> child.save! #=> 失敗

irb(main):024:0> child.varchar = 'あ'*21800
irb(main):030:0> child.varchar.bytesize #=> 65400
irb(main):027:0> child.save! #=> 成功


irb(main):024:0> child.varchar = 'b'*21801
irb(main):032:0> child.varchar.bytesize #=> 65403
irb(main):027:0> child.save! #=> 失敗

bytesizeメソッドでbyteサイズが測れる

VARCHARは65532までが最大有効長なのに、なぜ今回は21800にしているか

UTF-8は最大3バイト食うので、utf-8を使っている場合は、入力文字が全て3バイトだった時の文字数しか使えない!!
なのでMAXでもVARCHARでは、 65532➗3 = 21845文字になります。

VARCHARで、バイト数を指定する時の決め方

tokensテーブルにtokenをvarcharで保存するとする時、Railsではマイグレーションを下記のように記述する

db/migrate/20181029165624_create_tokens.rb
class CreateTokens < ActiveRecord::Migration[5.2]
  def change
    create_table :tokens do |t|
      t.string :token, limit:1500

      t.timestamps
    end
  end
end

今回は、tokenのバイト数の指定を1500としているが、バイト数の決め方の判断として
サンプルtokenのバイト数を計測し、保存するであろうtokenが必ず治るバイト数を指定するのが望ましいと考えられます。

$ sample_token = "hoge..........."
$ sample_token.bytesize #=> 15

# sample_tokenが暗号化前の時は、
$ len   = ActiveSupport::MessageEncryptor.key_len
$ salt  = SecureRandom.random_bytes(len)
$ key   = ActiveSupport::KeyGenerator.new('password').generate_key(salt, len)
$ crypt = ActiveSupport::MessageEncryptor.new(key)   
$ crypt.encrypt_and_sign(sample_token).bytesize # => 138になる!

暗号化の方法に関してはこちらを参照にしました
https://api.rubyonrails.org/v5.2.1/classes/ActiveSupport/MessageEncryptor.html

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?