Linux Tutorials | cPanel Tutorials | Remote System Administration
MySQL バージョン 5.0.3-alpha リファレンスマニュアル - 6 MySQL SQL言語リファレンス Go to the first, previous, next, last section, table of contents.


6 MySQL SQL言語リファレンス

MySQL は非常に複雑でありながら、直感的に使用できる覚えやすい SQL インタフェースです。この章では、MySQL を効率的かつ効果的に使用するために知っておく必要がある、さまざまなコマンド、データ型、および関数について説明します。また、この章から、MySQL に組み込まれているすべての機能について参照することもできます。多岐にわたるインデックスの中からそれぞれの内容を参照することによって、この章を効果的に使用することができます。

6.1 言語構造

6.1.1 リテラル:文字列と数値の記述方法

このセクションでは、MySQL で文字列と数値を記述するさまざまな方法を説明します。 また、MySQL でこれらの基本データ型を処理する時に遭遇するであろう、さまざまなニュアンスと ``了解事項'' についても扱います。

6.1.1.1 文字列

文字列は、単一引用符 (`'')または二重引用符(`"')で囲まれた文字の並び(シーケンス)です(ANSI モードでの実行時は引用符のみ)。次に例を示します。

'a string'
"another string"

一部のシーケンスは、個々の文字列内で特別な意味を持ちます。これらのシーケンスは、いずれも、エスケープ文字として知られるバックスラッシュ(`\')で始まります。MySQL では、次のエスケープシーケンスが認識されます。

\0
ASCII 0(NUL)文字。
\'
単一引用符(`'')。
\"
二重引用符(`"')。
\b
バックスペース文字。
\n
改行文字(LF)。
\r
復帰改行文字(CR)。
\t
タブ文字。
\z
ASCII(26)(Control-Z)。この文字をコード化することによって、ASCII(26) が Windows では END-OF-FILE を表すという問題を回避することができる(ASCII(26) では、mysql database < filename を使用する場合に問題が発生する)。
\\
バックスラッシュ(`\')文字。
\%
`%' 文字。これは、`%' をそのまま使用したときにワイルドカード文字として解釈されてしまうコンテキストで `%' 自体を検索する場合に使用する。 See section 6.3.2.1 文字列比較関数
\_
`_' 文字。これは、`_' をそのまま使用したときにワイルドカード文字として解釈されてしまうコンテキストで `_' 自体を検索する場合に使用する。 See section 6.3.2.1 文字列比較関数

文字列の一部のコンテキストでは、`\%' または `\_' を使用したときに、`%'`_' の代わりに、文字列 `\%'`\_' がそれぞれ返されることに注意してください。

文字列に引用符を含める方法は、いくつかあります。

次の SELECT ステートメントは、文字列の引用とエスケープが実際にどのように働くかを示しています。

mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
+-------+---------+-----------+--------+--------+
| hello | "hello" | ""hello"" | hel'lo | 'hello |
+-------+---------+-----------+--------+--------+

mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
+-------+---------+-----------+--------+--------+
| hello | 'hello' | ''hello'' | hel"lo | "hello |
+-------+---------+-----------+--------+--------+

mysql> SELECT "This\nIs\nFour\nlines";
+--------------------+
| This
Is
Four
lines |
+--------------------+

文字列のカラム(BLOB など)にバイナリデータを挿入する場合、次の文字はエスケープシーケンスを使って表現する必要があります。

NUL
ASCII 0。この文字は `\0' (バックスラッシュ + ASCII `0' 文字)で表現する。
\
ASCII 92、バックスラッシュ。`\\' として表現する。
'
ASCII 39、単一引用符。`\'' として表現する。
"
ASCII 34、二重引用符。`\"' として表現する。

C コードを書く場合は、INSERT ステートメントの文字をエスケープする目的で C API 関数 mysql_real_escape_string() を使用できます。See section 11.1.2 C API 関数の概要。Perl では、DBI パッケージの quote メソッドを使用して、特殊文字を適切なエスケープシーケンスに変換することができます。See section 11.5.2 DBI インタフェース

上記の特殊文字のいずれかが含まれている可能性がある文字列には、必ずエスケープ関数を使用するようにします。

または、MySQL API の多くのものが一種のプレースホルダ機能を備えているため、この機能を使ってクエリ文字列に特殊なマーカーを挿入し、クエリの発行時にデータ値をそれらのマーカーにバインドすることもできます。この場合、値内の特殊文字のエスケープ処理が API によって自動で行われます。

6.1.1.2 数値

整数は数字の列として表現されます。浮動小数点では、小数を区切るために `.' が使用されます。どちらの型の数値でも、先頭に `-' を付けることによって、負数を表すことができます。

有効な整数の例:

1221
0
-32

有効な浮動小数点数の例:

294.42
-32032.6809e+10
148.00

浮動小数点のコンテキストで整数を使用することもできます。この場合、整数は同等の浮動小数点数として解釈されます。

バージョン 4.1.0 以降、定数 TRUE1 として評価され、定数 FALSE0 として評価されます。

6.1.1.3 16 進値

MySQL では、16 進値をサポートしています。数値のコンテキストでは、16 進値は整数(64 ビット精度)のように動作します。文字列のコンテキストでは、16 進値はバイナリ文字列のように動作します。この場合、16 進数の各ペアが 1 文字に変換されます。

mysql> SELECT x'4D7953514C';
         -> MySQL
mysql> SELECT 0xa+0;
         -> 10
mysql> SELECT 0x5061756c;
         -> Paul

MySQL 4.1(および --new オプションを使用した MySQL 4.0)では、16 進値のデフォルトのデータ型は文字列です。16 進値の文字列が確実に数値として扱われるようにするには、その文字列に対して CAST( ... AS UNSIGNED) を使用します。

x'hexstring' 構文(4.0 の新機能)は標準 SQL に基づいており、0x 構文は ODBC に基づいています。16 進文字列は、BLOB カラムの値を提供する目的で、ODBC によって使用されることがよくあります。 文字列または数値を 16 進形式の文字列に変換するには、HEX() 関数を使用できます。

6.1.1.4 NULL

NULL 値は ``データなし'' を意味し、数値型での 0 や文字列型での空文字列などの値とは異なります。 See section A.5.3 NULL 値の問題

テキストファイルのインポートまたはエクスポート形式(LOAD DATA INFILESELECT ... INTO OUTFILE)の使用時、NULL\N で表現することができます。 See section 6.4.8 LOAD DATA INFILE 構文

6.1.2 データベース名、テーブル名、インデックス名、カラム名、エイリアス名

MySQL では、データベース名、テーブル名、インデックス名、およびエイリアス名には、すべて同じ規則が適用されます。

注意: 識別子(データベース名、テーブル名、カラム名)を ``' で引用する事ができます。MySQL バージョン 3.23.6 以降では、ANSI モードで実行した時は、`"' も識別子の引用処理に使用することができます。 See section 1.8.2 ANSI モードでの MySQL の実行

識別子 最大長(バイト) 使用可能な文字
データベース 64 ディレクトリ名に使用可能なすべての文字(ただし、`/'`\'、および `.' を除く)
テーブル 64 ファイル名に使用可能なすべての文字(ただし、`/'`.' を除く)
カラム 64 すべての文字
エイリアス 255 すべての文字

上記に補足して、ASCII(0)、ASCII(255)、および引用文字はいずれも識別子内では使用できないことに注意してください。

識別子が予約語である場合や、識別子に特殊文字が含まれている場合は、引用符として使用したバッククォート(「`」)文字でその識別子を必ず囲む必要があります。

mysql> SELECT * FROM `select` WHERE `select`.id > 100;

See section 6.1.7 MySQL での予約語の扱い

MAXDB または ANSI_QUOTES モードで MySQL を実行する場合は、識別子を囲む引用符として二重引用符も使用できます。

mysql> CREATE TABLE "test" (col INT);
ERROR 1064: You have an error in your SQL syntax. (...)
mysql> SET SQL_MODE="ANSI_QUOTES";
mysql> CREATE TABLE "test" (col INT);
Query OK, 0 rows affected (0.00 sec)

See section 4.1.1 mysqld コマンドラインオプション

バージョン 3.23.6 より前の MySQL バージョン では、名前に関して次の規則が適用されます。

1e のような名前は、使用しないでください。これは、1e+1 のような式があいまいになるためです。1e+1 は、式 1e + 1 として、または数値 1e+1 として解釈されます。

MySQL では、次の形式のいずれかを使用してカラムを参照することができます。

カラム参照 意味
col_name この名前のカラムが組み込まれたクエリで使用されているテーブル内のカラム col_name
tbl_name.col_name カレントデータベースのテーブル col_name 内のカラム tbl_name
db_name.tbl_name.col_name データベース db_name のテーブル tbl_name 内のカラム col_name。この形式は MySQL Version 3.22 以降で使用可能。
`column_name` それ自体がキーワードであるか、その中に特殊文字を含んでいるカラム。

対象となる参照があいまいな場合、カラム参照の前に tbl_namedb_name.tbl_name を付ける必要があります。 たとえば、テーブル t1t2 のそれぞれに同名のカラム c があり、t1t2 の両方を使用する SELECT ステートメントで c を読み取るとします。この場合 c は、ステートメントで使用されている 2 つのテーブル中で一意なカラムを表すものではなく、あいまいであるため、t1.c または t2.c と記述することによって、どちらのテーブルが対象か指定する必要があります。同様に、データベース db1 のテーブル t とデータベース db2 のテーブル t に含まれているカラムを取り出す場合は、それぞれのテーブルのカラムを db1.t.col_namedb2.t.col_name として参照します。

構文 .tbl_name はカレントデータベースのテーブル tbl_name を意味します。この構文は ODBC との互換性を確保する目的で許容されています。これは、一部の ODBC プログラムでテーブル名の先頭に `.' 文字が付けられるためです。

6.1.3 名前におけるケース依存

MySQL において、データベースとテーブルは、ディレクトリとそれらのディレクトリ内のファイルに対応しています。そのため、ベースとなっているオペレーティングシステムで大文字と小文字が区別される場合(ケース依存)、データベース名とテーブル名でも大文字と小文字が区別されます。つまり、Windows ではデータベース名とテーブル名で大文字と小文字は区別されず、ほとんどの種類の Unix では大文字と小文字が区別されることになります。ただし、重要な例外が 1 つあります。Mac OS X でデフォルトの HFS+ ファイルシステムを使用している場合です。 しかし、Mac OS X は UFS ボリュームもサポートしています。UFS ボリュームでは Unix の場合と同じように Mac OS X でも大文字と小文字が区別されます。 See section 1.8.3 SQL-92 標準に対する MySQL 拡張機能

注意: Windows ではデータベース名とテーブル名で大文字と小文字は区別されませんが(ケース非依存)、同じクエリ内で異なるケースを使用して同じデータベースやテーブルを参照しないようにしてください。次のクエリでは、同じテーブルが my_table および MY_TABLE として参照されています。したがって、このクエリは機能しません。

mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;

カラム名とカラムのエイリアスは、あらゆる状況においてケース非依存です。

テーブルのエイリアスはケース依存です。次のクエリでは、同じエイリアスが a および A として参照されています。したがって、このクエリは機能しません。

mysql> SELECT col_name FROM tbl_name AS a
    ->                 WHERE a.col_name = 1 OR A.col_name = 2;

データベース名やテーブル名に大文字と小文字のどちらを使用したか覚えにくい場合は、データベースとテーブルは必ず小文字の名前で作成するなどの一貫した規則を設けるようにします。

この問題に対処する 1 つの方法は、mysqld の先頭に -O lower_case_table_names=1 を付けることです。このオプションのデフォルトは Windows では 1 で、Unix では 0 です。

lower_case_table_names が 1 の場合、MySQL では、保管およびルックアップ時にすべてのテーブル名が小文字に変換されます(バージョン 4.0.2 以降、このオプションはデータベース名にも適用されます。4.1.1 以降、このオプションはテーブルエイリアスにも適用されます)。

このオプションを変更する場合は、最初に元のテーブル名を小文字に変換してから mysqld を起動する必要があります。

MyISAM ファイルを Windows から Unix のディスクに移動した場合、`mysql_fix_extensions' ツールを使用して、指定した各データベースディレクトリ内のファイル拡張子のケース(小文字の `.frm'、大文字の `.MYI' および `.MYD')を修正する必要がある場合があります `mysql_fix_extensions'`scripts' サブディレクトリにあります。

6.1.4 ユーザ変数

MySQL では、@variablename 構文での接続ごとのユーザ変数をサポートしています。変数名は、現在のキャラクタセット内の英数字、および `_'`$'`.' で構成することができます。デフォルトのキャラクタセットは ISO-8859-1 Latin1 です。このキャラクタセットは、--default-character-set オプションを指定した mysqld で変更可能です。See section 4.7.1 データおよびソート用キャラクタセット。ユーザ変数名は、バージョン 5.0 以降のバージョンではケース非依存で、バージョン 5.0 より前のバージョンではケース依存です。

変数は初期化する必要はありません。変数の値はデフォルトでは NULL であり、整数、実数、または文字列値を格納することができます。スレッドのすべての変数は、そのスレッドが終了すると自動的に解放されます。

変数は SET 構文を使用して設定することができます。

SET @variable= { integer expression | real expression | string expression }
[,@variable= ...].

SET 以外のステートメントで変数に値を代入することも可能です。 ただし、この場合、代入演算子は = ではなく := です。= は、SET 以外のステートメントにおいて、比較用に予約されています。

mysql> SET @t1=0, @t2=0, @t3=0;
mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

ユーザ変数は、式を使用できる箇所に使用することができます。ただし、SELECT 文の LIMIT 節や LOAD DATA 文の IGNORE number LINES 節など、数値が明示的に要求されている文脈での使用は含まれません。

注意: SELECT 文においては、それぞれの式は、クライアントに送られた時にはじめて評価されます。したがって、HAVINGGROUP BYORDER BY 節において、SELECT 部に設定された変数を含む式を参照することはできません。たとえば、次の文は、期待どおりに機能しません。

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

その理由は、@aa の値が現在のレコードの値ではなく、前に受け取ったレコードの id 値であるためです。

原則として、変数への値の代入と使用の両方の処理を、同じステートメントでは行わないでください。

変数の設定とその使用を同じステートメントで行った場合、変数のデフォルトの結果型がそのステートメントの開始時におけるその変数のデータ型に基づいて決まってしまう、という問題もあります(値が代入されていない変数は NULL 値を取り、STRING 型であると想定されます)。この例を次に示します。

mysql> SET @a="test";
mysql> SELECT @a,(@a:=20) FROM table_name;

この場合、MySQL では、カラム 1 が文字列としてクライアントに報告されます。そして、2 番目のレコードで @a が数値に設定されるにもかかわらず、@a へのすべてのアクセスが文字列に変換されます。ステートメントの実行後、@a は数値とみなされるようになります。

この場合、何か問題がある場合は、変数の設定とその使用を同じステートメントで行わないようにするか、もしくはその変数を使用する前に値を 0、0.0、または "" に設定するようにします。

6.1.5 システム変数

MySQL 4.0.3 以降では、多くのシステム変数や接続変数にアクセスしやすくなっています。それらの変数のほとんどは、サーバを停止することなく変更できます。

システム変数には、現在の接続だけに該当するスレッド固有(接続固有)変数と、グローバルイベントの設定に使用されるグローバル変数の 2 つの種類があります。 グローバル変数は、新しい接続に対応するスレッド固有変数の初期値を設定するためにも使用されます。

mysqld の起動時には、コマンドライン引数とオプションファイルからすべてのグローバル変数が初期化されます。この値は SET GLOBAL コマンドを使用して変更することができます。新しいスレッドが作成されると、グローバル変数からスレッド固有変数が初期化されます。この値は新しい SET GLOBAL コマンドを発行しても変更されません。

GLOBAL 変数の値を設定するには、次の構文のいずれかを使用します(ここでは、変数の例として sort_buffer_size を使用します)。

SET GLOBAL sort_buffer_size=value;
SET @@global.sort_buffer_size=value;

SESSION 変数の値を設定するには、次の構文のいずれかを使用することができます。

SET SESSION sort_buffer_size=value;
SET @@session.sort_buffer_size=value;
SET sort_buffer_size=value;

GLOBALSESSION のどちらも指定しないと、SESSION が使用されます。 See section 5.5.6 SET 構文

LOCALSESSION のシノニムです。

GLOBAL 変数の値を取り出すには、次のコマンドのいずれかを使用することができます。

SELECT @@global.sort_buffer_size;
SHOW GLOBAL VARIABLES like 'sort_buffer_size';

SESSION 変数の値を取り出すには、次のコマンドのいずれかを使用することができます。

SELECT @@session.sort_buffer_size;
SHOW SESSION VARIABLES like 'sort_buffer_size';

@@variable_name 構文で変数を取り出すときに GLOBALSESSION のどちらも指定しないと、MySQL では、スレッド固有(SESSION)の値がある場合は、その値が返されます。スレッド固有の値がない場合は、グローバル値が返されます。

GLOBAL の値しか存在しない変数の場合、取り出しには GLOBAL と指定する必要はありませんが、設定には GLOBAL と指定する必要があります。これは、後から、同名のスレッド固有変数を導入したり、削除したりするときに問題が発生しないようにするためです。この場合、自分の接続だけでなく、サーバの状態そのものを誤って変更してしまう可能性があります。

次の一覧に、変更および取り出し対象となるすべての変数と、それらの変数で GLOBALSESSION のどちらを使用できるかを示します。

変数名 値のデータ型 タイプ
autocommit bool SESSION
big_tables bool SESSION
binlog_cache_size num GLOBAL
bulk_insert_buffer_size num GLOBAL | SESSION
concurrent_insert bool GLOBAL
connect_timeout num GLOBAL
convert_character_set string SESSION
delay_key_write OFF | ON | ALL GLOBAL
delayed_insert_limit num GLOBAL
delayed_insert_timeout num GLOBAL
delayed_queue_size num GLOBAL
error_count num SESSION
flush bool GLOBAL
flush_time num GLOBAL
foreign_key_checks bool SESSION
identity num SESSION
insert_id bool SESSION
interactive_timeout num GLOBAL | SESSION
join_buffer_size num GLOBAL | SESSION
key_buffer_size num GLOBAL
last_insert_id bool SESSION
local_infile bool GLOBAL
log_warnings bool GLOBAL
long_query_time num GLOBAL | SESSION
low_priority_updates bool GLOBAL | SESSION
max_allowed_packet num GLOBAL | SESSION
max_binlog_cache_size num GLOBAL
max_binlog_size num GLOBAL
max_connect_errors num GLOBAL
max_connections num GLOBAL
max_error_count num GLOBAL | SESSION
max_delayed_threads num GLOBAL
max_heap_table_size num GLOBAL | SESSION
max_join_size num GLOBAL | SESSION
max_relay_log_size num GLOBAL
max_sort_length num GLOBAL | SESSION
max_tmp_tables num GLOBAL
max_user_connections num GLOBAL
max_write_lock_count num GLOBAL
myisam_max_extra_sort_file_size num GLOBAL | SESSION
myisam_repair_threads num GLOBAL | SESSION
myisam_max_sort_file_size num GLOBAL | SESSION
myisam_sort_buffer_size num GLOBAL | SESSION
net_buffer_length num GLOBAL | SESSION
net_read_timeout num GLOBAL | SESSION
net_retry_count num GLOBAL | SESSION
net_write_timeout num GLOBAL | SESSION
query_cache_limit num GLOBAL
query_cache_size num GLOBAL
query_cache_type enum GLOBAL
read_buffer_size num GLOBAL | SESSION
read_rnd_buffer_size num GLOBAL | SESSION
rpl_recovery_rank num GLOBAL
safe_show_database bool GLOBAL
server_id num GLOBAL
slave_compressed_protocol bool GLOBAL
slave_net_timeout num GLOBAL
slow_launch_time num GLOBAL
sort_buffer_size num GLOBAL | SESSION
sql_auto_is_null bool SESSION
sql_big_selects bool SESSION
sql_big_tables bool SESSION
sql_buffer_result bool SESSION
sql_log_binlog bool SESSION
sql_log_off bool SESSION
sql_log_update bool SESSION
sql_low_priority_updates bool GLOBAL | SESSION
sql_max_join_size num GLOBAL | SESSION
sql_quote_show_create bool SESSION
sql_safe_updates bool SESSION
sql_select_limit bool SESSION
sql_slave_skip_counter num GLOBAL
sql_warnings bool SESSION
table_cache num GLOBAL
table_type enum GLOBAL | SESSION
thread_cache_size num GLOBAL
timestamp bool SESSION
tmp_table_size enum GLOBAL | SESSION
tx_isolation enum GLOBAL | SESSION
wait_timeout num GLOBAL | SESSION
warning_count num SESSION
unique_checks bool SESSION

値のデータ型が num となっている変数には、数値を設定することができます。 bool となっている変数には、0、1、ON、または OFF を設定することができます。 enum 型の変数には、通常、その変数に対して利用可能な値の 1 つを設定できますが、該当の enum(列挙)値に対応する数値を設定することもできます(最初の列挙値は 0 です)。

これらの変数のいくつかについて説明します。

変数 説明
identity last_insert_id のエイリアス(Sybase との互換性を確保するため)
sql_low_priority_updates low_priority_updates のエイリアス
sql_max_join_size max_join_size のエイリアス
version VERSION() のエイリアス(Sybase(?)との互換性を確保するため)

その他の変数については、スタートアップオプション、SHOW VARIABLES、および SET に関するセクションで説明しています。 See section 4.1.1 mysqld コマンドラインオプション。 See section 4.6.8.4 SHOW VARIABLES。 See section 5.5.6 SET 構文

6.1.6 コメント構文

MySQL サーバでは、コメントスタイルとして、#(行末まで)--(行末まで)、および /*(行中または複数行)*/をサポートしています。

mysql> SELECT 1+1;     # このコメントは行末まで続く
mysql> SELECT 1+1;     -- このコメントは行末まで続く
mysql> SELECT 1 /* これは行中コメント */ + 1;
mysql> SELECT 1+
/*
これは
複数行コメント
*/
1;

--(ダッシュ2つ)のコメントスタイルでは、2 つ目のダッシュの後にスペースを 1 つ以上挿入する必要があることに注意してください。

サーバは上記のコメント構文を理解しますが、mysql クライアントでの /* ... */ コメントの解析には一定の制約があります。

これらの制約は、mysql を対話的に実行する場合と、mysql < some-fileを使用して、コマンドを格納したファイルから入力を読み取るよう mysql に指示する場合の両方に適用されます。

2 つ目のダッシュの後にスペースが 1 つもない場合、SQL-99 のコメントスタイル `--' は MySQL で有効とされません。 See section 1.8.4.7 コメントの開始記号としての `--'

6.1.7 MySQL での予約語の扱い

一般的な問題の 1 つとして、TIMESTAMPGROUP など、MySQL に組み込まれているデータ型や関数の名前を使用するカラム名を含むテーブルの作成に関連する問題があります。このようなカラム名を含むテーブルの作成は可能です(たとえば、ABS はカラム名として使用可能です)。しかし、デフォルトでは、関数の呼び出し時に、関数名とそれに続く `(' 文字との間に空白を挿入することはできません。これは、関数呼び出しをカラム名の参照と区別するためです。

--ansi または --sql-mode=IGNORE_SPACE オプションを指定してサーバを起動した場合は、関数呼び出しで、関数名とそれに続く `(' 文字との間に空白を挿入することができます。これらのオプションを指定すると、関数名が予約語として扱われるようになります。そのため、関数名と同一のカラム名は、section 6.1.2 データベース名、テーブル名、インデックス名、カラム名、エイリアス名 で説明しているように引用符で囲む必要があります。

以下の語は MySQL において明示的に予約されています。これらの語のほとんど(たとえば、GROUP)は、SQL-92 では、カラム名またはテーブル名としての使用を禁止されています。 いくつかの語は、MySQL でそれらの語を必要とし、(現在)MySQL で yacc パーサが使用されていることから予約されています。

Word Word Word
ADD ALL ALTER
ANALYZE AND AS
ASC ASENSITIVE BEFORE
BETWEEN BIGINT BINARY
BLOB BOTH BY
CALL CASCADE CASE
CHANGE CHAR CHARACTER
CHECK COLLATE COLUMN
CONDITION CONNECTION CONSTRAINT
CONTINUE CONVERT CREATE
CROSS CURRENT_DATE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR
DATABASE DATABASES DAY_HOUR
DAY_MICROSECOND DAY_MINUTE DAY_SECOND
DEC DECIMAL DECLARE
DEFAULT DELAYED DELETE
DESC DESCRIBE DETERMINISTIC
DISTINCT DISTINCTROW DIV
DOUBLE DROP DUAL
EACH ELSE ELSEIF
ENCLOSED ESCAPED EXISTS
EXIT EXPLAIN FALSE
FETCH FLOAT FOR
FORCE FOREIGN FROM
FULLTEXT GOTO GRANT
GROUP HAVING HIGH_PRIORITY
HOUR_MICROSECOND HOUR_MINUTE HOUR_SECOND
IF IGNORE IN
INDEX INFILE INNER
INOUT INSENSITIVE INSERT
INT INTEGER INTERVAL
INTO IS ITERATE
JOIN KEY KEYS
KILL LEADING LEAVE
LEFT LIKE LIMIT
LINES LOAD LOCALTIME
LOCALTIMESTAMP LOCK LONG
LONGBLOB LONGTEXT LOOP
LOW_PRIORITY MATCH MEDIUMBLOB
MEDIUMINT MEDIUMTEXT MIDDLEINT
MINUTE_MICROSECOND MINUTE_SECOND MOD
MODIFIES NATURAL NOT
NO_WRITE_TO_BINLOG NULL NUMERIC
ON OPTIMIZE OPTION
OPTIONALLY OR ORDER
OUT OUTER OUTFILE
PRECISION PRIMARY PROCEDURE
PURGE READ READS
REAL REFERENCES REGEXP
RENAME REPEAT REPLACE
REQUIRE RESTRICT RETURN
REVOKE RIGHT RLIKE
SCHEMA SCHEMAS SECOND_MICROSECOND
SELECT SENSITIVE SEPARATOR
SET SHOW SMALLINT
SONAME SPATIAL SPECIFIC
SQL SQLEXCEPTION SQLSTATE
SQLWARNING SQL_BIG_RESULT SQL_CALC_FOUND_ROWS
SQL_SMALL_RESULT SSL STARTING
STRAIGHT_JOIN TABLE TERMINATED
THEN TINYBLOB TINYINT
TINYTEXT TO TRAILING
TRIGGER TRUE UNDO
UNION UNIQUE UNLOCK
UNSIGNED UPDATE USAGE
USE USING UTC_DATE
UTC_TIME UTC_TIMESTAMP VALUES
VARBINARY VARCHAR VARCHARACTER
VARYING WHEN WHERE
WHILE WITH WRITE
XOR YEAR_MONTH ZEROFILL

以下のシンボル(上の表に含まれるもの)は SQL-99 では使用を禁止されていますが、MySQL ではカラム名またはテーブル名として使用可能です。これは、それらの名前がごく一般的なものであり、多くの人々にすでに使用されているためです。

6.2 カラム型

MySQL では、複数のカラム型をサポートしています。これらのカラム型は、数値型、日付と時刻型、文字列(文字)型の 3 つのカテゴリに分類することができます。このセクションでは、まず、使用できるカラム型の概要を示し、各カラム型で必要となる記憶容量について簡単に説明します。その後、各カテゴリのカラム型の特性を詳しく説明します。 概要はあえて簡単にまとめてあります。値の有効な指定形式など、個々のカラム型の追加情報については、それぞれの詳細な説明を参照してください。

以下に、MySQL でサポートしているカラム型を示します。 説明内では、次のコード文字を使用します。

M
最大表示サイズを表す。正式な最大表示サイズは 255。
D
小数点型に適用され、小数点以下の桁数を表す。最大値は 30 だが、M-2 より大きくしないようにする。

角かっこ(`['`]')は、オプションの型指定子の一部であることを表します。

カラムに対して ZEROFILL を指定すると、そのカラムに UNSIGNED 属性が自動で追加されることに注意してください。

警告: 整数値の減算で、どちらか一方の整数値が UNSIGNED 型の場合、結果の値は符号なしになります。 See section 6.3.5 キャスト関数

TINYINT[(M)] [UNSIGNED] [ZEROFILL]
非常に小さな整数。符号付きの範囲は -128127。符号なしの範囲は 0255
BIT
BOOL
BOOLEAN
いずれも TINYINT(1) のシノニム。 シノニム BOOLEAN はバージョン 4.1.0 で追加された。 ブール型の完全な処理は SQL-99 に基づいて導入される。
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
小さな整数。符号付きの範囲は -3276832767。符号なしの範囲は 065535
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
中間サイズの整数。符号付きの範囲は -83886088388607。符号なしの範囲は 016777215
INT[(M)] [UNSIGNED] [ZEROFILL]
通常サイズの整数。符号付きの範囲は -21474836482147483647。符号なしの範囲は 04294967295
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
INT のシノニム。
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
大きい整数。符号付きの範囲は -92233720368547758089223372036854775807。符号なしの範囲は 018446744073709551615BIGINT 型のカラムに関しては、次の点について注意すること。
  • すべての算術演算は符号付き BIGINT または DOUBLE 型の値を使って行われる。そのため、9223372036854775807(63 ビット)を超える、符号なしの大きい整数は、ビット関数以外では使用しないようにする。ビット関数以外でこのような大きい整数を使用すると、BIGINT から DOUBLE への変換時に発生する丸め誤差の影響で、結果の最後の桁の一部に誤りが出る場合がある。 次の場合、SQL 4.0 では BIGINT を処理できる。
    • 整数を使って、符号なしの大きい値を BIGINT カラムに格納する場合
    • MIN(big_int_column) および MAX(big_int_column) において
    • 演算子(+-* など)の使用時に両方のオペランドが整数の場合
  • 文字列として格納すれば、正確な整数値を BIGINT カラムに常に格納することができる。この場合、倍精度表現を介在しない、文字列から数値への変換が実行される。
  • `-'`+'、および `*' で両方の引数が整数値のときは、BIGINT 演算が使用される。したがって、2 つの大きな整数(または整数を返す関数の結果)を掛け算する場合、結果が 9223372036854775807 より大きいと、予期しない結果が返される場合がある。
FLOAT(precision) [UNSIGNED] [ZEROFILL]
浮動小数点数。precision は、単精度浮動小数点数の場合は <=24 で、倍精度浮動小数点数の場合は 25 〜 53 の間。これらの型はこのすぐ後に説明する FLOAT 型と DOUBLE 型に類似している。 FLOAT(X) は対応する FLOAT 型および DOUBLE 型と範囲は同じだが、表示サイズと小数部桁数は定義されない。 MySQL バージョン 3.23 では、これは真の浮動小数点値。それ以前の MySQL バージョンでは、FLOAT(precision) の小数部は常に 2 桁になる。 MySQL の計算はすべて倍精度で行われるため、FLOAT の使用時には予期しない問題が発生する場合があることに注意する。 See section A.5.6 不整合レコードの問題解決 この構文は ODBC との互換性を確保するために提供されている。
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
単精度浮動小数点数。使用可能な値は -3.402823466E+38-1.175494351E-380、および 1.175494351E-383.402823466E+38UNSIGNED を指定した場合、負数は使用できない。M は表示幅で、D は小数部桁数。引数のない FLOAT や、X が 24 以下の FLOAT(X) は、単精度浮動小数点数を表す。
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
倍精度浮動小数点数。 使用可能な値は -1.7976931348623157E+308-2.2250738585072014E-3080、および 2.2250738585072014E-3081.7976931348623157E+308UNSIGNED を指定した場合、負数は使用できない。M は表示幅で、D は小数部桁数。引数のない DOUBLE や、X が 25 以上 53 以下である FLOAT(X) は、倍精度浮動小数点数を表す。
DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]
REAL[(M,D)] [UNSIGNED] [ZEROFILL]
いずれも DOUBLE のシノニム。
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
アンパック浮動小数点数。CHAR カラムのように動作する。``アンパック'' とは、その数値が、各桁に 1 文字ずつ使用して文字列として格納されることを意味する。M では、小数点と、負数に使用される `-' 記号はカウントされない(しかし、これらのためのスペースは確保される)。D が 0 の場合、値は小数点も小数部も持たない。DECIMAL 値の最大範囲は、DOUBLE と同じだが、個々の DECIMAL カラムの実際の範囲は、MD の値によって制限される。UNSIGNED を指定した場合、負数は使用できない。 D を省略した場合、デフォルトは 0。M を省略した場合、デフォルトは 10。 MySQL バージョン 3.23 より前のバージョンでは、M 引数に、符号と小数点に必要なスペースを含める必要がある。
DEC[(M[,D])] [UNSIGNED] [ZEROFILL]
NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]
FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
いずれも DECIMAL のシノニム。 FIXED エイリアスは、他のサーバとの互換性を確保する目的で、バージョン 4.1.0 で追加された。
DATE
日付。サポートしている範囲は、'1000-01-01''9999-12-31'。MySQL では、DATE 値は 'YYYY-MM-DD' 形式で表示されるが、DATE カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。 See section 6.2.2.2 DATETIMEDATETIMESTAMP
DATETIME
日付と時刻の組み合わせ。サポートしている範囲は、'1000-01-01 00:00:00''9999-12-31 23:59:59'。MySQL では、DATETIME 値は 'YYYY-MM-DD HH:MM:SS' 形式で表示されるが、DATETIME カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。 See section 6.2.2.2 DATETIMEDATETIMESTAMP
TIMESTAMP[(M)]
タイムスタンプ。範囲は '1970-01-01 00:00:00'2037 年の一定の時点。 MySQL 4.0 以前のバージョンでは、TIMESTAMP 値は、M14(または指定なし)、128、または 6 のどれであるかに応じて、YYYYMMDDHHMMSSYYMMDDHHMMSSYYYYMMDD、または YYMMDD 形式で表示されるが、TIMESTAMP カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。 MySQL 4.1 以降では、TIMESTAMP'YYYY-MM-DD HH:MM:SS' 形式の文字列として返される。数値として返されるようにするには、タイムスタンプカラムに +0 を追加する。異なるタイムスタンプ長はサポートしていない。バージョン 4.0.12 以降、--new オプションを使用することで、バージョン 4.1 と同じようにサーバを動作させることができる。 TIMESTAMP カラムに値を指定しないと、最後に行われた操作の日付と時刻が自動的に設定されるため、このカラムは INSERT 操作や UPDATE 操作の日付と時刻を記録するのに役立つ。また、このカラムに NULL 値を割り当てることによって、現在の日付と時刻をカラムに設定することができる。 See section 6.2.2 日付と時刻型M 引数は、TIMESTAMP カラムの表示方法にのみ作用する。 この値は常に 4 バイトで格納される。 M が 8 または 14 の TIMESTAMP(M) カラムは数値として報告され、その他の TIMESTAMP(M) カラムは文字列として報告されることに注意する。これは単に、これらのデータ型のテーブルのダンプとリストアを確実に実行できるようにすることを目的としている。 See section 6.2.2.2 DATETIMEDATETIMESTAMP
TIME
時刻。範囲は '-838:59:59''838:59:59'。 MySQL では、TIME 値は 'HH:MM:SS' 形式で表示されるが、TIME カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。 See section 6.2.2.3 TIME
YEAR[(2|4)]
2 桁または 4 桁の形式の年(デフォルトは 4 桁)。使用可能な値は、4 桁形式では 190121550000、2 桁形式では 1970 〜 2069(70 〜 69)。MySQL では、YEAR 値は YYYY 形式で表示されるが、YEAR カラムへの値の割り当てには文字列または数値のいずれかを使用することができる(YEAR 型は MySQL バージョン 3.22 より前のバージョンでは使用できない)。 See section 6.2.2.4 YEAR
[NATIONAL] CHAR(M) [BINARY | ASCII | UNICODE]
固定長の文字列。格納時には、指定の長さになるよう、右側にスペースが埋め込まれる。M の範囲は 0 〜 255 文字(3.23 より前の MySQL バージョンでは 1 〜 255)。 値の取り出し時には、後続のスペースが削除される。BINARY キーワードを指定しない場合、CHAR 型の値のソートと比較は、デフォルトのキャラクタセットに基づいてケース非依存方式で行われる。 バージョン 4.1.0 以降では、255 より大きい M 値を指定すると、カラム型が TEXT 型に変換される。 これは互換性を考慮した機能。 NATIONAL CHAR(または、これに対応する短縮形式 NCHAR)は、SQL-99 における、CHAR カラムでデフォルトの CHARACTER セットを使用することを定義する方法。MySQL では、これはデフォルト。 CHARCHARACTER の省略形。 バージョン 4.1.0 以降では、latin1 キャラクタセットを CHAR カラムに割り当てる ASCII 属性を指定することができる。 バージョン 4.1.1 以降では、ucs2 キャラクタセットを CHAR カラムに割り当てる UNICODE 属性を指定することができる。 MySQL では、CHAR(0) 型のカラムを作成することができる。これは、主に、カラム自体は必要とするが、そのカラムの値を実際に使用することはない、というような古いアプリケーションに対応する必要があるときに役立つ。また、2 つの値しか取らないカラムが必要な場合にも非常に役立つ。 CHAR(0)NOT NULL としては定義されず、1 ビットのみ占め、NULL または "" の 2 つの値しか取らない。 See section 6.2.3.1 CHAR 型と VARCHAR
CHAR
CHAR(1) のシノニム。
[NATIONAL] VARCHAR(M) [BINARY]
可変長文字列。注意: 後続のスペースは値の格納時に削除される(これは SQL-99 の仕様とは異なる)。M の範囲は 0 〜 255 文字(MySQL バージョン 4.0.2 では 1 〜 255)。 BINARY キーワードを指定しないと、VARCHAR 値のソートと比較は、ケース非依存方式で行われる。 See section 6.5.3.1 カラムの暗黙的な変更。 バージョン 4.1.0 以降では、255 より大きい M 値を指定すると、カラム型が TEXT 型に変換される。 これは互換性を考慮した機能。 VARCHARCHARACTER VARYING の省略形。 See section 6.2.3.1 CHAR 型と VARCHAR
TINYBLOB
TINYTEXT
最大長が 255(2^8 - 1)文字の BLOB 型または TEXT 型のカラム。 See section 6.5.3.1 カラムの暗黙的な変更。 See section 6.2.3.2 BLOB 型と TEXT
BLOB
TEXT
最大長が 65535(2^16 - 1)文字の BLOB 型または TEXT 型のカラム。 See section 6.5.3.1 カラムの暗黙的な変更。 See section 6.2.3.2 BLOB 型と TEXT
MEDIUMBLOB
MEDIUMTEXT
最大長が 16777215(2^24 - 1)文字の BLOB 型または TEXT 型のカラム。 See section 6.5.3.1 カラムの暗黙的な変更。 See section 6.2.3.2 BLOB 型と TEXT
LONGBLOB
LONGTEXT
最大長が 4294967295 または 4G(2^32 - 1)バイトの BLOB 型または TEXT 型のカラム。 See section 6.5.3.1 カラムの暗黙的な変更。 MySQL バージョン 3.23 まで、サーバ/クライアントプロトコルおよび MyISAM テーブルでは、通信パケットまたはテーブルレコードごとに 16M の制約があった。バージョン 4.x 以降、LONGTEXT 型または LONGBLOB 型のカラムで許容される最大長は、クライアント/サーバプロトコル間の通信バッファおよび使用可能なメモリ量にしたがって調整された最大パケットサイズによって決まる。 See section 6.2.3.2 BLOB 型と TEXT
ENUM('value1','value2',...)
列挙。値のリスト 'value1''value2'...NULL または特殊な "" エラー値から選択された、1 つの値のみ持つことができる文字列オブジェクト。ENUM には最大 65535 の重複のない値を組み込むことができる。 See section 6.2.3.3 ENUM
SET('value1','value2',...)
セット。0 個以上の値を持つことができる文字列オブジェクト。これらの値はいずれも値のリスト 'value1', 'value2', ... から選択する必要がある。1 つの SET には、最大 64 個の要素を組み込むことができる。 See section 6.2.3.4 SET

6.2.1 数値型

MySQL では、SQL-92 のすべての数値データ型をサポートしています。これらのデータ型は、正確な数値データ型(NUMERICDECIMALINTEGERSMALLINT)だけでなく、近似数値データ型(FLOATREALDOUBLE PRECISION)を含みます。キーワード INTINTEGER のシノニムで、キーワード DECDECIMAL のシノニムです。

MySQL では、NUMERIC 型と DECIMAL 型は、SQL-92 標準で使用可能なデータ型と同じデータ型として実装されます。これらのデータ型は、金額データに関する値など、正確な精度で保存することが重要となる値に対して使用されます。これらのいずれかの型のカラムを宣言する際には、次のように、精度とスケールを指定することができます(通常、これらが指定されます)。

    salary DECIMAL(5,2)

この例で、5 (precision) は、値に対して格納される 10 進数の桁数を表わし、2 (scale) は、小数点に続いて格納される桁数を表わします。したがって、この場合、salary カラムに格納できる値の範囲は、-99.9999.99 になります(MySQL では、正数の符号を格納する必要がないため、このカラムには、実際には、999.99 までの数値を格納することができます)。

SQL-92 では、構文 DECIMAL(p)DECIMAL(p,0) と同じです。同様に、構文 DECIMALDECIMAL(p,0) と同じです。この場合、p の値を決定する実装を行うことができます。MySQL では、現在のところ、DECIMAL および NUMERIC データ型のこれらの異型をサポートしていません。通常、これらの型の主な利点は精度とスケールを明示的に制御できることによるため、これはそれほど問題にはなりません。

DECIMAL 値と NUMERIC 値は、値の小数部の精度を維持するため、バイナリの浮動小数点数としてではなく、文字列として格納されます。値の各桁、小数点(scale > 0 の場合)、そして `-' 符号(負数の場合)に対して、1 文字が使用されます。scale が 0 の場合、DECIMAL 値と NUMERIC 値には小数点も小数部も含まれません。

DECIMAL 値と NUMERIC 値の最大範囲は DOUBLE 値と同じですが、個々の DECIMAL または NUMERIC カラムの実際の範囲は、個々のカラムの precision または scale によって制限されます。指定されている scale で許容される桁数を超える桁数を小数部に持つ値がカラムに割り当てられた場合、値は指定されている scale に合わせて丸められます。指定されている(またはデフォルトの)precisionscale によって暗黙的に指定された範囲を超える大きさの値が DECIMAL または NUMERIC カラムに割り当てられた場合、その範囲の最大値が格納されます。

SQL-92 標準の拡張として、MySQL では、前出の表に挙げているように、TINYINTMEDIUMINT、および BIGINT 型もサポートしています。もう 1 つの拡張として、MySQL には、INT(4) のように、型の基本キーワードに続いて整数値の表示幅をかっこ内に指定できるオプションがあります。このオプションの表示幅の指定は、カラムに指定された幅より小さい幅を持つ値で表示の左側を埋める目的で使用されますが、そのカラムに格納できる値の範囲が制限されたり、そのカラムに指定された幅を超える幅を持つ値の桁数が制限されたりすることはありません。オプションの拡張属性 ZEROFILL と組み合せて使用した場合、デフォルトのスペースに代わってゼロが埋め込まれます。 たとえば、INT(5) ZEROFILL として宣言されたカラムの場合、値 400004 として取り出されます。注意: 整数カラムの表示幅より大きい値を格納すると、MySQL で一部の複雑な結合のテンポラリテーブルを生成するときに問題が発生することがあります。この場合、データはあくまでも本来のカラム幅に合っているものとして扱われます。

すべての整数型には、オプション(非標準)属性 UNSIGNED を設定することができます。符号なしの値は、正数値だけを入力できるようにしたいカラムで、やや大きい数値範囲を必要とする場合に使用することができます。

MySQL 4.0.2 以降では、浮動小数点型にも UNSIGNED を設定することができます。 この属性が指定されていると、整数型の場合と同じように、カラムに負数の値を格納できなくなりますが、整数型とは異なり、カラム値の上の範囲は変わりません。

FLOAT 型は近似数値データ型を表現する目的で使用されます。 SQL-92 標準では、キーワード FLOAT に続くかっこ内にオプションの精度をビットで指定することができます(指数の範囲は指定できません)。このオプションの精度指定は MySQL 実装でもサポートしています。精度を指定しないでカラムに対して FLOAT キーワードを使用した場合、MySQL では 4 バイトを使って値が格納されます。FLOAT キーワードに続けてかっこ内に 2 つの数字を指定する可変の構文も使用できます。このオプションでは、最初の数字は値に必要なバイト単位の記憶容量を表わし、2 番目の数字は格納および表示する小数部の桁数を表わします(DECIMAL および NUMERIC と同様)。MySQL では、カラムに対して指定されている小数部桁数を超える数の桁を格納しようとすると、格納時に値が丸められ、余分な桁が削除されます。

REAL 型と DOUBLE PRECISION 型では精度の指定は行えません。SQL-92 標準の拡張として、MySQL では、DOUBLE 型は DOUBLE PRECISION 型のシノニムとして認識されます。SQL-92 標準では、REAL 型の精度は DOUBLE PRECISION 型で使用されている精度より小さくなければならないのに対し、MySQL では、これらの両方が 8 バイトの倍精度浮動小数点値として実装されます(非 ``ANSI モード'' で実行した場合)。 最大限の移植性を確保するためには、近似数値データ値の格納を必要とするコードでは、FLOAT または DOUBLE PRECISION の使用時に精度と小数部の桁数をいずれも指定しないようにします。

数値型のカラムに、そのカラム型で許容されている範囲を超える値を格納しようとすると、MySQL では、値は許容範囲の最大値または最低値に丸められて格納されます。

たとえば、INT カラムの範囲は -2147483648 から 2147483647 です。この場合、INT カラムに -9999999999 という値を挿入しようとすると、値は範囲の最低値に丸められ、-2147483648 として格納されます。同様に、9999999999 という値を挿入しようとすると、値は 2147483647 として格納されます。

INT カラムが UNSIGNED として設定されている場合、このカラムの範囲のサイズは変わりませんが、最小値と最大値はそれぞれ 04294967295 になります。 したがって、-9999999999 および 9999999999 という値を格納しようとすると、このカラムにはそれぞれ 0 および 4294967296 という値が格納されます。

ALTER TABLELOAD DATA INFILEUPDATE、および複数行の INSERT ステートメントでは、切り落としによる値の変換は ``警告'' として報告されます。

バイト 最小値 最大値
TINYINT 1 -128 127
SMALLINT 2 -32768 32767
MEDIUMINT 3 -8388608 8388607
INT 4 -2147483648 2147483647
BIGINT 8 -9223372036854775808 9223372036854775807

6.2.2 日付と時刻型

日付と時刻型には、DATETIMEDATETIMESTAMPTIMEYEAR があります。これらの型のカラムは、いずれも、一定の範囲の正しい値を取りますが、その他に、実際には不正な値を指定するときに使用される ``ゼロ'' の値も取ります。MySQL では、'厳密' には正しくない一部の日付値(1999-11-31 など)も格納可能であることに注意してください。 これは、日付チェックはアプリケーションで実行されるので SQL サーバ側で行う必要はない、という前提に立っているためです。日付チェックを '迅速' に行うために、MySQL では、指定された月が 0 〜 12 の範囲にあるかどうかと、指定された日付が 0 〜 31 の範囲にあるかどうかのみチェックします。これらの範囲に 0 が含まれている理由は、MySQL では、DATE または DATETIME カラムの日の値または月日の値がゼロである日付の格納が許容されているためです。これは、誕生日を格納する必要があるアプリケーションで正確な日付がわからないときなどに非常に役立ちます。この場合、単に 1999-00-001999-01-00 などとして、日付を格納します(このような日付を指定した場合、DATE_SUB()DATE_ADD などの関数によって正しい値が返ると想定することはできません)。

以下に、日付と時刻型に関して留意すべき一般考慮事項をいくつか示します。

6.2.2.1 西暦 2000 年問題と日付型

MySQL 自体は西暦 2000 年問題に対応していますが(see section 1.2.5 西暦 2000 年対応)、MySQL への入力値がこの問題に対応していない場合があります。2 桁の年の値を持つ入力値は、世紀がわからないためいずれもあいまいです。MySQL では年の値は内部で 4 桁を使用して格納されるため、このような値は 4 桁形式に変換する必要があります。

DATETIME 型、DATE 型、TIMESTAMP 型、YEAR 型のカラムであいまいな年の値を含む日付が指定された場合、MySQL では、次の規則に従ってそれらの日付が解釈されます。

これらの規則では、入力したデータが何を表すかに関して、単に、妥当な推測が行われるだけです。MySQL で使用される発見的手法で正しい年の値が生成されない場合は、4 桁の年の値を含む、あいまいでない値を入力してください。

ORDER BY では、2 桁の YEAR/DATE/DATETIME 型が正しくソートされます。

一部の関数(MIN()MAX()など)では、TIMESTAMP/DATE 型の値が数値に変換されることに注意してください。したがって、2 桁の年を持つタイムスタンプはこれらの関数では正常に機能しません。この場合の修正方法としては、TIMESTAMP/DATE を 4 桁の年形式に変換するか、または MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS)) のようなものを使用します。

6.2.2.2 DATETIMEDATETIMESTAMP

データ型 DATETIMEDATETIMESTAMP はそれぞれ関連しています。 このセクションでは、これらのデータ型の特徴を示すとともに、これらのデータ型の類似点と相違点について説明します。

DATETIME 型は、日付と時刻の両方の情報を含む値を必要とするときに使用します。MySQL では、DATETIME 型の値の取り出しと表示は 'YYYY-MM-DD HH:MM:SS' 形式で行われます。サポートしている範囲は '1000-01-01 00:00:00''9999-12-31 23:59:59' です(``サポート'' 範囲より前の値でも動作する場合がありますが、確実に動作するという保証はありません)。

DATE 型は、日付値のみ必要とし、時刻部分は必要でない場合に使用されます。MySQL では、DATE 型の値の取り出しと表示は 'YYYY-MM-DD' 形式で行われます。サポートしている範囲は、'1000-01-01''9999-12-31' です。

TIMESTAMP カラム型の特性と動作は、MySQL のバージョンとサーバでの SQL 実行モードに応じて異なります。

MAXDB モードでの実行時の TIMESTAMP の動作

MySQL を MAXDB モードで実行している場合、TIMESTAMPDATETIME と同じように動作します。TIMESTAMP カラムの自動更新(次の段落で説明)は行われません。MySQL の MAXDB モードでの実行は、バージョン 4.1.1 以降で可能です。See section 4.1.1 mysqld コマンドラインオプション

MAXDB モードで実行していないときの TIMESTAMP の動作 @c INSERT STOP

TIMESTAMP カラム型では、INSERT または UPDATE 操作に対して現在の日付と時刻を自動的に指定することができます。TIMESTAMP カラムが複数ある場合は、最初のカラムのみが自動で更新されます。

最初の TIMESTAMP カラムの自動更新は、次のいずれかの条件で発生します。

2 番目以降の TIMESTAMP カラムにも、現在の日付と時刻を設定することができます。カラムに NULL または NOW() を設定します。

TIMESTAMP 型のいずれかのカラムに現在の日付と時刻以外の値を設定するには、そのカラムに対して、必要な値を明示的に設定します。これは、最初の TIMESTAMP カラムについても同様です。この特性は、次に示すように、レコードの作成時に TIMESTAMP カラムに現在の日時を設定し、その後そのレコードの更新時には設定済の値を変更しないようにする場合などに役立ちます。

とはいえ、DATETIME カラムを使用してレコードの作成時に値を NOW() に初期化し、後続の更新時にはそのままにしておくというのも、手軽な方法です。

MAXDB モードでの実行時の TIMESTAMP の特性

MySQL を MAXDB モードで実行している場合、TIMESTAMPDATETIME とまったく変わりません。格納と表示には同じ形式が使用され、また値の範囲も同じです。MySQL の MAXDB モードでの実行は、バージョン 4.1.1 以降で可能です。 See section 4.1.1 mysqld コマンドラインオプション

MAXDB モードで実行していないときの、MySQL 4.1 以降での TIMESTAMP の特性

MySQL 4.1.0 では、TIMESTAMP カラムの格納および表示には、 DATETIME カラムと同じ形式が使用されます。したがって、次の段落で説明している方法で狭くしたり、広げたりすることはできません。つまり、TIMESTAMP(2)TIMESTAMP(4) などは使用できないことになります。それ以外の特性は、以前の MySQL バージョンと同じです。

MySQL 4.1 より前のバージョンにおける TIMESTAMP の特性

TIMESTAMP 値は 1970 年の始まりから 2037 年の一定の時点までを範囲とし、時間分解能は 1 秒です。値は数値として表示されます。

MySQL で TIMESTAMP 型の値の取り出しと表示に使用される形式は、次の表に示すように、表示サイズによって異なります。最長の TIMESTAMP 形式は 14 桁ですが、TIMESTAMP 型のカラムはもっと短い表示サイズで作成することもできます。

カラム型 表示形式
TIMESTAMP(14) YYYYMMDDHHMMSS
TIMESTAMP(12) YYMMDDHHMMSS
TIMESTAMP(10) YYMMDDHHMM
TIMESTAMP(8) YYYYMMDD
TIMESTAMP(6) YYMMDD
TIMESTAMP(4) YYMM
TIMESTAMP(2) YY

TIMESTAMP 型のカラムでは、表示サイズにかかわらず、格納サイズはすべて同じです。最も一般的な表示サイズは 6、8、12、14 です。テーブルの作成時に任意の表示サイズを指定できますが、値 0 と 14 を超える値は強制的に 14 に設定されます。1 〜 13 の奇数値のサイズは強制的にすぐ上の偶数に設定されます。

注意: バージョン 4.1 以降、TIMESTAMP'YYYY-MM-DD HH:MM:SS' 形式の文字列として返されます。その他のタイムスタンプ長のサポートは中止されました。

DATETIMEDATETIMESTAMP 型の値は、以下の一連の共通形式のいずれかを使用して指定することができます。

不適切な DATETIMEDATETIMESTAMP 値は、それぞれの型の ``ゼロ'' 値('0000-00-00 00:00:00''0000-00-00'00000000000000)に変換されます。

日付部分の区切り記号を含む文字列として値を指定する場合、10 より少ない月または日の値を 2 桁で指定する必要はありません。'1979-6-9''1979-06-09' と同じ意味になります。同様に、時刻部分の区切り記号を含む文字列として値を指定する場合、10 より少ない時、分、または秒の値を 2 桁で指定する必要はありません。'1979-10-30 1:2:3''1979-10-30 01:02:03' と同じです。

数値として指定する値は 6、8、12、14 のいずれかの桁数にします。数値を 8 桁または 14 桁の長さにすると、YYYYMMDD または YYYYMMDDHHMMSS 形式であり、最初の 4 桁が年であると想定されます。数値を 6 桁または 12 桁の長さにすると、YYMMDD または YYMMDDHHMMSS 形式であり、最初の 2 桁が年であると想定されます。これら以外の長さの数値は、最も近い長さになるよう先頭にゼロが追加された数値として解釈されます。

区切りなしの文字列として指定した値は、その文字列の長さに基づいて解釈されます。文字列が 8 文字または 14 文字の場合、最初の 4 文字が年であると想定されます。それ以外の長さの文字列の場合、最初の 2 文字が年であると解釈されます。文字列は、それに含まれている各部分に対応して、左から右に、年、月、日、時、分、秒の値として解釈されます。したがって、6 文字より少ない文字列は使用できません。たとえば、1999 年 3 月を表わす値として '9903' を指定すると、MySQL では、テーブルに日付値として ``ゼロ'' が格納されます。これは、年と月の値が 9903 として指定されていても日の部分がまったくないことから、正しい日付ではないためです。しかし、MySQL 3.23 以降では、欠落している月または日の部分を表わすゼロの値を明示的に指定することができます。たとえば、'990300' と指定することで、'1999-03-00' という日付値を格納することができます。

TIMESTAMP カラムでは、正しい値は、表示サイズにかかわらず、その値が指定されたときの完全な精度で格納されます。このことは、暗黙的に次のことを意味します。

ある日付型の値を別の日付型のオブジェクトに割り当てることは、ある程度までは可能です。しかし、何らかの値の変化や情報の消失が起こる可能性があります。

日付値を指定する際には、次の点に注意してください。

6.2.2.3 TIME

MySQL では、TIME 型の値の取り出しと表示は、'HH:MM:SS' 形式(時間の部分が大きい値では 'HHH:MM:SS' 形式)で行われます。TIME 値の範囲は '-838:59:59''838:59:59' です。時間の部分が大きい理由は、TIME 型が 1 日の時刻を表現するためだけでなく、経過時間や 2 つのイベント間の間隔を表現するために使用される場合があるためです。1 日の時刻は 24 時以上になることはありませんが、イベント間の経過時間は 24 時間を大きく上回ったり、マイナスになったりすることがあります。

TIME 型の値は、次に示すさまざまな形式で指定することができます。

TIME 型の値を時刻部分の区切り記号を含む文字列として指定する場合、10 より少ない時、分、または秒の値を 2 桁で指定する必要はありません。'8:3:2''08:03:02' と同じです。

TIME 型のカラムに ``短い'' TIME 値を割り当てるときは注意してください。MySQL では、コロンがない場合、右側の桁が秒を表すという前提にたって値を解釈します(この場合、TIME 型の値は 1 日の時刻ではなく、経過時間として解釈されます)。たとえば、'1112'1112 は、'11:12:00'(11 時 12 分)を表すように見えますが、MySQL では、'00:11:12'(11 分 12 秒)として解釈されます。 同様に、'12'12'00:00:12' として解釈されます。 それに対し、コロンのある TIME 値は、常に 1 日の時刻として扱われます。そのため、'11:12' は、'00:11:12' ではなく '11:12:00' を意味します。

正しい値のうち、TIME 型の範囲外の値は、範囲の最大値または最小値に切り落とされます。たとえば、'-850:00:00''850:00:00' は、それぞれ '-838:59:59''838:59:59' に変換されます。

不正な TIME 値は '00:00:00' に変換されます。'00:00:00' 自体は正当な TIME 値ですが、元の値が '00:00:00' として指定されたのか、それとも不正な値だったのかを、テーブルに格納されている '00:00:00' 値から見分けることはできないことに注意してください。

6.2.2.4 YEAR

YEAR 型は、年を表現するときに使用する 1 バイトの型です。

MySQL では、YEAR 型の値の取り出しと表示は YYYY 形式で行われます。範囲は 19012155 です。

YEAR 型の値は、次に示すさまざまな形式で指定することができます。

不正な YEAR 値は 0000 に変換されます。

6.2.3 文字列型

文字列型には、CHARVARCHARBLOBTEXTENUMSET があります。このセクションでは、これらの型の機能を示すとともに、それぞれの記憶容量と、クエリでの使用方法について説明します。

最大サイズ バイト
TINYTEXT または TINYBLOB 2^8-1 255
TEXT または BLOB 2^16-1(64K-1) 65535
MEDIUMTEXT または MEDIUMBLOB 2^24-1(16M-1) 16777215
LONGBLOB 2^32-1(4G-1) 4294967295

6.2.3.1 CHAR 型と VARCHAR

CHAR 型と VARCHAR 型は似ていますが、格納および取り出しの方法が異なります。

CHAR 型のカラムの長さは、テーブルの作成時に宣言した長さに固定されます。この長さとして、1 〜 255 の任意の値を指定することができます(MySQL バージョン 3.23 以降では、CHAR 型の長さとして、0 〜 255 が可能)。CHAR 型の値は、格納時に、指定された長さになるよう右側にスペースが埋め込まれます。CHAR 値の取り出し時には、後続のスペースが削除されます。

VARCHAR 型のカラムの値は可変長の文字列です。VARCHAR カラムは、CHAR カラム同様、1 〜 255 の間の任意の長さとして宣言することができます。しかし、CHAR 型の値とは異なり、VARCHAR 型の値は、必要な文字と、長さを記録するための 1 バイトのみで格納されます。値に埋め込み処理が行われることはありません。値の格納時、後続のスペースは削除されます(このスペースの削除は SQL-99 の仕様と異なります)。格納時や取り出し時に、ケースの変換処理は行われません。

CHAR 型または VARCHAR 型のカラムに、そのカラムの最大長を超える値を割り当てると、カラムのサイズに合わせて値が切り捨てられます。

次の表に、さまざまな文字列値を CHAR(4) 型と VARCHAR(4) 型のカラムを格納したときの結果に基づく、これらのカラム型の違いについて示します。

CHAR(4) 必要な記憶容量 VARCHAR(4) 必要な記憶容量
'' ' ' 4 バイト '' 1 バイト
'ab' 'ab ' 4 バイト 'ab' 3 バイト
'abcd' 'abcd' 4 バイト 'abcd' 5 バイト
'abcdefgh' 'abcd' 4 バイト 'abcd' 5 バイト

CHAR 型のカラムでは、値の取り出し時に後続のスペースが削除されるため、CHAR(4) 型と VARCHAR(4) 型から取り出した値はそれぞれの場合で変わりません。

CHAR 型と VARCHAR 型のカラム値のソートと比較は、テーブルの作成時に BINARY 属性が指定されている場合を除いて、ケース非依存方式で行われます。BINARY 属性は、カラム値のソートと比較を、MySQL サーバが稼動しているマシンの ASCII 順に従って、ケース依存方式で行うことを表します。BINARY 属性はカラムの格納方法と取り出し方法には影響しません。

バージョン 4.1.0 以降では、カラム型 CHAR BYTECHAR BINARY として使用されます。これは互換性を考慮した機能です。

BINARY 属性は強固な属性です。BINARY として設定したカラムを式で使用すると、その式全体が BINARY 値として比較されます。

MySQL では、CHAR 型や VARCHAR 型のカラムの型が、テーブルの作成時に暗黙的に変更される場合があります。 See section 6.5.3.1 カラムの暗黙的な変更

6.2.3.2 BLOB 型と TEXT

BLOB 型は、可変長のデータを格納できる、大きなバイナリオブジェクトです。TINYBLOBBLOBMEDIUMBLOBLONGBLOB の 4 つの BLOB 型では、格納可能な値の最大長のみが異なります。 See section 6.2.6 各カラム型に必要な記憶容量

TINYTEXTTEXTMEDIUMTEXTLONGTEXT の 4 つの TEXT 型は、4 つの BLOB 型に対応しており、最大長と記憶容量がそれぞれの BLOB 型と同じです。BLOB 型と TEXT 型の唯一の違いは、ソートと比較が、BLOB 値ではケース依存方式で行われ、 TEXT 値ではケース非依存方式で行われる点です。つまり、TEXT 型は大文字と小文字を区別しない BLOB 型と考えることができます。格納時や取り出し時に、ケースの変換処理は行われません。

BLOB 型または TEXT 型のカラムにそのカラム型の最大長を超える値を割り当てると、カラムのサイズに合わせて値が切り捨てられます。

ほとんどの面において、TEXT 型のカラムは、任意の長さに設定できる VARCHAR 型のカラムとみなすことができます。同様に、BLOB 型のカラムについては、VARCHAR BINARY 型のカラムとみなすことができます。相違点は以下のとおりです。

バージョン 4.1.0 以降では、LONG 型と LONG VARCHAR 型は MEDIUMTEXT データ型にマップされます。これは互換性を考慮した機能です。

MyODBC では、BLOB 型の値は LONGVARBINARY として定義され、TEXT 型の値は LONGVARCHAR として定義されます。

BLOB 型と TEXT 型の値は極度に長くなることがあるため、これらの値の使用時には、次に示す一定の制約が適用されます。

注意: BLOB 型または TEXT 型のそれぞれの値は、内部で、個別に割り当てられたオブジェクトとして表現されます。これは他のすべてのカラム型と異なります。他のカラム型では、テーブルが開かれたときに、カラムごとに 1 度だけ記憶領域が割り当てられます。

6.2.3.3 ENUM

ENUM 型は、テーブルの作成時にカラムの仕様で明示的に列挙された使用可能な値のリストから、通常、値が選択される文字列オブジェクトです。

次に示すように、一定の状況では、空の文字列("")または NULL も値として使用できます。

次に示すように、各列挙値にはインデックスを付けることができる。

たとえば、ENUM("one", "two", "three") として指定されたカラムの場合、次の値のいずれかを取ります。それぞれの値では、対応するインデックスも示しています。

インデックス
NULL NULL
"" 0
"one" 1
"two" 2
"three" 3

列挙には、最大 65535 個の要素を組み込むことができます。

3.23.51 以降、ENUM 値の後続のスペースはテーブルの作成時に自動で削除されます。

ENUM 型のカラムに値を割り当てる際には、大文字と小文字の区別はありません。その後、カラムから取り出される値では、大文字と小文字が区別されます。この区別は、テーブルの作成時に使用可能な値として指定された値に基づいて決まります。

ENUM 型の値を数値のコンテキストで取り出すと、そのカラム値のインデックスが返されます。たとえば、ENUM 型のカラムから次のような数値を取り出すことができます。

mysql> SELECT enum_col+0 FROM tbl_name;

ENUM 型のカラムに数値を格納すると、その数値はインデックスとして扱われ、そのインデックスを持つ列挙要素が値として格納されます(ただし、LOAD DATA においては異なり、すべての入力が文字列として扱われます)。 まぎらわしいので、ENUM 型の文字列には数値を含めないようにしてください。

ENUM 型の値は、カラムの仕様で列挙要素がリストされたときの順序にもとづいてソートされます(つまり、ENUM はインデックス番号順にソートされます)。たとえば、ENUM("a", "b") の場合、"a""b" の前にソートされますが、ENUM("b", "a") の場合は、"b""a" の前にソートされます。空の文字列は空以外の文字列の前にソートされ、NULL 値はその他すべての列挙値の前にソートされます。 予期しない結果が起こらないよう、ENUM リストはアルファベット順に指定するようにします。また、GROUP BY CONCAT(col) を使用して、カラムがインデックス番号順ではなく、アルファベット順に確実にソートされるようにすることもできます。

ENUM 型のカラムの使用可能なすべての値が必要な場合は、SHOW COLUMNS FROM table_name LIKE enum_column_name を使用し、2 番目のカラムで ENUM 定義を解析します。

6.2.3.4 SET

SET 型は、ゼロ以上の値を持つことができる文字列オブジェクトです。これらの値はいずれもテーブルの作成時に指定された使用可能な値のリストから選択する必要があります。SET 型のカラム値が複数の要素で構成される場合は、各要素間をカンマ(`,')で区切ります。このことから、SET 要素の値自体には、カンマを使用できません。

たとえば、SET("one", "two") NOT NULL として指定されたカラムは、次に示す値のいずれかを取ります。

""
"one"
"two"
"one,two"

SET には最大 64 個の異なる要素を組み込むことができます。

3.23.51 以降、SET 値の後続のスペースはテーブルの作成時に自動で削除されます。

MySQL では、SET 値は数値として格納されます。格納値の最下位のビットが最初のセット要素に対応します。SET 値を数値型のコンテキストで取り出すと、取り出される値は、カラム値を構成するセット要素に対応するビットセットを持ちます。たとえば、次のように、SET 型のカラムから数値を取り出すことができます。

mysql> SELECT set_col+0 FROM tbl_name;

SET 型のカラムに数値を格納する場合、その数値のバイナリ表現に設定されたビットによって、カラム値のセット要素が決まります。たとえば、カラムが SET("a","b","c","d") として指定されているとします。この場合、セット要素は次のビット値を持ちます。

SET 要素 10 進数 2 進数
a 1 0001
b 2 0010
c 4 0100
d 8 1000

このカラムに値 9 を割り当てた場合、2 進数では 1001 になるため、SET 値の 1 番目と 4 番目の要素である "a""d" が選択され、結果の値は "a,d" になります。

SET 要素を複数持つ値では、値の挿入時には、要素を列記する順序は重要ではありません。値の中で特定の要素を列記する回数も重要ではありません。 その後、値を取り出すときには、値内の各要素は 1 回のみ出現し、テーブルの作成時に指定された順序でそれぞれの要素が列記されます。たとえば、カラムが SET("a","b","c","d") として指定されている場合、このカラムの値を取り出したときには、"a,d""d,a""d,a,a,d,d" はいずれも "a,d" として表現されます。

SET 型のカラムに非サポート値を設定すると、その値は無視されます。

SET 型の値は数値としてソートされます。NULL 値は非 NULL SET 値より前にソートされます。

次に示すように、通常、SET 型のカラムに対する SELECT 操作には、LIKE 演算子または FIND_IN_SET() 関数を使用します。

mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;

次のステートメントも有効です。

mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
mysql> SELECT * FROM tbl_name WHERE set_col & 1;

これらのステートメントの最初のものでは、完全に一致するものが検索されます。2 番目のステートメントでは、最初のセット要素を持つ値が検索されます。

SET 型のカラムの使用可能なすべての値が必要な場合は、SHOW COLUMNS FROM table_name LIKE set_column_name を使用し、2 番目のカラムで SET 定義を解析します。

6.2.4 正しいカラム型の選択

記憶領域を最も効率よく使用するためには、それぞれの場合に最も適した型を選択するようにします。たとえば、199999 の範囲の整数を格納するカラムには、MEDIUMINT UNSIGNED 型が最も適しています。

一般的な問題の 1 つとして、金額値の正確な表現があります。この場合、MySQL では、DECIMAL 型を使用すべきです。この型は文字列として格納されるため、正確さが失われることはありません。正確さがそれほど重要でない場合は、DOUBLE 型でも間に合います。

高精度が必要な場合は、BIGINT として格納される固定小数点型にいつでも変換することができます。それによって、すべての計算を整数で行い、必要に応じて、結果を浮動小数点値に再び変換できます。

6.2.5 他のデータベースエンジンのカラム型の使用

他のベンダの SQL 実装用に記述されたコードを使いやすくするために、MySQL では、次の表に示すカラム型がマップされます。このマッピングによって、他のデータベースエンジンから MySQL へのテーブル定義の移植が簡単に行えるようになっています。

他のベンダの型 MySQL の型
BINARY(NUM) CHAR(NUM) BINARY
CHAR VARYING(NUM) VARCHAR(NUM)
FLOAT4 FLOAT
FLOAT8 DOUBLE
INT1 TINYINT
INT2 SMALLINT
INT3 MEDIUMINT
INT4 INT
INT8 BIGINT
LONG VARBINARY MEDIUMBLOB
LONG VARCHAR MEDIUMTEXT
MIDDLEINT MEDIUMINT
VARBINARY(NUM) VARCHAR(NUM) BINARY

カラム型のマッピングは、テーブルの作成時に行われます。他のベンダで使用されている型でテーブルを作成した後に DESCRIBE tbl_name ステートメントを発行すると、その型に対応する MySQL の型を使用したテーブル構造が報告されます。

6.2.6 各カラム型に必要な記憶容量

以下に、MySQL でサポートしている各カラム型に必要な記憶容量をカテゴリ別に示します。

数値型に必要な記憶容量

カラム型 必要な記憶容量
TINYINT 1 バイト
SMALLINT 2 バイト
MEDIUMINT 3 バイト
INT 4 バイト
INTEGER 4 バイト
BIGINT 8 バイト
FLOAT(X) X <= 24 の場合は 4 バイト、25 <= X <= 53 の場合は 8 バイト
FLOAT 4 バイト
DOUBLE 8 バイト
DOUBLE PRECISION 8 バイト
REAL 8 バイト
DECIMAL(M,D) D > 0 の場合は M+2 バイト、D = 0 の場合は M+1 バイト(M < D の場合は D+2 バイト)
NUMERIC(M,D) D > 0 の場合は M+2 バイト、D = 0 の場合は M+1 バイト(M < D の場合は D+2 バイト)

日付型と時刻型に必要な記憶容量

カラム型 必要な記憶容量
DATE 3 バイト
DATETIME 8 バイト
TIMESTAMP 4 バイト
TIME 3 バイト
YEAR 1 バイト

文字列型に必要な記憶容量

カラム型 必要な記憶容量
CHAR(M) M バイト(1 <= M <= 255
VARCHAR(M) L+1 バイト(L <= M で、かつ 1 <= M <= 255
TINYBLOBTINYTEXT L+1 バイト(L < 2^8)
BLOBTEXT L+2 バイト(L < 2^16)
MEDIUMBLOBMEDIUMTEXT L+3 バイト(L < 2^24)
LONGBLOBLONGTEXT L+4 バイト(L < 2^32)
ENUM('value1','value2',...) 列挙値の数(最大 65535 個の値)に応じて、1 または 2 バイト
SET('value1','value2',...) セット要素の数(最大 64 個の要素)に応じて、1、2、3、4、8 バイトのいずれか

VARCHAR 型、および BLOB 型と TEXT 型は可変長であり、必要な記憶容量は、その型で使用できる最大サイズではなく、カラム値の実際の長さ(上の表の L)に応じて決まります。たとえば、VARCHAR(10) のカラムには、最大 10 文字の長さの文字列を格納することができます。実際に必要な記憶容量は、文字列の長さ(L)に、その文字列の長さを記録するために必要な 1 バイトを加えたものです。'abcd' という文字列の場合、L は 4 であり、必要な記憶容量は 5 バイトになります。

BLOB 型と TEXT 型では、その型で使用できる最大長に応じて、カラム値の長さを記録するために、1、2、3、または 4 バイトが必要になります See section 6.2.3.2 BLOB 型と TEXT

テーブルに可変長のカラム型が含まれている場合、記録形式も可変長になります。 注意: MySQL では、テーブルの作成時、一定の条件下でカラムが可変長型から固定長型(またはその逆)に変換される場合があります。 See section 6.5.3.1 カラムの暗黙的な変更

ENUM 型オブジェクトのサイズは、異なる列挙値の数で決まります。使用可能な値の数が 255 までの列挙には、1 バイトが使用されます。値の数が 65535 までの列挙には、2 バイトが使用されます。 See section 6.2.3.3 ENUM

SET 型オブジェクトのサイズは、異なるセット要素の数で決まります。セットのサイズが N の場合、そのオブジェクトは (N+7)/8 バイト(1、2、3、4、または 8 バイトに切り上げ)を占有します。SET には最大 64 個の要素を組み込むことができます。 See section 6.2.3.4 SET

MyISAM テーブルの 1 つのレコードの最大サイズは 65534 バイトです。各 BLOB 型と TEXT 型は、このサイズに対して 5 〜 9 バイトしか占有しません。

6.3 SELECT 節と WHERE 節で使用する関数

SQL ステートメント内の select_expression または where_definition は、以下に説明する関数を使用した任意の式で構成することができます。

NULL を含む式は、その式に含まれている演算子と関数に関する記述で特に断りがなければ、常に NULL 値を生成します。

注意: 関数名とそれに続くかっこの間には、空白は挿入できません。これは、関数呼び出しと、関数とたまたま同じ名前を持つテーブルまたはカラムの参照とを、MySQL のパーサが区別できるようにするためです。しかし、引数の周囲にはスペースを挿入できます。

--ansi を指定して mysqld を起動するか、または mysql_connect()CLIENT_IGNORE_SPACE を使用すると、MySQL で関数名の後のスペースが許容されるようになりますが、このようにした場合、すべての関数名が予約語になります。 See section 1.8.2 ANSI モードでの MySQL の実行

簡潔にするため、mysql プログラムの出力例では、出力を省略形式で示します。たとえば、次の出力の場合、

mysql> SELECT MOD(29,9);
1 rows in set (0.00 sec)

+-----------+
| mod(29,9) |
+-----------+
|         2 |
+-----------+

例では、次のように示します。

mysql> SELECT MOD(29,9);
        -> 2

6.3.1 各データ型共通の演算子と関数

6.3.1.1 かっこ

( ... )

式での評価を特定の順序で行うよう強制するには、次のようにかっこを使用します。

mysql> SELECT 1+2*3;
        -> 7
mysql> SELECT (1+2)*3;
        -> 9

6.3.1.2 比較演算子

比較演算は、1(TRUE)、0(FALSE)、または NULL の値を返します。このような関数は、数値と文字列の両方に作用します。必要に応じて、文字列は数値に、数値は文字列に、自動的に変換されます(Perl と同様)。

MySQL では、比較は次の規則に基づいて行われます。

デフォルトでは、文字列の比較は、現在のキャラクタセット(デフォルトでは ISO-8859-1 Latin1。これは英語でも非常によく動作する)を使用して、ケース非依存方式で行われます。

いずれかの標準演算子(=<> など。LIKE は含まない)を使用してケース非依存文字列を比較する場合、後続の空白(スペース、タブ、改行復帰)は無視されます。

mysql> SELECT "a" ="A \n";
        -> 1

以下の例は、比較演算での文字列から数値への変換を示したものです。

mysql> SELECT 1 > '6x';
         -> 0
mysql> SELECT 7 > '6x';
         -> 1
mysql> SELECT 0 > 'x6';
         -> 0
mysql> SELECT 0 = 'x6';
         -> 1

注意: 次のように、文字列型のカラムを数値型と比較する場合、MySQL では、インデックスを使用した値の迅速な検索は実行できません。

SELECT * FROM table_name WHERE string_key=1

その理由は、値 1 を返す可能性があるさまざまな文字列("1"" 1""1a" など)があるためです。

=
等しい
mysql> SELECT 1 = 0;
        -> 0
mysql> SELECT '0' = 0;
        -> 1
mysql> SELECT '0.0' = 0;
        -> 1
mysql> SELECT '0.01' = 0;
        -> 0
mysql> SELECT '.01' = 0.01;
        -> 1
<>
!=
等しくない
mysql> SELECT '.01' <> '0.01';
        -> 1
mysql> SELECT .01 <> '0.01';
        -> 0
mysql> SELECT 'zapp' <> 'zappp';
        -> 1
<=
より小さいか等しい
mysql> SELECT 0.1 <= 2;
        -> 1
<
より小さい
mysql> SELECT 2 < 2;
        -> 0
>=
より大きいか等しい
mysql> SELECT 2 >= 2;
        -> 1
>
より大きい
mysql> SELECT 2 > 2;
        -> 0
<=>
等しい(NULL 対応)
mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1 1 0
IS NULL
IS NOT NULL
値が NULL であるかないかのテスト
mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
        -> 0 0 1
mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
        -> 1 1 0
他のプログラムに対して適切に動作するように、MySQL では、IS NULL の使用時において次の追加機能をサポートしている。
  • 直前に挿入されたレコードの検索
    SELECT * FROM tbl_name WHERE auto_col IS NULL
    
    これを無効化するには、SQL_AUTO_IS_NULL=0 を設定する。 See section 5.5.6 SET 構文
  • NOT NULL DATE 型と DATETIME 型のカラムでの、特殊な日付 0000-00-00 の検索
    SELECT * FROM tbl_name WHERE date_column IS NULL
    
    これは、一部の ODBC アプリケーションで必要になる(ODBC では 0000-00-00 日付をサポートしていないため)。
expr BETWEEN min AND max
exprmin 以上で、max 以下の場合は 1 を返す。それ以外の場合は、0 を返す。すべての引数が同じ型の場合、これは式 (min <= expr AND expr <= max) と同じ。引数の型が異なる場合、前述の規則にもとづいて型変換が実行される。この場合、型変換は 3 つすべての引数に適用される。注意: 4.0.5 より前のバージョンでは、引数は expr の型に変換されていた。
mysql> SELECT 1 BETWEEN 2 AND 3;
        -> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
        -> 0
expr NOT BETWEEN min AND max
NOT (expr BETWEEN min AND max) と同じ。
expr IN (value,...)
exprIN リストのいずれかの値のときは 1 を返す。それ以外の場合は 0 を返す。すべての値が定数なら、値はすべて expr の型に基づいて評価され、ソートされる。その後、バイナリ検索によってアイテムが検索される。したがって、IN の値リストが定数だけで構成されている場合、IN は非常に迅速に行われる。expr がケース依存の文字列式の場合、文字列の比較はケース依存方式で行われる。
mysql> SELECT 2 IN (0,3,5,'wefwf');
        -> 0
mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
        -> 1
IN リストの値の数は、max_allowed_packet 値のみによって制限される。 4.1 以降(SQL-99 標準に準拠するため)、IN では、左側の式が NULL の場合だけでなく、リストに一致するものが見つからず、リスト内の式の 1 つが NULL の場合にも NULL が返る。 MySQL バージョン 4.1 以降では、IN() 節にサブクエリを組み込むこともできる。 See section 6.4.2.3 ANYINSOME とともに使用したサブクエリ
expr NOT IN (value,...)
NOT (expr IN (value,...)) と同じ。
ISNULL(expr)
exprNULL の場合は 1 を返す。それ以外の場合は 0 を返す。
mysql> SELECT ISNULL(1+1);
        -> 0
mysql> SELECT ISNULL(1/0);
        -> 1
注意: = を使用した NULL 値の比較は常に false になる。
COALESCE(list)
リスト内の最初の非 NULL 要素を返す。
mysql> SELECT COALESCE(NULL,1);
        -> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
        -> NULL
INTERVAL(N,N1,N2,N3,...)
N < N1 の場合は 0N < N2 の場合は 1(以下同様)というように値を返す。NNULL の場合は -1 を返す。引数はすべて整数として扱われる。この関数で N1 < N2 < N3 < ... < Nn を正しく動作させるには、引数を整数として扱う必要がある。これはバイナリ検索(非常に迅速)が使用されるからである。
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
        -> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
        -> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
        -> 0

6.3.1.3 論理演算子

SQL では、すべての論理演算子は、TRUE、FALSE、または NULL(UNKNOWN)を返します。 MySQL では、これは 1(TRUE)、0(FALSE)、NULL として実装されています。ほとんどの場合、これらの値は異なる SQL データベース間で共通していますが、場合によっては、TRUE に対してゼロ以外の値が返ることもあります。

NOT
!
論理 NOT。 オペランドが 0 の場合は 1 を返し、ゼロでない場合は 0 を返し、NOT NULL の場合は NULL を返す。
mysql> SELECT NOT 10;
        -> 0
mysql> SELECT NOT 0;
        -> 1
mysql> SELECT NOT NULL;
        -> NULL
mysql> SELECT ! (1+1);
        -> 0
mysql> SELECT ! 1+1;
        -> 1
最後の例の場合、式が (!1)+1 と同様に評価されるため、1 が返る。
AND
&&
論理積。 すべてのオペランドがゼロでも NULL でもない場合は 1 を返し、1 つ以上のオペランドが 0 の場合は 0 を返す。それ以外の場合は NULL を返す。
mysql> SELECT 1 && 1;
        -> 1
mysql> SELECT 1 && 0;
        -> 0
mysql> SELECT 1 && NULL;
        -> NULL
mysql> SELECT 0 && NULL;
        -> 0
mysql> SELECT NULL && 0;
        -> 0
注意: 4.0.5 より前のバージョンの MySQL では、NULL が検出されると、使用可能な 0 値をチェックするプロセスが継続されずに、評価が停止される。そのため、これらのバージョンの場合、SELECT (NULL AND 0) では 0 ではなく NULL が返る。 バージョン 4.0.5 では、引き続き可能な限り最適化を図る一方で、常に SQL標準で規定されたとおりの結果になるようコードが再設計されている。
OR
||
論理和。 いずれかのオペランドが非ゼロの場合は 1 を返し、いずれかのオペランドが NULL の場合は NULL を返します。それ以外の場合は 0 を返す。
mysql> SELECT 1 || 1;
        -> 1
mysql> SELECT 1 || 0;
        -> 1
mysql> SELECT 0 || 0;
        -> 0
mysql> SELECT 0 || NULL;
        -> NULL
mysql> SELECT 1 || NULL;
        -> 1
XOR
排他論理和。 いずれかのオペランドが NULL の場合は NULL を返す。 NULL 以外のオペランドに対しては、奇数個のオペランドが非ゼロの場合は 1 を返し、それ以外の場合は 0 を返す。
mysql> SELECT 1 XOR 1;
        -> 0
mysql> SELECT 1 XOR 0;
        -> 1
mysql> SELECT 1 XOR NULL;
        -> NULL
mysql> SELECT 1 XOR 1 XOR 1;
        -> 1
a XOR b は数学的に (a AND (NOT b)) OR ((NOT a) and b) と等価。 XOR はバージョン 4.0.2 で追加された。

6.3.1.4 フロー制御関数

CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...][ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...][ELSE result] END
最初の式では、value=compare-value である result を返す。2 番目の式では、最初の条件が true なら、その result 値を返す。一致する結果が検出されない場合は、ELSE 後の result 値を返す。ELSE 部分がない場合は、NULL を返す。
mysql> SELECT CASE 1 WHEN 1 THEN "one"
           WHEN 2 THEN "two" ELSE "more" END;
       -> "one"
mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
       -> "true"
mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
       -> NULL
戻り値の型(INTEGERDOUBLE、または STRING)は最初の戻り値(最初の THEN 後の式)の型と同じ。
IF(expr1,expr2,expr3)
expr1 が TRUE(expr1 <> 0 および expr1 <> NULL)の場合 IF()expr2 を返し、それ以外の場合は expr3 を返す。 IF() は、使用されているコンテキストに応じて、数値または文字列を返す。
mysql> SELECT IF(1>2,2,3);
        -> 3
mysql> SELECT IF(1<2,'yes','no');
        -> 'yes'
mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
        -> 'no'
expr2 または expr3 が明示的に NULL の場合、IF() 関数の結果の型は NULL 以外のカラムの型になる(この動作は MySQL 4.0.3 で新たに導入された)。 expr1 は整数値として評価される。したがって、浮動小数点型または文字列型の値をテストする場合は、比較演算を使用するようにする。
mysql> SELECT IF(0.1,1,0);
        -> 0
mysql> SELECT IF(0.1<>0,1,0);
        -> 1
上の最初の式では、IF(0.1)0 を返す。これは、0.1 が整数型の値に変換されることによって、IF(0) のテストが行われるためである。これでは期待した結果が得られない場合がある。2 番目の式では、元の浮動小数点値がゼロ以外の値かどうか比較によってテストされる。比較の結果は整数として使用される。 IF() のデフォルトの戻り値型は、MySQL バージョン 3.23 では次のように計算される(デフォルトの戻り値型はテンポラリテーブルへの格納時に重要になる場合がある)。
戻り値
expr2 または expr3 が文字列を返す。 文字列
expr2 または expr3 が浮動小数点値を返す。 浮動小数点
expr2 または expr3 が整数を返す。 整数
expr2 と expr3 が文字列の場合、両方の文字列がケース非依存のときは結果もケース非依存になる(バージョン 3.23.51 以降)。
IFNULL(expr1,expr2)
expr1NULL でない場合は expr1 を返し、それ以外の場合は expr2 を返す。IFNULL() は、使用されているコンテキストに応じて、数値または文字列を返す。
mysql> SELECT IFNULL(1,0);
        -> 1
mysql> SELECT IFNULL(NULL,10);
        -> 10
mysql> SELECT IFNULL(1/0,10);
        -> 10
mysql> SELECT IFNULL(1/0,'yes');
        -> 'yes'
MySQL 4.0.6 以降では、IFNULL(expr1,expr2) のデフォルトの結果値は、2 つの式のより ``一般的'' な方(STRINGREAL または INTEGER の順)になる。それ以前の MySQL バージョンとの違いは、式に基づくテーブルの作成時や、IFNULL() から得られた値を MySQL で内部的にテンポラリテーブルに格納する必要があるときに最も顕著である。
CREATE TABLE foo SELECT IFNULL(1,"test") as test;
MySQL 4.0.6 では、カラム 'テスト' の型は CHAR(4) だが、それ以前のバージョンでは、BIGINT
NULLIF(expr1,expr2)
expr1 = expr2 が TRUE の場合は NULL を返し、それ以外の場合は expr1 を返す。 これは CASE WHEN x = y THEN NULL ELSE x END と同じ。
mysql> SELECT NULLIF(1,1);
        -> NULL
mysql> SELECT NULLIF(1,2);
        -> 1
注意: MySQL では、引数が等しくない場合、expr1 は 2 回評価される。

6.3.2 文字列関数

文字列関数では、結果が max_allowed_packet サーバパラメータの設定より長くなると、NULL が返ります。 See section 5.5.2 サーバパラメータのチューニング

文字列の位置を処理する関数では、最初の位置は 1 として番号付けされます。

ASCII(str)
文字列 str の左端の文字の ASCII コード値を返す。str が空の文字列のときは 0 を返す。strNULL のときは NULL を返す。
mysql> SELECT ASCII('2');
        -> 50
mysql> SELECT ASCII(2);
        -> 50
mysql> SELECT ASCII('dx');
        -> 100
ORD() 関数も参照。
BIN(N)
longlong (BIGINT)型の数値である N のバイナリの文字列式を返す。これは CONV(N,10,2) と同じ。NNULL のときは NULL を返す。
mysql> SELECT BIN(12);
        -> '1100'
BIT_LENGTH(str)
文字列 str の長さをビットで返す。
mysql> SELECT BIT_LENGTH('text');
        -> 32
CHAR(N,...)
引数を整数として解釈し、それらの整数の ASCII コード値で表現された文字から成る文字列を返す。NULL 値はスキップされる。
mysql> SELECT CHAR(77,121,83,81,'76');
        -> 'MySQL'
mysql> SELECT CHAR(77,77.3,'77.3');
        -> 'MMM'
CHAR_LENGTH(str)
文字列 str の長さ(文字数)を返す。 マルチバイト文字は 1 文字とみなされる。 したがって、5 個のマルチバイト文字で構成される文字列の場合、LENGTH() では 10 が返るが、CHAR_LENGTH() では 5 が返る。
CHARACTER_LENGTH(str)
CHARACTER_LENGTH()CHAR_LENGTH() のシノニム。
CONCAT(str1,str2,...)
引数を連結した結果の文字列を返す。いずれかの引数が NULL のときは NULL を返す。3 つ以上の引数の指定が可能。 数値型の引数は同等の文字列形式に変換される。
mysql> SELECT CONCAT('My', 'S', 'QL');
        -> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
        -> NULL
mysql> SELECT CONCAT(14.3);
        -> '14.3'
CONCAT_WS(separator, str1, str2,...)
CONCAT_WS()CONCAT() の特殊型で、区切り文字付きの CONCAT(CONCAT With Separator)。最初の引数は残りの引数の区切り文字である。 この区切り文字は連結する各文字列の間に挿入される。 区切り文字は残りの引数同様、文字列として指定することができる。区切り文字が NULL の場合、結果は NULL になる。 区切り文字引数の後の NULL 値はスキップされる。
mysql> SELECT CONCAT_WS(",","First name","Second name","Last Name");
       -> 'First name,Second name,Last Name'
mysql> SELECT CONCAT_WS(",","First name",NULL,"Last Name");
       -> 'First name,Last Name'
MySQL 4.1.1 より前のバージョンの CONCAT_WS() では、NULL 値だけでなく、空の文字列もスキップされる。
CONV(N,from_base,to_base)
数値を、進数の異なる数値に変換する。数値 Nfrom_base 進数から to_base 進数に変換した数値の文字列表現を返す。いずれかの引数が NULL のときは NULL を返す。 引数 N は整数として解釈されるが、整数または文字列として指定することができる。最小の進数は 2 で、最大の進数は 36to_base が負数の場合、N は符号付きの数値とみなされる。それ以外の場合、N は符号なしの数値として処理される。CONV は 64 ビットの精度で動作する。
mysql> SELECT CONV("a",16,2);
        -> '1010'
mysql> SELECT CONV("6E",18,8);
        -> '172'
mysql> SELECT CONV(-17,10,-18);
        -> '-H'
mysql> SELECT CONV(10+"10"+'10'+0xa,10,10);
        -> '40'
ELT(N,str1,str2,str3,...)
N = 1 のときは str1 を返し、N = 2 のときは str2 を返す(以下同様)。N1 より小さいか、引数の数より大きい場合は、NULL を返す。ELT()FIELD() の逆。
mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
        -> 'ej'
mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
        -> 'foo'
EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
'bits' に指定された数値に対し、1 のビットを 'on' で指定された文字列で表現し、0 のビットを 'off' で指定された文字列で表現した文字列を返す。各文字列の間は 'separator' に指定された区切り文字'(デフォルトは ',')で区切られ、'number_of_bits' に指定されたビット数(デフォルトは 64)だけが表示される。
mysql> SELECT EXPORT_SET(5,'Y','N',',',4)
        -> Y,N,Y,N
FIELD(str,str1,str2,str3,...)
str1, str2, str3, ... リスト内の str のインデックスを返す。 str が検出されない場合は 0 を返す。 FIELD()ELT() の逆。
mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 2
mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 0
FIND_IN_SET(str,strlist)
N 個の部分文字列で構成されるリスト strlist に、文字列 str が含まれている場合は、1 から N までのいずれかの値を返す。文字列のリストは、それぞれの間を `,' 文字で区切られた各部分文字列で構成される文字列である。最初の引数が定数文字列で、2 番目の引数が SET 型のカラムの場合、FIND_IN_SET() 関数はビット演算を使用するよう最適化される。 strstrlist に含まれていない場合や、strlist が空の文字列の場合は、0 を返す。どちらの引数も NULL の場合は、NULL を返す。 最初の引数にカンマ `,' が含まれていると、この関数は正しく動作しない。
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2
HEX(N_or_S)
N_OR_S が数値の場合、longlong(BIGINT)型の数値である N の 16 進値の文字列表現を返す。 これは CONV(N,10,16) と同じ。 N_OR_S が文字列の場合は、N_OR_S の各文字を 2 桁の 16 進数に変換した N_OR_S の 16 進文字列を返す。これは 0xff 文字列の逆。
mysql> SELECT HEX(255);
        -> 'FF'
mysql> SELECT HEX("abc");
        -> 616263
mysql> SELECT 0x616263;
        -> "abc"
mysql> SELECT HEX('あ');
        -> 'A4A2'   ; # 注意 EUC-JP コードでの結果
INSERT(str,pos,len,newstr)
str 内の、位置 pos から始まる長さ len の部分文字列を文字列 newstr に置き換えた文字列を返す。
mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
        -> 'QuWhattic'
mysql> SELECT INSERT('あいうえお', 3, 2, 'か');
        -> あいかお
この関数はマルチバイト文字に対応している。
INSTR(str,substr)
文字列 str に最初に出現する部分文字列 substr の位置を返す。これは LOCATE() の 2 つの引数を使用する形式と同じだが、引数の順序が入れ替わっている。
mysql> SELECT INSTR('foobarbar', 'bar');
        -> 4
mysql> SELECT INSTR('xbar', 'foobar');
        -> 0
mysql> SELECT INSTR('あいうえお', 'う');
        -> 3
この関数はマルチバイト文字に対応している。 MySQL 3.23 では、この関数では大文字と小文字が区別されるが(ケース依存)、バージョン 4.0 では、どちらかの引数がバイナリ文字列の場合にのみケース依存になる。
LCASE(str)
LCASE()LOWER() のシノニム。
LEFT(str,len)
文字列 str の左端にある長さ len の文字を返す。
mysql> SELECT LEFT('foobarbar', 5);
        -> 'fooba'
mysql> SELECT LEFT('あいうえお', 2);
        -> 'あい'
LENGTH(str)
文字列 str の長さ(バイト)を返す。1個のマルチバイト文字は複数バイトになる。 したがって、5 個の 2 バイト文字で構成される文字列の場合、LENGTH() では 10 が返るが、CHAR_LENGTH() では 5 が返る。
mysql> SELECT LENGTH('text');
        -> 4
mysql> SELECT LENGTH('あいうえお');
        -> 10
LOAD_FILE(file_name)
ファイルを読み取り、ファイルの内容を文字列として返す。ファイルはサーバ上に存在しなければならず、ファイルのフルパス名を指定する必要がある。また、FILE 権限が必要となる。ファイルは全ユーザが読み取り可能でなければならず、max_allowed_packet より小さいサイズでなければならない。 ファイルが存在しない場合や、上記の理由のいずれかによって読み取り不可能な場合、この関数は NULL を返す。
mysql> UPDATE tbl_name
           SET blob_column=LOAD_FILE("/tmp/picture")
           WHERE id=1;
MySQL バージョン 3.23 以外のバージョンを使用している場合は、ファイルの読み取りをアプリケーション内で行い、その後 INSERT/UPDATE ステートメントを作成して、アプリケーションからデータベースにファイルの内容を書き出す必要がある。MySQL++ ライブラリを使用している場合は、これを行う方法の 1 つを http://www.mysql.com/documentation/mysql++/mysql++-examples.html で参照できる。
LOCATE(substr,str)
LOCATE(substr,str,pos)
最初の構文は、文字列 str に最初に出現する部分文字列 substr の位置を返す。 2 番目の構文は、文字列 str の位置 pos 以降に最初に出現する部分文字列 substr の位置を返す。 str 内に substr が存在しない場合は 0 を返す。
mysql> SELECT LOCATE('bar', 'foobarbar');
        -> 4
mysql> SELECT LOCATE('xbar', 'foobar');
        -> 0
mysql> SELECT LOCATE('bar', 'foobarbar',5);
        -> 7
mysql> SELECT LOCATE('え', 'あいうえおうえ');
        -> 4
mysql> SELECT LOCATE('え', 'あいうえおうえ', 5);
        -> 7
この関数はマルチバイト文字に対応している。 MySQL 3.23 では、この関数では大文字と小文字が区別されるが(ケース依存)、バージョン 4.0 では、どちらかの引数がバイナリ文字列の場合にのみケース依存になる。
LOWER(str)
str のすべての文字を現在のキャラクタセット(デフォルトは ISO-8859-1 Latin1)のマッピングに基づいて小文字に変更した文字列を返す。
mysql> SELECT LOWER('QUADRATICALLY');
        -> 'quadratically'
mysql> SELECT LOWER('あいうえお');
        -> 'あいうえお'
この関数はマルチバイト文字に対応している。
LPAD(str,len,padstr)
文字列 strlen に指定された長さの文字になるよう、str の左側に文字列 padstr を埋め込んだ文字列を返す。strlen より長い場合は、戻り値は len の長さの文字に縮められる。
mysql> SELECT LPAD('hi',4,'??');
        -> '??hi'

#バージョン4.1以上では以下のようになります。
mysql> SELECT LPAD('あいう', 5 , 'X');
        -> 'XXあいう'

#バージョン4.1未満では以下のようになります。
mysql> SELECT LPAD('あいう', 8 , 'X');
        -> 'XXあいう'
mysql> SELECT LPAD('あいう', 8 , 'お');
        -> 'おあいう'
mysql> SELECT LPAD('あいう', 5 , 'X');
        -> 'あい ' ; #注意。最後は1byte
LTRIM(str)
文字列 str から先頭のスペース文字を削除した文字列を返す。
mysql> SELECT LTRIM('  barbar');
        -> 'barbar'
MAKE_SET(bits,str1,str2,...)
bits に指定されたビットのセットに対応するビットを持つ文字列から成るセット(`,' 文字で間を区切られた各部分文字列を含む文字列)を返す。str1 はビット 0 に対応し、str2 はビット 1 に対応する(以下同様に続く)。str1, str2, ... 内の NULL 文字列は結果には組み込まれない。
mysql> SELECT MAKE_SET(1,'a','b','c');
        -> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
        -> 'hello,world'
mysql> SELECT MAKE_SET(0,'a','b','c');
        -> ''
MID(str,pos,len)
MID(str,pos,len)SUBSTRING(str,pos,len) のシノニム。
OCT(N)
longlong 型の数値である N の 8 進値の文字列表現を返す。これは CONV(N,10,8) と同じ。 NNULL のときは NULL を返す。
mysql> SELECT OCT(12);
        -> '14'
OCTET_LENGTH(str)
OCTET_LENGTH()LENGTH() のシノニム。
ORD(str)
文字列 str の左端の文字がマルチバイト文字の場合に、次の式を使用して計算した、その文字を構成する各文字の ASCII コード値を返す。((最初のバイトの ASCII コード)*256+(2 番目のバイトの ASCII コード))[*256+3 番目のバイトの ASCII コード...] 左端の文字がマルチバイト文字でないときは、ASCII() 関数を使用した場合と同じ値を返す。
mysql> SELECT ORD('2');
        -> 50
mysql> SELECT ORD('あ');
        -> 42146   ; #注意 EUC-JP コードでの結果
POSITION(substr IN str)
POSITION(substr IN str)LOCATE(substr,str) のシノニム。
QUOTE(str)
指定された文字列を、SQL ステートメントで正しいエスケープデータ値として使用できるように引用符で囲んだ文字列を返す。結果の文字列は単一引用符で囲まれ、文字列内に単一引用符(`'')、バックスラッシュ(`\')、ASCII NUL、Control-Z が含まれている場合はその直前にバックスラッシュが挿入される。引数が NULL の場合は、``NULL'' という語が単一引用符で囲まれずに返される。 QUOTE() 関数は MySQL バージョン 4.0.3 で追加された。 @c end_description_for_help_topic
mysql> SELECT QUOTE("Don't");
        -> 'Don\'t!'
mysql> SELECT QUOTE(NULL);
        -> NULL
REPEAT(str,count)
文字列 str を、count に指定された回数だけ繰り返した文字列を返す。count <= 0 の場合は、空の文字列を返す。str または countNULL の場合は、NULL を返す。
mysql> SELECT REPEAT('MySQL', 3);
        -> 'MySQLMySQLMySQL'
mysql> SELECT REPEAT('げ', 3);
        -> 'げげげ'
REPLACE(str,from_str,to_str)
文字列 str に含まれる文字列 from_str をすべて文字列 to_str に置換した文字列を返す。
mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
        -> 'WwWwWw.mysql.com'
mysql> SELECT REPLACE('あいあいうえお', 'い', 'す');
        -> 'あすあすうえお'
この関数はマルチバイト文字に対応している。
REVERSE(str)
文字列 str 内の文字の順序を逆にした文字列を返す。
mysql> SELECT REVERSE('abc');
        -> 'cba'
mysql> SELECT REVERSE('あいうえお');
        -> 'おえういあ'
この関数はマルチバイト文字に対応している。
RIGHT(str,len)
文字列 str の右端にある長さ len の文字を返す。
mysql> SELECT RIGHT('foobarbar', 4);
        -> 'rbar'
mysql> SELECT RIGHT('あいうえお', 4);
        -> 'いうえお'
この関数はマルチバイト文字に対応している。
RPAD(str,len,padstr)
文字列 strlen に指定された長さの文字になるよう、str の右側に文字列 padstr を埋め込んだ文字列を返す。strlen より長い場合は、戻り値は len の長さの文字に縮められる。
mysql> SELECT RPAD('hi',5,'?');
        -> 'hi???'

#バージョン4.1以上では以下のようになります。
mysql> SELECT RPAD('あい', 5, 'う');
        -> 'あいううう'

#バージョン4.1未満では以下のようになります。
mysql> SELECT RPAD('あい', 5, 'X');
        -> 'あいX'
mysql> SELECT RPAD('あい', 5, 'う');
        -> 'あい '  ; # 注意: 最後はマルチバイト文字の上位1byte
RTRIM(str)
文字列 str から後続のスペース文字を削除した文字列を返す。
mysql> SELECT RTRIM('barbar   ');
        -> 'barbar'
この関数はマルチバイト文字に対応している。
SOUNDEX(str)
文字列 str の soundex 文字列を返す。発音が似通った 2 つの文字列の soundex 文字列は同じものになる。標準の soundex 文字列の長さは 4 文字だが、SOUNDEX() 関数は任意の長さの文字列を返す。返された値に対して SUBSTRING() を使用すると、標準の soundex 文字列が得られる。指定された文字列内の英数字以外の文字は無視される。A 〜 Z の範囲外の各国語のアルファベット文字はすべて母音として扱われる。
mysql> SELECT SOUNDEX('Hello');
        -> 'H400'
mysql> SELECT SOUNDEX('Quadratically');
        -> 'Q36324'
expr1 SOUNDS LIKE expr2
SOUNDEX(expr1)=SOUNDEX(expr2) と同じ(バージョン 4.1 以降でのみ利用可能)。
SPACE(N)
N に指定された数のスペース文字で構成される文字列を返す。
mysql> SELECT SPACE(6);
        -> '      '
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
len 引数のない形式の場合は、文字列 str 内の位置 pos 以降の部分文字列を返す。 len 引数のある形式の場合は、文字列 str の位置 pos 以降の、len に指定された長さの部分文字列を返す。 FROM を使用する形式は SQL-92 の構文。
mysql> SELECT SUBSTRING('Quadratically',5);
        -> 'ratically'
mysql> SELECT SUBSTRING('foobarbar' FROM 4);
        -> 'barbar'
mysql> SELECT SUBSTRING('Quadratically',5,6);
        -> 'ratica'
mysql> SELECT SUBSTRING('あいうえおかきくけこ', 5);
        -> 'おかきくけこ'
この関数はマルチバイト文字に対応している。
SUBSTRING_INDEX(str,delim,count)
文字列 str から、delim に指定された区切り記号の count 個目の出現位置の直前までの部分文字列を返す。 count に指定された数が正数の場合は、(左から数えて)指定された数の最後の区切り記号の左側にあるすべての文字を返す。 count に指定された数が負数の場合は、(右から数えて)指定された数の最後の区切り記号の右側にあるすべての文字を返す。
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
        -> 'www.mysql'
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
        -> 'mysql.com'
mysql> SELECT SUBSTRING_INDEX('あいんうえおんかき', 'ん', 2);
        -> 'あいんうえお'
mysql> SELECT SUBSTRING_INDEX('あいんうえおんかき', 'ん', -2);
        -> 'うえおんかき'
この関数はマルチバイト文字に対応している。
TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
remstr に指定されたすべてのプリフィックスまたはサフィックス(あるいはその両方)を、文字列 str から削除した文字列を返す。指定子 BOTHLEADINGTRAILING がいずれも指定されていない場合は、BOTH が指定されたとみなされる。remstr が指定されていない場合は、スペースが削除される。
mysql> SELECT TRIM('  bar   ');
        -> 'bar'
mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
        -> 'barxxx'
mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
        -> 'bar'
mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
        -> 'barx'
mysql> SELECT TRIM(BOTH 'お' FROM 'おあいうえお');
        -> 'あいうえ'
この関数はマルチバイト文字に対応している。
UCASE(str)
UCASE()UPPER() のシノニム。
UPPER(str)
str のすべての文字を現在のキャラクタセット(デフォルトは ISO-8859-1 Latin1)のマッピングに基づいて大文字に変更した文字列を返す。
mysql> SELECT UPPER('Hej');
        -> 'HEJ'
mysql> SELECT UPPER('へい');
        -> 'へい'
この関数はマルチバイト文字に対応している。

6.3.2.1 文字列比較関数

MySQL では、必要に応じて数値から文字列への、また文字列から数値への変換が自動で行われます。

mysql> SELECT 1+"1";
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

数値を文字列に明示的に変換するには、対象の数値を引数として CONCAT() に渡します。

文字列関数の引数としてバイナリ文字列を指定した場合、返される文字列もバイナリ文字列になります。文字列に変換された数値はバイナリ文字列として扱われます。これは比較にのみ影響します。

通常、文字列の比較でいずれかの式がケース依存の場合、比較はケース依存方式で実行されます。

expr LIKE pat [ESCAPE 'escape-char']
SQL の単純な正規表現比較を使用したパターンマッチ。1(TRUE)または 0(FALSE)を返す。LIKE では、次の 2 つのワイルドカード文字をパターン内で使用できる。
文字 説明
% 任意の数の文字(ゼロ文字を含む)と一致する。
_ 厳密に 1 つの文字と一致する。
mysql> SELECT 'David!' LIKE 'David_';
        -> 1
mysql> SELECT 'David!' LIKE '%D%v%';
        -> 1
ワイルドカード文字を通常の文字として扱う場合は、直前にエスケープ文字を付ける。特定の ESCAPE 文字を指定しないと、`\' をエスケープ文字として使用するものとみなされる。
文字列 説明
\% 1 つの % 文字と一致する。
\_ 1 つの _ 文字と一致する。
mysql> SELECT 'David!' LIKE 'David\_';
        -> 0
mysql> SELECT 'David_' LIKE 'David\_';
        -> 1
別のエスケープ文字を指定する場合は、次のように、ESCAPE 節を使用する。
mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
        -> 1
次の 2 つのステートメントは、オペランドのどちらか一方がバイナリ文字列の場合、文字列の比較がケース依存方式で行われることを示している。
mysql> SELECT 'abc' LIKE 'ABC';
        -> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
        -> 0
LIKE は数値式で使用できる(これは SQL-99 の LIKE に対する MySQL の拡張)。
mysql> SELECT 10 LIKE '1%';
        -> 1
mysql> SELECT 'いあ' LIKE '%い%';
        -> 1
mysql> SELECT 'イあ' LIKE '%い%';
        -> 0
# 注意: EUC-JP コードで、'イあ' は 0xA5A4A4A2。'い' は 0xA4A4。
注意:MySQL では文字列で C のエスケープ構文(`\n' など)を使用するため、LIKE の文字列に `\' を挿入するときは、2 倍の数の `\' を使用する必要がある。たとえば、`\n' を検索する場合は、`\\n' と指定する。また、`\' を検索する場合は、`\\\\' と指定する(バックスラッシュはパーサによって一度取り除かれ、パターンマッチの実行時にもう一度取り除かれる。そして、残った 1 つのバックスラッシュがマッチングの対象となる)。
MATCH (col1,col2,...)AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION] )
MATCH ... AGAINST() は全文検索に使用され、カラム (col1,col2,...) のテキストと、クエリ expr のテキストとの関連性(類似度)を返す。関連性は正の浮動小数点数で表現される。関連性がゼロのときは、類似性がまったくないことを意味する。 MATCH ... AGAINST() は MySQL バージョン 3.23.23 以降で利用できる。IN BOOLEAN MODE 拡張はバージョン 4.0.1 で追加され、WITH QUERY EXPANSION は 4.1.1 で追加された。 詳細および使用例については、section 6.8 MySQL 全文検索を参照。
expr NOT LIKE pat [ESCAPE 'escape-char']
NOT (expr LIKE pat [ESCAPE 'escape-char']) と同じ。
expr NOT REGEXP pat
expr NOT RLIKE pat
NOT (expr REGEXP pat) と同じ。
expr REGEXP pat
expr RLIKE pat
パターン pat に対する文字列式 expr のパターンマッチを実行する。パターンとして、拡張正規表現を使用できる。 See section G MySQL の正規表現exprpat とマッチする場合は 1 を返し、マッチしない場合は 0 を返す。RLIKE は、mSQL との互換性を確保するための、REGEXP のシノニム。 注意:MySQL では、文字列で C のエスケープ構文(`\n' など)を使用するため、REGEXP の文字列に `\' を挿入するときは、2 倍の数の `\' を使用する必要がある。 MySQL バージョン 3.23.4 以降では、REGEXP は通常(非バイナリ)の文字列に対してはケース非依存。
mysql> SELECT 'Monty!' REGEXP 'm%y%%';
        -> 0
mysql> SELECT 'Monty!' REGEXP '.*';
        -> 1
mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
        -> 1
mysql> SELECT "a" REGEXP "A", "a" REGEXP BINARY "A";
        -> 1  0
mysql> SELECT "a" REGEXP "^[a-d]";
        -> 1
REGEXPRLIKE では、現在のキャラクタセット(デフォルトでは ISO-8859-1 Latin1)に基づいて文字の型が決定される。
STRCMP(expr1,expr2)
STRCMP() 両方の文字列が同じものである場合は 0 を返し、現在のソート順で最初の引数が 2 番目の引数より小さい場合は -1 を返し、それ以外の場合は -1 を返す。
mysql> SELECT STRCMP('text', 'text2');
        -> -1
mysql> SELECT STRCMP('text2', 'text');
        -> 1
mysql> SELECT STRCMP('text', 'text');
        -> 0

6.3.2.2 ケース依存性

BINARY
BINARY 演算子はこの演算子の後に続く文字列をバイナリ文字列にキャストする。 この演算子を使用すれば、BINARY または BLOB として定義されていないカラムに対しても、強制的にケース依存にしたカラムの比較を簡単に行うことができる。
mysql> SELECT "a" = "A";
        -> 1
mysql> SELECT BINARY "a" = "A";
        -> 0
BINARY stringCAST(string AS BINARY) の省略形。 See section 6.3.5 キャスト関数BINARY は MySQL バージョン 3.23.0 で導入された。 注意: MySQL の一部のコンテキストでは、インデックス付きのカラムを BINARY にキャストすると、インデックスを効率的に使用できなくなる。

BLOB 型の文字列をケース非依存方式で比較する必要がある場合は、比較の実行前に BLOB から大文字に変換することによって、常にこの比較が可能になります。

SELECT 'A' LIKE UPPER(blob_col) FROM table_name;

まもなく、異なるキャラクタセット間のキャストを導入する予定です。この導入によって、文字列の比較をさらに柔軟に実行できるようになります。

6.3.3 数値関数

6.3.3.1 算術演算

通常の算術演算子を利用することができます。注意: `-'`+'`*' で、両方の引数が整数の場合、結果は BIGINT(64 ビット)の精度で計算されます。 どちらか一方の引数が符号なしの整数で、もう一方も整数の場合、結果は符合なしの整数になります。 See section 6.3.5 キャスト関数

+
加算
mysql> SELECT 3+5;
        -> 8
-
減算
mysql> SELECT 3-5;
        -> -2
*
乗算
mysql> SELECT 3*5;
        -> 15
mysql> SELECT 18014398509481984*18014398509481984.0;
        -> 324518553658426726783156020576256.0
mysql> SELECT 18014398509481984*18014398509481984;
        -> 0
最後の式の結果は正しくない。これは、この整数乗算の結果が BIGINT 計算の 64 ビットの範囲を超えるため。
/
除算
mysql> SELECT 3/5;
        -> 0.60
ゼロで割ると結果は NULL になる。
mysql> SELECT 102/(1-1);
        -> NULL
除算が BIGINT 演算で計算されるのは、結果が整数に変換されるコンテキストでその演算が実行された場合に限られる。

6.3.3.2 数学関数

すべての数学関数はエラーの場合 NULL を返します。

-
単項マイナス。引数の符号を変更する。
mysql> SELECT - 2;
        -> -2
注意: BIGINT 型の値に対してこの演算子を使用すると、戻り値は BIGINT になる。したがって、値が -2^63 になる可能性がある整数に対しては - の使用を避ける。
ABS(X)
X の絶対値を返す。
mysql> SELECT ABS(2);
        -> 2
mysql> SELECT ABS(-32);
        -> 32
この関数は BIGINT 型の値に対して使用しても問題ない。
ACOS(X)
X のアークコサイン(つまり、コサインが X である値)を返す。X-1 から 1 の範囲にないときは NULL を返す。
mysql> SELECT ACOS(1);
        -> 0.000000
mysql> SELECT ACOS(1.0001);
        -> NULL
mysql> SELECT ACOS(0);
        -> 1.570796
ASIN(X)
X のアークサイン(つまり、サインが X である値)を返す。X-11 の範囲にないときは NULL を返す。
mysql> SELECT ASIN(0.2);
        -> 0.201358
mysql> SELECT ASIN('foo');
        -> 0.000000
ATAN(X)
X のアークタンジェント(つまり、タンジェントが X である値)を返す。
mysql> SELECT ATAN(2);
        -> 1.107149
mysql> SELECT ATAN(-2);
        -> -1.107149
ATAN(Y,X)
ATAN2(Y,X)
2 つの変数 XY のアークタンジェントを返す。これは Y / X によるアークタンジェントの計算と似ているが、異なる点として、この場合、両方の引数の符号に基づいて結果の四分円が決定される。
mysql> SELECT ATAN(-2,2);
        -> -0.785398
mysql> SELECT ATAN2(PI(),0);
        -> 1.570796
CEILING(X)
CEIL(X)
X 以上の最も小さい整数値を返す。
mysql> SELECT CEILING(1.23);
        -> 2
mysql> SELECT CEIL(-1.23);
        -> -1
CEIL() エイリアスはバージョン 4.0.6 で追加された。 注意: 戻り値は BIGINT に変換される。
COS(X)
X(ラジアン)のコサインを返す。
mysql> SELECT COS(PI());
        -> -1.000000
COT(X)
X のコタンジェントを返す。
mysql> SELECT COT(12);
        -> -1.57267341
mysql> SELECT COT(0);
        -> NULL
CRC32(expr)
巡回冗長検査値を計算し、32 ビットの符号なしの値を返す。 引数が NULL の場合、結果は NULL になる。引数では、文字列の指定が前提となる。文字列以外の値を指定しても、文字列として扱われる。
mysql> SELECT CRC32('MySQL');
        -> 3259397556
CRC32() は MySQL 4.1.0 以降で利用できる。
DEGREES(X)
引数 X をラジアンから度に変換して返す。
mysql> SELECT DEGREES(PI());
        -> 180.000000
DIV
整数の除算。 FLOOR() と同様。ただし、BIGINT 型の値に対応している。
mysql> SELECT 5 DIV 2
        -> 2
DIV は MySQL 4.1.0 の新機能。
EXP(X)
e(自然対数の底)を X 乗した値を返す。
mysql> SELECT EXP(2);
        -> 7.389056
mysql> SELECT EXP(-2);
        -> 0.135335
FLOOR(X)
X 以下の最も大きい整数値を返す。
mysql> SELECT FLOOR(1.23);
        -> 1
mysql> SELECT FLOOR(-1.23);
        -> -2
注意: 戻り値は BIGINT に変換される。
GREATEST(X,Y,...)
最も大きい(つまり、最も大きい値を指定された)引数を返す。 各引数の比較は LEAST の場合と同じ規則に基づいて行われる。
mysql> SELECT GREATEST(2,0);
        -> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
        -> 767.0
mysql> SELECT GREATEST("B","A","C");
        -> "C"
バージョン 3.22.5 より前の MySQL では、GREATEST の代わりに MAX() を使用できる。
LEAST(X,Y,...)
指定された 2 つ以上の引数の中で、最も小さい(つまり、最も小さい値を指定された)引数を返す。 各引数の比較は、次の規則に基づいて行われる。
  • 戻り値が INTEGER のコンテキストで使用される場合、またはすべての引数に整数値が指定されている場合は、各引数は整数として比較される。
  • 戻り値が REAL のコンテキストで使用される場合、またはすべての引数に実数が指定されている場合は、各引数は実数として比較される。
  • いずれかの引数がケース依存文字列である場合は、各引数はケース依存文字列として比較される。
  • その他の場合、引数はケース非依存文字列として比較される。
mysql> SELECT LEAST(2,0);
        -> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
        -> 3.0
mysql> SELECT LEAST("B","A","C");
        -> "A"
バージョン 3.22.5 より前の MySQL では、LEAST の代わりに MIN() を使用できる。
LN(X)
X の自然対数を返す。
mysql> SELECT LN(2);
        -> 0.693147
mysql> SELECT LN(-2);
        -> NULL
この関数は MySQL バージョン 4.0.3 で追加された。 MySQL における LOG(X) のシノニム。
LOG(X)
LOG(B,X)
パラメータ 1 つで呼び出された場合、この関数は X の自然対数を返す。
mysql> SELECT LOG(2);
        -> 0.693147
mysql> SELECT LOG(-2);
        -> NULL
パラメータ 2 つで呼び出された場合、この関数は任意の底 B に対する X の自然対数を返す。
mysql> SELECT LOG(2,65536);
        -> 16.000000
mysql> SELECT LOG(1,100);
        -> NULL
任意の底を指定できるオプションは MySQL バージョン 4.0.3 で追加された。 LOG(B,X)LOG(X)/LOG(B) と同じ。
LOG2(X)
2 を底とする X の自然対数を返す。
mysql> SELECT LOG2(65536);
        -> 16.000000
mysql> SELECT LOG2(-100);
        -> NULL
LOG2() は、特定の数値の格納に何ビット必要か調べるのに役立つ。 この関数は MySQL バージョン 4.0.3 で追加された。 それより前のバージョンでは、代わりに LOG(X)/LOG(2) を使用できる。
LOG10(X)
10 を底とする X の自然対数を返す。
mysql> SELECT LOG10(2);
        -> 0.301030
mysql> SELECT LOG10(100);
        -> 2.000000
mysql> SELECT LOG10(-100);
        -> NULL
MOD(N,M)
%
モジュロ(C の % 演算子に類する)。 NM で割ったときの余りを返す。
mysql> SELECT MOD(234, 10);
        -> 4
mysql> SELECT 253 % 7;
        -> 1
mysql> SELECT MOD(29,9);
        -> 2
mysql> SELECT 29 MOD 9;
        -> 2
この関数は BIGINT 型の値に使用しても問題ない。 最後の例は MySQL 4.1 でのみ有効。
PI()
π の値を返す。小数部の表示桁数はデフォルトで 5 桁だが、MySQL の内部では、π に完全な倍精度が使用される。
mysql> SELECT PI();
        -> 3.141593
mysql> SELECT PI()+0.000000000000000000;
        -> 3.141592653589793116
POW(X,Y)
POWER(X,Y)
XY 乗した値を返す。
mysql> SELECT POW(2,2);
        -> 4.000000
mysql> SELECT POW(2,-2);
        -> 0.250000
RADIANS(X)
引数 X を度からラジアンに変換して返す。
mysql> SELECT RADIANS(90);
        -> 1.570796
RAND()
RAND(N)
01.0 の範囲のランダムな浮動小数点数を返す。 整数の引数 N が指定された場合、その整数がシード値(繰り返し可能な数列を生成)として使用される。
mysql> SELECT RAND();
        -> 0.9233482386203
mysql> SELECT RAND(20);
        -> 0.15888261251047
mysql> SELECT RAND(20);
        -> 0.15888261251047
mysql> SELECT RAND();
        -> 0.63553050033332
mysql> SELECT RAND();
        -> 0.70100469486881
ORDER BY 節ではカラムが複数回評価されるため、RAND() の値を含むカラムは、ORDER BY 節では使用できない。 しかし、バージョン 3.23 以降では、SELECT * FROM table_name ORDER BY RAND() を使用できる。 これは、SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000 のセットからランダムなサンプルを得るのに役立つ。 注意: WHERE 節の RAND() は、WHERE が実行されるたびに再評価される。 RAND() は完全な乱数ジェネレータではなく、むしろ同じ MySQL バージョンのプラットフォーム間で移植可能な乱数を随時、すばやく生成するための方法として利用できる。
ROUND(X)
ROUND(X,D)
引数 X を最も近い整数に丸めた値を返す。 引数が 2 つの形式では、小数部の桁数を D に指定された桁数に丸める。
mysql> SELECT ROUND(-1.23);
        -> -1
mysql> SELECT ROUND(-1.58);
        -> -2
mysql> SELECT ROUND(1.58);
        -> 2
mysql> SELECT ROUND(1.298, 1);
        -> 1.3
mysql> SELECT ROUND(1.298, 0);
        -> 1
mysql> SELECT ROUND(23.298, -1);
        -> 20
注意: 引数の値が 2 つの整数の中間にある場合の ROUND() の動作は、C ライブラリの実装に応じて決まる。実装に応じて、最も近い偶数に丸められる場合と、常に切り上げまたは切り下げられる場合、あるいは常にゼロ方向に丸められる場合がある。特定の丸め方法を必要とする場合は、この関数ではなく、TRUNCATE()FLOOR() などの明確に定義された関数を使用するようにする。
SIGN(X)
X が負数か、ゼロか、正数かに応じて、この引数の符号を -10、または 1 として返す。
mysql> SELECT SIGN(-32);
        -> -1
mysql> SELECT SIGN(0);
        -> 0
mysql> SELECT SIGN(234);
        -> 1
SIN(X)
X(ラジアン)のサインを返す。
mysql> SELECT SIN(PI());
        -> 0.000000
SQRT(X)
X の負数でない平方根を返す。
mysql> SELECT SQRT(4);
        -> 2.000000
mysql> SELECT SQRT(20);
        -> 4.472136
TAN(X)
X(ラジアン)のタンジェントを返す。
mysql> SELECT TAN(PI()+1);
        -> 1.557408
TRUNCATE(X,D)
数値 X の小数部を D に指定された桁数に切り捨てた値を返す。D0 の場合、結果の値は小数点も小数部も持たない。
mysql> SELECT TRUNCATE(1.223,1);
        -> 1.2
mysql> SELECT TRUNCATE(1.999,1);
        -> 1.9
mysql> SELECT TRUNCATE(1.999,0);
        -> 1
mysql> SELECT TRUNCATE(-1.999,1);
        -> -1.9
MySQL 3.23.51 以降、すべての数値はゼロ方向に丸められる。 D が負数の場合、その数値の小数部以外の部分もゼロになる。
mysql> SELECT TRUNCATE(122,-2);
       -> 100
注意: 小数は通常、正確な数値としてではなく、倍精度の値としてコンピュータに格納されるため、次のようなおかしな結果が出ることがある。
mysql> SELECT TRUNCATE(10.28*100,0);
       -> 1027
これは、10.28 が実際には 10.2799999999999999 のような値として格納されることによって発生する。

6.3.4 日付と時刻関数

このセクションでは、時間に関係する値の操作に使用できる関数について説明します。 日付と時刻の各データ型の範囲と、値を指定するときの有効な形式については、section 6.2.2 日付と時刻型を参照してください。

日付関数の使用例を次に示します。このクエリでは、過去 30 日以内の日付の date_col 値を持つすべてのレコードが選択されます。

mysql> SELECT something FROM tbl_name
           WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;

(このクエリでは、将来の日付を持つレコードも選択されます。)

日付値を前提とする関数は、通常、日付時刻値を受け入れて、時刻部分を無視します。時刻値を前提とする関数は、通常、日付時刻値を受け入れて、日付部分を無視します。

現在の日付または時刻をそれぞれ返す関数は、クエリごとに、そのクエリの開始時に 1 回だけ評価されます。したがって、1 つのクエリ内で NOW() などの関数を何度も参照しても、常に同じ結果になります。この原則は、CURDATE()CURTIME()UTC_DATE()UTC_TIME()UTC_TIMESTAMP()、およびこれらのあらゆるシノニムに同様に適用されます。

以下の関数の説明で示している戻り値の範囲は、完全な日付に対して適用されます。日付が ``ゼロ'' 値であったり、'2001-11-00' などの不完全な日付である場合、日付の一部を取り出す関数では 0 が返ります。たとえば、DAYOFMONTH('2001-11-00') からは 0 が返ります。

ADDDATE(date,INTERVAL expr type)
ADDDATE(expr,days)
2 番目の引数の INTERVAL を指定する形式で呼び出した場合、ADDDATE()DATE_ADD() とシノニムになる。関連する関数 SUBDATE()DATE_SUB() のシノニム。
mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
2 番目の構文は MySQL 4.1.1 以降で使用できる。expr には日付式か日付時刻式を指定し、days には expr に加える日数を指定する。
mysql> SELECT ADDDATE('1998-01-02', 31);
        -> '1998-02-02'
ADDTIME(expr,expr2)
ADDTIME() では、exprexpr2 を加えた結果が返される。 expr には日付式か日付時刻式を指定し、expr2 には時刻式を指定する。
mysql> SELECT ADDTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
        -> '1998-01-02 01:01:01.000001'
mysql> SELECT ADDTIME("01:00:00.999999", "02:00:00.999998");
        -> '03:00:01.999997'
ADDTIME() は MySQL 4.1.1 で追加された。
CURDATE()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'YYYY-MM-DD' または YYYYMMDD 形式の値として、現在の日付を返す。
mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215
CURRENT_DATE
CURRENT_DATE()
CURRENT_DATECURRENT_DATE()CURDATE() のシノニム。
CURTIME()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'HH:MM:SS' または HHMMSS 形式の値として、現在の時刻を返す。
mysql> SELECT CURTIME();
        -> '23:50:26'
mysql> SELECT CURTIME() + 0;
        -> 235026
CURRENT_TIME
CURRENT_TIME()
CURRENT_TIMECURRENT_TIME()CURTIME() のシノニム。
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMPCURRENT_TIMESTAMP()NOW() のシノニム。
DATE(expr)
日付式または日付時刻式 expr の日付部分を取り出す。
mysql> SELECT DATE('2003-12-31 01:02:03');
        -> '2003-12-31'
DATE() は MySQL 4.1.1 以降で使用できる。
DATEDIFF(expr,expr2)
DATEDIFF() は開始日 expr と終了日 expr2 との間の日数を返す。 exprexpr2 には、日付式か、日付時刻式を指定する。 計算は値の日付部分のみに基づいて行われる。
mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
        -> 1
mysql> SELECT DATEDIFF('1997-11-31 23:59:59','1997-12-31');
        -> -30
DATEDIFF() は MySQL 4.1.1 で追加された。
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
これらの関数では日付演算が実行される。 MySQL バージョン 3.23 以降では、+ 演算子のどちらかの側にINTERVAL expr type を使用できる。この場合、もう一方の側の式には日付値または日付時刻値を指定する。 - 演算子を使用する場合は、演算子の右側にのみ INTERVAL expr type を使用できる。これは、日付値または日付時刻値を間隔から差し引いても意味がないため(下の例を参照)。 date には、開始日とする DATETIME または DATE 値を指定する。expr には、開始日に加える、または開始日から差し引く間隔値を表す式を文字列として指定する。先頭に `-' を付けて負の間隔を表すこともできる。type には、式の解釈方法を示すキーワードを指定する。 次の表に、type 引数と expr 引数がどのように関連するかを示す。
type 前提となる expr形式
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS
DAY DAYS
MONTH MONTHS
YEAR YEARS
MINUTE_SECOND 'MINUTES:SECONDS'
HOUR_MINUTE 'HOURS:MINUTES'
DAY_HOUR 'DAYS HOURS'
YEAR_MONTH 'YEARS-MONTHS'
HOUR_SECOND 'HOURS:MINUTES:SECONDS'
DAY_MINUTE 'DAYS HOURS:MINUTES'
DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS'
DAY_MICROSECOND 'DAYS.MICROSECONDS'
HOUR_MICROSECOND 'HOURS.MICROSECONDS'
MINUTE_MICROSECOND 'MINUTES.MICROSECONDS'
SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
MICROSECOND 'MICROSECONDS'
typeDAY_MICROSECONDHOUR_MICROSECONDMINUTE_MICROSECONDSECOND_MICROSECONDMICROSECOND は、MySQL 4.1.1 以降で使用できる。 MySQL では、expr の形式で任意の句読記号を使用できる。 上の表では、これらの句読記号の一部を示している。date 引数に DATE 型の値を指定し、計算に YEARMONTHDAY 部分のみを組み込む(つまり、時刻部分は含めない)場合、結果は DATE 型の値になる。それ以外の場合、DATETIME 型の値が返される。
mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;
        -> '1998-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '1997-12-31';
        -> '1998-01-01'
mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND;
        -> '1997-12-31 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 SECOND);
        -> '1998-01-01 00:00:00'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 DAY);
        -> '1998-01-01 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL '1:1' MINUTE_SECOND);
        -> '1998-01-01 00:01:00'
mysql> SELECT DATE_SUB('1998-01-01 00:00:00',
    ->                 INTERVAL '1 1:1:1' DAY_SECOND);
        -> '1997-12-30 22:58:59'
mysql> SELECT DATE_ADD('1998-01-01 00:00:00',
    ->                 INTERVAL '-1 10' DAY_HOUR);
        -> '1997-12-30 14:00:00'
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
    ->                 INTERVAL '1.999999' SECOND_MICROSECOND);
        -> '1993-01-01 00:00:01.000001'
指定した間隔値が短すぎる場合(つまり、type キーワードによって想定される間隔部分の一部を含んでいない場合)、MySQL では、間隔値の左端の部分がないとみなされる。たとえば、typeDAY_SECOND として指定すると、expr の値は、日、時、分、秒の各部で構成されると想定される。この場合、'1:10' のような値を指定すると、値は日部分と時間部分を持たず、分と秒を表すと解釈される。つまり、'1:10' DAY_SECOND と指定した場合、'1:10' MINUTE_SECOND と指定した場合と同じように解釈されることになる。これは、MySQL で TIME 値が 1 日の時刻ではなく経過時間として解釈されるのに類する。 注意:時刻部分を持つ値を日付値に加えたり、日付値から差し引いたりすると、結果は自動的に日付時刻型の値に変換される。
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);
        -> '1999-01-02'
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);
        -> '1999-01-01 01:00:00'
誤った日付を使用すると、結果は NULL になる。MONTHYEAR_MONTHYEAR のいずれかを加えた結果の日付が、新しい月の最大日数より大きい場合、新しい月の最大日数に調整される。
mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);
        -> '1998-02-28'
注意: 上記の例で、キーワード INTERVALtype 指定子はケース非依存。
DATE_FORMAT(date,format)
format 文字列に合わせて、date 値を形式設定する。format 文字列では、次の指定子を使用できる。
指定子 説明
%M 月の名前(January..December)。
%W 曜日名(Sunday..Saturday)。
%D 英語のサフィックス付きの日付(0th1st2nd3rd など)。
%Y 4 桁の数値で表した年。
%y 2 桁の数値で表した年。
%X 日曜日を週の最初の日とした場合の週に使用する、4 桁の数値で表した年。%V と組み合わせて使用。
%x 月曜日を週の最初の日とした場合の週に使用する、4 桁の数値で表した年。%v と組み合わせて使用。
%a 略式の曜日名(Sun..Sat)。
%d 数値で表した日付(00..31)。
%e 数値で表した日付(0..31)。
%m 数値で表した月(00..12)。
%c 数値で表した月(0..12)。
%b 略式の月名(Jan..Dec)。
%j 年間を通した日にち(001..366)。
%H 時(00..23)。
%k 時(0..23)。
%h 時(01..12)。
%I 時(01..12)。
%l 時(1..12)。
%i 数値で表した分(00..59)。
%r 12 時間形式の時刻(hh:mm:ss に続けて AM または PM)。
%T 24 時間形式の時刻(hh:mm:ss)。
%S 秒(00..59)。
%s 秒(00..59)。
%f マイクロ秒(000000..999999)。
%p AM または PM
%w 曜日(0=Sunday..6=Saturday)。
%U 日曜日を週の最初の日とした場合の週(00..53)。
%u 月曜日を週の最初の日とした場合の週(00..53)。
%V 日曜日を週の最初の日とした場合の週(01..53)。%X と組み合わせて使用。
%v 月曜日を週の最初の日とした場合の週(01..53)。%x と組み合わせて使用。
%% リテラルの `%'
その他の文字はいずれも、解釈されずにそのまま結果にコピーされる。 %f 形式指定子は MySQL 4.1.1 以降で使用できる。 MySQL バージョン 3.23 以降では、形式指定子文字の前に `%' 文字を挿入する必要がある。それより前のバージョンの MySQL では、`%' の使用は任意。 月と日の指定子の範囲がゼロから始まっている理由は、MySQL 3.23 以降では、'2004-00-00' のような不完全な日付の格納が許容されるため。
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
        -> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%D %y %a %d %m %b %j');
        -> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
DAY(date)
DAY()DAYOFMONTH() のシノニム。 MySQL 4.1.1 以降で使用できる。
DAYNAME(date)
date に指定された日付の曜日名を返す。
mysql> SELECT DAYNAME('1998-02-05');
        -> 'Thursday'
DAYOFMONTH(date)
date に指定された日付に対し、131 の範囲の日にちを返す。
mysql> SELECT DAYOFMONTH('1998-02-03');
        -> 3
DAYOFWEEK(date)
date の曜日インデックス(1 = 日曜、2 = 月曜、... 7 = 土曜)を返す。これらのインデックス値は ODBC 標準に対応している。
mysql> SELECT DAYOFWEEK('1998-02-03');
        -> 3
DAYOFYEAR(date)
date に指定された日付に対し、1366 の範囲の年間を通した日にちを返す。
mysql> SELECT DAYOFYEAR('1998-02-03');
        -> 34
EXTRACT(type FROM date)
EXTRACT() 関数では、DATE_ADD()DATE_SUB() と同じ種類の間隔型指定子が使用される。日付演算を行なわず、日付の一部を抽出する。
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
       -> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
       -> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
       -> 20102
mysql> SELECT EXTRACT(MICROSECOND FROM "2003-01-02 10:30:00.00123");
        -> 123
FROM_DAYS(N)
指定された日数 N に対して DATE 型の値を返す。
mysql> SELECT FROM_DAYS(729669);
        -> '1997-10-07'
FROM_DAYS() では、グレゴリオ暦(1582 年)より前の値の指定は想定していない。これは、カレンダが変更されたときに失われた日数が考慮されないためである。
FROM_UNIXTIME(unix_timestamp)
FROM_UNIXTIME(unix_timestamp,format)
文字列と数値のどちらのコンテキストで使用されているかに応じて、unix_timestamp の値を 'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 形式で返す。
mysql> SELECT FROM_UNIXTIME(875996580);
        -> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
        -> 19971004222300
format を指定した場合、結果は format 文字列に基づいて形式設定される。format には、DATE_FORMAT() 関数の入力値と同じ指定子を組み込める。
mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),
    ->                      '%Y %D %M %h:%i:%s %x');
        -> '2003 6th August 06:22:58 2003'
GET_FORMAT(DATE | TIME | TIMESTAMP, 'EUR' | 'USA' | 'JIS' | 'ISO' | 'INTERNAL')
フォーマットの文字列を返す。この関数は、DATE_FORMAT() 関数や STR_TO_DATE() 関数と組み合わせて使用したり、サーバ変数 DATE_FORMATTIME_FORMATDATETIME_FORMAT を設定したりするときに役立つ。最初の引数には 3 つの入力可能値があり、2 番目の引数には 5 つの入力可能値があるため、結果として返されるフォーマット文字列は全部で 15 通りある(使用される指定子については、DATE_FORMAT() 関数の説明に含まれている表を参照)。
関数呼び出し 結果
GET_FORMAT(DATE,'USA') '%m.%d.%Y'
GET_FORMAT(DATE,'JIS') '%Y-%m-%d'
GET_FORMAT(DATE,'ISO') '%Y-%m-%d'
GET_FORMAT(DATE,'EUR') '%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL') '%Y%m%d'
GET_FORMAT(TIMESTAMP,'USA') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'JIS') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'ISO') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'EUR') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'INTERNAL') '%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA') '%h:%i:%s %p'
GET_FORMAT(TIME,'JIS') '%H:%i:%s'
GET_FORMAT(TIME,'ISO') '%H:%i:%s'
GET_FORMAT(TIME,'EUR') '%H.%i.%S'
GET_FORMAT(TIME,'INTERNAL') '%H%i%s'
ISO 形式は ISO 8601 ではなく、ISO 9075。
mysql> SELECT DATE_FORMAT('2003-10-03', GET_FORMAT(DATE, 'EUR')
        -> '03.10.2003'
mysql> SELECT STR_TO_DATE('10.31.2003', GET_FORMAT(DATE, 'USA'))
        -> 2003-10-31
mysql> SET DATE_FORMAT=GET_FORMAT(DATE, 'USA'); SELECT '2003-10-31';
        -> 10-31-2003
GET_FORMAT() は MySQL 4.1.1 以降で使用できる。 See section 5.5.6 SET 構文 を参照。
HOUR(time)
time に指定された時刻の時間部分の値を返す。戻り値の範囲は、1 日の時間を示す値の場合は 0 から 23
mysql> SELECT HOUR('10:05:03');
        -> 10
しかし、TIME 値の範囲は、実際にはこれよりずっと広いため、23 より大きい値が HOUR として返ることがある。

mysql> SELECT HOUR('272:59:59');
        -> 272
LAST_DAY(date)
指定された日付または日付時刻の値に対し、その値が含まれる月の最後の日にちを返す。引数が無効な場合は、NULL を返す。
mysql> SELECT LAST_DAY('2003-02-05'), LAST_DAY('2004-02-05');
        -> '2003-02-28', '2004-02-29'
mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
        -> '2004-01-31'
mysql> SELECT LAST_DAY('2003-03-32');
        -> NULL
LAST_DAY() は MySQL 4.1.1 以降で使用できる。
LOCALTIME
LOCALTIME()
LOCALTIMELOCALTIME()NOW() のシノニム。
LOCALTIMESTAMP
LOCALTIMESTAMP()
LOCALTIMESTAMPLOCALTIMESTAMP()NOW() のシノニム。
MAKEDATE(year,dayofyear)
指定された年の値と年間を通した日にちの値に対応する日付を返す。 dayofyear には、0 より大きい値を指定する必要がある。0 以下の値を指定すると、結果として NULL が返される。
mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);
        -> '2001-01-31', '2001-02-01'
mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
        -> '2001-12-31', '2004-12-30'
mysql> SELECT MAKEDATE(2001,0);
        -> NULL
MAKEDATE() は MySQL 4.1.1 以降で使用できる。
MAKETIME(hour,minute,second)
引数 hourminutesecond に指定された値から計算した時刻値を返す。
mysql> SELECT MAKETIME(12,15,30);
        -> '12:15:30'
MAKETIME() は MySQL 4.1.1 以降で使用できる。
MICROSECOND(expr)
時刻式または日付時刻式 expr からマイクロ秒を、0999999 の範囲内の数値として返す。
mysql> SELECT MICROSECOND('12:00:00.123456');
        -> 123456
mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010');
        -> 10
MICROSECOND() は MySQL 4.1.1 以降で使用できる。
MINUTE(time)
time に指定された時刻の分を、059 の範囲の値として返す。
mysql> SELECT MINUTE('98-02-03 10:05:03');
        -> 5
MONTH(date)
date に指定された日付の月を、112 の範囲の値として返す。
mysql> SELECT MONTH('1998-02-03');
        -> 2
MONTHNAME(date)
date に指定された月の名前を返す。
mysql> SELECT MONTHNAME('1998-02-05');
        -> 'February'
NOW()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 形式の値として、現在の日付と時刻を返す。
mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 19971215235026
PERIOD_ADD(P,N)
N に指定された月数を期間 PYYMM または YYYYMM の形式)に加える。戻り値は YYYYMM の形式で返る。 注意: 期間引数 P には、日付値を指定しないようにする。
mysql> SELECT PERIOD_ADD(9801,2);
        -> 199803
PERIOD_DIFF(P1,P2)
期間 P1P2 の間の月数を返す。 P1P2 の指定は YYMM または YYYYMM 形式で行う。 注意: 期間引数 P1P2 には、日付値を指定しないようにする。
mysql> SELECT PERIOD_DIFF(9802,199703);
        -> 11
QUARTER(date)
date に指定された日付に対応する四半期を、14 の範囲の値として返す。
mysql> SELECT QUARTER('98-04-01');
        -> 2
SECOND(time)
time に指定された時刻の秒を、059 の範囲の値として返す。
mysql> SELECT SECOND('10:05:03');
        -> 3
SEC_TO_TIME(seconds)
seconds 引数に指定された秒数を時、分、秒の値に変換し、文字列と数値のどちらのコンテキストで使用されているかに応じて、'HH:MM:SS' または HHMMSS 形式の値として返す。
mysql> SELECT SEC_TO_TIME(2378);
        -> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
        -> 3938
STR_TO_DATE(str,format)
DATE_FORMAT() 関数と逆の働きをする。文字列 str と形式文字列 format を取り、DATETIME 型の値を返す。 str に指定した日付、時刻、または日付時刻の値が、format に指定した形式で返される。format に使用できる指定子については、DATE_FORMAT() 関数の説明にある表を参照。他の文字はいずれも、解釈されずに文字どおり受け取られる。 str に誤った日付、時刻、または日付時刻が含まれている場合、STR_TO_DATE()NULL を返す。
mysql> SELECT STR_TO_DATE('03.10.2003 09.20', '%d.%m.%Y %H.%i')
        -> 2003-10-03 09:20:00
mysql> SELECT STR_TO_DATE('10rap', '%crap')
        -> 0000-10-00 00:00:00
mysql> SELECT STR_TO_DATE('2003-15-10 00:00:00', '%Y-%m-%d %H:%i:%s')
        -> NULL
STR_TO_DATE() は MySQL 4.1.1 以降で使用できる。
SUBDATE(date,INTERVAL expr type)
SUBDATE(expr,days)
2 番目の引数の INTERVAL を指定する形式で呼び出した場合、SUBDATE()DATE_SUB() とシノニムになる。
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
2 番目の構文は MySQL 4.1.1 以降で使用できる。expr には日付式か日付時刻式を指定し、days には expr から差し引く日数を指定する。
mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31);
        -> '1997-12-02 12:00:00'
SUBTIME(expr,expr2)
SUBTIME() では、expr から expr2 を差し引いた結果が返される。 expr には日付式か日付時刻式を指定し、expr2 には時刻式を指定する。
mysql> SELECT SUBTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
        -> '1997-12-30 22:58:58.999997'
mysql> SELECT SUBTIME("01:00:00.999999", "02:00:00.999998");
        -> '-00:59:59.999999'
SUBTIME() は MySQL 4.1.1 で追加された。
SYSDATE()
SYSDATE()NOW() のシノニム。
TIME(expr)
時刻式または日付時刻式 expr の時刻部分を取り出す。
mysql> SELECT TIME('2003-12-31 01:02:03');
        -> '01:02:03'
mysql> SELECT TIME('2003-12-31 01:02:03.000123');
        -> '01:02:03.000123'
TIME() は MySQL 4.1.1 以降で使用できる。
TIMEDIFF(expr,expr2)
TIMEDIFF() では、開始時刻 expr と終了時刻 expr2 の間の時間が返される。 exprexpr2 には、時刻式か日付時刻式を指定できるが、どちらも同じ型にしなければならない。
mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00.000001');
        -> '-00:00:00.000001'
mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001','1997-12-30 01:01:01.000002');
        -> '46:58:57.999999'
TIMEDIFF() は MySQL 4.1.1 で追加された。
TIMESTAMP(expr)
TIMESTAMP(expr,expr2)
引数が 1 つの場合は、日付式または日付時刻式 expr を日付時刻値として返す。 引数が 2 つの場合は、日付式または日付時刻式 expr に時刻式 expr2 を加えた結果を日付時刻値として返す。
mysql> SELECT TIMESTAMP('2003-12-31');
        -> '2003-12-31 00:00:00'
mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
        -> '2004-01-01 00:00:00'
TIMESTAMP() は MySQL 4.1.1 以降で使用できる。
TIME_FORMAT(time,format)
この関数の使用法は DATE_FORMAT() 関数と同様だが、この関数の場合、format に指定できる文字列は、時、分、秒を処理する形式指定子に限られる。その他の指定子を指定した場合は、NULL 値または 0 が返される。 time 値の時間部分が 23 より大きい場合、時間形式指定子 %H%k では、通常の範囲 0..23 より大きい値が生成される。その他の時間形式指定子では、時間値のモジュロ 12 が生成される。
mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');
        -> '100 100 04 04 4'
TIME_TO_SEC(time)
time 引数に指定された時刻を秒数に変換して返す。
mysql> SELECT TIME_TO_SEC('22:23:00');
        -> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
        -> 2378
TO_DAYS(date)
date に指定された日付を日数(年 0 からの通し日数)に変換して返す。
mysql> SELECT TO_DAYS(950501);
        -> 728779
mysql> SELECT TO_DAYS('1997-10-07');
        -> 729669
TO_DAYS() では、グレゴリオ暦(1582 年)より前の値の指定は想定していない。これは、カレンダが変更されたときに失われた日数が考慮されないため。
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
引数なしで呼び出された場合、Unix タイムスタンプ('1970-01-01 00:00:00' GMT からの秒数)を符号なしの整数として返す。date 引数を指定して呼び出された場合、UNIX_TIMESTAMP() は引数に指定された日付を '1970-01-01 00:00:00' GMT からの秒数として返す。引数 date には、DATE 型文字列、DATETIME 型文字列、TIMESTAMP 型の値、YYMMDD または YYYYMMDD の形式の現地時間のいずれかを指定できる。
mysql> SELECT UNIX_TIMESTAMP();
        -> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
        -> 875996580
UNIX_TIMESTAMPTIMESTAMP 型のカラムに使用すると。``文字列から Unix タイムスタンプへの'' 暗黙的な変換を行わずに、内部のタイムスタンプ値が直接返される。 UNIX_TIMESTAMP() に範囲外の日付を渡すと、0 が返されるが、この場合、実行されるチェックは基本チェック(年 1970 〜 2037、月 01 〜 12、日 01 〜 31)に限られる。 UNIX_TIMESTAMP() カラム値を差し引く場合、結果を符号付き整数にキャストする必要がある場合がある。 See section 6.3.5 キャスト関数
UTC_DATE
UTC_DATE()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'YYYY-MM-DD' または YYYYMMDD形式の値として、現在の UTC 日付を返す。
mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
        -> '2003-08-14', 20030814
UTC_DATE() は MySQL 4.1.1 以降で使用できる。
UTC_TIME
UTC_TIME()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'HH:MM:SS' または HHMMSS 形式の値として、現在の UTC 時刻を返す。
mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
        -> '18:07:53', 180753
UTC_TIME() は MySQL 4.1.1 以降で使用できる。
UTC_TIMESTAMP
UTC_TIMESTAMP()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 形式の値として、現在の UTC の日付と時刻を返す。
mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;
        -> '2003-08-14 18:08:04', 20030814180804
UTC_TIMESTAMP() は MySQL 4.1.1 以降で使用できる。
WEEK(date [,mode])
date に指定された日付に対応する週数を返す。 引数を 2 つ取る形式の WEEK() では、週を日曜と月曜のどちらから開始するかと、戻り値の範囲を 0 〜 53 と 1 〜 52 のどちらにするかを指定できる。mode 引数を省略した場合は、default_week_format サーバ変数の値(または MySQL 4.0 以前のバージョンでは 0)が適用される。 See section 5.5.6 SET 構文。 次の表に、mode 引数の動作を示す。
意味
0 日曜から週を開始。戻り値の範囲は 0 〜 53。週 1 はその年に開始される最初の週。
1 月曜から週を開始。戻り値の範囲は 0 〜 53。週 1 は 4 日以上の日を持つその年の最初の週。
2 日曜から週を開始。戻り値の範囲は 1 〜 53。週 1 はその年に開始される最初の週。
3 月曜から週を開始。戻り値の範囲は 1 〜 53。週 1 は 4 日以上の日を持つその年の最初の週。
4 日曜から週を開始。戻り値の範囲は 0 〜 53。週 1 は 4 日以上の日を持つその年の最初の週。
5 月曜から週を開始。戻り値の範囲は 0 〜 53。週 1 はその年に開始される最初の週。
6 日曜から週を開始。戻り値の範囲は 1 〜 53。週 1 は 4 日以上の日を持つその年の最初の週。
7 月曜から週を開始。戻り値の範囲は 1 〜 53。週 1 はその年に開始される最初の週。
mode 値 3 は MySQL 4.0.5 以降で使用できる。 mode 値 4 以上は MySQL 4.0.17 以降で使用できる。
mysql> SELECT WEEK('1998-02-20');
        -> 7
mysql> SELECT WEEK('1998-02-20',0);
        -> 7
mysql> SELECT WEEK('1998-02-20',1);
        -> 8
mysql> SELECT WEEK('1998-12-31',1);
        -> 53
注意:バージョン 4.0 で、WEEK(date,0) は米国のカレンダに合わせて変更された。それ以前のバージョンでは、WEEK() の計算は米国の日付に対して正しく行われなかった(事実上、すべての場合で、WEEK(date)WEEK(date,0) で結果が誤っていた)。 注意: 指定された日付が前年の最後の週にあたる場合、オプションの mode 引数として 2、3、6、7 のいずれかが指定されていないと、MySQL から値 0 が返る。
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
        -> 2000, 0
この場合、指定された日付は実際には 1999 年の 52 週目に含まれるため、WEEK() 関数の結果として値 52 を返すべきだとする考え方もあるが、MySQL ではそのようにはせず、値 0 を返すようにした。これは、この関数によって、あくまでも ``指定された年の週数'' が返されるようにするためである。そうすることで、日付から日付部分を取り出す他の関数と組み合わせて WEEK() 関数を使用した場合の信頼性が確保される。 結果の評価を、指定した日付の週の最初の日が含まれる年に関連して行うには、オプションの mode 引数として 2、3、6、7 のいずれかを指定するようにする。
mysql> SELECT WEEK('2000-01-01',2);
        -> 52
または、YEARWEEK() 関数を使用する。
mysql> SELECT YEARWEEK('2000-01-01');
        -> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> '52'
WEEKDAY(date)
date に指定された日付の曜日インデックス(0 = 月曜、1 = 火曜、... 6 = 日曜)を返す。
mysql> SELECT WEEKDAY('1998-02-03 22:23:00');
        -> 1
mysql> SELECT WEEKDAY('1997-11-05');
        -> 2
WEEKOFYEAR(date)
指定された日付のカレンダ上の週を、153 の数値として返す。
mysql> SELECT WEEKOFYEAR('1998-02-20');
        -> 8
WEEKOFYEAR() は MySQL 4.1.1 以降で使用できる。
YEAR(date)
date に指定された日付の年を、10009999 の数値として返す。
mysql> SELECT YEAR('98-02-03');
        -> 1998
YEARWEEK(date)
YEARWEEK(date,start)
指定された日付の年と週を返す。start 引数は、WEEK() に対する start 引数とまったく同じように作用する。注意: date 引数に指定された日付の週がその年の最初の週である場合と最後の週である場合、結果の年が date 引数の年と異なることがある。
mysql> SELECT YEARWEEK('1987-01-01');
        -> 198653
結果の週数は、オプション引数 0 または 1 を指定した WEEK() 関数で返る値と異なる。WEEK() 関数では、指定した年のコンテキストで週数が返される。

6.3.5 キャスト関数

CAST() 関数と CONVERT() 関数は、あるデータ型の値から別のデータ型の値を生成する目的で使用することができます。構文は以下のとおりです。

CAST(expression AS type)
CONVERT(expression,type)
CONVERT(expr USING transcoding_name)

type には、次のいずれかのデータ型を指定できます。

CAST()CONVERT() は MySQL 4.0.2 以降で使用することができます。 変換型 CHAR は 4.0.6 以降で使用可能です。 USING を指定する CONVERT() は、4.1.0 以降で使用可能です。

CAST()CONVERT(... USING ...) は SQL-99 の構文です。 USING を指定しない CONVERT() は ODBC の構文です。

キャスト関数は、CREATE ... SELECT ステートメントで特定の型のカラムを作成する必要があるときに役立ちます。

CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);

また、キャスト関数は ENUM 型のカラムを語彙の順序でソートするときにも役立ちます。通常、ENUM 型のカラムのソートは、内部の数値に基づいて行われます。値を CHAR 型にキャストすると、語彙の順序でソートされるようになります。

SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);

CAST(string AS BINARY)BINARY string と同じです。 CAST(expr AS CHAR) では、指定した式がデフォルトのキャラクタセットの文字列として扱われます。

注意: MysQL 4.0 では、DATEDATETIMETIME 型のカラムに CAST() 操作を行った場合、カラムが特定の型としてマークされるだけで、カラム値が変わるわけではありません。

MySQL 4.1.0 では、カラム値は、ユーザに送られるときに適切なカラム型に変換されます(これは、クライアントへの日付情報の送信における、4.1 の新しいプロトコルの機能です)。

mysql> SELECT CAST(NOW() AS DATE);
       -> 2003-05-26

後続の MySQL バージョン(おそらく 4.1.2 か 5.0)では、CONCAT("Date: ",CAST(NOW() AS DATE)) のような、より複雑な式の一部として CAST を使用した場合にも、結果のデータ型が適切に変換されるよう修正する予定です。

データを別の形式で取り出すときには、CAST() は使用せず、代わりに、LEFTEXTRACT() のような文字列関数を使用してください。 See section 6.3.4 日付と時刻関数

文字列を数値にキャストするときには、通常は、特に何もしないで、そのままその文字列を数値として使用します。

mysql> SELECT 1+'1';
       -> 2

文字列のコンテキストで数値を使用すると、数値は BINARY 文字列に自動で変換されます。

mysql> SELECT CONCAT("hello you ",2);
       ->  "hello you 2"

MySQL では、符号付きと符号なしのどちらでも、64 ビット値の演算をサポートしています。 数値演算(+ など)でどちらか一方のオペランドが unsigned integer の場合、結果の値は符号なしになります。 ただし、キャスト演算子 SIGNEDUNSIGNED を使用することによって、それぞれ符号付き、または符号なしの 64 ビット整数にキャストできます。

mysql> SELECT CAST(1-2 AS UNSIGNED)
        -> 18446744073709551615
mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
        -> -1

注意: どちらか一方のオペランドが浮動小数点数の場合、結果の値は浮動小数点数になり、上記の規則は適用されません(このコンテキストでは、DECIMAL 型の値は浮動小数点数とみなされます)。

mysql> SELECT CAST(1 AS UNSIGNED) - 2.0;
        -> -1.0

算術演算に文字列を使用すると、その文字列は浮動小数点数に変換されます。

符号なしの値の扱いについては、BIGINT 型の値に適切に対応するよう、MySQL 4.0 で変更されました。MySQL 4.0 と 3.23 の両方で実行するコードがあるとき(通常、この場合、CAST() 関数は使用できない)、次の方法によって、2 つの符号なし整数カラムの減算の実行時に符号付きの結果値を得ることができます。

SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);

この方法では、減算の実行前に両方のカラムを浮動小数点型に変換しています。

以前の MySQL アプリケーションの UNSIGNED 型のカラムを MySQL 4.0 に移植した場合に問題があるときは、mysqld の起動時に --sql-mode=NO_UNSIGNED_SUBTRACTION オプションを指定します。注意: このオプションを指定した場合、BIGINT UNSIGNED カラム型を効率的に使用することはできません。

USING を指定する CONVERT() は、データのキャラクタセットを別のキャラクタセットに変換するときに使用します。MySQL では、トランスコーディング名は対応するキャラクタセット名と同じです。たとえば、次のステートメントでは、サーバのデフォルトのキャラクタセットに基づく文字列 'abc' が、utf8 キャラクタセットの対応する文字列に変換されます。

SELECT CONVERT('abc' USING utf8);

6.3.6 その他の関数

6.3.6.1 ビット関数

MySQL では、ビット演算に BIGINT(64 ビット)演算を使用します。したがって、以下のビット演算子の範囲は最大 64 ビットになります。

|
ビットごとの OR。
mysql> SELECT 29 | 15;
        -> 31
結果は符合なしの 64 ビット整数。
&
ビットごとの AND。
mysql> SELECT 29 & 15;
        -> 13
結果は符合なしの 64 ビット整数。
^
ビットごとの XOR。
mysql> SELECT 1 ^ 1;
        -> 0
mysql> SELECT 1 ^ 0;
        -> 1
mysql> SELECT 11 ^ 3;
        -> 8
結果は符合なしの 64 ビット整数。 XOR はバージョン 4.0.2 で追加された。
<<
longlong(BIGINT)値のビットを左にシフトする。
mysql> SELECT 1 << 2;
        -> 4
結果は符合なしの 64 ビット整数。
>>
longlong(BIGINT)値のビットを右にシフトする。
mysql> SELECT 4 >> 2;
        -> 1
結果は符合なしの 64 ビット整数。
~
すべてのビットを反転させる。
mysql> SELECT 5 & ~1;
        -> 4
結果は符合なしの 64 ビット整数。
BIT_COUNT(N)
引数 N に指定された数値を 2 進表記したときに 1 に設定されるビット数を返す。
mysql> SELECT BIT_COUNT(29);
        -> 4

6.3.6.2 その他の各種関数

AES_ENCRYPT(string,key_string)
AES_DECRYPT(string,key_string)
これらの関数では、公式の AES(Advanced Encryption Standard)アルゴリズム(以前、Rijndael と呼ばれていたもの)を使用してデータの暗号化と解読を実行できる。 エンコードに使用されるキー長は 128 ビットだが、ソースを変更することによって、256 ビットまで拡張できる。MySQL では 128 ビットを選択している。その理由は、そのほうが迅速で、かつ通常、安全性も十分に確保できるため。 入力引数は任意の長さにすることができる。どちらかの引数として NULL を指定した場合、この関数の結果も NULL になる。 AES はブロックレベルのアルゴリズムであるため、不揃いの長さの文字列のエンコード時には埋め込みが行われる。したがって、結果の文字列の長さは 16*(trunc(string_length/16)+1) として計算することができる。 AES_DECRYPT() では、無効なデータや誤った埋め込みが検出されると、NULL が返される。しかし、入力データやキーが無効でも、AES_DECRYPT() から NULL 以外の値(ガベージなど)が返されることがある。 クエリを次のように変更することによって、AES 関数を使用して暗号形式でデータを格納できる。
INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'));
各クエリの接続を通したキーの転送を行わないようにすれば、さらにセキュリティを強化することができる。この場合、キーは接続時にサーバ側の変数に格納する。
SELECT @password:='my password';
INSERT INTO t VALUES (1,AES_ENCRYPT('text',@password));
AES_ENCRYPT()AES_DECRYPT() はバージョン 4.0.2 で追加された。この 2 つは、現在のところ MySQL で使用可能な、暗号化方式として最も安全性の高い暗号化関数としてみなすことができる。
BENCHMARK(count,expr)
BENCHMARK() 関数は、expr に指定された式を count に指定された回数だけ繰り返し実行する。この関数は、MySQL での式の処理速度を計測するために使用できる。結果の値としては、常に 0 が返る。この関数を mysql クライアントで使用することによって、クエリの実行時間をレポートすることができる。
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (4.74 sec)
レポートされる時間は、サーバ側の CPU 時間ではなく、クライアント側の経過時間である。BENCHMARK() を数回実行し、結果を分析することによって、サーバマシンの負荷がどれくらいか調べることができる。
COMPRESS(string_to_compress)
文字列を圧縮する。
mysql> SELECT LENGTH(COMPRESS(REPEAT("a",1000)));
        -> 21
mysql> SELECT LENGTH(COMPRESS(""));
        -> 0
mysql> SELECT LENGTH(COMPRESS("a"));
        -> 13
mysql> SELECT LENGTH(COMPRESS(REPEAT("a",16)));
        -> 15
COMPRESS() は MySQL バージョン 4.1.1 で追加された。 この関数を使用するためには、zlib などの圧縮ライブラリを使用して MySQL をコンパイルしておく必要がある。コンパイルを行っていないと、戻り値は常に NULL になる。 圧縮した文字列の内容は次の方法で格納される。
  • 空の文字列は空の文字列として格納される。
  • 空以外の文字列は、まず 4 バイトの長さの非圧縮文字列として格納され(下位バイトが先)、その後 gzip によって文字列が圧縮される。文字列がスペースで終わっている場合は、追加の `.' が挿入される。これは、結果を CHAR 型または VARCHAR 型のカラムに格納する場合に末尾のスペースの切り取りで問題が発生しないようにするため。しかし、CHAR 型や VARCHAR 型カラムへの圧縮文字列の格納は推奨されない。代わりに、BLOB 型のカラムを使用するようにする。
CONNECTION_ID()
接続の接続 ID(スレッド ID)を返す。 各接続にはその接続固有の一意な ID が割り当てられる。
mysql> SELECT CONNECTION_ID();
        -> 23786
CURRENT_USER()
現在のセッションの認証に使用されたユーザ名とホスト名を返す。この値はアクセス権限の評価に使用されるアカウントに対応している。USER() の値とは異なる場合がある。
mysql> SELECT USER();
        -> 'davida@localhost'
mysql> SELECT * FROM mysql.user;
        -> ERROR 1044: Access denied for user: '@localhost' to database 'mysql'
mysql> SELECT CURRENT_USER();
        -> '@localhost'
上の例では、クライアントがユーザ名として davida を指定している(USER() の値により)にもかかわらず、サーバは匿名ユーザアカウントでクライアントの認証を行っている(CURRENT_USER() 値のユーザ名の部分が空)のがわかる。このようなことが起こる原因の 1 つとして、davida の権限テーブルにアカウントが登録されていない場合が考えられる。
DATABASE()
カレントデータベース名を返す。
mysql> SELECT DATABASE();
        -> 'test'
カレントデータベースがない場合、DATABASE() は、MySQL 4.1.1 以降では NULL を返し、それ以前のバージョンでは空の文字列を返す。
DECODE(crypt_str,pass_str)
pass_str に指定された文字列をパスワードとして使用して、暗号化された文字列 crypt_str を解読する。crypt_strENCODE() から返された文字列でなければならない。
ENCODE(str,pass_str)
pass_str に指定された文字列をパスワードとして使用して、str を暗号化する。 暗号化された結果を解読するには、 DECODE() を使用する。 結果として、string と同じ長さのバイナリ文字列が返される。 この文字列をカラムに保存するには、BLOB 型のカラムを使用する。
DES_DECRYPT(string_to_decrypt [, key_string])
DES_ENCRYPT() で暗号化された文字列を解読する。 注意: この関数は、MySQL で SSL のサポートが組み込まれている場合にのみ機能する。 See section 4.4.10 安全な接続の使用key_string 引数が指定されていない場合、DES_DECRYPT() は暗号化文字列の最初のバイトを調べて、元の文字列の暗号化に使用された DES キー番号を判別し、des-key-file からキーを読み取ってメッセージの暗号化を解除する。これを行うためには、ユーザは SUPER 権限を持っていなければならない。 この関数に key_string 引数を渡した場合、この引数に指定した文字列がメッセージの暗号化を解除するキーとして使用される。 string_to_decrypt に指定した文字列が暗号化された文字列として MySQL に認識されない場合、指定した文字列がそのまま返される。 エラー時には、NULL が返される。
DES_ENCRYPT(string_to_encrypt [, (key_number | key_string) ] )
指定されたキーを使用して、Triple-DES アルゴリズムによって文字列の暗号化を解除する。 注意: この関数は、MySQL で SSL のサポートが組み込まれている場合にのみ機能する。 See section 4.4.10 安全な接続の使用。 使用する暗号化キーは次の方法で選択される。
引数 説明
引数が 1 つだけ des-key-file ファイル内の最初のキーを使用。
キー番号 des-key-file ファイル内の、指定されたキー(0 〜 9)を使用。
文字列 key_string に指定された文字列を使用して string_to_encrypt の暗号化を解除。
関数の結果として、バイナリ文字列が返される。この文字列の最初の文字は CHAR(128 | key_number) になる。 128 は暗号化されたキーを見分けやすくする目的で追加される。 文字列キーを使用すると、key_number は 127 になる。 エラー時には、NULL が返される。 結果の文字列長は new_length= org_length + (8-(org_length % 8))+1 になる。 des-key-file の形式は次のとおり。
key_number des_key_string
key_number des_key_string
key_number は 0 〜 9 の範囲の番号でなければならない。ファイル内の行は任意の順序にすることができる。des_key_string は、メッセージの暗号化に使用する文字列。番号とキーの間には、1 つ以上のスペースを挿入する。最初のキーは、DES_ENCRYPT() にキー引数を何も指定しない場合に使用されるデフォルトのキー。 FLUSH DES_KEY_FILE コマンドを使用すると、MySQL にキーファイルから新しいキー値を読み取らせることができる。このコマンドを使用するには、Reload_priv 権限が必要になる。 デフォルトキーのセットを用意しておく利点の 1 つは、暗号化されたカラム値が存在するかどうかアプリケーションでチェックできることである。この場合、それらの値を解読する権利をエンドユーザに与える必要はない。
mysql> SELECT customer_address FROM customer_table WHERE
       crypted_credit_card = DES_ENCRYPT("credit_card_number");
ENCRYPT(str[,salt])
Unix の crypt() システムコールを使用して、str に指定された文字列を暗号化する。salt 引数は、2 つの文字から成る文字列でなければならない(MySQL バージョン 3.22.16 以降では、salt に 2 文字を超える長さの文字列を指定できる)。
mysql> SELECT ENCRYPT("hello");
        -> 'VxuFAJXVARROc'
一部のシステムでは、ENCRYPT()str に指定された文字列の最初の 8 文字以外のすべての文字を無視する。この動作は、基盤となる crypt() システムコールの実装によって決まる。 使用システムで crypt() を利用できない場合、ENCRYPT() は常に NULL を返す。そのため、ENCRYPT() の代用として、MD5() または SHA1() の使用が推奨される。これらの 2 つの関数はすべてのプラットフォームで利用できる。
FORMAT(X,D)
X に指定された数値の小数部を、D に指定された桁数に丸めて、'#,###,###.##' のような形式に設定し、結果を文字列として返す。 D0 の場合、結果の値は小数点も小数部も持たない。
mysql> SELECT FORMAT(12332.123456, 4);
        -> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
        -> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
        -> '12,332'
FOUND_ROWS()
SELECT ステートメントに LIMIT 節を組み込むことによって、サーバがクライアントに返すレコード数を制限できる。 状況によっては、LIMIT を指定しなかった場合にいくつのレコードが返されるかを、ステートメントを再度実行することなく確認したいことがある。 このレコード数を確認するには SELECT ステートメントに SQL_CALC_FOUND_ROWS オプションを指定し、その後 FOUND_ROWS() を呼び出す。
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
       WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
2 番目の SELECT では、最初の SELECTLIMIT 節なしで実行した場合に返されるレコード数を示す数が返る(先行する SELECT ステートメントに SQL_CALC_FOUND_ROWS オプションが含まれていないと、FOUND_ROWS()LIMIT が使用されない場合とは異なる、LIMIT が使用されたときの結果を返す)。 注意: SELECT SQL_CALC_FOUND_ROWS ... を使用した場合、MySQL では完全な結果セットに含まれるレコード数を計算する必要が生じる。しかし、この場合、結果セットをクライアントに送る必要がないため、LIMIT なしで再度クエリを実行するより時間がかからない。 SQL_CALC_FOUND_ROWSFOUND_ROWS() は、クエリで返されるレコード数を制限する必要がある場合に、完全な結果セットに含まれるレコード数を(クエリを再実行することなく)確認したいときに役立つ。例として、検索結果の別のセクションを示すページへのリンクを含むページ画面を表示する Web スクリプトを挙げることができる。FOUND_ROWS() を使用すると、結果の残りの部分を表示するのにあと何ページ必要か確認できる。 SQL_CALC_FOUND_ROWSFOUND_ROWS()UNION クエリで使用した場合、単純な SELECT ステートメントで使用した場合よりも複雑になる。これは、LIMITUNION 内の複数の場所で起こり得るためである。LIMIT は、UNION 内の個々の SELECT ステートメントに適用することも、UNION の結果全体にグローバルに適用することもできる。 UNION に対して SQL_CALC_FOUND_ROWS を使用する目的は、このオプションによって、グローバルな LIMIT を指定しなかった場合に返されるレコード数を確認できることにある。 UNION での SQL_CALC_FOUND_ROWS の使用には、以下の条件が適用される。
  • UNION の最初の SELECTSQL_CALC_FOUND_ROWS キーワードが指定されていなければならない。
  • FOUND_ROWS() の値は UNION ALL の使用時のみ正確になる。 ALL なしで UNION を使用した場合、重複の削除が行われるため、FOUND_ROWS() の値は近似値にすぎない。
  • UNION 内に LIMIT が存在しない場合、SQL_CALC_FOUND_ROWS は無視され、UNION を処理するために作成されたテンポラリテーブル内のレコード数が返される。
SQL_CALC_FOUND_ROWSFOUND_ROWS() は MySQL バージョン 4.0.0 以降で使用できる。
GET_LOCK(str,timeout)
str に指定された名前のロックを取得しようと試みる。この場合、timeout に指定された秒数をタイムアウトとする。正常にロックが取得されたときは 1 を返し、ロックの取得がタイムアウトになった(指定された名前が別のクライアントによってすでにロックされている場合など)ときは 0 を返し、エラーが発生した(メモリ不足や、mysqladmin kill でスレッドが強制終了された場合など)ときは NULL を返す。ロックは、RELEASE_LOCK() が実行されるか、新しい GET_LOCK() が実行されるか、またはスレッドが終了する(正常終了または異常終了)と解除される。 この関数はアプリケーションのロックを実行したり、レコードのロックをシミュレーションしたりする目的で使用できる。名前はサーバ全体の範囲で有効である。 1 つのクライアントがある名前のロックを得ている場合、GET_LOCK() は、その名前のロックに対する、別のクライアントからのすべての要求をブロックする。 ある名前のロックをもとにすれば、各クライアント間での同期をとらせるような動作が可能である:
mysql> SELECT GET_LOCK("lock1",10);
        -> 1
mysql> SELECT IS_FREE_LOCK("lock2");
        -> 1
mysql> SELECT GET_LOCK("lock2",10);
        -> 1
mysql> SELECT RELEASE_LOCK("lock2");
        -> 1
mysql> SELECT RELEASE_LOCK("lock1");
        -> NULL
注意: 2 番目の RELEASE_LOCK() 呼び出しでは NULL が返される。これは、ロック "lock1" が 2 番目の GET_LOCK() 呼び出しによって自動的に解除されるため。
INET_ATON(expr)
文字列として指定された、ドット 10 進表記のネットワークアドレスを、そのアドレスの数値を表す整数として返す。 アドレスとして、4 バイトまたは 8 バイトのアドレスを指定できる。
mysql> SELECT INET_ATON("209.207.224.40");
       ->  3520061480
生成される数値は、常にネットワークバイトオーダーで生成される。たとえば、上の例の数値は、209*256^3 + 207*256^2 + 224*256 +40 として計算される。
INET_NTOA(expr)
数値として表現されたネットワークアドレス(4 または 8 バイト)を、ドット 10 進表記のアドレス(文字列)として返す。
mysql> SELECT INET_NTOA(3520061480);
       ->  "209.207.224.40"
IS_FREE_LOCK(str)
str に指定された名前をもつロックが解放されているかどうか(つまり、ロックされていないかどうか)確認する。 ロックが解放されている(誰もそのロックを使用していない)場合は 1 を返し、そのロックが使用されている場合は 0 を返し、エラーが発生した(引数に誤りがあるなど)場合は NULL を返す。
LAST_INSERT_ID([expr])
AUTO_INCREMENT カラムに挿入された値のうち、最後に自動生成された値を返す。
mysql> SELECT LAST_INSERT_ID();
        -> 195
生成された最後の ID は、接続ごとにサーバで維持される。したがって、この関数から個々のクライアントに返される値は、そのクライアントによって生成された最新の AUTO_INCREMENT 値である。この値は、他のクライアントがそれぞれの AUTO_INCREMENT 値を生成しても、それによって影響されることはない。この動作によって、他のクライアントの活動にかかわりなく、また、ロックやトランザクションを必要とすることなく、自分の ID を確実に取り出すことができる。 非マジック値(つまり、NULL でも 0 でもない値)を持つレコードの AUTO_INCREMENT カラムを更新しても、LAST_INSERT_ID() の値は変更されない。 INSERT ステートメントで同時に複数のレコードを挿入した場合、LAST_INSERT_ID() は最初に挿入されたレコードの値を返す。これは、同じ INSERT ステートメントを他のいずれかのサーバに対して簡単に再生成できるようにするためである。 LAST_INSERT_ID() の引数として expr を指定した場合、引数の値が関数から返され、この値が LAST_INSERT_ID() によって返される次の値として設定される。これはシーケンスのシミュレーションに使用できる。 まず、テーブルを作成する。
mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);
その後、このテーブルを使用してシーケンス番号を次のように生成できる。
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
シーケンスの生成は LAST_INSERT_ID() を呼び出さなくても可能だが、この関数をこのように使用した場合、ID 値が最後に自動生成された値としてサーバに維持される(マルチユーザ対応)。 新しい ID は、MySQL で通常の AUTO_INCREMENT 値を読み取るときと同じように取り出せる。たとえば、LAST_INSERT_ID()(引数はいずれもなし)では、新しい ID が返される。C API 関数 mysql_insert_id() もこの ID 値の取得に使用できる。 注意: mysql_insert_id() が更新されるのは、INSERT ステートメントや UPDATE ステートメントの後になるため、SELECTSET などの他の SQL ステートメントの実行後に、C API 関数を使用して LAST_INSERT_ID(expr) の値を取り出すことはできない。 See section 11.1.3.32 mysql_insert_id()
MASTER_POS_WAIT(log_name, log_pos [, timeout])
スレーブがマスタログの指定された位置に達する(つまり、指定された位置まで更新をすべて読み取って適用する)までブロックする。マスタ情報が初期化されていない場合や、引数に誤りがある場合は、NULL を返す。スレーブが実行されていない場合は、スレーブが開始され、指定された位置まで到達するか、これを通過するまで、ブロックして待機する。スレーブが指定された位置をすでに通過している場合、この関数は直ちに戻る。 timeout(4.0.10 で導入)が指定されている場合は、timeout に指定された秒数が経過すると待機を中止する。timeout 値は 0 より大きくなければならない。ゼロや負の timeout 値はタイムアウトなしを意味する。戻り値として、指定された位置に到達するまでに待機しなければならかったログイベントの数が返される。エラー時には、NULL が返され、タイムアウトを超過した場合は -1 が返される。 このコマンドはマスタとスレーブの同期化に役立つ。
MD5(string)
指定された文字列の MD5 128 ビットチェックサムを計算する。値は 32 ビットの 16 進数として返される。この値は、ハッシュキーなどとして使用できる。
mysql> SELECT MD5("testing");
        -> 'ae2b1fca515949e5d54fb22b8ed95575'
これは "RSA Data Security, Inc. の MD5 Message-Digest Algorithm"。
PASSWORD(str)
OLD_PASSWORD(str)
平文テキストのパスワード str からパスワード文字列を計算する。これは、user 権限テーブルの Password カラムに格納する MySQL パスワードの暗号化に使用される関数。
mysql> SELECT PASSWORD('badpwd');
        -> '7f84554057dd964b'
PASSWORD() の暗号化は可逆ではない。 PASSWORD() は、パスワードの暗号化を Unix パスワードの暗号化と同じ方法では行わない。ENCRYPT() を参照。 注意: PASSWORD() 関数は、MySQL サーバの認証システムで使用される。アプリケーションでは使用しないこと。 アプリケーション用には、MD5()SHA1() を代わりに使用する。 アプリケーションでのパスワードと認証の安全な処理の詳細については、 RFC-2195 も参照。
RELEASE_LOCK(str)
GET_LOCK() によって取得された、文字列 str を名前として持つロックを解除する。そのロックが解除された場合は 1 を返し、そのロックがこのスレッドによってロックされているのでない場合は 0 を返し(この場合、ロックは解除されない)、指定されたロックが存在しない場合は NULL を返す(そのロックが GET_LOCK() を呼び出して取得されたのでない場合や、すでに解除されている場合、そのロックは存在しないことになる)。 DO ステートメントを RELEASE_LOCK() で使用すると便利である。 See section 6.4.10 DO 構文
SESSION_USER()
SESSION_USER()USER() のシノニム。
SHA1(string)
SHA(string)
指定された文字列に対して、RFC 3174(Secure Hash Algorithm)に定義された SHA1 160 ビットチェックサムを計算する。値は 40 桁の 16 進数として返される。入力引数が NULL の場合は、NULL が返される。 この関数の用途の 1 つとして、戻り値をハッシュキーとして使用できる。また、この関数は、パスワードを格納するための安全な暗号化関数としても使用できる。
mysql> SELECT SHA1("abc");
        -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
SHA1() はバージョン 4.0.2 で追加された。この関数は MD5() よりもさらに安全度が高い暗号化関数とみなすことができる。 SHA()SHA1() のシノニム。
SYSTEM_USER()
SYSTEM_USER()USER() のシノニム。
UNCOMPRESS(string_to_uncompress)
COMPRESS() 関数によって圧縮された文字列の圧縮を解除する。
mysql> SELECT UNCOMPRESS(COMPRESS("any string"));
        -> 'any string'
UNCOMPRESS() は MySQL バージョン 4.1.1 で追加された。 この関数を使用するためには、zlib などの圧縮ライブラリを使用して MySQL をコンパイルしておく必要がある。コンパイルを行っていないと、戻り値は常に NULL になる。
UNCOMPRESSED_LENGTH(compressed_string)
圧縮文字列の圧縮前の長さを返す。
mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT("a",30)));
        -> 30
UNCOMPRESSED_LENGTH() は MySQL バージョン 4.1.1 で追加された。
USER()
現在の MySQL ユーザ名とホスト名を返す。
mysql> SELECT USER();
        -> 'davida@localhost'
戻り値は、サーバへの接続時に指定したユーザ名と、接続元のクライアントホストを表す(MySQL バージョン 3.22.11 より前のバージョンでは、この関数の戻り値にはクライアントホスト名は含まれない)。 次のようにした場合、値にホスト名の部分が含まれているかどうかにかかわらず、ユーザ名の部分だけを取り出すこともできる。
mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
        -> 'davida'
VERSION()
MySQL サーバのバージョンを示す文字列を返す。
mysql> SELECT VERSION();
        -> '3.23.13-log'
注意: バージョンの後ろに -log が付いている場合、ログが有効になっていることを表す。

6.3.7 GROUP BY 節で使用する関数と修飾子

6.3.7.1 GROUP BY 関数

GROUP BY 節を含まないステートメントでグループ関数を使用すると、すべてのレコードに対してグループ化操作を実行するのと同じになります。

AVG(expr)
expr の平均値を返す。
mysql> SELECT student_name, AVG(test_score)
    ->        FROM student
    ->        GROUP BY student_name;
BIT_AND(expr)
expr のすべてのビットに対するビットごとの AND を返す。この計算は 64 ビット(BIGINT)の精度で実行される。 MySQL 4.0.17 以降では、マッチするレコードがない場合、この関数は 18446744073709551615 を返す(これはすべてのビットを 1 に設定した、符号なしの BIGINT 値)。 4.0.17 より前のバージョンでは、マッチするレコードがない場合、この関数は -1 を返す。
BIT_OR(expr)
expr のすべてのビットに対するビットごとの OR を返す。この計算は 64 ビット(BIGINT)の精度で実行される。 マッチするレコードがない場合、この関数は 0 を返す。
BIT_XOR(expr)
expr のすべてのビットに対するビットごとの XOR を返す。この計算は 64 ビット(BIGINT)の精度で実行される。 マッチするレコードがない場合、この関数は 0 を返す。 この関数は MySQL 4.1.1 以降で使用できる。
COUNT(expr)
SELECT ステートメントで取り出されたレコードのうち、NULL 以外の値の数のカウントを返す。
mysql> SELECT student.student_name,COUNT(*)
    ->        FROM student,course
    ->        WHERE student.student_id=course.student_id
    ->        GROUP BY student_name;

COUNT(*) は、レコードに NULL 値が含まれているかどうかにかかわらず、取り出されたレコード数のカウントを返すという点で多少異なる。 SELECT で 1 つのテーブルから値を取り出し、他のカラムからは値を取り出さず、かつ WHERE 節がない場合、COUNT(*) は迅速に戻るよう最適化される。次に例を示す。
mysql> SELECT COUNT(*) FROM student;
この最適化は、MyISAM テーブルと ISAM テーブルにのみ適用される。これは、この 2 つのテーブル型では正確なレコードカウントが格納され、迅速にアクセスできるためである。トランザクションストレージエンジン(InnodB, BDB)の場合、複数のトランザクションが発生し、それぞれがカウントに影響する場合があるため、正確なレコードカウントの格納はより難しくなる。
COUNT(DISTINCT expr,[expr...])
NULL 以外の異なる各値の数のカウントを返す。
mysql> SELECT COUNT(DISTINCT results) FROM student;
MySQL では、式のリストを指定することによって、NULL を含まない、重複のない式の組み合せの数を得ることができる。 SQL-99 では、COUNT(DISTINCT ...) 内ですべての式を連結する必要がある。
GROUP_CONCAT(expr)
完全な構文
GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
             [SEPARATOR str_val])
この関数は MySQL バージョン 4.1 で追加された。 この関数はグループ内の値を連結した結果の文字列を返す。
mysql> SELECT student_name,
    ->        GROUP_CONCAT(test_score)
    ->        FROM student 
    ->        GROUP BY student_name;
または
mysql> SELECT student_name,
    ->        GROUP_CONCAT(DISTINCT test_score
    ->                     ORDER BY test_score DESC SEPARATOR " ")
    ->        FROM student
    ->        GROUP BY student_name;
MySQL では、式の組み合わせの連結値を得ることができる。 DISTINCT を使用することで、重複する値は排除できる。 結果の値をソートするには、ORDER BY 節を使用する。 逆の順序でソートするには、ORDER BY 節でソートキーとするカラムの名前に DESC(降順)キーワードを付ける。デフォルトは昇順だが、昇順を明示的に指定するには、ASC キーワードを指定する。 SEPARATOR は結果の値と値の間に挿入する文字列値を表す。デフォルトはカンマ(`","')。区切り記号をまったく使用しない場合は、SEPARATOR "" と指定する。 使用可能な最大長は、変数 group_concat_max_len をオプション設定ファイルに記述することで設定できる。 設定を SQL クエリで行う構文は次のとおり。
SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
最大長が設定されている場合、結果はこの最大長に合わせて切り捨てられる。 GROUP_CONCAT() 関数は、Sybase SQL Anywhere でサポートされている基本の LIST() 関数を拡張した実装である。 カラムが 1 つだけで、その他のオプションが指定されていない場合、GROUP_CONCAT() は機能がかなり制限されている LIST() と下位互換になる。ただし、LIST() にはデフォルトのソート順序はある。
MIN(expr)
MAX(expr)
expr の最小値または最大値を返す。MIN()MAX() は文字列引数を取ることができる。その場合、最小または最大の文字列値を返す。 See section 5.4.3 MySQL でのインデックスの使用
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
    ->        FROM student
    ->        GROUP BY student_name;
MySQL では、現在のところ、MIN()MAX() やその他の集約関数において ENUM 型と SET 型のカラムの比較を、セット内での文字列の相対的な位置ではなくそれぞれの文字列値に基づいて行っている。 これは改正される予定。
STD(expr)
STDDEV(expr)
expr の標準偏差(VARIANCE() の平方根)を返す。これは SQL-99 に対する拡張。この関数の STDDEV() の形式は Oracle との互換性を確保するために提供されている。
SUM(expr)
expr の合計を返す。注意: 戻り値のセットにレコードが含まれていない場合、NULL を返す。
VARIANCE(expr)
expr の標準偏差を返す(レコードはサンプルではなく、母集団全体とみなされる。そのため、この関数はレコード数を分母として取る)。これは SQL-99 に対する拡張(バージョン 4.1 以降で使用可能)。

6.3.7.2 GROUP BY の修飾子

MySQL 4.1.1 以降では、GROUP BY 節に WITH ROLLUP 修飾子を使用することによって、合計出力に追加のレコードを挿入できます。これらの追加レコードは上位レベル(上位集約)の集計演算を表します。そのため、ROLLUP では、複数の分析レベルでの疑問に 1 回のクエリで答えることができます。たとえば、この修飾子は、OLAP(オンライン分析処理)をサポートする目的で使用できます。

例として、sales という名前のテーブルに、売上の利益を記録するための yearcountryproductprofit という名前のカラムがあるとします。

CREATE TABLE sales
(
    year    INT NOT NULL,
    country VARCHAR(20) NOT NULL,
    product VARCHAR(32) NOT NULL,
    profit  INT
);

このテーブルの内容は、次のように、単純な GROUP BY 節の使用により、集計することができます。

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |        4525 |
| 2001 |        3010 |
+------+-------------+

この出力からは各年度の総利益がわかりますが、すべての年度の利益を合計した総利益を調べる必要がある場合は、個々の値を自分で足すか、またはもう一度クエリを実行しなければなりません。

しかし、ROLLUP を使用すれば、2 つのレベルの分析を 1 回のクエリで実行することができます。 GROUP BY 節に WITH ROLLUP 修飾子を追加すると、クエリですべての年度値を足した総計を示すレコードが別に生成されます。

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |        4525 |
| 2001 |        3010 |
| NULL |        7535 |
+------+-------------+

総計の上位集約行は、year カラムの値 NULL によって示されます。

ROLLUP は、GROUP BY カラムが複数ある場合、より複雑に作用します。この場合、最後のグループ化カラム以外の場所で ``ブレーク''(値の変化)があると、そのつどクエリで追加の上位集約の集計レコードが生成されます。

たとえば、ROLLUP を指定していない場合に、sales テーブルの、yearcountryproduct に基づく集計が次のように出力されるとします。

mysql> SELECT year, country, product, SUM(profit)
    -> FROM sales
    -> GROUP BY year, country, product;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
| 2000 | USA     | Calculator |          75 |
| 2000 | USA     | Computer   |        1500 |
| 2001 | Finland | Phone      |          10 |
| 2001 | USA     | Calculator |          50 |
| 2001 | USA     | Computer   |        2700 |
| 2001 | USA     | TV         |         250 |
+------+---------+------------+-------------+

この出力は、年/国/製品レベルでの分析における集計値のみを示しています。ROLLUP を追加すると、クエリでいくつかの追加のレコードが生成されます。

mysql> SELECT year, country, product, SUM(profit)
    -> FROM sales
    -> GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | Finland | NULL       |        1600 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
| 2000 | India   | NULL       |        1350 |
| 2000 | USA     | Calculator |          75 |
| 2000 | USA     | Computer   |        1500 |
| 2000 | USA     | NULL       |        1575 |
| 2000 | NULL    | NULL       |        4525 |
| 2001 | Finland | Phone      |          10 |
| 2001 | Finland | NULL       |          10 |
| 2001 | USA     | Calculator |          50 |
| 2001 | USA     | Computer   |        2700 |
| 2001 | USA     | TV         |         250 |
| 2001 | USA     | NULL       |        3000 |
| 2001 | NULL    | NULL       |        3010 |
| NULL | NULL    | NULL       |        7535 |
+------+---------+------------+-------------+

このクエリの場合、ROLLUP を追加すると、単に 1 レベルではなく、4 レベルでの分析における集計情報が出力に組み込まれます。ROLLUP の出力は次のように解釈されます。

ROLLUP 使用時のその他の考慮事項

以下に、MySQL における ROLLUP の実装固有の動作について、いくつか説明します。

ROLLUP の使用時には、ORDER BY 節を使用して結果をソートすることはできません(ROLLUPORDER BY は相互排他的です)。しかし、ソート順序をある程度制御することは可能です。 MySQL で GROUP BY を使用すると結果がソートされます。また、GROUP BY リストに指定したカラムに明示的な ASC または DESC キーワードを付けることによって、個々のカラムのソート順序を指定できます(この場合も、ROLLUP によって追加される上位レベルの集計レコードは、ソート順序とはかかわりなく、それぞれの計算の対象となったレコードの後に表示されます)。

LIMIT を使用すると、クライアントに返されるレコードの数を制限することができます。LIMITROLLUP の後に適用されるため、制限は ROLLUP によって挿入される追加のレコードにも適用されます。次に例を示します。

mysql> SELECT year, country, product, SUM(profit)
    -> FROM sales
    -> GROUP BY year, country, product WITH ROLLUP
    -> LIMIT 5;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | Finland | NULL       |        1600 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
+------+---------+------------+-------------+

注意: LIMITROLLUP とともに使用すると、上位集約レコードを理解するためのコンテキストが少なくなるため、生成される結果の解釈が難しくなることがあります。

各上位集約レコードの NULL インジケータは、各レコードがクライアントに送られるときに生成されます。サーバは、値が変わった左端のカラムの後に、GROUP BY 節に指定された各カラムを確認します。 これらのカラム名と語彙が一致する名前を持つカラムが結果セットにあると、そのカラムの値を NULL に設定します(カラム番号によるカラムのグループ化が指定されている場合、サーバは NULL に設定するカラムを番号で識別します)。

上位集約レコードの NULL 値はクエリ処理の後の方の段階で結果セットに組み込まれるため、クエリ自体の中で上位集約レコードを NULL 値としてテストすることはできません。たとえば、クエリに HAVING product IS NULL を追加して、上位集約レコード以外のすべての出力を排除することはできません。

それに対し、クライアント側では、NULL 値が表示されるため、MySQL クライアントプログラミングインタフェースを使用して NULL 値としてテストすることができます。

6.3.7.3 非表示のフィールドに対する GROUP BY

MySQL では GROUP BY の使用を拡張しています。GROUP BY 部分にないカラムや計算を SELECT 式で使用することができます。これは、そのグループの使用可能なあらゆる値を表します。この機能により、不要項目に対するソートやグループ化を行わないことで、パフォーマンスを向上させることができます。たとえば、次のクエリの場合、customer.name をグループ化する必要はありません。

mysql> SELECT order.custid,customer.name,MAX(payments)
    ->        FROM order,customer
    ->        WHERE order.custid = customer.custid
    ->        GROUP BY order.custid;

標準 SQL では、customer.nameGROUP BY 節に組み込む必要があります。MySQL では、非 ANSI モードでの実行時にはこのカラム名は不要です。

GROUP BY 部分から取り除くカラムがグループ内で一意なものではない場合は、この機能を使用しないでください。予測不可能な結果になります。

場合によっては、MIN()MAX() を使用することによって、一意なものでないカラムの値を取り出すことができます。次の例では、sort カラムの値が最も小さいレコードの column 値が得られます。

SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)

See section 3.6.4 特定のフィールドのグループごとの最大値が格納されているレコード

注意: MySQL バージョン 3.22(またはこれより前のバージョン)を使用している場合や、SQL-99 に従う必要がある場合、GROUP BY 節と ORDER BY 節では式は使用できません。この制約は式のエイリアスを使用することによって回避できます。

mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
    ->        GROUP BY id,val ORDER BY val;

MySQL バージョン 3.23 では、次のようにします。

mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();

6.4 データの操作: SELECTINSERTUPDATEDELETE

6.4.1 SELECT 構文

SELECT [STRAIGHT_JOIN]
       [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
       [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
       [DISTINCT | DISTINCTROW | ALL]
    select_expression,...
    [INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
    [FROM table_references
      [WHERE where_definition]
      [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...
        [WITH ROLLUP]]
      [HAVING where_definition]
      [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] ,...]
      [LIMIT [offset,] row_count | row_count OFFSET offset]
      [PROCEDURE procedure_name(argument_list)]
      [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT は1 つ以上のテーブルからレコードを選択して取り出すときに使用します。 各 select_expression は、取り出すカラムを表します。 SELECT は、どのテーブルも参照することなく、計算によって求められたレコードを取り出すときにも使用できます。 次に例を示します。

mysql> SELECT 1 + 1;
         -> 2

使用する節はいずれも、構文の説明で示している順序とまったく同じ順序で記述する必要があります。たとえば、HAVING 節はあらゆる GROUP BY 節の後に、またあらゆる ORDER BY 節の前に配置しなければなりません。

6.4.1.1 JOIN 構文

MySQL では、SELECT ステートメントでの以下の JOIN 構文の使用をサポートしています。

table_reference, table_reference
table_reference [INNER | CROSS] JOIN table_reference [join_condition]
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference [join_condition]
table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
{ OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
table_reference RIGHT [OUTER] JOIN table_reference [join_condition]
table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

table_reference は次のように定義します。

table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]

join_condition は次のように定義します。

ON conditional_expr |
USING (column_list)

結果セットに含めるレコードを制限するために使用する ON 部分には、通常、条件は何も指定しません。それらの条件は WHERE 節で指定します。ただし、この規則には例外があります。

注意:INNER JOIN 構文で join_condition を使用できるのは、MySQL 3.23.17 以降に限られます。同様に、JOINCROSS JOIN に関しても、MySQL 4.0.11 以降でのみ条件を指定できます。

上の構文リストの最後に挙げた LEFT OUTER JOIN 構文は、単に ODBC との互換性を確保するためのものです。

注意: USE/IGNORE/FORCE INDEX は、MySQL でテーブル内のレコードの検索方法と結合の実行方法を決めるときにどのインデックスを使用するか、という点にのみに影響します。ORDER BYGROUP BY の解決時にインデックスを使用するかどうかには影響しません。

以下に、例をいくつか示します。

mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
    ->          LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
    ->          WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
    ->          WHERE key1=1 AND key2=2 AND key3=3;

See section 5.2.7 MySQL による LEFT JOINRIGHT JOIN の最適化

6.4.1.2 UNION 構文

SELECT ...
UNION [ALL]
SELECT ...
  [UNION
   SELECT ...]

UNION は MySQL 4.0.0 で導入されました。

UNION は、多くの SELECT ステートメントを 1 つの結果セットに結合するために使用します。

SELECTselect_expression 部分のカラムリストには、同じ型のカラムを指定します。最初の SELECT クエリで指定したカラム名が、返される結果のカラム名として使用されます。

これらの SELECT コマンドは通常の SELECT コマンドですが、次の制限が適用されます。

UNION にキーワード ALL を付けないと、総結果セットに対して DISTINCT を指定した場合と同じように、重複しない一意なレコードだけが返されます。ALL を指定すると、実行されたすべての SELECT ステートメントから、一致するすべてのレコードが返されます。

UNION の総結果に対して ORDER BY を適用する必要があるときは、かっこを使用します。

(SELECT a FROM table_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM table_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10)
ORDER BY a;

UNION の結果セット内のカラムの型と長さでは、すべての SELECT ステートメントで取り出された値が考慮されます。 MySQL 4.1.1 より前のバージョンの UNION では、最初の SELECT で使用された値のみに基づいて結果の型と長さが決まる、という制約がありました。 この場合、たとえば、最初の SELECT の値よりも長い値が 2 番目の SELECT で取り出されると、切り捨てが行われることがあります。

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| b             |
+---------------+

MySQL 4.1.1 以降、この制約はなくなりました。

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| bbbbbbbbbb    |
+---------------+

6.4.2 サブクエリ構文

サブクエリは、別のステートメントに含まれた SELECT ステートメントです。 次に例を示します。

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

上の例で、 SELECT * FROM t1 ...外側のクエリ(または外側のステートメント)であり、(SELECT column1 FROM t2)サブクエリです。 いわば、サブクエリは外側のクエリ内にネストされていることになります。実際のところ、サブクエリ内にさらにサブクエリをネストし、クエリを何重にも入れ子化することができます。 サブクエリは必ずかっこで囲む必要があります。

MySQL バージョン 4.1 以降では、標準 SQL で規定されているサブクエリのすべての形式と操作に加え、MySQL 固有のいくつかの機能をサポートしています。サブクエリを使用する主な利点は次のとおりです。

バージョン 4.0 より前の MySQL では、サブクエリの使用を避けたり、その使用に対処する必要がありましたが、これからコードを書き始める人々は、サブクエリがツールキットの非常に便利な要素であることがわかるはずです。

次のステートメント例は、標準 SQL で規定され、MySQL でサポートしているサブクエリ構文の重要な点を示したものです。

DELETE FROM t1
WHERE s11 > ANY
 (SELECT COUNT(*) /* no hint */ FROM t2
 WHERE NOT EXISTS
  (SELECT * FROM t3
   WHERE ROW(5*t2.s1,77)=
    (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
     (SELECT * FROM t5) AS t5)));

4.1 より前のバージョンの MySQL については、結合などの方法によって、ほとんどのサブクエリを記述し直すことができます。 See section 6.4.2.11 初期の MySQL バージョンに合わせたサブクエリの書き換え

6.4.2.1 スカラオペランドとしてのサブクエリ

最も単純な形式(スカラ副問い合わせ)では、サブクエリは単純なオペランドです(スカラ副問い合わせと対立するものとしてまたはテーブル副問い合わせがあります。これらについては後述します)。したがって、サブクエリは、正しいカラム値やリテラルが使用されているところならどこでも使用でき、また、他のすべてのオペランドと同じように、データ型、長さ、値が NULL になる場合があるかどうかの区別などの特性を持ちます。 次に例を示します。

CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
SELECT (SELECT s2 FROM t1);

上の SELECT 内のサブクエリのデータ型は CHAR で、長さは 5 です。また、CREATE TABLE 時において有効なデフォルトのキャラクタセットと照合順序を持っており、カラム値が NULL の場合があることが示されています。事実、ほぼすべてのサブクエリは NULL になる場合があります。これは、例にあるようにテーブルが空の場合、サブクエリの値が NULL になるためです。 次に示す、わずかな制約があります。

そのため、以降のセクションでは、どちらかというと簡素な構造 (SELECT column1 FROM t1) を含む例を示していますが、実際のコードにはもっと多様で複雑な構造が含まれると想像してください。

たとえば、次のように 2 つのテーブルを作るとします。

CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);

その後、SELECT を実行します。

SELECT (SELECT s1 FROM t2) FROM t1;

結果は 2 になります。なぜなら、t2 には、カラム s1 を持つレコードがあり、s1 の値は 2 であるためです。

サブクエリは式の一部にすることができます。関数のオペランドにするときは、かっこを忘れないでください。 次に例を示します。

SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

6.4.2.2 サブクエリを使用した比較

サブクエリの最も一般的は使用法は、次の形式のものです。

<non-subquery operand> <comparison operator> (<subquery>)

<comparison operator> には、次のいずれかを指定します。

= > < >= <= <>

次に例を示します。

... 'a' = (SELECT column1 FROM t1)

以前は、サブクエリを配置する正しい位置は比較の右側に限られていました。一部の古い DBMS で、今でもこの制約が適用されていることがあります。

次に示すのは、結合では処理できない、一般的な形式のサブクエリを使用した比較の例です。この例では、テーブル t2 の最大値と等しいすべての値がテーブル t1 で検索されます。

SELECT column1 FROM t1
       WHERE column1 = (SELECT MAX(column2) FROM t2);

もう 1 つ例を示します。テーブルの 1 つに対する集約が含まれているため、この場合も結合では処理できません。この例では、2 回出現する値を持つすべてのレコードがテーブル t1 で検索されます。

SELECT * FROM t1
       WHERE 2 = (SELECT COUNT(column1) FROM t1);

6.4.2.3 ANYINSOME とともに使用したサブクエリ

構文

<operand> <comparison operator> ANY (<subquery>)
<operand> IN (<subquery>)
<operand> <comparison operator> SOME (<subquery>)

ANY という語は比較演算子の後に指定するもので、``サブクエリが返すレコードの ANY(いずれか)に対して比較が TRUE の場合 TRUE を返す'' ことを表します。 次に例を示します。

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

テーブル t1 に {10} という値を含むレコードがあるとします。 テーブル t2 に含まれている値が {21,14,7} の場合、この式は TRUE になります。なぜなら t2 に、10 よりも小さい 7 という値が存在するからです。 テーブル t2 に含まれている値が {20,10} の場合や、テーブル t2 が空の場合、この式は FALSE になります。 テーブル t2 に含まれている値が {NULL,NULL,NULL} の場合、この式は UNKNOWN になります。

IN という語は = ANY のエイリアスです。したがって、次の 2 つのステートメントは同じです。

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

SOME という語は ANY のエイリアスです。したがって、次の 2 つのステートメントは同じです。

SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

SOME はめったに使用されませんが、上の例では、この語がどのような場合に役立つかを示しています。``a is not equal to any b'' という英語のフレーズを、ほとんどの人は ``a と等しい b はまったく存在しない'' という意味に受け取ります。しかし、SQL 構文では意味が異なります。ANY の代わりに <> SOME を使用することによって、このクエリの本当の意味を誰もが確実に理解できるようにすることができます。

6.4.2.4 ALL とともに使用したサブクエリ

構文

<operand> <comparison operator> ALL (<subquery>)

ALL という語は比較演算子の後に指定するもので、``サブクエリが返すレコードの ALL(すべて)に対して比較が TRUE の場合 TRUE を返す'' ことを表します。 次に例を示します。

SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

テーブル t1 に {10} という値を含むレコードがあるとします。 テーブル t2 に含まれている値が {-5,0,+5} の場合、この式は TRUE になります。なぜなら t2 に含まれている値はすべて 10 より小さいからです。 テーブル t2 に含まれている値が {12,6,NULL,-100} の場合、この式は FALSE になります。なぜなら t2 に、10 よりも大きい 12 という値が 1 つ存在するからです。 テーブル t2 に含まれている値が {0,NULL,1} の場合、この式は UNKNOWN になります。

最後に、テーブル t2 が空の場合、結果は TRUE になります。 この場合、結果は UNKNOWN になると考えたくなりますが、実際には TRUE です。わかりにくいかもしれませんが、

SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

上の例の場合、テーブル t2 が空なら TRUE になりますが、

SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

上の例の場合、テーブル t2 が空なら結果は UNKNOWN になります。

SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

さらに、上の例の場合も、テーブル t2 が空なら結果は UNKNOWN になります。 一般に、NULL 値を持つテーブル空のテーブルは、境目のケースです。サブクエリのコードを書くときには、この 2 つの可能性を常に念頭に置くようにしてください。

6.4.2.5 相関副問い合わせ

相関副問い合わせとは、その中に含まれるカラムの参照が外側のクエリにも含まれているサブクエリのことを言います。 次に例を示します。

SELECT * FROM t1 WHERE column1 = ANY
       (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

注意: 上の例のサブクエリには、t1 の参照が含まれていますが、このサブクエリの FROM 節ではテーブル t1 については言及されていません。そのため、MySQL によってサブクエリの外側が調べられ、外側のクエリで t1 が検出されます。

テーブル t1 に、column1 = 5 で、 column2 = 6 であるレコードが含まれており、テーブル t2 に、column1 = 5 で、column2 = 7 であるレコードが含まれているとします。... WHERE column1 = ANY (SELECT column1 FROM t2) という簡単な式の結果は TRUE になりますが、この例の場合、サブクエリ内の WHERE 節が FALSE になるので(7 <> 5 であるため)、サブクエリ全体は FALSE になります。

スコープの規則:MySQL では、内側から外側に向かって評価を行います。 次に例を示します。

SELECT column1 FROM t1 AS x
  WHERE x.column1 = (SELECT column1 FROM t2 AS x
    WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));

上の例では、SELECT column1 FROM t2 AS x ... によって t2 の名前が変更されることから、x.column2 はテーブル t2 のカラムでなければなりません。SELECT column1 FROM t1 ...ずっと離れた外側のクエリなので、x.column2 はテーブル t1 のカラムではありません。

HAVING 節や ORDER BY 節のサブクエリについても、MySQL では、外側の選択リストに指定されたカラム名が調べられます。

MySQL では、相関クエリを使用しないよう非公式に推奨しています。相関クエリは構成が複雑化するだけでなく、実行にもより多くの時間がかかります。

6.4.2.6 EXISTSNOT EXISTS

サブクエリで値がまったく返らない場合、EXISTS <subquery>TRUE になり、NOT EXISTS <subquery>FALSE になります。 次に例を示します。

SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

従来、EXISTS サブクエリは SELECT * で開始しますが、SELECT 5SELECT column1 などのように、どのように開始してもかまいません。このようなサブクエリ内の SELECT リストは MySQL で無視されるため、重要ではありません。

上の例で、t2 にレコードが含まれていれば、たとえそのレコードに含まれている値が NULL であっても、EXISTS 条件は TRUE になります。しかし、この例は現実的ではありません。なぜなら、ほとんどの場合、[NOT] EXISTS サブクエリには相関が含まれるためです。 次に、より現実に即した例をいくつか示します。

例: 1 つ以上の都市に存在するのは、どの種類の店舗ですか。

SELECT DISTINCT store_type FROM Stores
  WHERE EXISTS (SELECT * FROM Cities_Stores
                WHERE Cities_Stores.store_type = Stores.store_type);

例: どの都市にも存在しないのは、どの種類の店舗ですか。

SELECT DISTINCT store_type FROM Stores
  WHERE NOT EXISTS (SELECT * FROM Cities_Stores
                    WHERE Cities_Stores.store_type = Stores.store_type);

例: すべての都市にも存在するのは、どの種類の店舗ですか。

SELECT DISTINCT store_type FROM Stores S1
  WHERE NOT EXISTS (
    SELECT * FROM Cities WHERE NOT EXISTS (
      SELECT * FROM Cities_Stores
       WHERE Cities_Stores.city = Cities.city
       AND Cities_Stores.store_type = Stores.store_type));

最後の例は、二重にネストされた NOT EXISTS クエリです。このクエリでは、NOT EXISTS 内にさらに NOT EXISTS 節が含まれています。形式的には、このクエリは ``Stores に存在しない店舗が含まれる都市は存在するか'' という疑問に答えるものですが、むしろ、ネストされている NOT EXISTS によって、``x はすべての y に対して TRUE か'' という疑問の答えが得られると言ったほうが簡単です。

6.4.2.7 行副問い合わせ

ここまでの内容は、スカラ副問い合わせ -- つまり、単一のカラム値を返す -- サブクエリについてのものでした。行副問い合わせとは、単一のレコード値を返す異型サブクエリです。したがって、複数のカラム値を返すことがあります。 次に例を 2 つ示します。

SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

column1 = 1 で、column2 = 2 であるレコードがテーブル t2 に含まれている場合、これらのクエリはどちらも TRUE になります。

(1,2)コンストラクタと呼ばれることもあり、他のコンテキストでも正式に使用できます。次に、例を示します。

SELECT * FROM t1 WHERE (column1,column2) = (1,1);

上のステートメントは次のものと同じです。

SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

しかし、通常、コンストラクタは、複数のカラムを返すサブクエリを使った比較で使用されます。たとえば、次のクエリは、``テーブル t2 に重複するレコードを持つすべてのレコードを t1 で検索する'' という要求に対応します。

SELECT column1,column2,column3
       FROM t1
       WHERE (column1,column2,column3) IN
             (SELECT column1,column2,column3 FROM t2);

6.4.2.8 FROM 節のサブクエリ

サブクエリは SELECT ステートメントの FROM 節で正式に使用できます。 実際の構文は次のとおりです。

SELECT ... FROM (<subquery>) AS <name> ...

FROM 節のテーブルには名前が必要なため、AS <name> 節は必ず指定する必要があります。<subquery> 選択リスト内のカラムはいずれも一意な名前を持っていなければなりません。この構文については、このマニュアルの別の場所で、``派生テーブル'' という用語に関連して説明しています。

たとえば、次のようなテーブルがあると想定してください。

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

このテーブルに基づいて、FROM 節のサブクエリ機能を使用するには、次のように記述します。

INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
       FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
       WHERE sb1 > 1;

結果: 2、'2'、4.0

もう 1 つ例を示します。グループ化されたテーブルの合計の平均値を確認する必要があるとします。この場合、次のクエリは機能しません。

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

しかし、次のクエリを使用すれば、必要な情報が得られます。

SELECT AVG(sum_column1)
       FROM (SELECT SUM(column1) AS sum_column1
             FROM t1 GROUP BY column1) AS t1;

注意: サブクエリで使用されているカラム名 (sum_column1) は外側のクエリで認識されます。

現在のところ、FROM 節のサブクエリを相関クエリにすることはできません。

6.4.2.9 サブクエリのエラー

サブクエリだけに適用される新しい戻りエラーがいくつかあります。 このセクションでは、それらのエラーを一つにまとめ、重要な点についていくつか説明します。

サブクエリは SELECT ステートメントと同じく、UPDATE ステートメントや DELETE ステートメントでも正式に使用できるので、UPDATE ステートメント内の割り当てにサブクエリを使用しても問題ありません。 しかし、サブクエリの FROM 節と更新対象の両方に同じテーブル(この場合、テーブル t1)を使用することはできません。

通常、サブクエリがエラーになると、ステートメント全体がエラーになります。

6.4.2.10 サブクエリの最適化

開発は現在進行形で進められているため、長期間有効な最適化のヒントというのはありません。ここでは、いくつかのテクニックについて説明します。

上記のテクニックを使用すると、プログラムの実行が速くなったり、遅くなったりする場合があります。MySQL の BENCHMARK() 関数などの機能を使用すると、それぞれの状況において何が適切か、調べることができます。旧バージョンとの互換性を確保する場合を除いて、結合への変換についてはあまり気にしないでください。

MySQL 自体が行う最適化として次のものがあります。

  1. 非相関副問い合わせは 1 度しか実行されない(EXPLAIN を使用して、指定されたサブクエリが実際に非相関副問い合わせかどうか確認できる)
  2. IN/ALL/ANY/SOME サブクエリは、サブクエリ内の選択リストカラムがインデックス付きである可能性があるため、書き直される。
  3. 次の形式のサブクエリはインデックスルックアップ関数と置き換えられる。
    ... IN (SELECT indexed_column FROM single_table ...)
    
    インデックスルックアップ関数は、EXPLAIN では特殊な結合型として記述される。
  4. 次の形式の式は、MIN または MAX を含む式で拡張される(NULL 値や空のセットが含まれている場合を除く)。
    value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
    
    WHERE 5 > ALL (SELECT x FROM t)
    
    上の式は次のように処理される。
    WHERE 5 > (SELECT MAX(x) FROM t)
    

MySQL Internals Manual(MySQL 内部情報マニュアル)に ``How MySQL Transforms Subqueries(MySQL によるサブクエリの変換)'' という章があります。このマニュアルを参照するには、MySQL のソースパッケージをダウンロードして、`internals.texi' というファイルを探してください。

6.4.2.11 初期の MySQL バージョンに合わせたサブクエリの書き換え

バージョン 4.0 までは、ネストされたクエリのサポートは、INSERT ... SELECT ... 形式と REPLACE ... SELECT ... 形式だけに限定されています。 その他のコンテキストでは、IN() 構造を使用することができます。

サブクエリを含むクエリは、多くの場合、サブクエリなしのクエリに書き換えることができます。

SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

上のクエリは次のように書き換えることができます。

SELECT t1.* FROM t1,t2 WHERE t1.id=t2.id;

次のクエリの場合、

SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

次のように書き換えることができます。

SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
                                       WHERE table2.id IS NULL;

LEFT [OUTER] JOIN は同等のサブクエリよりも迅速に実行されることがあります。なぜなら、LEFT [OUTER] JOIN のほうがサーバによる最適化がより適切に行われることがあるためです。これは、MySQL Server だけでなく、サーバ一般について言えます。 SQL-92 より前は外部結合が存在しなかったため、それまで、サブクエリは特定の処理を行う唯一の方法でした。しかし現在、MySQL サーバを始めとする最新のデータベースシステムでは、さまざまな型の外部結合を提供しています。

より複雑なサブクエリでは、多くの場合、サブクエリを保持するためのテンポラリテーブルを作成することができます。しかし、一部のケースでは、この方法は有効ではありません。このようなケースの多くは、DELETE ステートメントで発生します。この場合、標準 SQL では、結合をサポートしていません(サブクエリ内を除く)。この状況には、次の 3 つの方法のいずれかで対処することができます。

MySQL サーバ 4.0 では、複数テーブルの DELETE ステートメントをサポートしています。このようなステートメントを使用すると、1 つのテーブルのデータだけでなく、複数のテーブルのデータに基づくレコードを一度に効率的に削除することができます。 バージョン 4.0 以降では、複数テーブルの UPDATE ステートメントもサポートしています。

6.4.3 INSERT 構文

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES ((expression | DEFAULT),...),(...),...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]
または  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
または  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name=(expression | DEFAULT), ...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]

INSERT ステートメントでは、既存のテーブルに新しいレコードが挿入されます。INSERT ... VALUES 形式の INSERT では、明示的に指定した値に基づくレコードが挿入されます。INSERT ... SELECT 形式の INSERT では、別の 1 つまたは複数のテーブルから選択されたレコードが挿入されます。複数の値のリストを持つ INSERT ... VALUES 形式は、MySQL バージョン 3.22.5 以降でサポートしています。col_name=expression 構文は MySQL バージョン 3.22.10 以降でサポートしています。

tbl_name には、レコードを挿入するテーブルを指定します。カラム名のリストまたは SET 節には、そのステートメントで値を指定する対象のカラムを指定します。

INSERT ... SELECT または INSERT ... VALUES ステートメントを複数の値のリスト付きで使用する場合は、C API 関数 mysql_info() を使用してクエリに関する情報を取得することができます。情報文字列の形式は次のとおりです。

Records: 100 Duplicates: 0 Warnings: 0

Duplicates は、特定の既存のユニークインデックス値と重複することになるため挿入されなかったレコード数を表します。 Warnings は、何らかの問題があるカラム値を挿入しようとした回数を表します。Warnings(警告)は次のいずれかの条件の下に発生します。

6.4.3.1 INSERT ... SELECT 構文

INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column list)] SELECT ...

INSERT ... SELECT ステートメントでは、1 つまたは複数のテーブルの数多くのレコードを別の 1 つのテーブルにすばやく挿入することができます。

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
tblTemp1.fldOrder_ID > 100;

INSERT ... SELECT ステートメントでは、以下の条件が適用されます。

以前のレコードを上書きするには、INSERT の代わりに REPLACE を使用します。以前のレコードの値と重複するユニークキー値を持つ新しいレコードの処理に関して、REPLACEINSERT IGNORE に対立する働きをします。つまり、新しいレコードが廃棄されるのではなく、新しいレコードによって以前のレコードが置き換えられます。

6.4.3.2 INSERT DELAYED 構文

INSERT DELAYED ...

INSERT の完了を待てないクライアントがある場合、MySQL 固有のオプションである DELAYED を指定した INSERT ステートメントが非常に役立ちます。このようなクライアントの問題は、MySQL を使用してログを記録する一方で、完了までに時間がかかる SELECTUPDATE ステートメントを定期的に実行している場合によく起こります。DELAYED は、MySQL バージョン 3.22.15 で導入された、SQL-92 に対する MySQL の拡張です。

INSERT DELAYED は、ISAM および MyISAM テーブルに対してのみ作用します。注意: MyISAM テーブルでは、データファイルの中央に空きブロックがない場合、同時 SELECT と同時 INSERT が可能なため、MyISAM テーブルで INSERT DELAYED を使用する必要はほとんどありません。 See section 7.1 MyISAM テーブル

INSERT DELAYED を使用すると、クライアントは直ちに処理の続行を許可されます。そして、テーブルが別のスレッドによって使用されていなければ、レコードが挿入されます。

INSERT DELAYED のもう 1 つの主な利点は、多くのクライアントによる挿入が 1 つにまとめられて、1 ブロックに書き込まれることです。この場合、数多くの挿入を個別に行うより、処理速度がはるかに速くなります。

注意: 現在のところ、キューに入れられたレコードは、テーブルに挿入されるまでは単にメモリに格納されているに過ぎません。つまり、mysqldkill -9 によって強制終了した場合や、mysqld が予期しない状況で突然終了した場合、ディスクに書き込まれていないキューの中のレコードはすべて消失します。

以下に、INSERT または REPLACE ステートメントで DELAYED オプションを指定した場合の処理について詳しく説明します。この説明中、``スレッド'' は INSERT DELAYED コマンドを受け取ったスレッドを指し、``ハンドラ'' は個々のテーブルの INSERT DELAYED ステートをすべて処理するスレッドを指します。

注意: 対象のテーブルが使用中でない場合、INSERT DELAYED は通常の INSERT より遅くなります。また、INSERT DELAYED を使用する各テーブルに対応するスレッドを個別に処理するためにサーバで追加のオーバーヘッドが発生します。そのため、INSERT DELAYED はどうしても使う必要があるときのみ使用してください。

6.4.4 UPDATE 構文

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT row_count]

または

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...]
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

UPDATE は既存のテーブルレコードのカラムを新しい値で更新します。 SET 節は値の変更対象のカラムと値を示します。WHERE 節がある場合、この節は更新するレコードを示します。更新対象のレコードが指定されていない場合は、すべてのレコードが更新されます。ORDER BY 節が指定されていると、そこに指定された順序でレコードが更新されます。

キーワード LOW_PRIORITY が指定されていると、他のクライアントによるそのテーブルからの読み取りがなくなるまで、UPDATE の実行は遅らされます。

キーワード IGNORE が指定されていると、更新中に重複キーエラーが発生しても更新ステートメントは中断されません。コンフリクトを発生させるレコードは更新されません。

式内の tbl_name からカラムがアクセスされる場合、UPDATE はそのカラムの現在の値を使用します。たとえば次のステートメントで、age カラムの値はこのカラムの現在の値より 1 だけ多い値に設定されます。

mysql> UPDATE persondata SET age=age+1;

UPDATE は左から右へ評価されます。たとえば、次のステートメントでは、age カラムの値がまず 2 倍にされ、その後、加算されます。

mysql> UPDATE persondata SET age=age*2, age=age+1;

カラムの値がそのカラムの現在の値に設定される場合、MySQL はそれが現在の値であることを認識し、更新処理を行いません。

UPDATE は実際に変更されたレコード数を返します。 MySQL バージョン 3.22 以降では、C API 関数 mysql_info() を使用すると、更新されたレコード数と UPDATE の実行中に発生した警告の数が返されます。 NOT NULL として宣言されたカラムに対して NULL 値を設定し、このカラムを更新すると、そのカラムにはそのカラム型に対応するデフォルト値が設定され、警告のカウントが加算されます。デフォルト値は数値型では 0 であり、文字列型では空の文字列('')であり、日付と時刻型では ``ゼロ'' 値です。

MySQL バージョン 3.23 以降では、LIMIT row_count を使用して UPDATE のスコープを制限することができます。LIMIT 節は次のように機能します。

ORDER BY が使用されている場合(MySQL 4.0.0 以降で使用可能)、レコードは指定された順序で更新されます。ORDER BY 節は、実際には、LIMIT と組み合わせて使用した場合にのみ役立ちます。

MySQL バージョン 4.0.4 以降では、複数のテーブルに対する UPDATE 操作も実行可能です。

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

上の例では、カンマ演算子を使用した内部結合を示していますが、複数テーブルの UPDATE ステートメントでは、LEFT JOIN など、SELECT ステートメントで使用可能な任意の結合型を使用することができます。

注意: 複数テーブルの UPDATE では、ORDER BYLIMIT はいずれも使用できません。

6.4.5 DELETE 構文

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM table_name
       [WHERE where_definition]
       [ORDER BY ...]
       [LIMIT row_count]

または

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] table_name[.*] [, table_name[.*] ...]
       FROM table-references
       [WHERE where_definition]

または

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
       FROM table_name[.*] [, table_name[.*] ...]
       USING table-references
       [WHERE where_definition]

DELETE は、where_definition で指定されている条件にマッチするレコードを、table_name に指定されているテーブルから削除し、削除したレコードの数を返します。

WHERE 節が指定されていない DELETE では、すべてのレコードが削除されます。AUTOCOMMIT モードで実行された場合、WHERE 節なしの DELETETRUNCATE と同じように動作します。See section 6.4.6 TRUNCATE 構文。MySQL 3.23 では、WHERE 節のない DELETE は影響を受けたレコード数として値ゼロを返します。

すべてのレコードの削除時に、削除されたレコード数を確認する必要がある場合、処理速度が遅くなってもかまわなければ、次の形式の DELETE ステートメントを使用できます。

mysql> DELETE FROM table_name WHERE 1>0;

注意: この形式の場合、レコードが一度に 1 つずつ削除されるため、WHERE 節のない DELETE FROM table_name よりはるかに処理が遅くなります。

キーワード LOW_PRIORITY が指定されていると、他のクライアントによるそのテーブルからの読み取りがなくなるまで、DELETE の実行は遅らされます。

MyISAM テーブルの場合、QUICK という語が指定されていると、削除時にストレージエンジンでインデックスのリーフをマージしません。そのため、一部の削除操作では、処理が迅速化されます。

削除操作の速度は、section 5.2.12 DELETE クエリの速度 で説明している要因にも影響されます。

オプション IGNORE が指定されていると、MySQL はレコードの削除中にすべてのエラーを無視します。解析段階で発生したエラーは通常の方法で処理されます。このオプションの使用によって無視されたエラーは警告として返されます。このオプションはバージョン 4.1.1 で導入されました。

MyISAM テーブルの場合、削除されたレコードはリンクされたリストに維持され、元のレコード位置が後続の INSERT 操作で再利用されます。使用されていないスペースを取り戻してファイルのサイズを削減するには、OPTIMIZE TABLE ステートメントまたは myisamchk ユーティリティを使用してテーブルを再編成します。 この場合、OPTIMIZE TABLE の方が簡単ですが、myisamchk の方が処理が迅速です。section 4.6.1 OPTIMIZE TABLE 構文 および section 4.5.6.10 テーブルの最適化 を参照してください。

複数テーブルの削除の最初の形式は、MySQL 4.0.0 以降でサポートしています。 複数テーブルの削除の 2 番目の形式は、MySQL 4.0.2 以降でサポートしています。

複数テーブルの削除では、FROM 節の、または USING 節の前にリストされたテーブル内の一致するレコードのみが削除されます。そのため、多くのテーブルのレコードを一度に削除できるとともに、検索に使用するその他のテーブルを指定することができます。

テーブル名の後に .* を付けるのは、単に Access との互換性を確保するためです。

DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

または

DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

これらの例では、テーブル t1t2 内の一致するレコードだけが削除されます。

上の例ではカンマ演算子を使用した内部結合を示していますが、複数テーブルの DELETE ステートメントでは、LEFT JOIN など、SELECT ステートメントで使用可能な任意の結合型を使用することができます。

ORDER BY が使用されている場合(MySQL 4.0.0 以降で使用可能)、レコードは指定された順序で削除されます。ORDER BY 節は、実際には、LIMIT と組み合わせて使用した場合にのみ役立ちます。次に例を示します。

DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp
LIMIT 1

この場合、 WHERE 節の指定に一致するレコードで最も古いエントリ(timestamp 値に基づく)が削除されます。

DELETE に MySQL 固有のオプションである LIMIT row_count を指定すると、クライアントに制御を戻す前に削除する最大レコード数をサーバに指示することができます。このオプションは、特定の DELETE コマンドで実行にあまり時間がかからないようにする必要があるときに使用できます。この場合、影響を受けたレコードの数が LIMIT 値よりも小さくなるまで、DELETE コマンドを単純に繰り返すことができます。

MySQL 4.0 以降では、DELETE ステートメントに複数のテーブルを指定することによって、複数テーブルにおける特定の条件に応じて、1 つ以上のテーブルからレコードを削除することができます。しかし、複数テーブルの DELETE では、ORDER BYLIMIT はいずれも使用できません。

6.4.6 TRUNCATE 構文

TRUNCATE TABLE table_name

3.23 では、TRUNCATE TABLECOMMIT; DELETE FROM table_name にマップされる。 See section 6.4.5 DELETE 構文

TRUNCATE TABLE は次の点で DELETE FROM ... と異なります。

TRUNCATE TABLE は Oracle の SQL 拡張です。 このステートメントは MySQL 3.23.28 で追加されました。ただし、3.23.28 〜 3.23.32 では、キーワード TABLE を省略する必要があります。

6.4.7 REPLACE 構文

    REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
または  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
または  REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression,...

REPLACEINSERT とほぼ同じように動作しますが、唯一異なる点として、UNIQUE インデックスまたは PRIMARY KEY に関して新しいレコードと同じ値がテーブル内の以前のレコードに含まれていると、以前のレコードが削除されてから新しいレコードが挿入されます。 See section 6.4.3 INSERT 構文

つまり、REPLACE ステートメントでは、以前からあるレコードの値にはアクセスできないことになります。一部の初期バージョンの MySQL では、このアクセスが可能のように見えましたが、これはバグであり、修正されました。

REPLACE を使用するためには、対象のテーブルに対する INSERT 権限と DELETE 権限が必要です。

REPLACE コマンドの使用時、以前のレコード 1 つが新しいレコードで置き換えられると、mysql_affected_rows() によって 2 が返されます。これは重複の削除後にレコードが 1 つ挿入されたためです。

これに基づき、影響されたレコードの値が 1(追加)と 2(置換)のどちらかチェックすることによって、REPLACE によってレコードが 1 つ追加されたのか、または置き換えられたのかを簡単に判別できます。

注意: テーブルに UNIQUE インデックスまたは PRIMARY KEY が設定されていない場合、REPLACE コマンドを使用しても意味がありません。この場合、新しいレコードが既存のものと重複しているかどうかの判別に使用するインデックスがないため、REPLACE コマンドは INSERT と同じになります。

以下は、使用されるアルゴリズムを詳細に示したものです(このアルゴリズムは LOAD DATA ... REPLACE でも使用されます)。

- Insert the row into the table
  - While duplicate key error for primary or unique key
    - Revert changed keys
    - Read conflicting row from the table through the duplicate key value
    - Delete conflicting row
    - Try again to insert the original primary key and unique keys in the tree

6.4.8 LOAD DATA INFILE 構文

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY '\t']
        [[OPTIONALLY] ENCLOSED BY '']
        [ESCAPED BY '\\' ]
    ]
    [LINES 
        [STARTING BY '']    
        [TERMINATED BY '\n']
    ]
    [IGNORE number LINES]
    [(col_name,...)]

LOAD DATA INFILE ステートメントは、テキストファイルからテーブルにレコードを高速で読み取ります。LOCAL キーワードが指定されている場合、このキーワードは接続のクライアント側に関連して解釈されます。LOCAL が指定されていると、クライアントホスト上のクライアントプログラムによってファイルが読み取られ、サーバに送られます。LOCAL が指定されていない場合、ファイルはサーバホスト上に存在しなければならず、サーバによって直接読み取られなければなりません(LOCAL は MySQL バージョン 3.22.6 以降で使用できます)。

セキュリティ上の理由から、サーバに存在するテキストファイルを読み取るときには、そのファイルがデータベースディレクトリに存在するか、または全ユーザがそのファイルを読み取り可能でなければなりません。また、サーバのファイルに対して LOAD DATA INFILE を使用するには、サーバホストでの FILE 権限が必要になります。 See section 4.3.7 MySQL が提供する権限

MySQL 3.23.49 と MySQL 4.0.2(Windows では 4.0.13)以降では、LOCAL はサーバとサーバクライアントの両方でこれが有効として設定されている場合にのみ機能します。たとえば、--local-infile=0 を指定して mysqld を起動した場合、LOCAL は機能しません。 See section 4.3.4 LOAD DATA LOCAL のセキュリティ関連事項

キーワード LOW_PRIORITY を指定すると、LOAD DATA ステートメントの実行は、他のクライアントによるテーブルからの読み取りが終了するまで遅らされます。

MyISAM テーブルに対してキーワード CONCURRENT を指定すると、LOAD DATA の実行中に他のスレッドがこのテーブルからデータを取り出すことができます。当然ながら、このオプションの使用は、同時にテーブルを使用している他のスレッドがなくても、LOAD DATA のパフォーマンスに多少影響します。

LOCAL を指定した場合、ファイルの内容を接続によってクライアントからサーバに送らなければならないため、サーバがファイルに直接アクセスする場合よりも処理がやや遅くなります。その反面、ローカルファイルのロードには FILE 権限は必要ありません。

バージョン 3.23.24 より前のバージョンの MySQL を使用している場合は、LOAD DATA INFILE を使用して FIFO から読み取ることはできません。FIFO から読み取る必要がある場合は(gunzip の出力など)、代わりに LOAD DATA LOCAL INFILE を使用します。

データファイルのロードは、mysqlimport ユーティリティでも実行できます。この場合、LOAD DATA INFILE コマンドがサーバに送られます。--local オプションを指定した mysqlimport では、データファイルがクライアントホストから読み取られます。--compress オプションを指定すると、クライアントとサーバで圧縮されたプロトコルがサポートされている場合に、速度の遅いネットワークのパフォーマンスを良くすることができます。

ファイルがサーバホスト上にある場合、サーバは次の規則に従います。

注意: これらの規則に基づき、`./myfile.txt' という名前のファイルはサーバのデータディレクトリから読み取られるのに対し、`myfile.txt' という名前の同じファイルについてはカレントデータベースのデータベースディレクトリから読み取られます。たとえば、次の LOAD DATA ステートメントでは、db2 データベース内のテーブルへのファイルのロードが明示的に指定されていますが、ファイル `data.txt' はカレントデータベースである db1 のデータベースディレクトリから読み取られます。

mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;

REPLACE キーワードと IGNORE キーワードでは、既存のレコードの値と重複するユニークキー値を持つ入力レコードの処理が制御されます。

REPLACE が指定されている場合、入力レコードによって既存のレコードが置き換えられます(つまり、レコードのプライマリまたはユニークインデックスの値が既存のレコードの値と同じである場合、そのレコードによって既存のレコードが置き換えられます)。 See section 6.4.7 REPLACE 構文

IGNORE が指定されている場合、ユニークキー値が既存のレコードの値と重複する入力レコードがスキップされます。 どちらのオプションも指定されていない場合、動作は LOCAL キーワードが指定されているかどうかによって異なります。 LOCAL が指定されていない場合、重複したキーの値が検出されるとエラーになり、テキストファイルの残りの部分が無視されます。 LOCAL が指定されている場合、デフォルトの動作は IGNORE が指定されている場合と同じです。なぜなら、サーバは処理の最中にファイルの送信を停止することができないためです。

ロード時に外部キー制約を無視するには、LOAD DATA の実行前に SET FOREIGN_KEY_CHECKS=0 を指定します。

空の MyISAM テーブルに対して LOAD DATA INFILE を使用すると、非ユニークなインデックスのすべてが別のバッチに作成されます(REPAIR の場合と同様)。インデックスが数多くある場合、通常、これによって LOAD DATA INFILE の処理がはるかに迅速化されます。通常、この処理は非常に迅速ですが、極端なケースでは、ALTER TABLE .. DISABLE KEYS でインデックスを無効にした後、ALTER TABLE .. ENABLE KEYS を使用してインデックスを再作成する方がさらに迅速にインデックスを作成できることもあります。 See section 4.5.6 myisamchk を使用したテーブルの保守とクラッシュのリカバリ

LOAD DATA INFILESELECT ... INTO OUTFILE の逆です。 See section 6.4.1 SELECT 構文。 テーブルからファイルにデータを書き込むには、SELECT ... INTO OUTFILE を使用します。 ファイルを再びテーブルに読み取るには、LOAD DATA INFILE を使用します。 FIELDS 節と LINES 節の構文は、どちらのコマンドでも同じです。どちらの節もオプションとして指定できますが、これらの節を両方とも指定する場合は、FIELDSLINES より前に指定する必要があります。

FIELDS 節を指定する場合は、その節の従属節(TERMINATED BY[OPTIONALLY] ENCLOSED BYESCAPED BY) もオプションとして指定できますが、少なくともこれらのうちの 1 つは必ず指定する必要があります。

FIELDS 節を指定しない場合、デフォルトは次のように記述した場合と同じです。

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

LINES 節を指定しない場合、デフォルトは次のように記述した場合と同じです。

LINES TERMINATED BY '\n'

注意: Winodows では行終端記号として 2 文字を使用しているため、テキストファイルを Windows システムで生成した場合は、通常、上の記述を LINES TERMINATED BY '\r\n' に変更する必要があります。wordpad などの一部のプログラムでは、行終端記号として \r を使用できます。

読み取り対象行のすべてに存在するプリフィックスをスキップする必要があるときは、LINES STARTING BY prefix_string を使用できます。

したがって、デフォルトの LOAD DATA INFILE は入力データの読み取り時に次のように動作します。

逆に、デフォルトの SELECT ... INTO OUTFILE は出力の書き込み時に次のように動作します。

注意: FIELDS ESCAPED BY '\\' と記述する際には、単一バックスラッシュとして読み取らせる値を表すものとして、バックスラッシュを 2 つ指定する必要があります。

IGNORE number LINES オプションは、ファイルの先頭にある行を無視させる目的で使用します。たとえば、次のように、IGNORE 1 LINES と指定することによって、カラム名が含まれた最初のヘッダ行(1 行)をスキップさせることができます。

mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;

SELECT ... INTO OUTFILELOAD DATA INFILE を並行して使用して、データベースからファイルにデータを書き込み、その後ファイルからデータベースに再び読み取る場合は、フィールドと行の処理に関する両方のコマンドのオプションが一致していなければなりません。一致していない場合、ファイルの内容が LOAD DATA INFILE によって正しく解釈されません。たとえば、SELECT ... INTO OUTFILE を使用して、カンマで区切られたフィールドを持つファイルを書き込むとします。

mysql> SELECT * INTO OUTFILE 'data.txt'
    ->          FIELDS TERMINATED BY ','
    ->          FROM ...;

カンマで区切られたファイルを再び読み取る正しいステートメントは、次のようになります。

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY ',';

上のステートメントではなく、次に示すステートメントでファイルを読み取ろうとすると、処理は正しく行われません。なぜなら、このステートメントでは、フィールド間にタブ文字を探すよう LOAD DATA INFILE に指示しているためです。

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY '\t';

この場合、入力ファイルの各行が単一のフィールドとして解釈されてしまいます。

LOAD DATA INFILE では、外部ソースから得られたファイルを読み取ることもできます。たとえば、dBASE 形式のファイルには、カンマで区切られ、かつ二重引用符で囲まれたフィールドが含まれています。ファイルの各行の終端が改行文字によって示されている場合、このファイルをロードするには次のコマンドを使用します。このコマンドでは、このファイルのフィールドと行の処理に関するオプションを指定しています。

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
    ->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    ->           LINES TERMINATED BY '\n';

フィールドや行の各処理オプションには、いずれも空の文字列('')を指定することができます。空の文字列でない場合、FIELDS [OPTIONALLY] ENCLOSED BYFIELDS ESCAPED BY の値は単一の文字でなければなりません。FIELDS TERMINATED BYLINES TERMINATED BY の値には、複数の文字も使用できます。たとえば、終端に改行/復帰のペアが付いた行を書き込んだり、このような行を含むファイルを読み取る場合は、LINES TERMINATED BY '\r\n' 節を指定します。

たとえば、%% の行で区切られたジョーク集のファイルを SQL テーブルに読み取る場合は、次のように記述します。

CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT NOT NULL);
LOAD DATA INFILE "/tmp/jokes.txt" INTO TABLE jokes FIELDS TERMINATED BY ""
LINES TERMINATED BY "\n%%\n" (joke);

FIELDS [OPTIONALLY] ENCLOSED BY では、フィールドの引用処理が制御されます。出力(SELECT ... INTO OUTFILE)の場合、OPTIONALLY という語を省略すると、すべてのフィールドが ENCLOSED BY 指定文字で囲まれます。このような出力(フィールド区切り記号としてカンマを使用したもの)の例を、次に示します。

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

OPTIONALLY を指定すると、ENCLOSED BY 指定文字は CHAR 型と VARCHAR 型のフィールドを囲むためだけに使用されます。

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

注意: フィールド値内に ENCLOSED BY 指定文字が含まれる場合は、直前に ESCAPED BY 指定文字を付けることによってエスケープされます。注意: ESCAPED BY に空の文字列を指定すると、生成された出力を LOAD DATA INFILE が正しく読み取れないことがあります。たとえば、エスケープ文字が空の場合、前出の例の出力は次のように表示されます。4 行目の 2 番目のフィールドには、引用符に続いてカンマが含まれています。このカンマはフィールドの(実際には終端記号ではないのに)終端記号のように見えます。

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

入力の場合、フィールド値の終わりに ENCLOSED BY 指定文字があると、その文字が除去されます(これは、OPTIONALLY の指定の有無にかかわらず適用されます。OPTIONALLY は入力の解釈には作用しません)。 ESCAPED BY 指定文字に続いて ENCLOSED BY 指定文字があると、その文字は、現在のフィールド値の一部を成すものとして解釈されます。

フィールドが ENCLOSED BY 指定文字で始まっている場合、後続の ENCLOSED BY 指定文字は、その後ろにフィールドまたは行の TERMINATED BY 指定文字列がある場合にのみ、フィールド値の終端として解釈されます。 あいまい性を排除するため、ENCLOSED BY 指定文字をフィールド内で通常の文字として使用する場合、2 回続けて使用することで通常の 1 文字として解釈させることができます。たとえば、ENCLOSED BY '"' と指定されている場合、引用符は次のように処理されます。

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY では、特殊文字の書き込みと読み取り方法が制御されます。FIELDS ESCAPED BY に空以外の文字が指定されている場合、出力でその文字が次の文字の前に付けられます。

FIELDS ESCAPED BY の指定が空の場合、どの文字もエスケープ処理されません。 データのフィールド値に上記の文字が含まれている場合は特に、エスケープ文字として空文字は指定すべきではありません。

入力では、FIELDS ESCAPED BY に空以外の文字が指定されている場合、その文字は除去され、それに続く文字がフィールド値の一部として通常の文字と同じように解釈されます。ただし、`0' または `N' がエスケープされている場合(たとえば、エスケープ文字が `\' の場合の \0 または \N)は例外です。これらの文字列は ASCII 0(ゼロ値のバイト)および NULL として解釈されます。下記の NULL の処理に関する規則を参照してください。

`\' を使用したエスケープ構文の詳細については、section 6.1.1 リテラル:文字列と数値の記述方法 を参照してください。

場合によっては、次に示すように、フィールドと行の各処理オプションが相互に作用することがあります。

NULL 値の処理は、使用されている FIELDS オプションと LINES オプションによって異なります。

次に示すケースは LOAD DATA INFILE でサポートしていません。

次の例では、persondata テーブルのすべてのカラムがロードされます。

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

フィールドリストは指定されていないため、LOAD DATA INFILE は入力レコードに各テーブルカラムのフィールドが含まれているとみなします。デフォルトの FIELDS 値と LINES 値が使用されます。

テーブルの一部のカラムのみロードする場合は、フィールドリストを指定します。

mysql> LOAD DATA INFILE 'persondata.txt'
    ->           INTO TABLE persondata (col1,col2,...);

入力ファイル内のフィールドの順序がテーブルのカラムの順序と異なる場合も、フィールドリストを指定する必要があります。リストを指定しないと、入力フィールドとテーブルの各カラムをどのように一致させたらいいか MySQL で認識できません。

レコードに含まれているフィールドの数が足りない場合、入力フィールドが欠落しているカラムにはデフォルト値が設定されます。デフォルト値の割り当てについては、section 6.5.3 CREATE TABLE 構文 で説明しています。

空のフィールド値はフィールド値が欠落している場合とは異なる解釈をされます。

注意: これらは、INSERTUPDATE ステートメントで文字列型、数値型、日付または時刻型のカラムに空白の文字列を明示的に割り当てた場合と同じ値です。

TIMESTAMP 型のカラムでは、そのカラムに NULL 値(つまり \N)があるときか、フィールドリストの指定時にその TIMESTAMP 型のカラムが省略されていたときだけ(これは最初の TIMESTAMP カラムに対してのみ適用)、カラムの値として現在の日時が設定されます。

入力レコードに含まれるフィールドが多すぎる場合、余分なフィールドは無視され、警告数が加算されます。注意: MySQL 4.1.1 より前のバージョンでは、警告は発生した何らかの問題を示す数でしかありませんでした。 MySQL 4.1.1 では、SHOW WARNINGS によって、発生した問題の詳細を表示することができます。

LOAD DATA INFILE はすべての入力を文字列としてみなすため、INSERT ステートメントの場合とは異なり、ENUM 型や SET 型のカラムに数値を使用することはできません。ENUM 型と SET 型の値はすべて文字列として指定する必要があります。

C API を使用している場合は、LOAD DATA INFILE クエリの完了時に API 関数 mysql_info() を呼び出すことによって、クエリに関する情報を取得できます。情報文字列の形式は次のとおりです。

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Warnings(警告)は、INSERT ステートメント(see section 6.4.3 INSERT 構文)で値を挿入するときと同じ状況で発生しますが、その他に、入力レコードに含まれるフィールドが多すぎる場合と少なすぎる場合にも警告が生成されます。警告はどこにも格納されません。単に、警告の数を、処理が正常に行われたかどうかを示すインジケータとして利用できるだけです。

警告が出力された場合にその正確な理由を確認する必要があるときは、1 つの方法として、SELECT ... INTO OUTFILE を使用して別のファイルに出力し、元の入力ファイルと比較することができます。

LOAD DATA にパイプから読み取らせる必要がある場合は、次の方法を使用できます。

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

3.23.25 より前のバージョンの MySQL を使用している場合は、上記の方法は LOAD DATA LOCAL INFILE でのみ使用可能です。

MySQL 4.1.1 では、SHOW WARNINGS を使用して、max_error_count に指定された数の警告の最初のリストを取得できます。 See section 4.6.8.9 SHOW WARNINGS | ERRORS

INSERTLOAD DATA INFILE の効率性の比較や、LOAD DATA INFILE の迅速化の詳細については、See section 5.2.10 INSERT クエリの速度

6.4.9 HANDLER 構文

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name CLOSE

HANDLER ステートメントでは、MyISAM テーブルのストレージエンジンインタフェースに直接アクセスすることができます。

最初の形式の HANDLER ステートメントでは、テーブルが開かれ、後続の HANDLER ... READ ステートメントでのアクセスが可能になります。 このテーブルオブジェクトは他のスレッドと共有されていないため、そのスレッドが HANDLER tbl_name CLOSE を呼び出すか、またはそのスレッドが終了するまで、テーブルオブジェクトが閉じられることはありません。

2 番目の形式の HANDLER ステートメントでは、指定したインデックスが指定した値にマッチし、かつ WHERE 条件を満たしている 1 つ(または、LIMIT 節の指定に基づく複数)のレコードが読み取られます。複合インデックスがある場合は、対象のインデックスカラム値をカンマで区切られたリストとして指定します。この場合、インデックスのすべてのカラムの各値を指定するか、またはインデックスカラムの左端のプリフィックスの値を指定します。たとえば、col_acol_bcol_c という名前の 3 つのカラムがこの順序でインデックスに含まれているとします。 HANDLER ステートメントでは、インデックスの 3 つすべてのカラムの値を指定するか、または左端のプリフィックスのカラムの値を指定することができます。次に例を示します。

HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... index_name = (col_a_val,col_b_val) ...
HANDLER ... index_name = (col_a_val) ...

3 番目の形式の HANDLER ステートメントでは、WHERE 条件を満たしている 1 つ(または、LIMIT節の指定に基づく複数)のレコードがテーブルからインデックスの順序で読み取られます。

4 番目の形式の HANDLER ステートメント(インデックスの指定なし)では、WHERE 条件を満たしている 1 つ(または、LIMIT 節の指定に基づく複数)のレコードがテーブルからそのまままのレコード順序(データファイルに格納されている順序)で読み取られます。テーブルのフルスキャンを行う必要がある場合、この形式は HANDLER tbl_name READ index_name 形式より迅速です。

HANDLER ... CLOSE では、HANDLER ... OPEN で開かれたテーブルが閉じられます。

注意:PRIMARY KEYHANDLER インタフェースを使用している場合は、HANDLER tbl READ `PRIMARY` > (...) のように、キーワード PRIMARY をバッククォート記号で必ず囲みます。

HANDLER は、やや低レベルのステートメントです。たとえば、整合性は確保されません。つまり、HANDLER ... OPEN はテーブルのスナップショットを取るものではなく、テーブルのロックも行いません。そのため、HANDLER ... OPEN の発行後に、テーブルデータが変更される(そのスレッドまたは他のスレッドによって)可能性があります。このような変更は HANDLER ... NEXT スキャンや HANDLER ... PREV スキャンでは部分的にしか示されないことがあります。

通常の SQL の代わりにこのインタフェースを使用する理由は、次のとおりです。

6.4.10 DO 構文

DO expression, [expression, ...]

上の構文では、式が実行されますが、結果は何も返されません。これは SELECT expression, expression の省略形ですが、結果が必要ない場合には、処理速度がやや速いという利点があります。

この構文は、主に、RELEASE_LOCK などのように副次的な影響のある関数に使用すると便利です。

6.5 データ定義: CREATEDROPALTER

6.5.1 CREATE DATABASE 構文

CREATE DATABASE [IF NOT EXISTS] db_name

CREATE DATABASE では、指定した名前のデータベースが作成されます。

使用可能なデータベース名の規則は、section 6.1.2 データベース名、テーブル名、インデックス名、カラム名、エイリアス名 で説明しています。IF NOT EXISTS を指定していないときに、データベースが既に存在していると、エラーが発生します。

MySQL では、データベースは、対応するファイルをその内部に含むディレクトリとして実装されます。作成当初のデータベースにはテーブルは何もないため、CREATE DATABASE ステートメントの実行では、MySQL データディレクトリの下にディレクトリが作成されるだけです。

データベースの作成は mysqladmin でも可能です。 See section 4.9 MySQL クライアントサイドのスクリプトとユーティリティ

6.5.2 DROP DATABASE 構文

DROP DATABASE [IF EXISTS] db_name

DROP DATABASE では、データベース内のすべてのテーブルが破棄され、データベースが削除されます。シンボリックリンクのあるデータベースに対して DROP DATABASE を実行すると、リンクと元のデータベースとの両方が削除されます。このコマンドの使用時には、十分に注意してください。

DROP DATABASE では、データベースディレクトリから削除されたファイルの数が返されます。MyISAM テーブルの場合、通常、各テーブルが `.MYD'`.MYI'`.frm' の 3 つのファイルに対応しているため、ファイル数はテーブル数の 3 倍になります。

DROP DATABASE コマンドでは、次の拡張子を持つすべてのファイルが、指定したデータベースディレクトリから削除されます。

拡張子 拡張子 拡張子 拡張子
.BAK .DAT .HSH .ISD
.ISM .ISM .MRG .MYD
.MYI .db .frm

2 桁の数値で構成されるサブディレクトリ(RAID ディレクトリ)もすべて削除されます。

MySQL バージョン 3.22 以降では、キーワード IF EXISTS を使用して、データベースが存在しない場合に発生するエラーを回避することができます。

データベースの破棄は mysqladmin でも可能です。 See section 4.9 MySQL クライアントサイドのスクリプトとユーティリティ

6.5.3 CREATE TABLE 構文

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]

または

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(] LIKE old_tbl_name [)];

create_definition:
    col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [[PRIMARY] KEY] [COMMENT 'string'] [reference_definition]
  | [CONSTRAINT [symbol]] PRIMARY KEY (index_col_name,...)
  | KEY [index_name] (index_col_name,...)
  | INDEX [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] UNIQUE [INDEX] [index_name] (index_col_name,...)
  | FULLTEXT [INDEX] [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
  | CHECK (expr)

type:
    TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  | INT[(length)] [UNSIGNED] [ZEROFILL]
  | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  | CHAR(length) [BINARY | ASCII | UNICODE]
  | VARCHAR(length) [BINARY]
  | DATE
  | TIME
  | TIMESTAMP
  | DATETIME
  | TINYBLOB
  | BLOB
  | MEDIUMBLOB
  | LONGBLOB
  | TINYTEXT
  | TEXT
  | MEDIUMTEXT
  | LONGTEXT
  | ENUM(value1,value2,value3,...)
  | SET(value1,value2,value3,...)

index_col_name:
        col_name [(length)] [ASC | DESC]

reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options: table_option [table_option] ...

table_option:
    TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM }
  | AUTO_INCREMENT = #
  | AVG_ROW_LENGTH = #
  | CHECKSUM = {0 | 1}
  | COMMENT = 'string'
  | MAX_ROWS = #
  | MIN_ROWS = #
  | PACK_KEYS = {0 | 1 | DEFAULT}
  | PASSWORD = 'string'
  | DELAY_KEY_WRITE = {0 | 1}
  | ROW_FORMAT = { DEFAULT | DYNAMIC | FIXED | COMPRESSED }
  | RAID_TYPE = { 1 | STRIPED | RAID0 } RAID_CHUNKS=#  RAID_CHUNKSIZE=#
  | UNION = (table_name,[table_name...])
  | INSERT_METHOD = { NO | FIRST | LAST }
  | DATA DIRECTORY = 'absolute path to directory'
  | INDEX DIRECTORY = 'absolute path to directory'
  | DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]

select_statement:
    [IGNORE | REPLACE] [AS] SELECT ...     (Some legal select statement)

CREATE TABLE では、指定した名前のテーブルが作成されます。 使用可能なテーブル名の規則は、section 6.1.2 データベース名、テーブル名、インデックス名、カラム名、エイリアス名 で説明しています。 デフォルトでは、テーブルはカレントデータベースに作成されます。 テーブルがすでに存在する場合、カレントデータベースがない場合、またはデータベースが存在しない場合には、エラーが発生します。

MySQL バージョン 3.22 以降では、テーブル名を db_name.tbl_name の形式で指定することで、指定したデータベースにテーブルを作成することができます。 これは、カレントデータベースの有無にかかわらず有効です。

MySQL バージョン 3.23 以降では、テーブルの作成時に TEMPORARY キーワードを指定することができます。テンポラリテーブルは現在の接続の間のみ有効で、接続が閉じると自動で削除されます。そのため、異なる 2 つの接続が同じテンポラリテーブル名を使用できます。この場合、それぞれの接続のテンポラリテーブル間でコンフリクトが発生したり、同名の既存のテーブルとの間でコンフクリトが発生したりすることはありません(既存のテーブルはテンポラリテーブルが削除されるまで表示されません)。MySQL 4.0.2 以降では、テンポラリテーブルの作成には、CREATE TEMPORARY TABLES 権限が必要です。

MySQL バージョン 3.23 以降では、キーワード IF NOT EXISTS を使用して、テーブルがすでに存在する場合に発生するエラーを回避することができます。注意: 既存のテーブルの構造が、CREATE TABLE ステートメントで指定されたテーブルの構造と同じかどうかは検証されません。

バージョン 4.1.0 以降では、属性 SERIALBIGINT NOT NULL AUTO_INCREMENT UNIQUE のエイリアスとして使用できます。これは互換性を考慮した機能です。

MySQL 3.23 以降では、CREATE TABLE ステートメントの最後に SELECT ステートメントを追加することによって、1 つのテーブルから別のテーブルを作成することができます。

CREATE TABLE new_tbl SELECT * FROM orig_tbl;

インデックスは新しいテーブルに持ち越されません。また、一部のカラム型の変換が行われる場合があります。たとえば、AUTO_INCREMENT 属性は維持されず、VARCHAR 型のカラムは CHAR 型のカラムになることがあります。

CREATE ... SELECT でテーブルを作成するときには、クエリ内の関数呼び出しや式に対して必ずエイリアスを指定するようにします。エイリアスを指定しないと、CREATE ステートメントが正常に実行されなかったり、不適切なカラム名が生成されたりする場合があります。

CREATE TABLE artists_and_works
SELECT artist.name, COUNT(work.artist_id) AS number_of_works
FROM artist LEFT JOIN work ON artist.id = work.artist_id
GROUP BY artist.id;

MySQL 4.1 以降では、生成されるカラムの型を明示的に指定することができます。

CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;

MySQL 4.1 では、LIKE でも、別のテーブルの定義に基づいて新しいテーブル(元のテーブルのカラム属性やインデックスをすべて含む)を作成することができます。

CREATE TABLE new_tbl LIKE orig_tbl;

CREATE TABLE ... LIKE では、元のテーブルに指定された DATA DIRECTORYINDEX DIRECTORY のテーブルオプションはいずれもコピーされません。

データベースディレクトリ内の一部のファイルには、各テーブルの tbl_name が反映されます。MyISAM 型のテーブルの場合、次のようになります。

ファイル 用途
tbl_name.frm テーブル形式(定義)ファイル
tbl_name.MYD データファイル
tbl_name.MYI インデックスファイル

さまざまなカラム型の特性の詳細については、section 6.2 カラム型 を参照してください。

6.5.3.1 カラムの暗黙的な変更

場合によっては、CREATE TABLE ステートメントで指定されているカラムの型、属性が、MySQL によって暗黙的に変更されることがあります(このような変更は ALTER TABLE でも発生する場合があります)。

指定した以外のカラム型が MySQL によって使用されたかどうか確認するには、テーブルの作成または変更後に、DESCRIBE tbl_name ステートメントを発行します。

myisampack を使用してテーブルを圧縮すると、特定の他のカラム型の変更が発生する場合があります。 See section 7.1.2.3 圧縮テーブルの特性

6.5.4 ALTER TABLE 構文

ALTER [IGNORE] TABLE tbl_name alter_specification [, alter_specification ...]

alter_specification:
    ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
  | ADD [COLUMN] (create_definition, create_definition,...)
  | ADD INDEX [index_name] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]] PRIMARY KEY (index_col_name,...)
  | ADD [CONSTRAINT [symbol]] UNIQUE [index_name] (index_col_name,...)
  | ADD FULLTEXT [index_name] (index_col_name,...)
  | ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...)
           [reference_definition]
  | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  | CHANGE [COLUMN] old_col_name create_definition
           [FIRST | AFTER column_name]
  | MODIFY [COLUMN] create_definition [FIRST | AFTER column_name]
  | DROP [COLUMN] col_name
  | DROP PRIMARY KEY
  | DROP INDEX index_name
  | DISABLE KEYS
  | ENABLE KEYS
  | RENAME [TO] new_tbl_name
  | ORDER BY col
  | CHARACTER SET character_set_name [COLLATE collation_name]
  | table_options

ALTER TABLE では、既存のテーブルの構造を変更することができます。 たとえば、カラムの追加や削除、インデックスの作成や破壊、既存のカラムの型変更、カラム名やテーブル名自体の変更などの操作を実行できます。また、テーブルおよびテーブル型に関するコメントを変更することもできます。 See section 6.5.3 CREATE TABLE 構文

ALTER TABLE を使用してカラムの仕様を変更したにもかかわらず、カラムが変更されていないと DESCRIBE tbl_name で示された場合は、section 6.5.3.1 カラムの暗黙的な変更 で挙げている理由のいずれかにより、変更が MySQL によって無視された可能性があります。たとえば、VARCHAR 型のカラムを CHAR 型に変更しようとしたときに、他の可変長カラムがテーブルにまだ含まれていると、このカラムに対しては VARCHAR 型が引き続き使用されます。

ALTER TABLE の処理では、元のテーブルの一時的なコピーが作成されます。 変更はこのコピーに対して実行されます。その後元のテーブルが削除され、新しいテーブルの名前が変更されます。この変更処理は、すべての更新が、エラーになることなく、確実に新しいテーブルに自動でリダイレクトされるように実行されます。ALTER TABLE の実行中、元のテーブルは他のクライアントによって読み取り可能です。このテーブルの更新とテーブルへの書き込みは、新しいテーブルの準備が整うまで停止されます。

注意: RENAME 以外のオプションを ALTER TABLE に指定した場合は、厳密にはデータをコピーする必要がないとき(カラム名の変更時など)でも、必ずテンポラリテーブルが MySQL によって作成されます。これについては今後修正する予定ですが、通常 ALTER TABLE はそれほど頻繁に使用されないため、TODOリストにおけるこの修正の優先順位はそれほど高くありません。 MyISAM テーブルについては、myisam_sort_buffer_size 変数に高い値を設定することによって、インデックスの再作成部分(再作成プロセスでもっとも処理が遅い部分)を迅速化することができます。

以下に、ALTER TABLE に使用例をいくつか示します。まず、次のコマンドでテーブル t1 を作成するとします。

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

このテーブルの名前を t1 から t2 に変更するには、次のようにします。

mysql> ALTER TABLE t1 RENAME t2;

カラム aINTEGER から TINYINT NOT NULL に変更し(名前は変えずに)、さらにカラム bCHAR(10) から CHAR(20) に変更し、かつこのカラムの名前を b から c に変更するには、次のようにします。

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

d という名前を持つ TIMESTAMP 型の新しいカラムを追加するには、次のようにします。

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

カラム d にインデックスを追加し、カラム a を主キーにするには、次のようにします。

mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

カラム c を削除するには、次のようにします。

mysql> ALTER TABLE t2 DROP COLUMN c;

c という名前を持つ、整数型の新しい AUTO_INCREMENT カラムを追加するには、次のようにします。

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
           ADD INDEX (c);

注意: 上の例で c のインデックスを作成しているのは、AUTO_INCREMENT カラムにはインデックスが必要なためです。また、cNOT NULL として宣言しているのは、インデックス付きカラムは値として NULL を取れないためです。

AUTO_INCREMENT カラムを追加すると、カラム値として連続番号が自動的に挿入されます。最初の連続番号を設定するには、ALTER TABLE の前に SET INSERT_ID=value を実行するか、または AUTO_INCREMENT=value テーブルオプションを指定します。 See section 5.5.6 SET 構文

MyISAM テーブルでは、AUTO_INCREMENT カラムを変更しない限り、連続番号は影響されません。AUTO_INCREMENT カラムを破棄した後に別の AUTO_INCREMENT カラムを追加すると、再び 1 から採番されます。

See section A.7.1 ALTER TABLE の問題

6.5.5 RENAME TABLE 構文

RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]

名前の変更は原子的に実行されます。つまり、テーブル名が変更されている間、他のスレッドからはこれらのテーブルのいずれにもアクセスできなくなります。それによって、テーブルを空のテーブルと置換することが可能になります。 :

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

名前の変更は左から右へ実行されるため、2 つのテーブルの名前を交換する場合は、次のように記述する必要があります。

RENAME TABLE old_table    TO backup_table,
             new_table    TO old_table,
             backup_table TO new_table;

データベース名を変更することもできますが、その場合は、変更後のデータベースが変更前のデータベースと同じディスク上に存在していなければなりません。

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

ロックされたテーブルやアクティブなトランザクションがあると、RENAME は実行できません。また、元のテーブルに対する ALTER 権限と DROP 権限、新しいテーブルに対する CREATE 権限と INSERT 権限が必要です。

MySQL で複数テーブルの名前の変更時にエラーが発生した場合、名前を変更されたすべてのテーブルに対して逆方向の名前の変更処理が行われ、すべてが元の状態に戻されます。

RENAME TABLE は MySQL 3.23.23 で追加されました。

6.5.6 DROP TABLE 構文

DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]

DROP TABLE では、1 つ以上のテーブルが削除されます。テーブルデータとテーブル定義のすべてが削除されるため、このコマンドは慎重に使用してください。

MySQL バージョン 3.22 以降では、キーワード IF EXISTS を使用することによって、指定したテーブルが存在しない場合に発生するエラーを回避できます。4.1 では、IF EXISTS を指定した場合、存在しないすべてのテーブルに関する NOTE が出力されます。 See section 4.6.8.9 SHOW WARNINGS | ERRORS

RESTRICTCASCADE は、移植を容易化するためのものです。 現在のところ、これらを指定しても何も行われません。

注意: DROP TABLE では、現在のアクティブなトランザクションが自動的にコミットされます(4.1 を使用していて、TEMPORARY キーワードを指定した場合を除く)。

オプション TEMPORARY は、4.0 では無視されます。4.1 では、このオプションは次のように動作します。

TEMPORARY は、実際のテーブルが誤って廃棄されないようにするための手段として役立ちます。

6.5.7 CREATE INDEX 構文

CREATE [UNIQUE|FULLTEXT] INDEX index_name
       ON tbl_name (index_col_name,...)

index_col_name:
        col_name [(length)] [ASC | DESC]

バージョン 3.22 より前の MySQL の場合、CREATE INDEX ステートメントでは何も実行されません。バージョン 3.22 以降では、CREATE INDEX は、インデックスを作成する ALTER TABLE ステートメントにマップされています。 See section 6.5.4 ALTER TABLE 構文

通常、テーブルのインデックスはすべて、テーブル自体を CREATE TABLE で作成するときに一緒に作成します。 See section 6.5.3 CREATE TABLE 構文CREATE INDEX では、既存のテーブルにインデックスを追加することができます。

(col1,col2,...) 形式のカラムリストでは、複合インデックスが作成されます。インデックス値は、リストに指定したカラムの値を連結して作成されます。

CHAR 型と VARCHAR 型については、カラムの一部のみを使用するインデックスを作成できます。この場合、col_name(length) 構文を使用して、各カラム値の最初から length に指定した数のバイトのインデックスを作成します(BLOB 型と TEXT 型では、プリフィックスの長さを必ず指定する必要があります。length には 255 までの数値を指定できます)。次のステートメントでは、name カラムの最初の 10 文字を使用したインデックスが作成されます。

mysql> CREATE INDEX part_of_name ON customer (name(10));

ほとんどの名前は最初の 10 文字が異なるため、このインデックスの場合、name カラム全体から作成したインデックスよりはるかに遅くなるということはありません。 また、カラムの一部でインデックスを作成するとインデックスファイルのサイズを大幅に削減できるため、ディスク領域が節約されるとともに、INSERT 操作が迅速化される場合があります。

注意: NULL 値を持てるカラムに対するインデックスの追加は、MySQL バージョン 3.23.2 以降で MyISAMInnoDBBDB のいずれかのテーブル型を使用している場合にのみ可能です。 BLOB 型や TEXT 型のカラムに対するインデックスの追加は、MySQL バージョン 3.23.2 以降で MyISAM または BDB のいずれかのテーブル型を使用している場合か、MySQL バージョン 4.0.14 以降で InnoDB テーブル型を使用している場合にのみ可能です。 BLOB 型や TEXT 型カラムのインデックスでは、プリフィックスの長さを必ず指定する必要があります。

index_col_name の指定では、最後に ASC または DESC を付けることができます。 これらのキーワードは、昇順または降順によるインデックス値の格納を指定できるようにする今後の拡張に対応するものです。現時点では、これらのキーワードは解析されても無視され、インデックス値は常に昇順で格納されます。

MySQL でのインデックスの使用方法の詳細については、section 5.4.3 MySQL でのインデックスの使用 を参照してください。

FULLTEXT インデックスでは、MyISAM テーブルにおける CHAR 型、VARCHAR 型、TEXT 型のカラムに対してのみ、インデックスを作成することができます。FULLTEXT インデックスは MySQL バージョン 3.23.23 以降で使用できます。 section 6.8 MySQL 全文検索

6.5.8 DROP INDEX 構文

DROP INDEX index_name ON tbl_name

DROP INDEX では、index_name に指定したインデックスが tbl_name に指定したテーブルから破棄されます。バージョン 3.22 より前の MySQL では、DROP INDEX では何の処理も行われません。バージョン 3.22 以降では、DROP INDEX はインデックスを破棄する ALTER TABLE ステートメントにマップされています。 See section 6.5.4 ALTER TABLE 構文

6.6 MySQL 基本ユーザユーティリティコマンド

6.6.1 USE 構文

USE db_name

USE db_name ステートメントでは、db_name に指定したデータベースを、後続のクエリのデフォルトのデータベースとして使用するよう MySQL に指示することができます。指定したデータベースは、セッションの終了まで、または別の USE ステートメントを発行するまでカレントデータベースになります。

mysql> USE db1;
mysql> SELECT COUNT(*) FROM mytable;      # selects from db1.mytable
mysql> USE db2;
mysql> SELECT COUNT(*) FROM mytable;      # selects from db2.mytable

USE ステートメントで特定のデータベースをカレントにしても、それによって、他のデータベースのテーブルにアクセスできなくなるわけではありません。次の例では、db1 データベースの author テーブルと、db2 データベースの editor テーブルにアクセスします。

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
    ->        WHERE author.editor_id = db2.editor.editor_id;

USE ステートメントは Sybase との互換性を確保するためのものです。

6.6.2 DESCRIBE 構文(カラムに関する情報の取得)

{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBESHOW COLUMNS FROM の簡略形です。 See section 4.6.8.1 データベース、テーブル、カラム、およびインデックスに関する情報の取得

DESCRIBE では、テーブルのカラムに関する情報が出力されます。col_name には、カラム名を指定する他に、SQL のワイルドカード文字 `%'`_' を含む文字列を指定できます。この場合、この文字列に一致する名前を持つカラム名のみが出力されます。文字列を引用符でエスケープする必要はありません。

カラム情報で示されたカラムの型は、そのカラムの CREATE TABLE ステートメントで指定したものと異なっている場合があります。これは、カラムの型が MySQL によって自動で変更されることがあるためです。 See section 6.5.3.1 カラムの暗黙的な変更

このステートメントは Oracle との互換性を確保するためのものです。

SHOW ステートメントでも、同様の情報が出力されます。 See section 4.6.8 SHOW 構文

6.7 MySQL トランザクションコマンドとロックコマンド

6.7.1 START TRANSACTIONCOMMITROLLBACK の各構文

デフォルトでは、MySQL は自動コミットモードで稼動します。この場合、テーブルを更新(変更)するステートメントを実行すると、MySQL によって直ちにその更新がディスクに格納されます。

トランザクションセーフテーブル(InnoDBBDB)を使用している場合は、次のコマンドを使用して MySQL を非自動コミットモードに設定することができます。

SET AUTOCOMMIT=0

AUTOCOMMIT 変数をゼロに設定して自動コミットモードを無効にした後は、COMMIT を使用して変更内容をディスクに格納するか、または、トランザクションの開始以来行った変更を無視する場合は ROLLBACK を使用する必要があります。

ひと続きのステートメントのみに対して自動コミットモードを無効にするときには、START TRANSACTION ステートメントを使用できます。 :

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

トランザクションを開始するときには、START TRANSACTION の代わりに BEGINBEGIN WORK も使用できます。 START TRANSACTION は MySQL 4.0.11 で追加されました。これは SQL-99 の構文であり、トランザクションを随時開始するときにはこの構文が推奨されます。BEGIN は MySQL 3.23.17 以降で、BEGIN WORK は MySQL 3.23.19 以降で使用できます。

注意: 使用しているテーブルがトランザクションセーフテーブルでない場合は、自動コミットモードのステータスにかかわらず、すべての変更が直ちに格納されます。

非トランザクションテーブルを更新した後に ROLLBACK ステートメントを発行すると、エラー(ER_WARNING_NOT_COMPLETE_ROLLBACK)が警告として出力されます。トランザクションセーフテーブルはいずれもリストアされますが、非トランザクションセーフテーブルは変更されません。

START TRANSACTION または SET AUTOCOMMIT=0 を使用している場合は、以前の更新ログの変わりにMySQL バイナリログをバックアップ用に使用してください。トランザクションは COMMIT と同時にひとまとまりでバイナリログに格納されるため、ロールバックされたトランザクションが格納されることはありません。 See section 4.10.4 バイナリログ

トランザクションの分離レベルを変更するには、SET TRANSACTION ISOLATION LEVEL を使用します。 See section 6.7.6 SET TRANSACTION 構文

6.7.2 ロールバックできないステートメント

一部のステートメントはロールバックできません。通常、このようなステートメントとして、データベースの作成や破棄を行うステートメントや、テーブルの作成、破棄、変更を行うステートメントなどのデータ定義言語(DDL)ステートメントがあります。

場合によっては、このようなステートメントを組み込まないよう、トランザクションを設計する必要があります。 ロールバックできないステートメントをトランザクションの始めの方で発行したときに、その後別のステートメントでエラーが発生した場合、トランザクションの結果全体を ROLLBACK ステートメントでロールバックすることはできません。

6.7.3 暗黙的なコミットを引き起こすステートメント

次のコマンドでは、トランザクションが(コマンドの実行前に COMMIT を発行した場合と同じように)暗黙的に終了します。

コマンド コマンド コマンド
ALTER TABLE BEGIN CREATE INDEX
DROP DATABASE DROP INDEX DROP TABLE
LOAD MASTER DATA LOCK TABLES RENAME TABLE
SET AUTOCOMMIT=1 START TRANSACTION TRUNCATE

いずれかのテーブルが現在ロックされている場合は、UNLOCK TABLES でもトランザクションが終了します。MySQL 4.0.13 より前のバージョンでは、バイナリ更新ログが有効になっていると、CREATE TABLE でもトランザクションが終了します。

トランザクションはネストできません。これは、START TRANSACTION ステートメントやそのいずれかのシノニムの発行時に現在のトランザクションに対して実行される暗黙的な COMMIT の影響によるものです。

6.7.4 SAVEPOINT および ROLLBACK TO SAVEPOINT 構文

MySQL 4.0.14 および 4.1.1 以降では、InnoDB で SQL コマンド SAVEPOINT および ROLLBACK TO SAVEPOINT をサポートしています。

SAVEPOINT identifier

このステートメントでは、identifier に指定した名前を持つトランザクションセーブポイントが設定されます。現在のトランザクションに同名のセーブポイントがすでに存在する場合は、元のセーブポイントが削除され、新しいセーブポイントが設定されます。

ROLLBACK TO SAVEPOINT identifier

このステートメントでは、指定したセーブポイントまでトランザクションがロールバックされます。 セーブポイントの設定後にこのトランザクションでレコードに対して行った変更は、ロールバックによって取り消されますが、InnoDB では、セーブポイントの後にメモリに格納された行ロックは解除されません(注意: 新たに挿入されたレコードについては、ロック情報はレコードに格納されたトランザクション ID によって渡されます。ロック自体が別にメモリに格納されることはありません。この場合、レコードのロックは取消し処理で解除されます)。 指定したセーブポイントより後に設定されたセーブポイントは削除されます。

コマンドで次のエラーが返された場合は、指定した名前のセーブポイントが存在しないことを意味します。

ERROR 1181: Got error 153 during ROLLBACK

セーブポイントを指定しないで COMMIT または ROLLBACK を実行すると、現在のトランザクションのセーブポイントがすべて削除されます。

6.7.5 LOCK TABLES および UNLOCK TABLES 構文

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
            [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES

LOCK TABLES では、現在のスレッドのテーブルがロックされます。UNLOCK TABLES では、現在のスレッドが保有しているロックが解除されます。現在のスレッドが別の LOCK TABLES を発行したり、サーバへの接続が閉じられると、現在のスレッドがロックしているテーブルのロックはすべて暗黙的に解除されます。

MySQL 4.0.2 で LOCK TABLES を使用するには、関連するテーブルに対するグローバルな LOCK TABLES 権限と SELECT 権限が必要です。MySQL 3.23 では、関連するテーブルに対する SELECTinsertDELETEUPDATE の各権限が必要です。

LOCK TABLES を使用する主な理由は、トランザクションをエミュレートしたり、テーブルの更新時に処理を迅速化したりするためです。これについては、詳しく後述します。

あるスレッドがテーブルに対する READ ロックを取得すると、そのスレッド(および他のすべてのスレッド)はそのテーブルからの読み取りのみ実行できるようになります。あるスレッドがテーブルに対する WRITE ロックを取得すると、ロックを保有しているスレッドだけがそのテーブルからの読み取りやテーブルへの書き込みを実行できるようになります。他のスレッドはブロックされます。

READ LOCALREAD の違いは、READ LOCAL の場合、ロックの保有中に、コンフクリトを発生させない INSERT ステートメントを実行できることです。しかし、ロックの保有中にデータベースを MySQL の外部で操作しようとする場合は、この機能を使用できません。

LOCK TABLES の使用時には、使用するテーブルをすべてロックし、またクエリで使用するエイリアスと同じ名前を使用する必要があります。1 つのクエリで同じテーブルを何度も指定する(エイリアスを使用して)場合は、各エイリアスに対してロックを取得しなければなりません。

更新をできるだけ早く処理するために、WRITE ロックは、通常、READ ロックより優先されます。そのため、あるスレッドが READ ロックを取得し、別のスレッドが WRITE ロックを要求している場合、後続の READ ロック要求は、WRITE スレッドがロックを取得し、その後そのロックを解除するまで待機します。LOW_PRIORITY WRITE ロックでは、そのスレッドが WRITE ロックを取得する前に、他のスレッドが READ ロックを取得することができます。その間、LOW_PRIORITY WRITE ロックを発行したスレッドは待機します。LOW_PRIORITY WRITE は、READ ロックを取得しようとするスレッドが皆無になるときがあるとわかっている場合にのみ使用してください。

LOCK TABLES は次のように機能します。

  1. ロックするテーブルを内部定義された順序(ユーザから見た場合は未定義)でソートする。
  2. 読み取りロックと書き込みロックでテーブルがロックされる場合は、読み取りロックより書き込みロックを優先する。
  3. 一度に 1 つのテーブルをロックし、スレッドがすべてのロックを取得するまでロック処理を繰り返す。

このポリシーによって、テーブルのロックでデッドロックの発生が回避されます。ただし、このスキーマに関しては注意すべき点が他にもあります。

MySQL でテーブルに対して LOW_PRIORITY WRITE ロックを使用した場合、そのスレッドは READ ロックを要求する他のスレッドがなくなるまでの間のみ待機し、READ を要求する他のスレッドがなくなった時点でロックを取得します。そのスレッドで WRITE ロックを取得した後に、ロックテーブルリストの次のテーブルのロックを取得しようと待機しているときには、他のスレッドの方がいずれも WRITE ロックが解除されるまで待つことになります。これによってアプリケーションで深刻な問題が発生する場合は、一部のテーブルをトランザクションセーフテーブルに変換することを検討してください。

テーブルのロックを取得しようと待機しているスレッドを、安全な方法で強制終了するには、KILL を使用します。 See section 4.6.7 KILL 構文

注意: INSERT DELAYED で使用しているテーブルは、ロックすべきではありません。なぜなら、この場合、INSERT が独立したスレッドで実行されるためです。

個々の UPDATE ステートメントでは、いずれも処理が原子的に行われるため、通常、テーブルをロックする必要はありません。現在実行中の SQL ステートメントが、他のスレッドによって妨害されることはまったくありません。しかし、次に示すように、テーブルをロックする必要が生じる場合もいくつかあります。

多くの場合、自身の加算を行う更新(UPDATE customer SET value=value+new_value)や LAST_INSERT_ID() 関数の使用により、LOCK TABLES の使用を避けることができます。

また、ユーザレベルのロック関数 GET_LOCK()RELEASE_LOCK() を使用して問題を解決できる場合もあります。これらのロックはサーバのハッシュテーブルに保存され、高速にするため pthread_mutex_lock()pthread_mutex_unlock() で実装されます。 See section 6.3.6.2 その他の各種関数

ロックポリシーの詳細については、section 5.3.1 MySQL のテーブルロック方法 を参照してください。

全データベースの全テーブルを読み取りロックでロックするには、FLUSH TABLES WITH READ LOCK コマンドを使用します。See section 4.6.4 FLUSH 構文。特定の時点のスナップショットを取ることができる、Veritas などのファイルシステムを使用している場合には、このコマンドがバックアップを作成するときに非常に役立ちます。

注意: LOCK TABLES はトランザクションセーフではありません。アクティブなトランザクションは、テーブルロックの試行前に暗黙的にコミットされます。

6.7.6 SET TRANSACTION 構文

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

この構文では、トランザクションの分離レベルが、グローバルなセッション全体または次のトランザクションのどちらかとして設定されます。

デフォルトの動作では、次の(まだ開始されていない)トランザクションの分離レベルが設定されます。このステートメントに GLOBAL キーワードを使用すると、それ以降に作成されるすべての新しい接続(既存の接続は対象外)に対してグローバルにデフォルトのトランザクションレベルが設定されます。 これを行うには、SUPER 権限が必要です。SESSION キーワードを使用すると、現在の接続で実行されるすべての新しいトランザクションに対してデフォルトのトランザクションレベルが設定されます。

InnoDB トランザクションの各分離レベルについては、section 7.5.9.1 InnoDB と SET ... TRANSACTION ISOLATION LEVEL ... を参照してください。MySQL 4.0.5 以降、InnoDB ではこれらの各レベルをサポートしています。デフォルトのレベルは REPEATABLE READ です。

mysqld のデフォルトのグローバル分離レベルは、--transaction-isolation=... で設定することができます。 See section 4.1.1 mysqld コマンドラインオプション

6.8 MySQL 全文検索

MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION] )

バージョン 3.23.23 以降、MySQL ではフルテキストインデックスと全文検索をサポートしています。 MySQL のフルテキストインデックスは FULLTEXT 型のインデックスです。 FULLTEXT インデックスは MyISAM テーブルにのみ使用され、CHAR 型、VARCHAR 型、TEXT 型のいずれかのカラムから作成することができます。この作成は CREATE TABLE 時に行えますが、ALTER TABLECREATE INDEX を使用して後から追加することも可能です。データセットのサイズが大きい場合は、FULLTEXT インデックスを持たないテーブルにデータをロードしてから、ALTER TABLE(または CREATE INDEX)を使用してインデックスを作成する方が処理がはるかに迅速です。すでに FULLTEXT インデックスを持っているテーブルにデータをロードすると、処理がかなり遅くなることがあります。

全文検索を実行するには、MATCH() 関数を使用します。

mysql> CREATE TABLE articles (
    ->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    ->   title VARCHAR(200),
    ->   body TEXT,
    ->   FULLTEXT (title,body)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
    -> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
    -> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
    -> (NULL,'Optimizing MySQL','In this tutorial we will show ...'),
    -> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    -> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
    -> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles
    ->          WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

MATCH() 関数では、テキストのコレクション(FULLTEXT インデックスに含まれる 1 つ以上のカラムのセット)に対して、文字列の自然言語検索が実行されます。検索文字列は AGAINST() の引数として指定します。検索はケース非依存方式で実行されます。 MATCH() からは、テーブルの各レコードについて、関連性を示す値(つまり、検索文字列と、そのレコードの MATCH() リストに指定したカラムのテキストとの間の類似度)が返されます。

MATCH()WHERE 節で使用すると(上の例を参照)、返されるレコードは関連性が最も高いレコードから低いレコードの順に自動でソートされます。 関連性を示す値は負の数でない浮動小数点数です。関連性がゼロのときは、類似性がまったくないことを意味します。関連性は、レコードに含まれるワード数、そのレコードに含まれる一意のワード数、コレクションに含まれる合計ワード数、特定のワードを含むドキュメント(レコード)数に基づいて計算されます。

ブール値モードの検索も実行できます。これについては後述します。

上記の例は、MATCH() 関数の基本的な使用方法を示したものです。レコードは関連性が高いものから低いものの順に返されます。

次の例は、関連値を明示的に取り出す方法を示したものです。 WHERE 節も ORDER BY 節もないので、返されるレコードは順序付けられていません。

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
|  1 |                        0.64840710366884 |
|  2 |                                       0 |
|  3 |                        0.66266459031789 |
|  4 |                                       0 |
|  5 |                                       0 |
|  6 |                                       0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

次の例はより複雑です。このクエリでは、関連性が返され、関連性の高いものから低いものの順にレコードがソートされます。この結果を出力するためには、MATCH() を 2 回指定します。それによって追加のオーバーヘッドが発生することはありません。なぜなら、MySQL のオプティマイザは 2 つの MATCH() 呼び出しが同じものであると認識し、全文検索コードを 1 度しか起動しないためです。

mysql> SELECT id, body, MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root') AS score
    -> FROM articles WHERE MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
|  6 | When configured properly, MySQL ... |   1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

バージョン 4.1.1 以降、全文検索ではクエリの拡張(特に、その異型の ``ブラインドクエリ拡張'')をサポートしています。通常、これは、検索語句が短すぎるときに役立ちます。検索語句が短い場合、その語句を指定したユーザが暗黙的な知識に頼っていることがよくあります。暗黙的な知識といったものは、通常、全文検索エンジンは備えていません。たとえば、ユーザが ``データベース'' という語句を検索している場合、実際にはそのユーザは、単に ``データベース'' だけでなく、``MySQL''、``Oracle''、``DB2''、``RDBMS'' といった語句もすべて ``データベース'' に一致し、返されるはずだと想定していることがあります。暗黙的な知識とは、このようなことを意味します。

ブラインドクエリ拡張(自動関連性フィードバック)では、検索が 2 回実行されます。2 回目の検索の検索語句には、元の検索語句に、最初の検索で上位に検出された少数のドキュメントが結び付けられたものが使用されます。したがって、たとえば、これらのドキュメントの 1 つに ``データベース'' という語と ``MySQL'' という語が含まれている場合、2 回目の検索では、``MySQL'' という語を含み、``データベース'' という語は含まないドキュメントが検索されます。また、たとえば、Georges Simenonの著書で ``Maigret'' 警視に関する本を検索しようとするときに、``Maigret'' のスペルが正確にわからないとします。この場合、``Megre and the reluctant witnesses'' を検索語句として指定すると、クエリの拡張を使用しなければ ``Maigret and the Reluctant Witnesses'' しか検出されません。しかし、クエリの拡張を使用すると、2 回目の検索で ``Maigret'' という語が含まれるすべての本が検出されます。注意:ブラインドクエリ拡張では、関連しないドキュメントが返されることでノイズが大幅に増加しがちです。そのため、この機能を使用する意味があるのは、検索語句が比較的短い場合に限られます。

MySQL では、非常に単純なパーサを使用してテキストをワード(語)に分割します。``ワード'' とは、文字、数字、`''`_' で構成される文字列です。ストップワードリストに含まれる ``ワード'' や短すぎるものは無視されます。全文検索で検出されるワードのデフォルトの最小長は 4 文字です。この長さは section 6.8.2 MySQL 全文検索の調整 の説明に従って変更可能です。

コレクションおよびクエリに含まれる正しい各ワードには、そのクエリまたはコレクションでのそのワードの重要度に基づいて重みが設定されます。そのため、多くのドキュメントに存在するワードは低く重み付けされます(重みがゼロの場合もあります)。なぜなら、そのワードはそのコレクションにおいて意味値が低いためです。そのワードがまれにしか存在しない場合は、高く重み付けされます。その後、各ワードの重みが結合されてレコードの関連性が計算されます。

このようなテクニックは、サイズの大きなコレクションの場合に最も効果があります(実際に、それを目的として入念に調整されています)。小さいテーブルでは、ワードの分布はそれぞれの意味値を正しく反映するものとはならず、このモデルを使用した場合、奇妙な結果が出ることがあります。

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

上の例では、MySQL というワードの検索で何も結果が生成されません。これは、このワードが半分以上のレコードに存在するためです。したがって、このワードは事実上ストップワード(意味値がゼロのワード)として扱われます。これは最も望ましい動作です。自然言語のクエリの場合 、1 GB のテーブルから 1 つおきにレコードが返されるのは適切ではありません。

ワードがテーブルの半分を占めるレコードに一致する場合、関連するドキュメントが検出される見込みはあまりありません。むしろ、無関係のドキュメントが大量に検出される可能性が多分にあります。 これは、検索エンジンを使用してインターネットで検索をするときに誰もが頻繁に経験することです。このようなレコードに該当のデータセットにおいて低い意味値が設定されている理由は、ここにあります。

バージョン 4.0.1 以降、MySQL では、IN BOOLEAN MODE 修飾子を使用してブール値の全文検索も実行できます。

mysql> SELECT * FROM articles WHERE MATCH (title,body)
    ->     AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title                        | body                                |
+----+------------------------------+-------------------------------------+
|  1 | MySQL Tutorial               | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Efficiently | After you went through a ...        |
|  3 | Optimizing MySQL             | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security               | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

このクエリでは、MySQL というワードを含み(注意: 50% のしきい値は使用されません)、YourSQL というワードは含まないすべてのレコードが取り出されます。注意: ブール値モードの検索では、関連値の高いもの順のレコードの自動ソートは行われません。これは上のクエリの結果を見るとわかります。上のクエリでは、関連性が最も高いレコード(MySQL というワードを 2 つ含むレコード)が最初ではなく最後にリストされています。また、ブール値の全文検索は FULLTEXT インデックスがなくても機能します。ただし、この場合、処理速度は遅くなります。

ブール値の全文検索機能では、次の演算子をサポートしています。

+
先行するプラス記号は、返される各レコードにそのワードが存在しなければならないことを表す。
-
先行するマイナス記号は、返される各レコードにそのワードが存在してはならないことを表す。
デフォルト(プラスもマイナスも指定しない場合)では、そのワードは必ずしも存在する必要はないが、そのワードを含むレコードは高く評価される。これは、IN BOOLEAN MODE 修飾子を指定していない MATCH() ... AGAINST() の動作に類似する。
< >
これら 2 つの演算子は、各レコードに割り当てられる関連性の値に対する個々のワードの貢献度を変更するために使用される。< 演算子は貢献度を減少させ、> 演算子は貢献度を増加させる。 下の例を参照。
( )
かっこは、ワードを副次式にグループ化するために使用される。
~
先行するチルダは否定演算子として機能し、レコードの関連性に対するワードの貢献度をマイナスにする。これはノイズワードをマークするのに役立つ。このようなワードを含むレコードは、他のワードより低く評価されるが、- 演算子を使用したときのように完全に除外されるわけではない。
*
アスタリスクは切り捨て演算子。他の演算子と異なり、これはワードの前ではなく後ろに付ける。
"
二重引用符 " で囲んだ語句は、この語句とまったく同じ語句を含むレコードにのみ一致する。

次に、例をいくつか示します。

apple banana
これらのワードの最低 1 つを含むレコードが検索される。
+apple +juice
... 両方のワードを含むレコードを検索。
+apple macintosh
... ワード ``apple'' を含むレコードを検索。``apple'' に加えて ``macintosh'' というワードも含んでいれば、高く評価される。
+apple -macintosh
... ワード ``apple'' を含み、``macintosh'' は含まないレコードを検索。
+apple +(>turnover <strudel)
... ``apple'' と ``turnover''、または ``apple'' と ``strudel'' を含むレコード(2 つのワードの順序は問わない)を検索。ただし、``apple pie'' は ``apple strudel'' より高く評価される。
apple*
... ``apple''、``apples''、``applesauce''、``applet'' はいずれもこれと一致する。
"some words"
... ``some words of wisdom'' とは一致するが、``some noise words'' とは一致しない。

6.8.1 全文検索における制約

6.8.2 MySQL 全文検索の調整

残念ながら、ユーザによる調整が可能な全文検索のパラメータは現在のところ少ししかありません。しかし、調整可能なパラメータの追加は、TODO リストにおいて優先度の高い位置にランクされています。MySQL ソースディストリビューション(see section 2.3 MySQL ソースディストリビューションのインストール)がある場合は、全文検索の動作をより詳細に制御できます。

注意: 全文検索は検索の効率を良くするよう入念に調整されています。デフォルトの動作を変更すると、多くの場合、結果的に検索結果が悪くなります。MySQL のソースは、十分な知識がない限り変更しないでください。

以下に説明するフルテキスト変数は、サーバの起動時に設定されていなければなりません。サーバの稼動中にこれらの変数を動的に変更することはできません。

FULLTEXT インデックスの再構築が必要になるフルテキスト関連の変更の場合、MyISAM テーブルに対してこれを行う最も簡単な方法は、インデックスファイルを再ビルドする次のステートメントを使用することです。

mysql> REPAIR TABLE tbl_name QUICK;

6.8.3 全文検索に関連する TODO 項目

6.9 MySQL クエリキャッシュ

バージョン 4.0.1 以降、MySQL サーバ には Query Cache 機能があります。 クエリキャッシュの使用時、このキャッシュには、SELECT クエリのテキストと、クライアントに送られたその結果が格納されます。 後でまったく同じクエリを受け取ると、サーバはそのクエリの解析と実行をもう一度繰り返す代わりに、クエリキャッシュから結果を取り出します。

注意:クエリキャッシュから古いデータが返されることはありません。データが変更されると、クエリキャッシュの関連するエントリがすべてフラッシュされます。

(一部の)テーブルがそれほど頻繁には変更されず、同じクエリが何度も実行される環境では、クエリキャッシュが非常に役立ちます。 動的コンテンツを大量に持つ多くの Web サーバでは、このような状況が一般的です。

クエリキャッシュのパフォーマンスに関するデータの一部を、以下に示します(これらの結果は、2 GB の RAM、64 MB のクエリキャッシュを搭載する Linux Alpha 2 x 500 MHz での MySQL ベンチマークスィートの実行により生成されたものです):

6.9.1 クエリキャッシュの動作

クエリは解析前に比較されるため、

SELECT * FROM tbl_name

Select * from tbl_name

は、クエリキャッシュで別のクエリとみなされます。完全に一致する(各バイトが)クエリ以外、同一とはみなされません。 また、たとえば、あるクライアントで新しい形式の通信プロトコルを使用している場合や、別のクライアントが使用しているものとは異なるキャラクタセットを使用している場合も、同じものであるはずのクエリが異なるものとして認識されることがあります。

異なるデータベースを使用するクエリや、使用プロトコルのバージョンが異なるクエリ、またデフォルトのキャラクタセットが異なるクエリは、いずれも異なるクエリとして認識され、別々にキャッシュされます。

キャッシュは SELECT SQL_CALC_FOUND_ROWS ... および SELECT FOUND_ROWS() ... 型のクエリでも機能します。これは、検出されたレコードの数もキャッシュに格納されるためです。

クエリの結果がクエリキャッシュから返された場合、ステータス変数 Com_select の値は増加しませんが、Qcache_hits の値は増加します。 See section 6.9.4 クエリキャッシュのステータスと保守

テーブルが変更されると(INSERTUPDATEDELETETRUNCATEALTERDROP TABLE|DATABASE のいずれかによって)、そのテーブルを(場合によっては、MRG_MyISAM テーブルを通して)使用したキャッシュ内のクエリはすべて無効になり、キャッシュから削除されます。

変更された InnoDB トランザクションテーブルは、COMMIT が実行されると無効化されます。

MySQL 4.0 では、クエリキャッシュはトランザクション内では無効です(結果は返されません)。MySQL 4.1.1 以降では、InnoDB テーブルの使用時、クエリキャッシュはトランザクション内でも機能します(テーブルのバージョン番号に基づいて、データがまだカレントかどうかが検出されます)。

MySQL 5.0 より前のバージョンでは、先行するコメントで始まるクエリの場合、キャッシュへの格納は可能でも、キャッシュから取得できませんでした。この問題は MySQL 5.0 で修正されています。

次の関数のいずれかを含んでいるクエリは、キャッシュできません。
関数 関数 関数
User-Defined Functions CONNECTION_ID FOUND_ROWS
GET_LOCK RELEASE_LOCK LOAD_FILE
MASTER_POS_WAIT NOW SYSDATE
CURRENT_TIMESTAMP CURDATE CURRENT_DATE
CURTIME CURRENT_TIME DATABASE
ENCRYPT (パラメータを 1 つ持つもの) LAST_INSERT_ID RAND
UNIX_TIMESTAMP (パラメータなし) USER BENCHMARK

また、ユーザ変数を含んでいるクエリ、mysql システムデータベースを参照しているクエリ、SELECT ... IN SHARE MODESELECT ... INTO OUTFILE ...SELECT ... INTO DUMPFILE ... のいずれかの形式のクエリ、および SELECT * FROM AUTOINCREMENT_FIELD IS NULL 形式のクエリ(最後に挿入された ID の取り出し - ODBC 回避策)についても、キャッシュできません。

ただし、FOUND_ROWS() は、先行するクエリがキャッシュからフェッチされたものであっても正しい値を返します。

クエリでテーブルを何も使用しない、またはテンポラリテーブルを使用する場合や、関連するテーブルのいずれかに対するカラムのアクセス権限をユーザが持っていない場合、クエリはキャッシュされません。

MySQL では、クエリをクエリキャッシュから読み取る前に、関連するすべてのデータベースとテーブルに対する SELECT 権限をユーザが持っているかチェックします。この権限をユーザが持っていない場合、キャッシュに格納されている結果は使用されません。

6.9.2 クエリキャッシュの設定

mysqld の起動時には、コマンドラインで mysqld の少数の MySQL システム変数がクエリキャッシュにより追加されます。これらのシステム変数はオプション設定ファイルで設定することができます。

クエリキャッシュの動作は、スレッド(接続)内でデフォルトから変更することができます。構文は次のとおりです。

QUERY_CACHE_TYPE = OFF | ON | DEMAND QUERY_CACHE_TYPE = 0 | 1 | 2

オプション 説明
0 または OFF キャッシュへの格納、結果の取り出しをいずれも行わない。
1 または ON SELECT SQL_NO_CACHE ... クエリを除くすべての結果をキャッシュする。
2 または DEMAND SELECT SQL_CACHE ... クエリのみキャッシュする。

6.9.3 SELECT でのクエリキャッシュオプション

SELECT クエリでは、クエリキャッシュ関連の次の 2 つのパラメータを指定することができます。

オプション 説明
SQL_CACHE QUERY_CACHE_TYPEDEMAND の場合、クエリをキャッシュ可能にする。 QUERY_CACHE_TYPEON の場合、これがデフォルト。 QUERY_CACHE_TYPEOFF の場合、何もしない。
SQL_NO_CACHE このクエリをキャッシュ不可にする。このクエリをキャッシュに格納しない。

6.9.4 クエリキャッシュのステータスと保守

FLUSH QUERY CACHE コマンドでは、クエリキャッシュをデフラグメント化して、メモリの使用効率を良くすることができます。このコマンドを発行しても、キャッシュからクエリが削除されることはありません。 FLUSH TABLES でも、クエリキャッシュがフラッシュされます。

RESET QUERY CACHE コマンドでは、すべてのクエリ結果がクエリキャッシュから削除されます。 使用している MySQL バージョンにクエリキャッシュがあるかどうかは、次のコマンドで確認できます。

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

クエリキャッシュのパフォーマンスは、SHOW STATUS で監視できます。

変数 説明
Qcache_queries_in_cache キャッシュに登録されているクエリ数
Qcache_inserts キャッシュに追加されたクエリ数
Qcache_hits キャッシュヒット数
Qcache_lowmem_prunes メモリ不足のためにキャッシュから削除されたクエリ数
Qcache_not_cached キャッシュされていない(キャッシュ不可、または QUERY_CACHE_TYPE により)クエリ数
Qcache_free_memory クエリキャッシュの空きメモリ量
Qcache_free_blocks クエリキャッシュ内の空きメモリブロック数
Qcache_total_blocks クエリキャッシュ内の合計ブロック数

合計クエリ数 = Qcache_inserts + Qcache_hits + Qcache_not_cached

クエリキャッシュでは可変長ブロックが使用されるため、Qcache_total_blocksQcache_free_blocks によって、クエリキャッシュメモリのフラグメント化が示されることがあります。 FLUSH QUERY CACHE を実行すると、1 つの(大きな)空きブロックだけが残ります。

注意:各クエリには、最低でも 2 ブロック必要です(クエリテキスト用に 1 ブロック、クエリ結果用に 1 ブロック以上)。また、クエリで使用される各テーブル用にも 1 ブロック必要です。ただし、複数のクエリで同じテーブルを使用している場合は、1 ブロックの割り当てですみます。

クエリのキャッシュサイズは、Qcache_lowmem_prunes ステータス変数に基づいて調整できます。この値は、新しいクエリを格納できるようメモリを解放するためにキャッシュから削除されたクエリ数を示します。クエリキャッシュでは、使用されたうち最も古いLRU)方針に従って、キャッシュから削除するクエリが決定されます。


Go to the first, previous, next, last section, table of contents.