MySQL – 文字コード・照合順序

データベース

確認

データベースの文字コード設定と照合順序設定の確認方法。いずれも対象のデータベースをUSEで使っている状態で実行。

文字コード

SHOW VARIABLES LIKE 'char%';

照合順序

SHOW VARIABLES lIKE 'col%';

変数で一度に確認

SELECT @@character_set_database, @@collation_database;

変更

ALTER DATABASE test CHARACTER SET 文字コード COLLATE 照合順序;

テーブル

確認

SELECT TABLE_NAME, TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='テーブル名';

変更

ALTER TABLE test_table
CONVERT TO CHARACTER SET 文字コード
COLLATE 照合順序;

 

MySQL – 文字コードを変更したのにエラー

概要

MySQLで日本語入力対策でロケールや文字コードを設定変更しても、なお日本語入力でエラーが出ることがある。

これは、設定変更前にデータベースやテーブルを作成し、後から設定を変更してもcharacter_set_databaselatin1のような状態で残ってしまうため。

また、他の環境で作成したデータベースをCSVで取り込もうとしたとき、文字コードを合わせたのにcollation(照合順序)が違うと怒られてインポートできないという場合がある。

ここでは、既作成のデータベースやテーブルの文字コード、照合順序を変更する手順をまとめる。

現象

文字コードを変更したのに入力できない

ロケールも変更して

MySQLの文字コードも変更して

再起動もしたのに、日本語が入力できてもデータベースに登録できない。

確認

character_set

MySQLの文字コードを確認するのにUSEでデータベースを指定する前に確認したが、データベース指定後に確認した結果が以下。

既作成のデータベースでは、作成時の文字コード設定が残っている。

データベースの文字コード

既作成データベースの文字コード確認。文字コードがlatin1になっている。

テーブルの文字コード

既作成テーブルの文字コード確認。こちらも文字コードがlatin1になっている。

対応

データベースを作りなおす

文字コードがlatin1でまだデータ未入力の段階で発覚したようなときは、一旦dropでデータベースを消して新たに作りなおせば、全体の文字コードに従ったデータベース、テーブルが作成される。

設定を変更する

既にデータが入力されているときに設定を変更したいときは、データベース、テーブルの別に文字コードを変更する。

データベースの文字コードセットを変更する。

テーブルの文字コードセットを変更する。

これでやっと日本語の入力のエラーがなくなった。

 

MySQL – 日本語入力ができない

概要

LinuxのMySQLクライアントからMySQLに対して日本語を入力したとき、以下のような状況となった。

  • 変換中は表示されるが、確定のためEnterを押すと消えてしまう
  • 下記のようにデータベースに登録できない

これを解決するため、OSのロケール設定とMySQLの文字コード設定を変更する。

OSのロケール設定

localeコマンドで現在のロケール設定を確認。デフォルトでCロケールが設定されている。

/etc/profileに以下の2行を追加して再読み込みor再起動。=の前後には空白を入れないこと

設定変更後。

MySQLの文字コード設定

確認方法と指定方法

初期状態のMySQLの文字コードは以下のような状況。

my.cnfmysqlセクションとmysqldセクションにそれぞれ以下を追加。my.cnfの場所は以下のような方法で特定。

  • mysql --help | grep my.cnf
  • find / -name my.sql

この結果文字コード設定は以下のようになり、日本語の入力が可能になった。

コンソールの文字コード

なおこのとき、Windowsホスト上のVagrantをコマンドプロンプトで操作していた。コンソールの文字コードは932(shift_jis)だったが、入力時に文字化けはしなかった。

それでも入力できない

なお、この設定変更をしても、変更前に作成したデータベースに対して入力できない場合がある。

そのようなときは、以下の2つのいずれかの方法をとる。

  • 新たな設定の下で、データベースから作りなおす
  • データベースとテーブルの設定を個別に変更する

MySQL – 起動しない

概要

稼働していたMySQLに突然ログインできなくなり、MySQLサーバーも起動できない状態となった。

これに関しては様々な対応策がネット上にあり、症状によって効くものと効かないものがあるようだ。

今回は、単にMySQLを消してインストールし直したところ元に戻った。

環境

仮想環境:Vagrant + VirtualBox

OS:bento/freebsd-11.2

MySQL:5.7をpkgでインストール

症状

VagrantのFreeBSD仮想環境にMySQLをインストールして動作していたのに、翌日ログインしようとしたらエラーになった。

導入時にも遭遇した現象で、MySQLサーバーが起動していない。

サーバーを起動しようとするとPIDファイルの更新ができないというエラーで起動できない。これはネット上でも頻出の現象だ。

対応~解決せず

pidファイルが消える

sudo touch.pidファイルをつくってみたが、MySQLサーバーを起動すると同じエラーとなった。起動後に確認すると、つくった.pidファイルがなくなっていた。

プロセスはない

mysql関係のプロセスを見てみたが、実行したgrep以外には動いていない。

pkg clean

/var/chache/pkg下の40ほどのtxzファイルが消されたが、PIDファイルが更新できない、というエラーは変わらない。

対応~解決

MySQLサーバーをアンインストールして、my.cnfを消す。

VagrantをリロードしてMySQLサーバーを再インストール。

この段階ではMySQLサーバーは動いていないが、無事起動に成功。

また、

  • 前に作ったデータベースは残っていた
  • そのままexit→Vagrantリロードすると、サーバーが起動(profileにmysql_enable="YES"を記述しているため)

 

MySQL – ログインとパスワード変更

ログイン

以下のコマンド入力後にパスワードを入力。

mysql -u username -p

たとえばrootで入る場合。”Enter password:”に対してパスワードを入力する。

パスワード変更

OSプロンプトから

OSのプロンプトに対して、以下のコマンド入力後に変更前のパスワードを入力。

mysqladmin password new_password -u root -p

たとえばrootのパスワードを変更する場合。”Enter password:”に対しては変更前のパスワードを入力する。

MySQLログイン中

MySQLのプロンプトで以下のコマンドを入力。

SET PASSWORD FOR user@host=password('new_password');

たとえばrootのパスワードを変更する場合。

 

MySQL – CSVファイルのインポートでエラー

概要

MySQLでデータベースにCSVファイルをインポートしようとしたときに以下のようなエラーが出た。

MySQLのバージョンが新しいと出るらしく、メッセージにあるようにサーバーとクライアントの双方で許可を与える必要があるそうだ。

手順

クライアント側の指定

mysqlのログイン時にオプションでローカルの入力ファイルを許可する。オプションの書き方は以下2通りのいずれか

  • --enable-local-infile
  • --local_infile=1またはon

これを設定しておかないと、後述のグローバルパラメーターを有効にしても、LOAD DATA実行時に以下のようなエラーが出る。

サーバー側の指定

MySQLにログイン後、以下のコマンドでサーバーのlocal_infileの設定を確認すると0(無効)になっている。

local_infileを有効にして、設定が反映されていることを確認。

読み込み成功

 

MySQL – 日付・時刻のフォーマット

概要

日付、時刻のフォーマットにはDATE_FORMAT()、TIME_FORMAT()を使う。

DATE_FORMAT(date, format);

TIME_FORMAT(time, format);

datetimeにはDATETIME型の値を入れてもよい。

書式の雛形

以下のデータで日付・時刻の書式を確認する。

日付

日付4or2桁でゼロ埋め %Y %m %d
日付ゼロ埋めなし %y %c %e
月名(短縮/全部) %b / %M
曜日名(番号/短縮/全部) %w / %a / %W

※曜日番号は日曜~土曜が0~6

時刻

24時間制の時刻(ゼロ埋め) %H
24時間制の時刻(ゼロ埋めなし) %k
12時間制の時刻 %h
分(ゼロ埋め) %i
秒(ゼロ埋め) %s
AM/PM %p

※12時間制の時刻は0時/12時の扱いに一貫性がない。

 

MySQL – DISTINCTによる重複の排除

概要

DISTINCTはフィールドの重複を除いた結果を返す。

確認に使用するデータ

以下のデータを使う。日時ごとのパスタのメニューの注文票で、パスタはソースと麺の種類の組み合わせ。

フィールドの重複を除いた抽出

まずソース、麺それぞれのフィールドから重複を除いた結果を抽出。ソースの種類、麺の種類は3種類のため、それぞれ3つのレコードが返される。

日付による集計

日付単位の表示

DATETIMEで登録されているフィールドを日付のみの表現に変更する。その結果、同じ日付で複数のソースと麺の組み合わせのレコードになる。

日付ごとのユニークデータの数

単一のフィールド

単一フィールド中のユニークなデータの数は以下のようにしてカウントする。

COUNT(DISTINCT col)

以下は、日付ごとにグルーピングし、各日付で重複を除いたソースの数をカウントしている。2/2はクリームとトマトの2種類だけというのが反映されている。

また、日付ごとの麺の種類の数もカウントしてみる。2/2がスパゲッティーとリングイネの2種類になっている。

複数フィールド

複数フィールドの組み合わせがユニークなものの数のカウントは以下のようにする。

COUNT(DISTINCT CONCAT(col1, col2, ...))

以下の例では、ソースとパスタの組み合わせがユニークなものの数を日付ごとに集計する。2/2はトマトスパゲッティーが2回、2/3はオイルスパゲッティーがあり、重複を除いてカウントしている。

 

MySQL – グループごとの最大値のレコード

概要

インラインビューグルーピングを使って、レコード中のある列の値が最大値/最小値となるレコードをグループごとに抽出できる。

以下、実行例に沿ってその方法を整理する。

実行例

以下のデータを使う。

ここでは各科目ごとの最高点をとった学生と教科を抽出する。

手順

グループごとの最大値

科目によってグルーピングし、各科目の最高得点を得る。

インラインビューによる最高得点列の追加

インラインビューに別名を定義し、元のテーブルと併記することで、全レコードに新たな最高スコアの列が追加される。

最高得点のレコードの追加

各学生・科目のレコードのうち、スコアが最高スコアに等しいレコードを抽出する。

 

MySQL – シェアの計算

概要

インラインビューを使って、各レコードのある列の値のシェアを計算できる。

以下、実行例に沿ってその方法を整理する。

実行例

以下のデータを使う。

ここでは各成分の量quantityのシェアを計算する。

手順

合計値の計算

合計値はSUM()関数で計算。

インラインビューによる合計列の追加

インラインビューに別名を定義し、元のテーブルと併記することで、全レコードに新たな合計値の列が追加される。

各レコードのシェアの計算

各レコードのquantityを合計値で割ってシェアを計算する。