目次
MySQL は非常に複雑でありながら、直感的に使用できる覚えやすい SQL インタフェースです。この章では、MySQL を効率的かつ効果的に使用するために知っておく必要がある、さまざまなコマンド、データ型、および関数について説明します。また、この章から、MySQL に組み込まれているすべての機能について参照することもできます。多岐にわたるインデックスの中からそれぞれの内容を参照することによって、この章を効果的に使用することができます。
このセクションでは、MySQL で文字列と数値を記述するさまざまな方法を説明します。 また、MySQL でこれらの基本データ型を処理する時に遭遇するであろう、さまざまなニュアンスと ``了解事項'' についても扱います。
文字列は、単一引用符
(‘'
’)または二重引用符(‘"
’)で囲まれた文字の並び(シーケンス)です(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
項6.3.2.1. 「文字列比較関数」。
\_
‘_
’
文字。これは、‘_
’
をそのまま使用したときにワイルドカード文字として解釈されてしまうコンテキストで
‘_
’
自体を検索する場合に使用する。 See
項6.3.2.1. 「文字列比較関数」。
文字列の一部のコンテキストでは、'\%
'
または '\_
'
を使用したときに、‘%
’
と ‘_
’
の代わりに、文字列 '\%
' と
'\_
'
がそれぞれ返されることに注意してください。
文字列に引用符を含める方法は、いくつかあります。
‘'
’
で囲んだ文字列内で
‘'
’
を使用する場合、文字列内の
‘'
’ は
'''
'
と記述することができる。
‘"
’
で囲んだ文字列内で
‘"
’
を使用する場合、文字列内の
‘"
’ は
'""
'
と記述することができる。
引用符の直前にエスケープ文字(‘\
’)を使用することができる。
‘"
’
で囲んだ文字列内で
‘'
’
を使用する場合は、‘'
’
を 2
つ続けて入力したり、エスケープしたりなどの特別な処置を行う必要はない。同様に、‘'
’
で囲んだ文字列内で
‘"
’
を使用する場合も、特別扱いする必要はない。
次の 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
項11.1.2. 「C API 関数の概要」。Perl
では、DBI
パッケージの
quote
メソッドを使用して、特殊文字を適切なエスケープシーケンスに変換することができます。See
項11.5.2. 「DBI
インタフェース」。
上記の特殊文字のいずれかが含まれている可能性がある文字列には、必ずエスケープ関数を使用するようにします。
または、MySQL API の多くのものが一種のプレースホルダ機能を備えているため、この機能を使ってクエリ文字列に特殊なマーカーを挿入し、クエリの発行時にデータ値をそれらのマーカーにバインドすることもできます。この場合、値内の特殊文字のエスケープ処理が API によって自動で行われます。
整数は数字の列として表現されます。浮動小数点では、小数を区切るために
‘.
’
が使用されます。どちらの型の数値でも、先頭に
‘-
’
を付けることによって、負数を表すことができます。
有効な整数の例:
1221 0 -32
有効な浮動小数点数の例:
294.42 -32032.6809e+10 148.00
浮動小数点のコンテキストで整数を使用することもできます。この場合、整数は同等の浮動小数点数として解釈されます。
バージョン 4.1.0 以降、定数 TRUE
は 1
として評価され、定数
FALSE
は 0
として評価されます。
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()
関数を使用できます。
NULL
値は ``データなし''
を意味し、数値型での 0
や文字列型での空文字列などの値とは異なります。
See 項A.5.3. 「NULL
値の問題」。
テキストファイルのインポートまたはエクスポート形式(LOAD
DATA INFILE
、SELECT ... INTO
OUTFILE
)の使用時、NULL
は
\N
で表現することができます。
See 項6.4.8. 「LOAD DATA INFILE
構文」。
MySQL では、データベース名、テーブル名、インデックス名、およびエイリアス名には、すべて同じ規則が適用されます。
注意:
識別子(データベース名、テーブル名、カラム名)を
‘`
’
で引用する事ができます。MySQL バージョン 3.23.6
以降では、ANSI
モードで実行した時は、‘"
’
も識別子の引用処理に使用することができます。
See 項1.8.2. 「ANSI モードでの MySQL の実行」。
識別子 | 最大長(バイト) | 使用可能な文字 |
データベース | 64 | ディレクトリ名に使用可能なすべての文字(ただし、‘/ ’、‘\ ’、および
‘. ’ を除く) |
テーブル | 64 | ファイル名に使用可能なすべての文字(ただし、‘/ ’
と ‘. ’ を除く) |
カラム | 64 | すべての文字 |
エイリアス | 255 | すべての文字 |
上記に補足して、ASCII(0)、ASCII(255)、および引用文字はいずれも識別子内では使用できないことに注意してください。
識別子が予約語である場合や、識別子に特殊文字が含まれている場合は、引用符として使用したバッククォート(「`
」)文字でその識別子を必ず囲む必要があります。
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
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 項4.1.1. 「mysqld
コマンドラインオプション」。
バージョン 3.23.6 より前の MySQL バージョン では、名前に関して次の規則が適用されます。
個々の名前は、現在のキャラクタセットに従った英数字、および
‘_
’ と
‘$
’
で構成することができる。デフォルトのキャラクタセットは
ISO-8859-1 Latin1。このキャラクタセットは、
mysqld
に
--default-character-set
オプションを指定することにより変更可能。
See 項4.7.1. 「データおよびソート用キャラクタセット」。
個々の名前では、名前に使用可能な任意の文字を、先頭文字とすることができる。先頭を数字にすることも可能(この点は、他の多くのデータベースシステムと異なる)。ただし、数字だけで構成される名前は使用できない。
‘.
’
文字は名前には使用できない。この文字は、カラムを参照するための拡張形式で使用される(これについては後述する)。
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_name
や
db_name.tbl_name
を付ける必要があります。 たとえば、テーブル
t1
と t2
のそれぞれに同名のカラム c
があり、t1
と t2
の両方を使用する SELECT
ステートメントで c
を読み取るとします。この場合 c
は、ステートメントで使用されている 2
つのテーブル中で一意なカラムを表すものではなく、あいまいであるため、t1.c
または t2.c
と記述することによって、どちらのテーブルが対象か指定する必要があります。同様に、データベース
db1
のテーブル t
とデータベース db2
のテーブル
t
に含まれているカラムを取り出す場合は、それぞれのテーブルのカラムを
db1.t.col_name
、db2.t.col_name
として参照します。
構文 .tbl_name
はカレントデータベースのテーブル
tbl_name
を意味します。この構文は
ODBC
との互換性を確保する目的で許容されています。これは、一部の
ODBC プログラムでテーブル名の先頭に
‘.
’
文字が付けられるためです。
MySQL において、データベースとテーブルは、ディレクトリとそれらのディレクトリ内のファイルに対応しています。そのため、ベースとなっているオペレーティングシステムで大文字と小文字が区別される場合(ケース依存)、データベース名とテーブル名でも大文字と小文字が区別されます。つまり、Windows ではデータベース名とテーブル名で大文字と小文字は区別されず、ほとんどの種類の Unix では大文字と小文字が区別されることになります。ただし、重要な例外が 1 つあります。Mac OS X でデフォルトの HFS+ ファイルシステムを使用している場合です。 しかし、Mac OS X は UFS ボリュームもサポートしています。UFS ボリュームでは Unix の場合と同じように Mac OS X でも大文字と小文字が区別されます。 See 項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
サブディレクトリにあります。
MySQL では、@variablename
構文での接続ごとのユーザ変数をサポートしています。変数名は、現在のキャラクタセット内の英数字、および
‘_
’、‘$
’、‘.
’
で構成することができます。デフォルトのキャラクタセットは
ISO-8859-1 Latin1
です。このキャラクタセットは、--default-character-set
オプションを指定した mysqld
で変更可能です。See
項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
文においては、それぞれの式は、クライアントに送られた時にはじめて評価されます。したがって、HAVING
、GROUP
BY
、ORDER 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、または "" に設定するようにします。
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;
GLOBAL
と SESSION
のどちらも指定しないと、SESSION
が使用されます。 See 項5.5.6. 「SET
構文」。
LOCAL
は SESSION
のシノニムです。
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
構文で変数を取り出すときに
GLOBAL
と SESSION
のどちらも指定しないと、MySQL
では、スレッド固有(SESSION
)の値がある場合は、その値が返されます。スレッド固有の値がない場合は、グローバル値が返されます。
GLOBAL
の値しか存在しない変数の場合、取り出しには
GLOBAL
と指定する必要はありませんが、設定には
GLOBAL
と指定する必要があります。これは、後から、同名のスレッド固有変数を導入したり、削除したりするときに問題が発生しないようにするためです。この場合、自分の接続だけでなく、サーバの状態そのものを誤って変更してしまう可能性があります。
次の一覧に、変更および取り出し対象となるすべての変数と、それらの変数で
GLOBAL
と SESSION
のどちらを使用できるかを示します。
変数名 | 値のデータ型 | タイプ |
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
項4.1.1. 「mysqld
コマンドラインオプション」。 See
項4.6.8.4. 「SHOW VARIABLES
」。 See
項5.5.6. 「SET
構文」。
MySQL
サーバでは、コメントスタイルとして、#(行末まで)
、--(行末まで)
、および
/*(行中または複数行)*/
をサポートしています。
mysql>SELECT 1+1; # このコメントは行末まで続く
mysql>SELECT 1+1; -- このコメントは行末まで続く
mysql>SELECT 1 /* これは行中コメント */ + 1;
mysql>SELECT 1+
/* これは 複数行コメント */ 1;
--
(ダッシュ2つ)のコメントスタイルでは、2
つ目のダッシュの後にスペースを 1
つ以上挿入する必要があることに注意してください。
サーバは上記のコメント構文を理解しますが、mysql
クライアントでの /* ... */
コメントの解析には一定の制約があります。
単一引用符と二重引用符は、コメント内であっても、引用文字列の開始を示すものとして解釈される。そのコメント内に、最初の引用符と一致するもう
1
つの引用符がない場合、パーサはそのコメントの終了を認識しない。mysql
を対話的に実行している場合は、プロンプトが
mysql>
から '>
または ">
に変わるため、パーサがコメントの終了を認識できずにいることがわかる。
セミコロンは、現在の SQL ステートメントの終了を表すものとして解釈され、セミコロンの後は、次のステートメントの開始を表すものとして解釈される。
これらの制約は、mysql
を対話的に実行する場合と、mysql <
some-file
を使用して、コマンドを格納したファイルから入力を読み取るよう
mysql
に指示する場合の両方に適用されます。
2 つ目のダッシュの後にスペースが 1
つもない場合、SQL-99 のコメントスタイル
'--
' は MySQL で有効とされません。
See 項1.8.4.7. 「コメントの開始記号としての '--
'」。
一般的な問題の 1
つとして、TIMESTAMP
や
GROUP
など、MySQL
に組み込まれているデータ型や関数の名前を使用するカラム名を含むテーブルの作成に関連する問題があります。このようなカラム名を含むテーブルの作成は可能です(たとえば、ABS
はカラム名として使用可能です)。しかし、デフォルトでは、関数の呼び出し時に、関数名とそれに続く
‘(
’
文字との間に空白を挿入することはできません。これは、関数呼び出しをカラム名の参照と区別するためです。
--ansi
または
--sql-mode=IGNORE_SPACE
オプションを指定してサーバを起動した場合は、関数呼び出しで、関数名とそれに続く
‘(
’
文字との間に空白を挿入することができます。これらのオプションを指定すると、関数名が予約語として扱われるようになります。そのため、関数名と同一のカラム名は、項6.1.2. 「データベース名、テーブル名、インデックス名、カラム名、エイリアス名」
で説明しているように引用符で囲む必要があります。
以下の語は MySQL
において明示的に予約されています。これらの語のほとんど(たとえば、GROUP
)は、SQL-92
では、カラム名またはテーブル名としての使用を禁止されています。
いくつかの語は、MySQL
でそれらの語を必要とし、(現在)MySQL で
yacc
パーサが使用されていることから予約されています。
ADD | ALL | ALTER |
ANALYZE | AND | AS |
ASC | BEFORE | BETWEEN |
BIGINT | BINARY | BLOB |
BOTH | BY | CASCADE |
CASE | CHANGE | CHAR |
CHARACTER | CHECK | COLLATE |
COLUMN | COLUMNS | CONSTRAINT |
CONVERT | CREATE | CROSS |
CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP |
CURRENT_USER | DATABASE | DATABASES |
DAY_HOUR | DAY_MICROSECOND | DAY_MINUTE |
DAY_SECOND | DEC | DECIMAL |
DEFAULT | DELAYED | DELETE |
DESC | DESCRIBE | DISTINCT |
DISTINCTROW | DIV | DOUBLE |
DROP | DUAL | ELSE |
ENCLOSED | ESCAPED | EXISTS |
EXPLAIN | FALSE | FIELDS |
FLOAT | FLOAT4 | FLOAT8 |
FOR | FORCE | FOREIGN |
FROM | FULLTEXT | GRANT |
GROUP | HAVING | HIGH_PRIORITY |
HOUR_MICROSECOND | HOUR_MINUTE | HOUR_SECOND |
IF | IGNORE | IN |
INDEX | INFILE | INNER |
INSERT | INT | INT1 |
INT2 | INT3 | INT4 |
INT8 | INTEGER | INTERVAL |
INTO | IS | JOIN |
KEY | KEYS | KILL |
LEADING | LEFT | LIKE |
LIMIT | LINES | LOAD |
LOCALTIME | LOCALTIMESTAMP | LOCK |
LONG | LONGBLOB | LONGTEXT |
LOW_PRIORITY | MATCH | MEDIUMBLOB |
MEDIUMINT | MEDIUMTEXT | MIDDLEINT |
MINUTE_MICROSECOND | MINUTE_SECOND | MOD |
NATURAL | NOT | NO_WRITE_TO_BINLOG |
NULL | NUMERIC | ON |
OPTIMIZE | OPTION | OPTIONALLY |
OR | ORDER | OUTER |
OUTFILE | PRECISION | PRIMARY |
PRIVILEGES | PROCEDURE | PURGE |
RAID0 | READ | REAL |
REFERENCES | REGEXP | RENAME |
REPLACE | REQUIRE | RESTRICT |
REVOKE | RIGHT | RLIKE |
SECOND_MICROSECOND | SELECT | SEPARATOR |
SET | SHOW | SMALLINT |
SONAME | SPATIAL | SQL_BIG_RESULT |
SQL_CALC_FOUND_ROWS | SQL_SMALL_RESULT | SSL |
STARTING | STRAIGHT_JOIN | TABLE |
TABLES | TERMINATED | THEN |
TINYBLOB | TINYINT | TINYTEXT |
TO | TRAILING | TRUE |
UNION | UNIQUE | UNLOCK |
UNSIGNED | UPDATE | USAGE |
USE | USING | UTC_DATE |
UTC_TIME | UTC_TIMESTAMP | VALUES |
VARBINARY | VARCHAR | VARCHARACTER |
VARYING | WHEN | WHERE |
WITH | WRITE | X509 |
XOR | YEAR_MONTH | ZEROFILL |
以下のシンボル(上の表に含まれるもの)は SQL-99 では使用を禁止されていますが、MySQL ではカラム名またはテーブル名として使用可能です。これは、それらの名前がごく一般的なものであり、多くの人々にすでに使用されているためです。
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
MySQL では、複数のカラム型をサポートしています。これらのカラム型は、数値型、日付と時刻型、文字列(文字)型の 3 つのカテゴリに分類することができます。このセクションでは、まず、使用できるカラム型の概要を示し、各カラム型で必要となる記憶容量について簡単に説明します。その後、各カテゴリのカラム型の特性を詳しく説明します。 概要はあえて簡単にまとめてあります。値の有効な指定形式など、個々のカラム型の追加情報については、それぞれの詳細な説明を参照してください。
以下に、MySQL でサポートしているカラム型を示します。 説明内では、次のコード文字を使用します。
M
最大表示サイズを表す。正式な最大表示サイズは 255。
D
小数点型に適用され、小数点以下の桁数を表す。最大値は
30 だが、M
-2
より大きくしないようにする。
角かっこ(‘[
’ と
‘]
’)は、オプションの型指定子の一部であることを表します。
カラムに対して ZEROFILL
を指定すると、そのカラムに
UNSIGNED
属性が自動で追加されることに注意してください。
警告:
整数値の減算で、どちらか一方の整数値が
UNSIGNED
型の場合、結果の値は符号なしになります。 See
項6.3.5. 「キャスト関数」。
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
非常に小さな整数。符号付きの範囲は
-128
〜
127
。符号なしの範囲は
0
〜 255
。
BIT
, BOOL
,
BOOLEAN
いずれも TINYINT(1)
のシノニム。
シノニム BOOLEAN
はバージョン
4.1.0 で追加された。
ブール型の完全な処理は SQL-99 に基づいて導入される。
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
小さな整数。符号付きの範囲は
-32768
〜
32767
。符号なしの範囲は
0
〜 65535
。
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
中間サイズの整数。符号付きの範囲は
-8388608
〜
8388607
。符号なしの範囲は
0
〜 16777215
。
INT[(M)] [UNSIGNED] [ZEROFILL]
通常サイズの整数。符号付きの範囲は
-2147483648
〜
2147483647
。符号なしの範囲は
0
〜 4294967295
。
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
INT
のシノニム。
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
大きい整数。符号付きの範囲は
-9223372036854775808
〜
9223372036854775807
。符号なしの範囲は
0
〜
18446744073709551615
。
BIGINT
型のカラムに関しては、次の点について注意すること。
すべての算術演算は符号付き
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 項A.5.6. 「不整合レコードの問題解決」。
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
単精度浮動小数点数。使用可能な値は
-3.402823466E+38
〜
-1.175494351E-38
、0
、および
1.175494351E-38
〜
3.402823466E+38
。UNSIGNED
を指定した場合、負数は使用できない。M
は表示幅で、D
は小数部桁数。引数のない FLOAT
や、X
が 24 以下の
FLOAT(X)
は、単精度浮動小数点数を表す。
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
倍精度浮動小数点数。 使用可能な値は
-1.7976931348623157E+308
〜
-2.2250738585072014E-308
、0
、および
2.2250738585072014E-308
〜
1.7976931348623157E+308
。UNSIGNED
を指定した場合、負数は使用できない。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
カラムの実際の範囲は、M
と
D
の値によって制限される。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 で追加された。
日付。サポートしている範囲は、'1000-01-01'
〜 '9999-12-31'
。MySQL
では、DATE
値は
'YYYY-MM-DD'
形式で表示されるが、DATE
カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。
See 項6.2.2.2. 「DATETIME
、DATE
、TIMESTAMP
型」。
日付と時刻の組み合わせ。サポートしている範囲は、'1000-01-01
00:00:00'
〜 '9999-12-31
23:59:59'
。MySQL
では、DATETIME
値は
'YYYY-MM-DD HH:MM:SS'
形式で表示されるが、DATETIME
カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。
TIMESTAMP[(M)]
タイムスタンプ。範囲は '1970-01-01
00:00:00'
〜 2037
年の一定の時点。
MySQL 4.0
以前のバージョンでは、TIMESTAMP
値は、M
が
14
(または指定なし)、12
、8
、または
6
のどれであるかに応じて、YYYYMMDDHHMMSS
、YYMMDDHHMMSS
、YYYYMMDD
、または
YYMMDD
形式で表示されるが、TIMESTAMP
カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。
MySQL 4.1 以降では、TIMESTAMP
は
'YYYY-MM-DD HH:MM:SS'
形式の文字列として返される。数値として返されるようにするには、タイムスタンプカラムに
+0
を追加する。異なるタイムスタンプ長はサポートしていない。バージョン
4.0.12 以降、--new
オプションを使用することで、バージョン 4.1
と同じようにサーバを動作させることができる。
TIMESTAMP
カラムに値を指定しないと、最後に行われた操作の日付と時刻が自動的に設定されるため、このカラムは
INSERT
操作や UPDATE
操作の日付と時刻を記録するのに役立つ。また、このカラムに
NULL
値を割り当てることによって、現在の日付と時刻をカラムに設定することができる。
See 項6.2.2. 「日付と時刻型」。
M
引数は、TIMESTAMP
カラムの表示方法にのみ作用する。
この値は常に 4 バイトで格納される。
M
が 8 または 14 の
TIMESTAMP(M)
カラムは数値として報告され、その他の
TIMESTAMP(M)
カラムは文字列として報告されることに注意する。これは単に、これらのデータ型のテーブルのダンプとリストアを確実に実行できるようにすることを目的としている。
See 項6.2.2.2. 「DATETIME
、DATE
、TIMESTAMP
型」。
TIME
時刻。範囲は '-838:59:59'
〜
'838:59:59'
。 MySQL
では、TIME
値は
'HH:MM:SS'
形式で表示されるが、TIME
カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。
See 項6.2.2.3. 「TIME
型」。
YEAR[(2|4)]
2 桁または 4 桁の形式の年(デフォルトは 4
桁)。使用可能な値は、4 桁形式では
1901
〜 2155
と
0000
、2 桁形式では 1970 〜 2069(70
〜 69)。MySQL では、YEAR
値は
YYYY
形式で表示されるが、YEAR
カラムへの値の割り当てには文字列または数値のいずれかを使用することができる(YEAR
型は MySQL バージョン 3.22
より前のバージョンでは使用できない)。 See
項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
では、これはデフォルト。
CHAR
は CHARACTER
の省略形。
バージョン 4.1.0 以降では、latin1
キャラクタセットを CHAR
カラムに割り当てる ASCII
属性を指定することができる。
バージョン 4.1.1 以降では、ucs2
キャラクタセットを CHAR
カラムに割り当てる UNICODE
属性を指定することができる。
MySQL では、CHAR(0)
型のカラムを作成することができる。これは、主に、カラム自体は必要とするが、そのカラムの値を実際に使用することはない、というような古いアプリケーションに対応する必要があるときに役立つ。また、2
つの値しか取らないカラムが必要な場合にも非常に役立つ。
CHAR(0)
は NOT NULL
としては定義されず、1
ビットのみ占め、NULL
または
""
の 2 つの値しか取らない。 See
項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 項6.5.3.1. 「カラムの暗黙的な変更」。
バージョン 4.1.0 以降では、255 より大きい
M
値を指定すると、カラム型が
TEXT
型に変換される。
これは互換性を考慮した機能。
VARCHAR
は CHARACTER
VARYING
の省略形。
TINYBLOB
, TINYTEXT
最大長が 255(2^8 - 1)文字の BLOB
型または TEXT
型のカラム。 See
項6.5.3.1. 「カラムの暗黙的な変更」。 See
項6.2.3.2. 「BLOB
型と TEXT
型」。
BLOB
, TEXT
最大長が 65535(2^16 - 1)文字の
BLOB
型または TEXT
型のカラム。 See
項6.5.3.1. 「カラムの暗黙的な変更」。 See
項6.2.3.2. 「BLOB
型と TEXT
型」。
MEDIUMBLOB
, MEDIUMTEXT
最大長が 16777215(2^24 - 1)文字の
BLOB
型または TEXT
型のカラム。 See
項6.5.3.1. 「カラムの暗黙的な変更」。 See
項6.2.3.2. 「BLOB
型と TEXT
型」。
LONGBLOB
, LONGTEXT
最大長が 4294967295 または 4G(2^32 - 1)バイトの
BLOB
型または TEXT
型のカラム。 See
項6.5.3.1. 「カラムの暗黙的な変更」。 MySQL
バージョン 3.23
まで、サーバ/クライアントプロトコルおよび
MyISAM
テーブルでは、通信パケットまたはテーブルレコードごとに
16M の制約があった。バージョン 4.x
以降、LONGTEXT
型または
LONGBLOB
型のカラムで許容される最大長は、クライアント/サーバプロトコル間の通信バッファおよび使用可能なメモリ量にしたがって調整された最大パケットサイズによって決まる。
See 項6.2.3.2. 「BLOB
型と TEXT
型」。
ENUM('value1','value2',...)
列挙。値のリスト
'value1'
、'value2'
、...
、NULL
または特殊な ""
エラー値から選択された、1
つの値のみ持つことができる文字列オブジェクト。ENUM
には最大 65535
の重複のない値を組み込むことができる。 See
項6.2.3.3. 「ENUM
型」。
SET('value1','value2',...)
セット。0
個以上の値を持つことができる文字列オブジェクト。これらの値はいずれも値のリスト
'value1'
, 'value2'
,
...
から選択する必要がある。1
つの SET
には、最大 64
個の要素を組み込むことができる。 See
項6.2.3.4. 「SET
型」。
MySQL では、SQL-92
のすべての数値データ型をサポートしています。これらのデータ型は、正確な数値データ型(NUMERIC
、DECIMAL
、INTEGER
、SMALLINT
)だけでなく、近似数値データ型(FLOAT
、REAL
、DOUBLE
PRECISION
)を含みます。キーワード
INT
は INTEGER
のシノニムで、キーワード DEC
は
DECIMAL
のシノニムです。
MySQL では、NUMERIC
型と
DECIMAL
型は、SQL-92
標準で使用可能なデータ型と同じデータ型として実装されます。これらのデータ型は、金額データに関する値など、正確な精度で保存することが重要となる値に対して使用されます。これらのいずれかの型のカラムを宣言する際には、次のように、精度とスケールを指定することができます(通常、これらが指定されます)。
salary DECIMAL(5,2)
この例で、5
(precision
)
は、値に対して格納される 10
進数の桁数を表わし、2
(scale
)
は、小数点に続いて格納される桁数を表わします。したがって、この場合、salary
カラムに格納できる値の範囲は、-99.99
〜 99.99
になります(MySQL
では、正数の符号を格納する必要がないため、このカラムには、実際には、999.99
までの数値を格納することができます)。
SQL-92 では、構文 DECIMAL(p)
は
DECIMAL(p,0)
と同じです。同様に、構文 DECIMAL
は DECIMAL(p,0)
と同じです。この場合、p
の値を決定する実装を行うことができます。MySQL
では、現在のところ、DECIMAL
および NUMERIC
データ型のこれらの異型をサポートしていません。通常、これらの型の主な利点は精度とスケールを明示的に制御できることによるため、これはそれほど問題にはなりません。
DECIMAL
値と NUMERIC
値は、値の小数部の精度を維持するため、バイナリの浮動小数点数としてではなく、文字列として格納されます。値の各桁、小数点(scale
> 0 の場合)、そして
‘-
’
符号(負数の場合)に対して、1
文字が使用されます。scale
が 0
の場合、DECIMAL
値と
NUMERIC
値には小数点も小数部も含まれません。
DECIMAL
値と NUMERIC
値の最大範囲は DOUBLE
値と同じですが、個々の DECIMAL
または NUMERIC
カラムの実際の範囲は、個々のカラムの
precision
または scale
によって制限されます。指定されている
scale
で許容される桁数を超える桁数を小数部に持つ値がカラムに割り当てられた場合、値は指定されている
scale
に合わせて丸められます。指定されている(またはデフォルトの)precision
と scale
によって暗黙的に指定された範囲を超える大きさの値が
DECIMAL
または NUMERIC
カラムに割り当てられた場合、その範囲の最大値が格納されます。
SQL-92 標準の拡張として、MySQL
では、前出の表に挙げているように、TINYINT
、MEDIUMINT
、および
BIGINT
型もサポートしています。もう 1
つの拡張として、MySQL には、INT(4)
のように、型の基本キーワードに続いて整数値の表示幅をかっこ内に指定できるオプションがあります。このオプションの表示幅の指定は、カラムに指定された幅より小さい幅を持つ値で表示の左側を埋める目的で使用されますが、そのカラムに格納できる値の範囲が制限されたり、そのカラムに指定された幅を超える幅を持つ値の桁数が制限されたりすることはありません。オプションの拡張属性
ZEROFILL
と組み合せて使用した場合、デフォルトのスペースに代わってゼロが埋め込まれます。
たとえば、INT(5) ZEROFILL
として宣言されたカラムの場合、値
4
は 00004
として取り出されます。注意:
整数カラムの表示幅より大きい値を格納すると、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
として設定されている場合、このカラムの範囲のサイズは変わりませんが、最小値と最大値はそれぞれ
0
と 4294967295
になります。
したがって、-9999999999
および
9999999999
という値を格納しようとすると、このカラムにはそれぞれ
0
および 4294967296
という値が格納されます。
ALTER TABLE
、LOAD DATA
INFILE
、UPDATE
、および複数行の
INSERT
ステートメントでは、切り落としによる値の変換は
``警告'' として報告されます。
型 | バイト | 最小値 | 最大値 |
TINYINT | 1 | -128 | 127 |
SMALLINT | 2 | -32768 | 32767 |
MEDIUMINT | 3 | -8388608 | 8388607 |
INT | 4 | -2147483648 | 2147483647 |
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
日付と時刻型には、DATETIME
、DATE
、TIMESTAMP
、TIME
、YEAR
があります。これらの型のカラムは、いずれも、一定の範囲の正しい値を取りますが、その他に、実際には不正な値を指定するときに使用される
``ゼロ'' の値も取ります。MySQL では、'厳密'
には正しくない一部の日付値(1999-11-31
など)も格納可能であることに注意してください。
これは、日付チェックはアプリケーションで実行されるので
SQL
サーバ側で行う必要はない、という前提に立っているためです。日付チェックを
'迅速' に行うために、MySQL
では、指定された月が 0 〜 12
の範囲にあるかどうかと、指定された日付が 0
〜 31
の範囲にあるかどうかのみチェックします。これらの範囲に
0 が含まれている理由は、MySQL
では、DATE
または
DATETIME
カラムの日の値または月日の値がゼロである日付の格納が許容されているためです。これは、誕生日を格納する必要があるアプリケーションで正確な日付がわからないときなどに非常に役立ちます。この場合、単に
1999-00-00
や 1999-01-00
などとして、日付を格納します(このような日付を指定した場合、DATE_SUB()
や DATE_ADD
などの関数によって正しい値が返ると想定することはできません)。
以下に、日付と時刻型に関して留意すべき一般考慮事項をいくつか示します。
MySQL では、個々の日付または時刻型の値の取り出しは標準形式で行われるが、入力した値(たとえば、日付または時刻型に割り当てる値、またはこれらの型と比較する値の指定時など)については、さまざまな形式で解釈が試みられる。ただし、サポートしている形式は、以降のセクションで説明している形式に限られる。正しい値を指定することが前提となるため、非サポート形式で値を指定すると、予測できない結果が発生する場合がある。
MySQL
では、値の解釈が複数の形式で試みられるが、日付値の年部分は必ず左端と想定される。日付は、年-月-日の順序(例:
'98-09-04'
)で指定する必要がある。一般に使用されている月-日-年や日-月-年の順序(例:
'09-04-98'
、'04-09-98'
)は使用しない。
MySQL では、日付または時刻型の値を数値型のコンテキストで使用した場合、日付または時刻型の値は数値に自動的に変換される。その逆の場合も、同様の変換が行われる。
MySQL
では、日付または時刻型で範囲外の値や不正な値(このセクションの最初の部分を参照)を入力すると、値はその型の
``ゼロ''
値に変換される(この例外として、範囲外の
TIME
値は TIME
型の範囲の最大値または最小値に切り落とされる)。次の表に、それぞれの型の
``ゼロ'' 値を示す。
カラム型 | ``ゼロ'' 値 |
DATETIME | '0000-00-00 00:00:00' |
DATE | '0000-00-00' |
TIMESTAMP | 00000000000000 (長さは表示サイズに依存) |
TIME | '00:00:00' |
YEAR | 0000 |
``ゼロ''
値は特殊な値だが、上の表に示した値を使用することによって、``ゼロ''
値を明示的に格納または参照することができる。また、この他に、より簡単に記述できる値
'0'
または 0
も、``ゼロ''
値の格納または参照に使用できる。
ODBC では、日付または時刻型の値 ``ゼロ''
を処理できないため、MyODBC
バージョン 2.50.12
以降では、MyODBC
を通して日付または時刻型の値 ``ゼロ''
を使用すると、自動的に NULL
に変換される。
MySQL 自体は西暦 2000 年問題に対応していますが(see 項1.2.5. 「西暦 2000 年対応」)、MySQL への入力値がこの問題に対応していない場合があります。2 桁の年の値を持つ入力値は、世紀がわからないためいずれもあいまいです。MySQL では年の値は内部で 4 桁を使用して格納されるため、このような値は 4 桁形式に変換する必要があります。
DATETIME
型、DATE
型、TIMESTAMP
型、YEAR
型のカラムであいまいな年の値を含む日付が指定された場合、MySQL
では、次の規則に従ってそれらの日付が解釈されます。
範囲 00-69
の年の値は
2000-2069
に変換
範囲 70-99
の年の値は
1970-1999
に変換
これらの規則では、入力したデータが何を表すかに関して、単に、妥当な推測が行われるだけです。MySQL で使用される発見的手法で正しい年の値が生成されない場合は、4 桁の年の値を含む、あいまいでない値を入力してください。
ORDER BY
では、2 桁の
YEAR/DATE/DATETIME
型が正しくソートされます。
一部の関数(MIN()
や
MAX()
など)では、TIMESTAMP/DATE
型の値が数値に変換されることに注意してください。したがって、2
桁の年を持つタイムスタンプはこれらの関数では正常に機能しません。この場合の修正方法としては、TIMESTAMP/DATE
を 4 桁の年形式に変換するか、または
MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS))
のようなものを使用します。
データ型
DATETIME
、DATE
、TIMESTAMP
はそれぞれ関連しています。
このセクションでは、これらのデータ型の特徴を示すとともに、これらのデータ型の類似点と相違点について説明します。
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
モードで実行している場合、TIMESTAMP
は DATETIME
と同じように動作します。TIMESTAMP
カラムの自動更新(次の段落で説明)は行われません。MySQL
の MAXDB
モードでの実行は、バージョン 4.1.1
以降で可能です。See
項4.1.1. 「mysqld
コマンドラインオプション」。
MAXDB
モードで実行していないときの
TIMESTAMP
の動作
TIMESTAMP
カラム型では、INSERT
または
UPDATE
操作に対して現在の日付と時刻を自動的に指定することができます。TIMESTAMP
カラムが複数ある場合は、最初のカラムのみが自動で更新されます。
最初の TIMESTAMP
カラムの自動更新は、次のいずれかの条件で発生します。
INSERT
または LOAD DATA
INFILE
ステートメントで、カラムが明示的に指定されていない場合。
UPDATE
ステートメントおよびその他の何らかのカラム変更値でカラムが明示的に指定されていない場合(注意:
カラムにすでに設定されている値を設定しようとする
UPDATE
では、TIMESTAMP
カラムは更新されない。カラムに現在の値を設定しようとしても、MySQL
では、効率性を考慮して更新操作が無視される)。
TIMESTAMP
カラムに値
NULL
が明示的に設定された場合。
2 番目以降の TIMESTAMP
カラムにも、現在の日付と時刻を設定することができます。カラムに
NULL
または NOW()
を設定します。
TIMESTAMP
型のいずれかのカラムに現在の日付と時刻以外の値を設定するには、そのカラムに対して、必要な値を明示的に設定します。これは、最初の
TIMESTAMP
カラムについても同様です。この特性は、次に示すように、レコードの作成時に
TIMESTAMP
カラムに現在の日時を設定し、その後そのレコードの更新時には設定済の値を変更しないようにする場合などに役立ちます。
レコードの作成時に、MySQL によってカラムを設定する。 それにより、そのカラムが現在の日付と時刻に初期化される。
そのレコードの他のカラムに対して後続の更新を行ったときには、TIMESTAMP
カラムにそのカラムの現在の値を明示的に設定する。
とはいえ、DATETIME
カラムを使用してレコードの作成時に値を
NOW()
に初期化し、後続の更新時にはそのままにしておくというのも、手軽な方法です。
MAXDB
モードでの実行時の TIMESTAMP
の特性
MySQL を MAXDB
モードで実行している場合、TIMESTAMP
は DATETIME
とまったく変わりません。格納と表示には同じ形式が使用され、また値の範囲も同じです。MySQL
の MAXDB
モードでの実行は、バージョン 4.1.1
以降で可能です。 See
項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'
形式の文字列として返されます。その他のタイムスタンプ長のサポートは中止されました。
DATETIME
、DATE
、TIMESTAMP
型の値は、以下の一連の共通形式のいずれかを使用して指定することができます。
'YYYY-MM-DD HH:MM:SS'
または
'YY-MM-DD HH:MM:SS'
形式の文字列として指定。``柔軟''
な構文が許容される ---
日付部分と時刻部分の区切り記号として、任意の句読文字を使用することができる。
たとえば、'98-12-31
11:30:45'
、'98.12.31
11+30+45'
、'98/12/31
11*30*45'
、'98@12@31
11^30^45'
はいずれも同じ。
'YYYY-MM-DD'
または
'YY-MM-DD'
形式の文字列として指定。 この場合も
``柔軟''
な構文が許容される。たとえば、'98-12-31'
、'98.12.31'
、'98/12/31'
、'98@12@31'
はいずれも同じ。
'YYYYMMDDHHMMSS'
または
'YYMMDDHHMMSS'
形式の、区切り記号のない文字列(日付として適切なもの)として指定。たとえば、'19970523091528'
と '970523091528'
は
'1997-05-23 09:15:28'
として解釈されるが、'971122129015'
は正しくないため(分の部分が不適切)、'0000-00-00
00:00:00'
になる。
'YYYYMMDD'
または
'YYMMDD'
形式の、区切り記号のない文字列(日付として適切なもの)として指定。たとえば、'19970523'
と '970523'
は
'1997-05-23'
として解釈される、'971332'
は正しくないため(月と日付の部分が不適切)、'0000-00-00'
になる。
YYYYMMDDHHMMSS
または
YYMMDDHHMMSS
形式の数値(日付として適切なもの)として指定。たとえば、19830905132800
と 830905132800
は
'1983-09-05 13:28:00'
として解釈される。
YYYYMMDD
または
YYMMDD
形式の数値(日付として適切なもの)として指定。たとえば、19830905
と 830905
は
'1983-09-05'
として解釈される。
DATETIME
、DATE
、または
TIMESTAMP
型のコンテキストで許容される値を返す、NOW()
や CURRENT_DATE
などの関数の結果として指定。
不適切な
DATETIME
、DATE
、TIMESTAMP
値は、それぞれの型の ``ゼロ''
値('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
では、テーブルに日付値として ``ゼロ''
が格納されます。これは、年と月の値が
99
と 03
として指定されていても日の部分がまったくないことから、正しい日付ではないためです。しかし、MySQL
3.23
以降では、欠落している月または日の部分を表わすゼロの値を明示的に指定することができます。たとえば、'990300'
と指定することで、'1999-03-00'
という日付値を格納することができます。
TIMESTAMP
カラムでは、正しい値は、表示サイズにかかわらず、その値が指定されたときの完全な精度で格納されます。このことは、暗黙的に次のことを意味します。
カラム型が TIMESTAMP(4)
または
TIMESTAMP(2)
の場合でも、必ず年、月、日を指定する必要がある。このすべてを指定しないと、値は正しい日付とはならず、0
が格納される。
ALTER TABLE
を使用して表示桁数の小さな
TIMESTAMP
カラムの桁数を広げると、それまで
``非表示''
になっていた情報が表示される。
同様に、TIMESTAMP
カラムを狭くしても、単に、値を表示したときに表示される情報が少なくなるだけで、情報自体が失われるわけではない。
TIMESTAMP
型の値は完全な精度で格納されるが、基盤の格納値に対して直接作用する関数は
UNIX_TIMESTAMP()
だけである。他の関数は、取り出され、形式設定された値に作用する。したがって、HOUR()
や SECOND()
などの関数は、形式設定された値に
TIMESTAMP
値の該当の部分が含まれていない場合、使用できない。たとえば、TIMESTAMP
カラムの HH
部分は、表示サイズが 10
以上でないと表示されないため、それより短い
TIMESTAMP
値に対して
HOUR()
操作を行っても、無意味な値しか得られない。
ある日付型の値を別の日付型のオブジェクトに割り当てることは、ある程度までは可能です。しかし、何らかの値の変化や情報の消失が起こる可能性があります。
DATE
型の値を
DATETIME
または
TIMESTAMP
型のオブジェクトに割り当てた場合、値に時刻情報が含まれていないため、結果の値の時刻部分は
'00:00:00'
に設定される。
DATETIME
または
TIMESTAMP
型の値を
DATE
型のオブジェクトに割り当てた場合、DATE
型には時刻情報が格納されないため、結果の値の時刻部分は削除される。
DATETIME
、DATE
、および
TIMESTAMP
型の値はいずれも、同じ形式セットで指定することができるが、値の範囲については、すべての型で同じであるわけではない。たとえば、TIMESTAMP
型の値は、1970
より前にしたり、2037
より後にすることはできない。したがって、'1968-01-01'
などの日付は、DATETIME
型や
DATE
型の値としては正しいが、TIMESTAMP
型の値としては正しくないため、このようなオブジェクトに割り当てると、値は
0
に変換される。
日付値を指定する際には、次の点に注意してください。
文字列として指定する値で許容される柔軟な形式は、まぎらわしいことがある。
たとえば、'10:11:12'
などの値は、‘:
’
区切り記号のせいで時刻値のように見えるが、日付のコンテキストで使用した場合は、年
'2010-11-12'
として解釈される。値
'10:45:15'
は、'45'
が正しい月ではないため、'0000-00-00'
に変換される。
MySQL サーバでは、日 00-31
、月
00-12
、年
1000-9999
の有効性に関する基本チェックのみ実行される。この範囲外の日付はすべて
0000-00-00
に戻される。
この場合、2002-04-31
のような誤った日付も格納可能であることに注意する。Web
アプリケーションでは、追加のチェックを行わずに、フォームからデータを格納できる。日付が有効なものかどうか確認するには、アプリケーションでチェックを行う必要がある。
2 桁で指定された年の値は、何世紀かわからないため、あいまいである。MySQL では、次の規則に基づいて、2 桁の年の値が解釈される。
範囲 00-69
の年の値は
2000-2069
に変換
範囲 70-99
の年の値は
1970-1999
に変換
MySQL では、TIME
型の値の取り出しと表示は、'HH:MM:SS'
形式(時間の部分が大きい値では
'HHH:MM:SS'
形式)で行われます。TIME
値の範囲は '-838:59:59'
〜
'838:59:59'
です。時間の部分が大きい理由は、TIME
型が 1
日の時刻を表現するためだけでなく、経過時間や
2
つのイベント間の間隔を表現するために使用される場合があるためです。1
日の時刻は 24
時以上になることはありませんが、イベント間の経過時間は
24
時間を大きく上回ったり、マイナスになったりすることがあります。
TIME
型の値は、次に示すさまざまな形式で指定することができます。
'D HH:MM:SS.fraction'
形式の文字列として指定(注意: MySQL
では、小数部は今のところ時刻カラムに格納されない)。``柔軟''
な構文として、HH:MM:SS.fraction
、HH:MM:SS
、HH:MM
、D
HH:MM:SS
、D
HH:MM
、D
HH
、SS
のいずれかも使用できる。この場合、D
は 0 〜 33 の間の日。
区切り記号のない、'HHMMSS'
形式の文字列(時刻として適切なもの)として指定。たとえば、'101112'
は '10:11:12'
として認識されるが、'109712'
は正しくないため(分部分が不適切)、'00:00:00'
になる。
HHMMSS
形式の数値(時刻として適切なもの)として指定。
たとえば、101112
は
'10:11:12'
として認識される。代替形式として、SS
、MMSS
、HHMMSS
、HHMMSS.fraction
も認識される。MySQL
では、小数部分は今のところ格納されないことに注意する。
TIME
型のコンテキストで許容される値を返す、CURRENT_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'
値から見分けることはできないことに注意してください。
YEAR
型は、年を表現するときに使用する 1
バイトの型です。
MySQL では、YEAR
型の値の取り出しと表示は YYYY
形式で行われます。範囲は 1901
〜 2155
です。
YEAR
型の値は、次に示すさまざまな形式で指定することができます。
範囲 '1901'
〜
'2155'
の、4
桁の文字列として指定。
範囲 1901
〜 2155
の、4 桁の数値として指定。
範囲 '00'
〜 '99'
の、2 桁の文字列として指定。範囲
'00'
〜 '69'
と
'70'
〜 '99'
の値は、それぞれ範囲 2000
〜
2069
と 1970
〜
1999
の YEAR
値に変換される。
範囲 1
〜 99
の、2 桁の数値として指定。範囲
1
〜 69
と
70
〜 99
の値は、それぞれ範囲 2001
〜
2069
と 1970
〜
1999
の YEAR
値に変換される。注意: 2
桁の数値の範囲は、2
桁の文字列の範囲と多少異なる。数値として指定した場合、ゼロを直接入力して
2000
と解釈させることはできない。2000
と解釈させるには、必ず文字列の
'0'
または '00'
として指定する必要がある。数値として指定すると、0000
として解釈される。
YEAR
型のコンテキストで許容される値を返す、NOW()
などの関数の結果として指定。
不正な YEAR
値は
0000
に変換されます。
文字列型には、CHAR
、VARCHAR
、BLOB
、TEXT
、ENUM
、SET
があります。このセクションでは、これらの型の機能を示すとともに、それぞれの記憶容量と、クエリでの使用方法について説明します。
型 | 最大サイズ | バイト |
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 |
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 BYTE
が CHAR
BINARY
として使用されます。これは互換性を考慮した機能です。
BINARY
属性は強固な属性です。BINARY
として設定したカラムを式で使用すると、その式全体が
BINARY
値として比較されます。
MySQL では、CHAR
型や
VARCHAR
型のカラムの型が、テーブルの作成時に暗黙的に変更される場合があります。
See 項6.5.3.1. 「カラムの暗黙的な変更」。
BLOB
型は、可変長のデータを格納できる、大きなバイナリオブジェクトです。TINYBLOB
、BLOB
、MEDIUMBLOB
、LONGBLOB
の 4 つの BLOB
型では、格納可能な値の最大長のみが異なります。
TINYTEXT
、TEXT
、MEDIUMTEXT
、LONGTEXT
の 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
型の値は極度に長くなることがあるため、これらの値の使用時には、次に示す一定の制約が適用されます。
GROUP BY
または ORDER
BY
を BLOB
型または
TEXT
型のカラムに使用する場合、カラムの値を固定長のオブジェクトに変換する必要がある。標準的な変換方法としては、次のように、SUBSTRING
関数を使用する。
mysql>SELECT comment FROM tbl_name,SUBSTRING(comment,20) AS substr
->ORDER BY substr;
この変換を行わないと、ソート時にカラムの最初の
max_sort_length
バイトだけが使用される。max_sort_length
のデフォルト値は
1024。この値は、mysqld
サーバの起動時に -O
オプションを指定することによって変更可能。次に示すように、カラムの位置を指定するか、エイリアスを使用することによって、BLOB
型または TEXT
型の値を含む式に対してグループ化操作を行うことができる。
mysql>SELECT id,SUBSTRING(blob_col,1,100) FROM tbl_name GROUP BY 2;
mysql>SELECT id,SUBSTRING(blob_col,1,100) AS b FROM tbl_name GROUP BY b;
BLOB
型または
TEXT
型オブジェクトの最大サイズは、その型によって決まるが、クライアントとサーバ間で実際に送信できる最大値は使用可能なメモリ量と通信バッファのサイズで決まる。メッセージバッファのサイズ(max_allowed_packet
)は変更できるが、サーバ側とクライアント側の両方で変更を行う必要がある。
See 項5.5.2. 「サーバパラメータのチューニング」。
注意: BLOB
型または
TEXT
型のそれぞれの値は、内部で、個別に割り当てられたオブジェクトとして表現されます。これは他のすべてのカラム型と異なります。他のカラム型では、テーブルが開かれたときに、カラムごとに
1 度だけ記憶領域が割り当てられます。
ENUM
型は、テーブルの作成時にカラムの仕様で明示的に列挙された使用可能な値のリストから、通常、値が選択される文字列オブジェクトです。
次に示すように、一定の状況では、空の文字列(""
)または
NULL
も値として使用できます。
不正な値(使用可能な値のリストに含まれない文字列)を
ENUM
型のカラムに挿入すると、特殊なエラー値として、空の文字列が挿入される。この文字列は数値
0 を持つため、'通常'
の空の文字列とは区別することができる(これについては後述)。
ENUM
型が NULL
として宣言されている場合、そのカラムでは
NULL
も正しい値となり、デフォルト値は
NULL
になる。ENUM
型が NOT
NULL
として宣言されている場合は、使用可能な値の最初の要素がデフォルト値として使用される。
次に示すように、各列挙値にはインデックスを付けることができる。
カラムの仕様の使用可能な要素のリストに含まれる値は 1 から順に番号付けされる。
空の文字列エラー値のインデックス値は
0。したがって、次の SELECT
ステートメントでは、無効な
ENUM
が割り当てられているレコードを検索できる。
mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
値のインデックスは
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
定義を解析します。
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
定義を解析します。
記憶領域を最も効率よく使用するためには、それぞれの場合に最も適した型を選択するようにします。たとえば、1
〜 99999
の範囲の整数を格納するカラムには、MEDIUMINT
UNSIGNED
型が最も適しています。
一般的な問題の 1
つとして、金額値の正確な表現があります。この場合、MySQL
では、DECIMAL
型を使用すべきです。この型は文字列として格納されるため、正確さが失われることはありません。正確さがそれほど重要でない場合は、DOUBLE
型でも間に合います。
高精度が必要な場合は、BIGINT
として格納される固定小数点型にいつでも変換することができます。それによって、すべての計算を整数で行い、必要に応じて、結果を浮動小数点値に再び変換できます。
他のベンダの 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
の型を使用したテーブル構造が報告されます。
以下に、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 ) |
TINYBLOB 、TINYTEXT | L +1 バイト(L < 2^8) |
BLOB 、TEXT | L +2 バイト(L < 2^16) |
MEDIUMBLOB 、MEDIUMTEXT | L +3 バイト(L < 2^24) |
LONGBLOB 、LONGTEXT | 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
項6.2.3.2. 「BLOB
型と TEXT
型」。
テーブルに可変長のカラム型が含まれている場合、記録形式も可変長になります。 注意: MySQL では、テーブルの作成時、一定の条件下でカラムが可変長型から固定長型(またはその逆)に変換される場合があります。 See 項6.5.3.1. 「カラムの暗黙的な変更」。
ENUM
型オブジェクトのサイズは、異なる列挙値の数で決まります。使用可能な値の数が
255 までの列挙には、1
バイトが使用されます。値の数が 65535
までの列挙には、2 バイトが使用されます。 See
項6.2.3.3. 「ENUM
型」。
SET
型オブジェクトのサイズは、異なるセット要素の数で決まります。セットのサイズが
N
の場合、そのオブジェクトは
(N+7)/8
バイト(1、2、3、4、または
8
バイトに切り上げ)を占有します。SET
には最大 64
個の要素を組み込むことができます。 See
項6.2.3.4. 「SET
型」。
MyISAM
テーブルの 1
つのレコードの最大サイズは 65534
バイトです。各 BLOB
型と
TEXT
型は、このサイズに対して 5
〜 9 バイトしか占有しません。
SQL ステートメント内の
select_expression
または
where_definition
は、以下に説明する関数を使用した任意の式で構成することができます。
NULL
を含む式は、その式に含まれている演算子と関数に関する記述で特に断りがなければ、常に
NULL
値を生成します。
注意: 関数名とそれに続くかっこの間には、空白は挿入できません。これは、関数呼び出しと、関数とたまたま同じ名前を持つテーブルまたはカラムの参照とを、MySQL のパーサが区別できるようにするためです。しかし、引数の周囲にはスペースを挿入できます。
--ansi
を指定して mysqld
を起動するか、または mysql_connect()
に CLIENT_IGNORE_SPACE
を使用すると、MySQL
で関数名の後のスペースが許容されるようになりますが、このようにした場合、すべての関数名が予約語になります。
See 項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
( ... )
式での評価を特定の順序で行うよう強制するには、次のようにかっこを使用します。
mysql>SELECT 1+2*3;
-> 7 mysql>SELECT (1+2)*3;
-> 9
比較演算は、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
項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
expr
が min
以上で、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,...)
expr
が IN
リストのいずれかの値のときは
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 項6.4.2.3. 「ANY
、IN
、SOME
とともに使用したサブクエリ」。
expr NOT IN (value,...)
NOT (expr IN (value,...))
と同じ。
ISNULL(expr)
expr
が NULL
の場合は 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
の場合は 0
、N
< N2
の場合は
1
(以下同様)というように値を返す。N
が NULL
の場合は
-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
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
で追加された。
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
戻り値の型(INTEGER
、DOUBLE
、または
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)
expr1
が NULL
でない場合は 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 つの式のより
``一般的''
な方(STRING
、REAL
または 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 回評価される。
文字列関数では、結果が
max_allowed_packet
サーバパラメータの設定より長くなると、NULL
が返ります。 See 項5.5.2. 「サーバパラメータのチューニング」。
文字列の位置を処理する関数では、最初の位置は 1 として番号付けされます。
ASCII(str)
文字列 str
の左端の文字の ASCII
コード値を返す。str
が空の文字列のときは 0
を返す。str
が
NULL
のときは 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)
と同じ。N
が NULL
のときは 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)
数値を、進数の異なる数値に変換する。数値
N
を from_base
進数から to_base
進数に変換した数値の文字列表現を返す。いずれかの引数が
NULL
のときは NULL
を返す。 引数 N
は整数として解釈されるが、整数または文字列として指定することができる。最小の進数は
2
で、最大の進数は
36
。to_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
を返す(以下同様)。N
が
1
より小さいか、引数の数より大きい場合は、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()
関数はビット演算を使用するよう最適化される。
str
が strlist
に含まれていない場合や、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)
文字列 str
が len
に指定された長さの文字になるよう、str
の左側に文字列 padstr
を埋め込んだ文字列を返す。str
が len
より長い場合は、戻り値は 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)
と同じ。
N
が NULL
のときは 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 で追加された。
mysql>SELECT QUOTE("Don't");
-> 'Don\'t!' mysql>SELECT QUOTE(NULL);
-> NULL
REPEAT(str,count)
文字列 str
を、count
に指定された回数だけ繰り返した文字列を返す。count
<= 0
の場合は、空の文字列を返す。str
または count
が
NULL
の場合は、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)
文字列 str
が len
に指定された長さの文字になるよう、str
の右側に文字列 padstr
を埋め込んだ文字列を返す。str
が len
より長い場合は、戻り値は 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
から削除した文字列を返す。指定子
BOTH
、LEADING
、TRAILING
がいずれも指定されていない場合は、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('へい');
-> 'へい'
この関数はマルチバイト文字に対応している。
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 で追加された。
詳細および使用例については、項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 付録 G. MySQL の正規表現。 expr
が pat
とマッチする場合は
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
REGEXP
と RLIKE
では、現在のキャラクタセット(デフォルトでは
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
BINARY
BINARY
演算子はこの演算子の後に続く文字列をバイナリ文字列にキャストする。
この演算子を使用すれば、BINARY
または BLOB
として定義されていないカラムに対しても、強制的にケース依存にしたカラムの比較を簡単に行うことができる。
mysql>SELECT "a" = "A";
-> 1 mysql>SELECT BINARY "a" = "A";
-> 0
BINARY string
は CAST(string
AS BINARY)
の省略形。 See
項6.3.5. 「キャスト関数」。
BINARY
は MySQL バージョン 3.23.0
で導入された。
注意: MySQL
の一部のコンテキストでは、インデックス付きのカラムを
BINARY
にキャストすると、インデックスを効率的に使用できなくなる。
BLOB 型の文字列をケース非依存方式で比較する必要がある場合は、比較の実行前に BLOB から大文字に変換することによって、常にこの比較が可能になります。
SELECT 'A' LIKE UPPER(blob_col) FROM table_name;
まもなく、異なるキャラクタセット間のキャストを導入する予定です。この導入によって、文字列の比較をさらに柔軟に実行できるようになります。
通常の算術演算子を利用することができます。注意:
‘-
’、‘+
’、‘*
’
で、両方の引数が整数の場合、結果は
BIGINT
(64
ビット)の精度で計算されます。
どちらか一方の引数が符号なしの整数で、もう一方も整数の場合、結果は符合なしの整数になります。
See 項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
演算で計算されるのは、結果が整数に変換されるコンテキストでその演算が実行された場合に限られる。
すべての数学関数はエラーの場合
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
が
-1
〜 1
の範囲にないときは 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 つの変数 X
と
Y
のアークタンジェントを返す。これは
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
整数の除算。 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 の %
演算子に類する)。 N
を
M
で割ったときの余りを返す。
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)
X
を Y
乗した値を返す。
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)
0
〜 1.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
が負数か、ゼロか、正数かに応じて、この引数の符号を
-1
、0
、または
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
に指定された桁数に切り捨てた値を返す。D
が 0
の場合、結果の値は小数点も小数部も持たない。
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.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()
では、expr
に
expr2
を加えた結果が返される。 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_DATE
と
CURRENT_DATE()
は
CURDATE()
のシノニム。
CURTIME()
文字列と数値のどちらのコンテキストで使用されているかに応じて、'HH:MM:SS'
または HHMMSS
形式の値として、現在の時刻を返す。
mysql>SELECT CURTIME();
-> '23:50:26' mysql>SELECT CURTIME() + 0;
-> 235026
CURRENT_TIME
,
CURRENT_TIME()
CURRENT_TIME
と
CURRENT_TIME()
は
CURTIME()
のシノニム。
CURRENT_TIMESTAMP
,
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP
と
CURRENT_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
との間の日数を返す。
expr
と expr2
には、日付式か、日付時刻式を指定する。
計算は値の日付部分のみに基づいて行われる。
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' |
type
値
DAY_MICROSECOND
、HOUR_MICROSECOND
、MINUTE_MICROSECOND
、SECOND_MICROSECOND
、MICROSECOND
は、MySQL 4.1.1 以降で使用できる。
MySQL では、expr
の形式で任意の句読記号を使用できる。
上の表では、これらの句読記号の一部を示している。date
引数に DATE
型の値を指定し、計算に
YEAR
、MONTH
、DAY
部分のみを組み込む(つまり、時刻部分は含めない)場合、結果は
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
では、間隔値の左端の部分がないとみなされる。たとえば、type
を DAY_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
になる。MONTH
、YEAR_MONTH
、YEAR
のいずれかを加えた結果の日付が、新しい月の最大日数より大きい場合、新しい月の最大日数に調整される。
mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);
-> '1998-02-28'
注意: 上記の例で、キーワード
INTERVAL
と type
指定子はケース非依存。
DATE_FORMAT(date,format)
format
文字列に合わせて、date
値を形式設定する。format
文字列では、次の指定子を使用できる。
指定子 | 説明 |
%M | 月の名前(January ..December )。 |
%W | 曜日名(Sunday ..Saturday )。 |
%D | 英語のサフィックス付きの日付(0th 、1st 、2nd 、3rd
など)。 |
%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
に指定された日付に対し、1
〜
31
の範囲の日にちを返す。
mysql> SELECT DAYOFMONTH('1998-02-03');
-> 3
DAYOFWEEK(date)
date
の曜日インデックス(1
=
日曜、2
= 月曜、...
7
=
土曜)を返す。これらのインデックス値は
ODBC 標準に対応している。
mysql> SELECT DAYOFWEEK('1998-02-03');
-> 3
DAYOFYEAR(date)
date
に指定された日付に対し、1
〜
366
の範囲の年間を通した日にちを返す。
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_FORMAT
、TIME_FORMAT
、DATETIME_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 項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()
LOCALTIME
と
LOCALTIME()
は NOW()
のシノニム。
LOCALTIMESTAMP
,
LOCALTIMESTAMP()
LOCALTIMESTAMP
と
LOCALTIMESTAMP()
は
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)
引数
hour
、minute
、second
に指定された値から計算した時刻値を返す。
mysql> SELECT MAKETIME(12,15,30);
-> '12:15:30'
MAKETIME()
は MySQL 4.1.1
以降で使用できる。
MICROSECOND(expr)
時刻式または日付時刻式 expr
からマイクロ秒を、0
〜
999999
の範囲内の数値として返す。
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
に指定された時刻の分を、0
〜
59
の範囲の値として返す。
mysql> SELECT MINUTE('98-02-03 10:05:03');
-> 5
MONTH(date)
date
に指定された日付の月を、1
〜
12
の範囲の値として返す。
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
に指定された月数を期間
P
(YYMM
または
YYYYMM
の形式)に加える。戻り値は
YYYYMM
の形式で返る。
注意: 期間引数 P
には、日付値を指定しないようにする。
mysql> SELECT PERIOD_ADD(9801,2);
-> 199803
PERIOD_DIFF(P1,P2)
期間 P1
と P2
の間の月数を返す。 P1
と
P2
の指定は YYMM
または YYYYMM
形式で行う。
注意: 期間引数 P1
と
P2
には、日付値を指定しないようにする。
mysql> SELECT PERIOD_DIFF(9802,199703);
-> 11
QUARTER(date)
date
に指定された日付に対応する四半期を、1
〜 4
の範囲の値として返す。
mysql> SELECT QUARTER('98-04-01');
-> 2
SECOND(time)
time
に指定された時刻の秒を、0
〜
59
の範囲の値として返す。
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
の間の時間が返される。
expr
と expr2
には、時刻式か日付時刻式を指定できるが、どちらも同じ型にしなければならない。
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_TIMESTAMP
を
TIMESTAMP
型のカラムに使用すると。``文字列から Unix
タイムスタンプへの''
暗黙的な変換を行わずに、内部のタイムスタンプ値が直接返される。
UNIX_TIMESTAMP()
に範囲外の日付を渡すと、0
が返されるが、この場合、実行されるチェックは基本チェック(年
1970 〜 2037、月 01 〜 12、日 01 〜
31)に限られる。
UNIX_TIMESTAMP()
カラム値を差し引く場合、結果を符号付き整数にキャストする必要がある場合がある。
See 項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
項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)
指定された日付のカレンダ上の週を、1
〜 53
の数値として返す。
mysql> SELECT WEEKOFYEAR('1998-02-20');
-> 8
WEEKOFYEAR()
は MySQL 4.1.1
以降で使用できる。
YEAR(date)
date
に指定された日付の年を、1000
〜 9999
の数値として返す。
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()
関数では、指定した年のコンテキストで週数が返される。
CAST()
関数と CONVERT()
関数は、あるデータ型の値から別のデータ型の値を生成する目的で使用することができます。構文は以下のとおりです。
CAST(expression AS type) CONVERT(expression,type) CONVERT(expr USING transcoding_name)
type
には、次のいずれかのデータ型を指定できます。
BINARY
CHAR
DATE
DATETIME
SIGNED {INTEGER}
TIME
UNSIGNED {INTEGER}
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
では、DATE
、DATETIME
、TIME
型のカラムに 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()
は使用せず、代わりに、LEFT
や
EXTRACT()
のような文字列関数を使用してください。 See
項6.3.4. 「日付と時刻関数」。
文字列を数値にキャストするときには、通常は、特に何もしないで、そのままその文字列を数値として使用します。
mysql> SELECT 1+'1';
-> 2
文字列のコンテキストで数値を使用すると、数値は
BINARY
文字列に自動で変換されます。
mysql> SELECT CONCAT("hello you ",2);
-> "hello you 2"
MySQL
では、符号付きと符号なしのどちらでも、64
ビット値の演算をサポートしています。
数値演算(+
など)でどちらか一方のオペランドが
unsigned integer
の場合、結果の値は符号なしになります。
ただし、キャスト演算子 SIGNED
と
UNSIGNED
を使用することによって、それぞれ符号付き、または符号なしの
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);
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
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_str
は
ENCODE()
から返された文字列でなければならない。
ENCODE(str,pass_str)
pass_str
に指定された文字列をパスワードとして使用して、str
を暗号化する。
暗号化された結果を解読するには、
DECODE()
を使用する。
結果として、string
と同じ長さのバイナリ文字列が返される。
この文字列をカラムに保存するには、BLOB
型のカラムを使用する。
DES_DECRYPT(string_to_decrypt [,
key_string])
DES_ENCRYPT()
で暗号化された文字列を解読する。
注意: この関数は、MySQL で SSL のサポートが組み込まれている場合にのみ機能する。 See 項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 項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
に指定された桁数に丸めて、'#,###,###.##'
のような形式に設定し、結果を文字列として返す。
D
が 0
の場合、結果の値は小数点も小数部も持たない。
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
では、最初の
SELECT
を LIMIT
節なしで実行した場合に返されるレコード数を示す数が返る(先行する
SELECT
ステートメントに
SQL_CALC_FOUND_ROWS
オプションが含まれていないと、FOUND_ROWS()
は LIMIT
が使用されない場合とは異なる、LIMIT
が使用されたときの結果を返す)。
注意: SELECT SQL_CALC_FOUND_ROWS ...
を使用した場合、MySQL
では完全な結果セットに含まれるレコード数を計算する必要が生じる。しかし、この場合、結果セットをクライアントに送る必要がないため、LIMIT
なしで再度クエリを実行するより時間がかからない。
SQL_CALC_FOUND_ROWS
と
FOUND_ROWS()
は、クエリで返されるレコード数を制限する必要がある場合に、完全な結果セットに含まれるレコード数を(クエリを再実行することなく)確認したいときに役立つ。例として、検索結果の別のセクションを示すページへのリンクを含むページ画面を表示する
Web
スクリプトを挙げることができる。FOUND_ROWS()
を使用すると、結果の残りの部分を表示するのにあと何ページ必要か確認できる。
SQL_CALC_FOUND_ROWS
と
FOUND_ROWS()
を
UNION
クエリで使用した場合、単純な
SELECT
ステートメントで使用した場合よりも複雑になる。これは、LIMIT
が UNION
内の複数の場所で起こり得るためである。LIMIT
は、UNION
内の個々の
SELECT
ステートメントに適用することも、UNION
の結果全体にグローバルに適用することもできる。
UNION
に対して
SQL_CALC_FOUND_ROWS
を使用する目的は、このオプションによって、グローバルな
LIMIT
を指定しなかった場合に返されるレコード数を確認できることにある。
UNION
での
SQL_CALC_FOUND_ROWS
の使用には、以下の条件が適用される。
UNION
の最初の
SELECT
に
SQL_CALC_FOUND_ROWS
キーワードが指定されていなければならない。
FOUND_ROWS()
の値は
UNION ALL
の使用時のみ正確になる。
ALL
なしで
UNION
を使用した場合、重複の削除が行われるため、FOUND_ROWS()
の値は近似値にすぎない。
UNION
内に
LIMIT
が存在しない場合、SQL_CALC_FOUND_ROWS
は無視され、UNION
を処理するために作成されたテンポラリテーブル内のレコード数が返される。
SQL_CALC_FOUND_ROWS
と
FOUND_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
ステートメントの後になるため、SELECT
や SET
などの他の SQL
ステートメントの実行後に、C API
関数を使用して
LAST_INSERT_ID(expr)
の値を取り出すことはできない。 See
項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()
は、パスワードの暗号化を Unix
パスワードの暗号化と同じ方法では行わない。ENCRYPT()
を参照。
注意:
PASSWORD()
関数は、MySQL
サーバの認証システムで使用される。アプリケーションでは使用しないこと。
アプリケーション用には、MD5()
か SHA1()
を代わりに使用する。
アプリケーションでのパスワードと認証の安全な処理の詳細については、
RFC-2195
も参照。
RELEASE_LOCK(str)
GET_LOCK()
によって取得された、文字列
str
を名前として持つロックを解除する。そのロックが解除された場合は
1
を返し、そのロックがこのスレッドによってロックされているのでない場合は
0
を返し(この場合、ロックは解除されない)、指定されたロックが存在しない場合は
NULL
を返す(そのロックが
GET_LOCK()
を呼び出して取得されたのでない場合や、すでに解除されている場合、そのロックは存在しないことになる)。
DO
ステートメントを
RELEASE_LOCK()
で使用すると便利である。 See
項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
が付いている場合、ログが有効になっていることを表す。
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 項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
以降で使用可能)。
MySQL 4.1.1 以降では、GROUP BY
節に
WITH ROLLUP
修飾子を使用することによって、合計出力に追加のレコードを挿入できます。これらの追加レコードは上位レベル(上位集約)の集計演算を表します。そのため、ROLLUP
では、複数の分析レベルでの疑問に 1
回のクエリで答えることができます。たとえば、この修飾子は、OLAP(オンライン分析処理)をサポートする目的で使用できます。
例として、sales
という名前のテーブルに、売上の利益を記録するための
year
、country
、product
、profit
という名前のカラムがあるとします。
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
テーブルの、year
、country
、product
に基づく集計が次のように出力されるとします。
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
の出力は次のように解釈されます。
特定の年度と国に対応する各製品レコードセットの後に、製品ごとのすべて値の合計を示す追加の集計レコードが
1
つずつ生成される。これらのレコードでは、product
カラムの値が NULL
に設定される。
特定の年度に対応する各レコードセットの後に、国ごと、製品ごとのすべての値の合計を示す追加の集計レコードが
1
つずつ生成される。これらのレコードでは、country
カラムと products
カラムの値が NULL
に設定される。
最後に、他のすべてのレコードの後に、年度ごと、国ごと、製品ごとのすべての値の総計を示す追加の集計レコードが
1
つ生成される。このレコードでは、year
、country
、products
の各カラムの値が NULL
に設定される。
ROLLUP
使用時のその他の考慮事項
以下に、MySQL における ROLLUP
の実装固有の動作について、いくつか説明します。
ROLLUP
の使用時には、ORDER
BY
節を使用して結果をソートすることはできません(ROLLUP
と ORDER BY
は相互排他的です)。しかし、ソート順序をある程度制御することは可能です。
MySQL で GROUP BY
を使用すると結果がソートされます。また、GROUP
BY
リストに指定したカラムに明示的な
ASC
または DESC
キーワードを付けることによって、個々のカラムのソート順序を指定できます(この場合も、ROLLUP
によって追加される上位レベルの集計レコードは、ソート順序とはかかわりなく、それぞれの計算の対象となったレコードの後に表示されます)。
LIMIT
を使用すると、クライアントに返されるレコードの数を制限することができます。LIMIT
は ROLLUP
の後に適用されるため、制限は
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 | +------+---------+------------+-------------+
注意: LIMIT
を ROLLUP
とともに使用すると、上位集約レコードを理解するためのコンテキストが少なくなるため、生成される結果の解釈が難しくなることがあります。
各上位集約レコードの NULL
インジケータは、各レコードがクライアントに送られるときに生成されます。サーバは、値が変わった左端のカラムの後に、GROUP
BY
節に指定された各カラムを確認します。
これらのカラム名と語彙が一致する名前を持つカラムが結果セットにあると、そのカラムの値を
NULL
に設定します(カラム番号によるカラムのグループ化が指定されている場合、サーバは
NULL
に設定するカラムを番号で識別します)。
上位集約レコードの NULL
値はクエリ処理の後の方の段階で結果セットに組み込まれるため、クエリ自体の中で上位集約レコードを
NULL
値としてテストすることはできません。たとえば、クエリに
HAVING product IS NULL
を追加して、上位集約レコード以外のすべての出力を排除することはできません。
それに対し、クライアント側では、NULL
値が表示されるため、MySQL
クライアントプログラミングインタフェースを使用して
NULL
値としてテストすることができます。
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.name
を
GROUP BY
節に組み込む必要があります。MySQL では、非
ANSI
モードでの実行時にはこのカラム名は不要です。
GROUP BY
部分から取り除くカラムがグループ内で一意なものではない場合は、この機能を使用しないでください。予測不可能な結果になります。
場合によっては、MIN()
と
MAX()
を使用することによって、一意なものでないカラムの値を取り出すことができます。次の例では、sort
カラムの値が最も小さいレコードの
column
値が得られます。
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
See 項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();
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
節の前に配置しなければなりません。
SELECT
式には、AS
alias_name
を使用してエイリアスを指定することができる。
このエイリアスは式のカラム名として使用されるもので、ORDER
BY
節または HAVING
節とともに使用できる。次に例を示す。
mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
FROM mytable ORDER BY full_name;
SELECT
式のエイリアスの指定時、AS
キーワードは省略できる。
前の例は、次のように記述することも可能。
mysql> SELECT CONCAT(last_name,', ',first_name) full_name
FROM mytable ORDER BY full_name;
AS
は省略できるため、2 つの
SELECT
式の間にカンマを付け忘れると微妙な問題が生じることがある。この場合、2
番目の式は MySQL
によってエイリアス名として解釈される。たとえば、次のステートメントで、columnb
はエイリアス名とみなされる。
mysql> SELECT columna columnb FROM mytable;
WHERE
節ではカラム名のエイリアスは使用できない。これは、WHERE
節の実行時点でカラム値がまだ判別されないことがあるため。
See 項A.5.4. 「alias
の問題」。
FROM table_references
節は、レコードの取り出し元のテーブルを表す。複数のテーブルを指定する場合は、結合操作を実行する。結合構文については、項6.4.1.1. 「JOIN
構文」
を参照。
指定する各テーブルについて、必要に応じて、そのテーブルのエイリアスを指定することができる。
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]
MySQL バージョン 3.23.12
以降では、テーブルからのデータの取り出し時に、どのインデックスを使用すべきか
MySQL
に知らせるためのヒントを指定することができる。これは、EXPLAIN
で MySQL
が使用可能なインデックスのリストの中から誤ったインデックスを使用していることが明らかになったときに役立つ。USE
INDEX (key_list)
と指定することによって、使用可能なインデックスの中から特定のインデックスを使ってテーブル内のレコードを検索するよう
MySQL に指示できる。もう 1 つの IGNORE
INDEX (key_list)
構文は、特定のインデックスを使用しないよう
MySQL に指示するときに使用する。
MySQL 4.0.9 では、FORCE INDEX
も使用できる。これは USE INDEX
(key_list)
と同じように動作するが、異なる点として、この構文の場合、テーブルのスキャンは非常にコストがかかるという前提に立つ。つまり、テーブルのスキャンが実行されるのは、どのインデックスを使用してもテーブル内のレコードを検索できない場合に限られる。
USE/IGNORE/FORCE KEY
は
USE/IGNORE/FORCE INDEX
のシノニム。
注意:
USE/IGNORE/FORCE INDEX
は、MySQL
でテーブル内のレコードの検索方法と結合の実行方法を決めるときにどのインデックスを使用するか、という点にのみ影響する。ORDER
BY
や GROUP BY
の解決時にインデックスを使用するかどうかには影響しない。
MySQL 4.0.14 では、MySQL
にテーブルのスキャンよりもキーのスキャンを優先させるための代替方法として、SET
MAX_SEEKS_FOR_KEY=value
も使用できる。
テーブルは(カレントデータベース内のものなら)tbl_name
として参照できる。データベースを明示的に指定する場合は、dbname.tbl_name
として参照する。
カラムは、col_name
、tbl_name.col_name
、または
db_name.tbl_name.col_name
として参照できる。SELECT
ステートメントでカラムを参照するときには、その参照があいまいにならない限り、カラム名の前に
tbl_name
や
db_name.tbl_name
を付ける必要はない。より明示的なカラム参照形式が必要となるあいまいな例については、項6.1.2. 「データベース名、テーブル名、インデックス名、カラム名、エイリアス名」を参照。
バージョン 4.1.0
以降では、どのテーブルも参照されない状況において、ダミーテーブル名として
DUAL
を指定することができる。これはもっぱら互換性を考慮した機能である。一部の他のサーバではこの構文が必要となる。
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
テーブル参照には、tbl_name [AS]
alias_name
を使用してエイリアスを指定することができる。
mysql>SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
->WHERE t1.name = t2.name;
mysql>SELECT t1.name, t2.salary FROM employee t1, info t2
->WHERE t1.name = t2.name;
出力用に選択されるカラムは、ORDER
BY
節と GROUP BY
節において、カラム名、カラムエイリアス、またはカラム位置を使用して参照することができる。カラム位置は
1 から始まる。
mysql>SELECT college, region, seed FROM tournament
->ORDER BY region, seed;
mysql>SELECT college, region AS r, seed AS s FROM tournament
->ORDER BY r, s;
mysql>SELECT college, region, seed FROM tournament
->ORDER BY 2, 3;
逆の順序でソートするには、ORDER
BY
節においてソートキーとするカラムの名前に
DESC
(降順)キーワードを付ける。
デフォルトは昇順だが、昇順を明示的に指定するには、ASC
キーワードを指定する。
WHERE
節では、MySQL
でサポートしている任意の機能を使用できるが、例外として集約(集計)機能だけは使用できない。
See 項6.3. 「SELECT
節と WHERE
節で使用する関数」。
HAVING
節では、select_expression
で指定した任意のカラムまたはエイリアスを参照することができる。この節は、処理の終わり近くになって(項目がクライアントに送られる直前)、最適化されることなく適用される(LIMIT
は HAVING
の後に適用)。WHERE
節に組み込むべき項目に対しては、HAVING
を使用してはならない。たとえば、次のように記述しないようにする。
mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
正しくは次のように記述する。
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
MySQL バージョン 3.22.5 以降では、次のようなクエリも使用できる。
mysql>SELECT user,MAX(salary) FROM users
->GROUP BY user HAVING MAX(salary)>10;
それより前の MySQL バージョンでは、代わりに次のように記述する。
mysql>SELECT user,MAX(salary) AS sum FROM users
->group by user HAVING sum>10;
DISTINCT
、DISTINCTROW
、ALL
の各オプションでは、重複レコードを返すかどうかを指定する。デフォルト(ALL
)では、マッチするすべてのレコードが返される。DISTINCT
と DISTINCTROW
はシノニムで、これらを指定した場合、結果セットから重複レコードが削除される。
STRAIGHT_JOIN
と
HIGH_PRIORITY
、および
SQL_
で始まる各オプションは、SQL-99 に対する
MySQL の拡張。
STRAIGHT_JOIN
では、オプティマイザに、FROM
節に指定された順序で強制的にテーブルを結合させることができる。オプティマイザが最適でない順序でテーブルを結合するときには、このオプションを使用することによって、クエリを高速化できる。
See 項5.2.1. 「EXPLAIN
構文(SELECT
に関する情報の取得)」。
HIGH_PRIORITY
を指定すると、SELECT
ステートメントがテーブルを更新するステートメントよりも優先される。このオプションは、非常に迅速に処理され、かつ直ちに実行する必要があるクエリに対してのみ使用するようにする。SELECT
HIGH_PRIORITY
クエリは、対象のテーブルが読み取り用にロックされれば、たとえテーブルが解放されるのを待っている更新ステートメントがあっても、実行される。
SQL_BIG_RESULT
は、GROUP
BY
または DISTINCT
とともに使用することができ、それによって、結果セットに多くのレコードが組み込まれることをオプティマイザに通知できる。この場合、MySQL
で、ディスクベースの一時テーブルが必要に応じて直接使用される。
また、この場合、GROUP BY
要素のキーで一時テーブルを処理するよりソートを行うほうが優先される。
SQL_BUFFER_RESULT
では、結果が一時テーブルに強制的に格納される。結果セットをクライアントに送るのに時間がかかる場合には、このオプションを指定することによって、MySQL
によるテーブルのロックを早く解放させることができる。
SQL_SMALL_RESULT
は MySQL
固有のオプション。このオプションを
GROUP BY
または
DISTINCT
とともに使用することで、結果セットが小さいものになることをオプティマイザに通知できる。この場合、ソートを行う代わりに、迅速な一時テーブルを使用して結果のテーブルが格納される。MySQL
バージョン 3.23
では、通常、このオプションを使用する必要はない。
SQL_CALC_FOUND_ROWS
(バージョン
4.0.0 以降)では、LIMIT
節を無視した場合に結果セットに含まれるすべてのレコード数を計算するよう
MySQL に指示できる。 その後、SELECT
FOUND_ROWS()
を使用して、計算されたレコード数を取り出せる。
See 項6.3.6.2. 「その他の各種関数」。
注意: 4.1.0
より前のバージョンでは、LIMIT
0
を指定した場合、このオプションは機能しない。この場合、迅速に戻るよう最適化される(その結果、レコードカウントは
0 になる)。 See
項5.2.9. 「MySQL による LIMIT
の最適化」。
SQL_CACHE
では、QUERY_CACHE_TYPE=2
(DEMAND
)を使用した場合に、クエリの結果をクエリキャッシュに格納するよう
MySQL に指示できる。 See
項6.9. 「MySQL クエリキャッシュ」。
UNION
またはサブクエリを使用したクエリでは、このオプションはクエリのあらゆる
SELECT
ステートメントで適用される。
SQL_NO_CACHE
では、クエリの結果をクエリキャッシュに格納しないよう、MySQL
に指示することができる。 See
項6.9. 「MySQL クエリキャッシュ」。
UNION
またはサブクエリを使用したクエリでは、このオプションはクエリのあらゆる
SELECT
ステートメントで適用される。
GROUP BY
を使用すると、GROUP BY
のすべてのフィールドに対して ORDER
BY
を使用した場合と同じように、出力レコードが
GROUP BY
に指定した基準に基づいてソートされる。MySQL
では、GROUP BY
節を拡張しており、この節で指定したカラムの後に
ASC
と DESC
のいずれかを指定することができる。
SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
MySQL では、GROUP BY
の使用を拡張しており、GROUP BY
節に指定していないフィールドも選択できる。
クエリで期待した結果が得られない場合は、GROUP
BY
の説明を参照。 See
項6.3.7. 「GROUP BY
節で使用する関数と修飾子」。
MySQL 4.1.1 以降、GROUP BY
には
WITH ROLLUP
修飾子を使用できる。 See
項6.3.7.2. 「GROUP BY
の修飾子」。
LIMIT
節を使用すると、SELECT
ステートメントで返されるレコード数を制限することができる。LIMIT
は 1 つまたは 2
つの数値引数を取る。これらの引数は整数定数でなければならない。
引数が 1 つの場合、その値は、戻り値として返す、結果セットの冒頭からのレコード数を表す。 引数が 2 つの場合、最初の引数は戻り値として返す最初のレコードまでのオフセットを表し、2 つ目の引数は戻り値として返す最大レコード数を表す。最初のレコードのオフセット値は 0(1 ではない)。
PostgreSQL との互換性を確保するため、MySQL
では LIMIT row_count OFFSET offset
構文もサポートしている。
mysql> SELECT * FROM table LIMIT 5,10; # Retrieve rows 6-15
特定のオフセット位置から結果セットの終わりまでのすべてのレコードを取り出すには、2 つ目のパラメータに大きな数値を指定できる。
mysql> SELECT * FROM table LIMIT 95,18446744073709551615; # Retrieve rows 96-last.
引数が 1 つの場合、その値は戻り値として返す最大レコード数を表す。
mysql> SELECT * FROM table LIMIT 5; # Retrieve first 5 rows
つまり、LIMIT n
は LIMIT
0,n
と指定するのと同じである。
SELECT ... INTO OUTFILE 'file_name'
形式の SELECT
では、SELECT
したレコードがファイルに書き込まれる。ファイルはサーバホスト上に作成される。既存のファイルを指定することはできない(この制限は、特に、/etc/passwd
などのデータベーステーブルやファイルが破壊されないようにするため)。この形式の
SELECT
を使用するには、サーバホストに対する
FILE
権限が必要となる。
SELECT ... INTO OUTFILE
ステートメントの用途は、主に、サーバマシン上のテーブルのダンプをきわめて迅速に実行できるようにすることである。サーバホスト以外のホストに結果のファイルを作成する必要があるときには、SELECT
... INTO OUTFILE
は使用できない。この場合、代わりに、mysqldump
--tab
や mysql -e "SELECT ..." >
outfile
などのクライアントプログラムを使用してファイルを生成する。
SELECT ... INTO OUTFILE
は LOAD
DATA INFILE
の逆。このステートメントの
export_options
部分の構文は、LOAD DATA INFILE
ステートメントで使用される
FIELDS
および LINES
節と同じ構成になっている。 See
項6.4.8. 「LOAD DATA INFILE
構文」。
結果のテキストファイルでは、以下の文字だけが
ESCAPED BY
指定の文字でエスケープされる。
ESCAPED BY
指定文字自体
FIELDS TERMINATED BY
指定の最初の文字
LINES TERMINATED BY
指定の最初の文字
また、ASCII 0
は、ESCAPED
BY
の指定文字の後ろに 0(ASCII
48
)を付けたものに変換される。
上記の文字をエスケープする理由は、ファイルを確実に読み返せるようにするには、FIELDS
TERMINATED BY
、ESCAPED
BY
、LINES TERMINATED BY
指定されている文字をすべてエスケープしなければならないため。ASCII
0
は一部のページャーでの表示を容易化するためにエスケープされる。
結果のファイルは SQL の構文に従う必要はないため、その他のエスケープ処理は必要ない。
次に、多くの古いプログラムで使用されている形式でファイルを生成する例を示す。
SELECT a,b,a+b INTO OUTFILE "/tmp/result.text" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\n" FROM test_table;
INTO OUTFILE
の代わりに
INTO DUMPFILE
を使用すると、MySQL
によってファイルに 1
つのレコードだけが書き込まれる。この場合、カラムや行の終了は何も含まれず、エスケープ処理もまったく行われない。これは、ファイルに
BLOB
値を格納するときに役立つ。
注意: INTO OUTFILE
と INTO
DUMPFILE
で作成されるファイルは、サーバホスト上にあるアカウントで書き込み可能であるかもしれない。その理由は、MySQL
サーバを実行しているアカウントで、それらファイルを作成するからであり、作成されたファイルはそのアカウントがオーナーになっているからである(mysqld
は root
として実行すべきでない)。
ファイルの内容を操作できるようにするには、ファイルを全ユーザ書き込み可能にする必要がある。
PROCEDURE
節には、結果セット内のデータの処理に使用するプロシージャを指定する。例については、項13.3.1. 「プロシージャの分析」を参照。
ページロックまたは行ロック機能があるストレージエンジンに対して
FOR UPDATE
を使用すると、現在のトランザクションが終了するまで、検査対象のレコードは書き込みに対してロックされる。
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_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
以降に限られます。同様に、JOIN
と CROSS JOIN
に関しても、MySQL
4.0.11 以降でのみ条件を指定できます。
上の構文リストの最後に挙げた LEFT OUTER
JOIN
構文は、単に ODBC
との互換性を確保するためのものです。
テーブル参照では、tbl_name AS
alias_name
または tbl_name
alias_name
を使用してエイリアスを指定することができる。
mysql>SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
->WHERE t1.name = t2.name;
ON
条件句には、WHERE
節で使用できる形式の任意の条件を指定できる。
LEFT JOIN
の ON
または USING
部分に右側のテーブルにマッチするレコードがない場合、すべてのカラムを
NULL
に設定した 1
つのレコードが右側のテーブルとして使用される。この規則に基づいて、対応するレコードが別のテーブルに存在しないレコードをテーブル内で検索することができる。
mysql>SELECT table1.* FROM table1
->LEFT JOIN table2 ON table1.id=table2.id
->WHERE table2.id IS NULL;
この例では、table2
に存在しない id
値を持つすべてのレコード(table2
に対応するレコードがないすべてのレコード)が
table1
で検索される。当然、この場合、table2.id
が NOT NULL
として宣言されていることが前提となる。
See 項5.2.7. 「MySQL による LEFT JOIN
と RIGHT JOIN
の最適化」。
USING
(column_list)
節に指定するカラムリスト内のカラムは、両方のテーブルに存在しなければならない。次の
2 つの節は同じことを意味する。
a LEFT JOIN b USING (c1,c2,c3) a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
2 つのテーブルの NATURAL [LEFT]
JOIN
の定義は、両方のテーブルに存在するすべてのカラムを指定した
USING
節を持つ INNER
JOIN
または LEFT JOIN
と同じ意味になる。
INNER JOIN
と
,
(カンマ)は、結合条件が指定されていない場合、同じ意味になり、どちらについても、指定されたテーブル間でデカルト積が生成される(つまり、最初のテーブルの各レコードが
2
番目のテーブルのすべてのレコードに結合される)。
RIGHT JOIN
は LEFT
JOIN
の類似機能。コードをデータベース間で移植可能にするには、RIGHT
JOIN
ではなく LEFT JOIN
を使用するようにする。
STRAIGHT_JOIN
は
JOIN
と同様のものだが、異なる点として、STRAIGHT_JOIN
では常に右側のテーブルの前に左側のテーブルが読み取られる。この構文は、結合オプティマイザによってテーブルが誤った順序で並べられるといった(まれな)事態に対処するために使用できる。
MySQL バージョン 3.23.12
以降では、テーブルからのデータの取り出し時に、どのインデックスを使用すべきか
MySQL
に知らせるためのヒントを指定することができる。これは、EXPLAIN
で MySQL
が使用可能なインデックスのリストの中から誤ったインデックスを使用していることが明らかになったときに役立つ。USE
INDEX (key_list)
と指定することによって、使用可能なインデックスの中から特定のインデックスを使ってテーブル内のレコードを検索するよう
MySQL に指示できる。もう 1 つの IGNORE
INDEX (key_list)
構文は、特定のインデックスを使用しないよう
MySQL に指示するときに使用する。
MySQL 4.0.9 では、FORCE INDEX
も使用できる。これは USE INDEX
(key_list)
と同じように動作するが、異なる点として、この構文の場合、テーブルのスキャンは非常にコストがかかるといいう前提に立つ。つまり、テーブルのスキャンが実行されるのは、どのインデックスを使用してもテーブル内のレコードを検索できない場合に限られる。
USE/IGNORE KEY
は USE/IGNORE
INDEX
のシノニム。
注意:
USE/IGNORE/FORCE INDEX
は、MySQL
でテーブル内のレコードの検索方法と結合の実行方法を決めるときにどのインデックスを使用するか、という点にのみに影響します。ORDER
BY
や GROUP 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;
SELECT ... UNION [ALL] SELECT ... [UNION SELECT ...]
UNION
は MySQL 4.0.0
で導入されました。
UNION
は、多くの
SELECT
ステートメントを 1
つの結果セットに結合するために使用します。
SELECT
の
select_expression
部分のカラムリストには、同じ型のカラムを指定します。最初の
SELECT
クエリで指定したカラム名が、返される結果のカラム名として使用されます。
これらの SELECT
コマンドは通常の SELECT
コマンドですが、次の制限が適用されます。
最後の SELECT
コマンドにのみ
INTO OUTFILE
を指定できる。
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 |
+---------------+
サブクエリは、別のステートメントに含まれた
SELECT
ステートメントです。
次に例を示します。
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
上の例で、 SELECT * FROM t1 ...
は外側のクエリ(または外側のステートメント)であり、(SELECT
column1 FROM t2)
はサブクエリです。
いわば、サブクエリは外側のクエリ内にネストされていることになります。実際のところ、サブクエリ内にさらにサブクエリをネストし、クエリを何重にも入れ子化することができます。
サブクエリは必ずかっこで囲む必要があります。
MySQL バージョン 4.1 以降では、標準 SQL で規定されているサブクエリのすべての形式と操作に加え、MySQL 固有のいくつかの機能をサポートしています。サブクエリを使用する主な利点は次のとおりです。
クエリの各部分が互いに分離されるように、クエリを記述することができる。
複雑な結合や集合処理を必要とする操作を、それらの処理を行わずに実行できる。
(多くの人々の意見として)判読しやすい。
事実、初期の SQL
が
``構造化問い合わせ言語''
と呼ばれるようになったきっかけは、サブクエリにある。
バージョン 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 項6.4.2.11. 「初期の MySQL バージョンに合わせたサブクエリの書き換え」。
最も単純な形式(スカラ副問い合わせ)では、サブクエリは単純なオペランドです(スカラ副問い合わせと対立するものとして行またはテーブル副問い合わせがあります。これらについては後述します)。したがって、サブクエリは、正しいカラム値やリテラルが使用されているところならどこでも使用でき、また、他のすべてのオペランドと同じように、データ型、長さ、値が
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
、INSERT
、UPDATE
、DELETE
、SET
、DO
のいずれかを使用できる。
サブクエリには、通常の
SELECT
に組み込める任意のキーワードまたは節(DISTINCT
、GROUP
BY
、ORDER
BY
、LIMIT
、結合、ヒント、UNION
構造、コメント、関数など)を組み込める。
そのため、以降のセクションでは、どちらかというと簡素な構造
(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;
サブクエリの最も一般的は使用法は、次の形式のものです。
<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);
構文
<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
を使用することによって、このクエリの本当の意味を誰もが確実に理解できるようにすることができます。
構文
<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
つの可能性を常に念頭に置くようにしてください。
相関副問い合わせとは、その中に含まれるカラムの参照が外側のクエリにも含まれているサブクエリのことを言います。 次に例を示します。
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 では、相関クエリを使用しないよう非公式に推奨しています。相関クエリは構成が複雑化するだけでなく、実行にもより多くの時間がかかります。
サブクエリで値がまったく返らない場合、EXISTS
<subquery>
は TRUE
になり、NOT EXISTS <subquery>
は
FALSE
になります。
次に例を示します。
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
従来、EXISTS
サブクエリは
SELECT *
で開始しますが、SELECT 5
や
SELECT 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 か''
という疑問の答えが得られると言ったほうが簡単です。
ここまでの内容は、スカラ副問い合わせ -- つまり、単一のカラム値を返す -- サブクエリについてのものでした。行副問い合わせとは、単一のレコード値を返す異型サブクエリです。したがって、複数のカラム値を返すことがあります。 次に例を 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);
サブクエリは 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
節のサブクエリを相関クエリにすることはできません。
サブクエリだけに適用される新しい戻りエラーがいくつかあります。 このセクションでは、それらのエラーを一つにまとめ、重要な点についていくつか説明します。
ERROR 1235 (ER_NOT_SUPPORTED_YET) SQLSTATE = 42000 Message = "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'"
これは、次のステートメントが機能しないことを意味する。
SELECT * FROM t1 WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)
ただし、これは、一部の初期のバージョン(MySQL 4.1.1 など)にのみ適用される。
ERROR 1240 (ER_CARDINALITY_COL) SQLSTATE = 21000 Message = "Operand should contain 1 column(s)"
このエラーは次のような場合に発生する。
SELECT (SELECT column1, column2 FROM t2) FROM t1;
比較を目的とするものならば、複数のカラムを返すサブクエリを使用できる。 See 項6.4.2.7. 「行副問い合わせ」。 しかし、他のコンテキストでは、サブクエリはスカラオペランドでなければならない。
ERROR 1241 (ER_SUBSELECT_NO_1_ROW) SQLSTATE = 21000 Message = "Subquery returns more than 1 row"
このエラーは次のような場合に発生する。
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
ただし、これは t2
に複数のレコードが存在する場合に限られる。たとえば、このエラーは長い間使用されているコードで発生することがある。つまり、サブクエリで返すことができるレコード数に影響するような変更を誰かが行ったような場合である。1
つに限らず任意の数のレコードをオブジェクトで検出するようにするときの正しいステートメントは、次のようになる。
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);
Error 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000 Message = "You can't specify target table 'x' for update in FROM clause"
このエラーは次のような場合に発生する。
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);
サブクエリは SELECT
ステートメントと同じく、UPDATE
ステートメントや DELETE
ステートメントでも正式に使用できるので、UPDATE
ステートメント内の割り当てにサブクエリを使用しても問題ありません。
しかし、サブクエリの FROM
節と更新対象の両方に同じテーブル(この場合、テーブル
t1
)を使用することはできません。
通常、サブクエリがエラーになると、ステートメント全体がエラーになります。
開発は現在進行形で進められているため、長期間有効な最適化のヒントというのはありません。ここでは、いくつかのテクニックについて説明します。
サブクエリのレコード数やレコードの順序に影響するサブクエリ節を使用する。次はその例。
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
結合をサブクエリに置き換える。次はその例。
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
サブクエリの外側から内側へ節を移動する。次はその例。
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
もう 1 つの例。
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
上のステートメントは次のステートメントの代わりに使用できる。
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
相関副問い合わせの代わりに行副問い合わせを使用する。次はその例。
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
上のステートメントは次のステートメントの代わりに使用できる。
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
a <> ALL (...)
ではなく、NOT (a = ANY (...))
を使用する。
x=1 OR x=2
ではなく x =
ANY (table containing {1,2})
を使用する。
EXISTS
ではなく =
ANY
を使用する。
上記のテクニックを使用すると、プログラムの実行が速くなったり、遅くなったりする場合があります。MySQL
の BENCHMARK()
関数などの機能を使用すると、それぞれの状況において何が適切か、調べることができます。旧バージョンとの互換性を確保する場合を除いて、結合への変換についてはあまり気にしないでください。
MySQL 自体が行う最適化として次のものがあります。
非相関副問い合わせは 1
度しか実行されない(EXPLAIN
を使用して、指定されたサブクエリが実際に非相関副問い合わせかどうか確認できる)
IN
/ALL
/ANY
/SOME
サブクエリは、サブクエリ内の選択リストカラムがインデックス付きである可能性があるため、書き直される。
次の形式のサブクエリはインデックスルックアップ関数と置き換えられる。
... IN (SELECT indexed_column FROM single_table ...)
インデックスルックアップ関数は、EXPLAIN
では特殊な結合型として記述される。
次の形式の式は、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
というファイルを探してください。
バージョン 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
つの方法のいずれかで対処することができます。
第 1 の選択肢: MySQL バージョン 4.1 にアップグレードする。
第 2 の選択肢:
手続き型プログラミング言語(Perl や PHP
など)を使用し、SELECT
クエリを送信して削除対象のレコードの主キーを取得し、その後、それらの値を使用して
DELETE
ステートメント(DELETE FROM ... WHERE ...
IN (key1, key2, ...)
)を構築する。
第 3 の選択肢: 対話式 SQL で、MySQL の拡張
CONCAT()
を使用して(標準の
||
演算子の代わりに)、DELETE
ステートメントのセットを自動で構築する。
次はその例。
SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';') FROM tab1, tab2 WHERE tab1.col1 = tab2.col2;
このクエリをスクリプトファイルに保管することによって、ファイルからの入力を
mysql
コマンドラインインタープリタにリダイレクトし、さらにインタープリタの
2
つ目のインスタンスに出力を渡すことができる。
shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
MySQL サーバ 4.0 では、複数テーブルの
DELETE
ステートメントをサポートしています。このようなステートメントを使用すると、1
つのテーブルのデータだけでなく、複数のテーブルのデータに基づくレコードを一度に効率的に削除することができます。
バージョン 4.0 以降では、複数テーブルの
UPDATE
ステートメントもサポートしています。
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 ... VALUES
または
INSERT ... SELECT
でカラムリストを指定しない場合、VALUES()
リストまたは SELECT
で、テーブルのすべてのカラムの値を提供する必要がある。テーブル内のカラムの順序がわからない場合は、DESCRIBE
tbl_name
を使用して順序を調べる。
値が明示的に指定されていないカラムは、そのカラムのデフォルトに設定される。たとえば、カラムリストでテーブルのすべのカラムが指定されていない場合、指定されていないカラムはそのデフォルト値に設定される。デフォルト値の割り当てについては、項6.5.3. 「CREATE TABLE
構文」
で説明している。
キーワード DEFAULT
を使用して、カラムにデフォルト値を設定することもできる(MySQL
4.0.3 の新機能)。この場合、不完全な
VALUES()
リスト(テーブル内のすべてのカラムの各値を含んでいないリスト)を記述しなくてすむため、一部のわずかなカラムを除いたすべてのカラムに値を割り当てる
INSERT
ステートメントを書きやすくなる。
このキーワードを使用しない場合、VALUES()
リストの各値に対応するカラム名のリストを記述しなければならない。
MySQL では、常にすべてのフィールドにデフォルト値がある。デフォルト値の存在は、MySQL がトランザクションテーブルと非トランザクションテーブルのどちらも処理できるようにするための必要条件となっている。
MySQL では、フィールド内容のチェックはデータベースサーバではなくアプリケーション側で行う、という見解に立っている。
expression
では、値リストに先に設定された任意のカラムを参照することができる。たとえば、次のように記述できる。
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
しかし、次のようには記述できない。
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
キーワード DELAYED
が指定されていると、サーバはレコードをバッファに挿入する。その後、INSERT
DELAYED
ステートメントを発行したクライアントは処理を続行することができる。テーブルが使用されていると、サーバはレコードを保持する。テーブルが解放されると、サーバはレコードの挿入を開始し、そのテーブルに対する新しい読み取り要求がないか定期的にチェックする。新しい読み取り要求があると、そのテーブルが再び解放されるまで、遅延されたレコードのキューの処理は中断される。
キーワード LOW_PRIORITY
が指定されている場合、他のクライアントによるそのテーブルからの読み取りがなくなるまで、INSERT
の実行は遅らされる。これには、既存のクライアントの読み取り中、および
INSERT LOW_PRIORITY
ステートメントの待機中に読み取りを開始した他のクライアントも含まれる。したがって、読み取り過多な環境の場合、INSERT
LOW_PRIORITY
ステートメントを発行したクライアントは長時間(または永続的に)待機させられることがある(それに対して
INSERT DELAYED
では、クライアントは直ちに処理を続行することができる)。See
項6.4.3.2. 「INSERT DELAYED
構文」注意:
LOW_PRIORITY
では同時挿入が無効になるため、このオプションは通常
MyISAM
テーブルに対しては使用しない。 See
項7.1. 「MyISAM
テーブル」。
多くのレコードの INSERT
でキーワード IGNORE
が指定されていると、テーブルの既存の
PRIMARY
または
UNIQUE
キーと重複するレコードはすべて無視され、挿入されない。IGNORE
が指定されていない場合に既存のキー値を重複して持つレコードがあると、挿入処理が中断される。C
API 関数 mysql_info()
では、テーブルに挿入されたレコード数を調べることができる。
ON DUPLICATE KEY UPDATE
節(MySQL 4.1.0
の新機能)が指定されている場合に、PRIMARY
または UNIQUE
キーでの重複値の生成を招くレコードが挿入されると、古いレコードの
UPDATE
が実行される。次に例を示す。
mysql>INSERT INTO table (a,b,c) VALUES (1,2,3)
->ON DUPLICATE KEY UPDATE c=c+1;
このコマンドでは、a
が
UNIQUE
として宣言されていて、かつすでに 1 度、値
1
を保持している場合、次のコマンドと同じになる。
mysql> UPDATE table SET c=c+1 WHERE a=1;
注意: カラム
b
も一意である場合、UPDATE
コマンドは次のようになる。
mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
a=1 OR b=2
が複数のレコードに一致する場合、1
つのレコードだけが更新される。通常、複数の
UNIQUE
キーを持つテーブルに対しては ON
DUPLICATE KEY
節を使用しないようにする。
MySQL 4.1.1 以降では、関数
VALUES(col_name)
を使用して、INSERT ... UPDATE
コマンドの INSERT
部分のカラム値を参照できる。これは、重複キーのコンフリクトがない場合に挿入される値である。この関数は複数行の挿入時に特に役立つ。当然、VALUES()
関数は INSERT ... UPDATE
コマンドでのみ意味を持ち、それ以外のコマンドで使用した場合は
NULL
が返される。
次に例を示す。
mysql>INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
->ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
上のコマンドは次のコマンドと同じである。
mysql>INSERT INTO table (a,b,c) VALUES (1,2,3)
->ON DUPLICATE KEY UPDATE c=3;
mysql>INSERT INTO table (a,b,c) VALUES (4,5,6)
->ON DUPLICATE KEY UPDATE c=9;
ON DUPLICATE KEY UPDATE
が指定されている場合、DELAYED
オプションは無視される。
MySQL のコンフィギャ時に
DONT_USE_DEFAULT_FIELDS
オプションが指定されている場合、NULL
以外の値を必要とするすべてのカラムに明示的に値を指定しないと、INSERT
ステートメントでエラーが生成される。 See
項2.3.3. 「一般的な configure
オプション」。
AUTO_INCREMENT
カラムに使用されている値は、mysql_insert_id
関数を使用して確認することができる。 See
項11.1.3.32. 「mysql_insert_id()
」。
INSERT ... SELECT
または INSERT
... VALUES
ステートメントを複数の値のリスト付きで使用する場合は、C
API 関数 mysql_info()
を使用してクエリに関する情報を取得することができます。情報文字列の形式は次のとおりです。
Records: 100 Duplicates: 0 Warnings: 0
Duplicates
は、特定の既存のユニークインデックス値と重複することになるため挿入されなかったレコード数を表します。
Warnings
は、何らかの問題があるカラム値を挿入しようとした回数を表します。Warnings(警告)は次のいずれかの条件の下に発生します。
NOT NULL
として宣言されているカラムへの
NULL
の挿入。
この場合、カラムにはそのカラム型に対応するデフォルト値が設定される。
つまり、数値型のカラムでは
0
、文字列型のカラムでは空の文字列(''
)、日付と時刻型のカラムでは
``ゼロ'' 値が適用される。
数値型のカラムへの、そのカラムの値の範囲を超える値の設定。 この場合、値は範囲の最大値または最小値に切り落とされる。
数値型のカラムへの '10.34 a'
などの値の設定。この場合、後続のガーベジは除去され、残りの数値の部分だけが挿入される。値が数値として意味をなさない場合、カラムの値は
0
に設定される。
CHAR
型、VARCHAR
型、TEXT
型、または
BLOB
型のカラムへの、そのカラムの最大長を超える文字列の挿入。この場合、値はカラムの最大長に合わせて切り捨てられる。
日付または時刻型のカラムへの、そのカラム型に不適切な値の挿入。この場合、カラムの値はその型に対応するゼロ値に設定される。
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
ステートメントでは、以下の条件が適用されます。
MySQL 4.0.1
より前のバージョンでは、INSERT ...
SELECT
は暗黙的に IGNORE
モードで動作する。MySQL 4.0.1
以降では、重複キー違反を引き起こすレコードを無視するには、IGNORE
を明示的に指定しなければならない。
MySQL 4.0.14
より前のバージョンでは、INSERT
ステートメントの対象テーブルをクエリの
SELECT
部分の
FROM
節に示すことはできない。 この制約は
4.0.14 でなくなった。
AUTO_INCREMENT
カラムは通常どおり機能する。
C プログラムでは、C API 関数
mysql_info()
を使用してクエリに関する情報を取得できる。
See 項6.4.3. 「INSERT
構文」。
バイナリログを使用して元のテーブルを確実に再作成できるようにするため、MySQL
では、INSERT ... SELECT
実行中の同時挿入は行えない。
以前のレコードを上書きするには、INSERT
の代わりに REPLACE
を使用します。以前のレコードの値と重複するユニークキー値を持つ新しいレコードの処理に関して、REPLACE
は INSERT IGNORE
に対立する働きをします。つまり、新しいレコードが廃棄されるのではなく、新しいレコードによって以前のレコードが置き換えられます。
INSERT DELAYED ...
INSERT
の完了を待てないクライアントがある場合、MySQL
固有のオプションである DELAYED
を指定した INSERT
ステートメントが非常に役立ちます。このようなクライアントの問題は、MySQL
を使用してログを記録する一方で、完了までに時間がかかる
SELECT
や UPDATE
ステートメントを定期的に実行している場合によく起こります。DELAYED
は、MySQL バージョン 3.22.15
で導入された、SQL-92 に対する MySQL
の拡張です。
INSERT DELAYED
は、ISAM
および
MyISAM
テーブルに対してのみ作用します。注意:
MyISAM
テーブルでは、データファイルの中央に空きブロックがない場合、同時
SELECT
と同時 INSERT
が可能なため、MyISAM
テーブルで
INSERT DELAYED
を使用する必要はほとんどありません。 See
項7.1. 「MyISAM
テーブル」。
INSERT DELAYED
を使用すると、クライアントは直ちに処理の続行を許可されます。そして、テーブルが別のスレッドによって使用されていなければ、レコードが挿入されます。
INSERT DELAYED
のもう 1
つの主な利点は、多くのクライアントによる挿入が
1 つにまとめられて、1
ブロックに書き込まれることです。この場合、数多くの挿入を個別に行うより、処理速度がはるかに速くなります。
注意:
現在のところ、キューに入れられたレコードは、テーブルに挿入されるまでは単にメモリに格納されているに過ぎません。つまり、mysqld
を kill -9
によって強制終了した場合や、mysqld
が予期しない状況で突然終了した場合、ディスクに書き込まれていないキューの中のレコードはすべて消失します。
以下に、INSERT
または
REPLACE
ステートメントで
DELAYED
オプションを指定した場合の処理について詳しく説明します。この説明中、``スレッド''
は INSERT DELAYED
コマンドを受け取ったスレッドを指し、``ハンドラ''
は個々のテーブルの INSERT DELAYED
ステートをすべて処理するスレッドを指します。
スレッドがいずれかのテーブルに対する
DELAYED
ステートメントを実行すると、そのテーブルのすべての
DELAYED
ステートメントを処理するハンドラスレッドが作成される(このようなハンドラがすでに存在しない場合)。
スレッドは、ハンドラが
DELAYED
ロックをすでに取得しているかチェックし、まだの場合はロックを取得するようハンドラに指示する。DELAYED
ロックは、他のスレッドがそのテーブルに対する
READ
または WRITE
ロックを持っている場合でも取得できる。ただし、その場合ハンドラは、必ず最新のテーブル構造が得られるよう、すべての
ALTER TABLE
ロックまたは
FLUSH TABLES
が完了するまで待機する。
スレッドは INSERT
ステートメントを実行する。ただし、この場合、スレッドはレコードをテーブルに書き込む代わりに、ハンドラスレッドが管理するキューに最後のレコードのコピーを入れる。構文エラーがある場合はスレッドによって検出され、クライアントプログラムに報告される。
クライアントは重複の数や結果のレコードの
AUTO_INCREMENT
値はいずれも報告できない。INSERT
は挿入処理が完了する前に戻るため、クライアントはこれらの情報をサーバから取得できない。C
API
を使用している場合、同じ理由で、mysql_info()
関数でも、意味のある情報は何も返されない。
バイナリログは、レコードがテーブルに挿入されると、ハンドラスレッドによって更新される。複数のレコードの挿入時では、バイナリログは最初のレコードが挿入された時点で更新される。
各 delayed_insert_limit
レコードが書き込まれると、そのつど、ハンドラはまだ保留中になっている
SELECT
ステートメントがないかチェックする。ある場合、ハンドラは処理を続行する前に保留中のステートメントの実行を許可する。
ハンドラのキューにレコードが何もなくなると、テーブルのロックが解除される。delayed_insert_timeout
に指定された秒数が経過する前に、新しい
INSERT DELAYED
コマンドが渡されないと、ハンドラは終了する。
delayed_queue_size
に指定された数を超えるレコードが特定のハンドラキューにすでに保留になっていると、INSERT
DELAYED
を要求しているスレッドはキューに空きスペースができるまで待機する。これは、mysqld
サーバで遅延メモリキューのメモリをすべて使ってしまわないようにするためである。
ハンドラスレッドは MySQL プロセスリストの
Command
カラムに
delayed_insert
として表示される。FLUSH TABLES
コマンドを実行するか、または KILL
thread_id
を使用して強制終了すると、ハンドラスレッドは強制終了される。しかし、この場合ハンドラスレッドは、キュー内のすべてのレコードをテーブルに格納してから終了する。この間、ハンドラスレッドは別のスレッドからの新しい
INSERT
コマンドをまったく受け入れない。この後に
INSERT DELAYED
コマンドを実行すると、新しいハンドラスレッドが作成される。
注意:これは、すでに実行されている
INSERT DELAYED
が存在する場合、通常の
INSERT
コマンドより
INSERT DELAYED
コマンドの方が優先されることを意味する。他の更新コマンドは、INSERT
DELAYED
キューが空になるか、誰かがハンドラスレッドを強制終了するか(KILL
thread_id
を使用して)、または誰かが FLUSH
TABLES
を実行するまで待機しなければならない。
以下のステータス変数では、INSERT
DELAYED
コマンドの情報が提供される。
変数 | 意味 |
Delayed_insert_threads | ハンドラスレッドの数 |
Delayed_writes | INSERT DELAYED で書き込まれたレコード数 |
Not_flushed_delayed_rows | 書き込み待ちのレコード数 |
これらの変数を表示するには、SHOW
STATUS
ステートメントを発行するか、または
mysqladmin extended-status
コマンドを実行する。
注意:
対象のテーブルが使用中でない場合、INSERT
DELAYED
は通常の INSERT
より遅くなります。また、INSERT
DELAYED
を使用する各テーブルに対応するスレッドを個別に処理するためにサーバで追加のオーバーヘッドが発生します。そのため、INSERT
DELAYED
はどうしても使う必要があるときのみ使用してください。
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
節は次のように機能します。
MySQL 4.0.13
より前のバージョンでは、LIMIT
による制限は影響を受けたレコードに基づいて適用される。
WHERE
節の指定にマッチするレコードが、row_count
に指定された数だけ変更されると、ステートメントは直ちに停止する。
4.0.13 以降では、LIMIT
による制限はマッチしたレコードに基づいて適用される。WHERE
節の指定にマッチするレコードが、row_count
に指定された数だけ検出されると、それらのレコードが実際に変更されたかどうかにかからわず、ステートメントは直ちに終了する。
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 BY
と
LIMIT
はいずれも使用できません。
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
節なしの DELETE
は
TRUNCATE
と同じように動作します。See
項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
という語が指定されていると、削除時にストレージエンジンでインデックスのリーフをマージしません。そのため、一部の削除操作では、処理が迅速化されます。
削除操作の速度は、項5.2.12. 「DELETE
クエリの速度」
で説明している要因にも影響されます。
オプション IGNORE
が指定されていると、MySQL
はレコードの削除中にすべてのエラーを無視します。解析段階で発生したエラーは通常の方法で処理されます。このオプションの使用によって無視されたエラーは警告として返されます。このオプションはバージョン
4.1.1 で導入されました。
MyISAM
テーブルの場合、削除されたレコードはリンクされたリストに維持され、元のレコード位置が後続の
INSERT
操作で再利用されます。使用されていないスペースを取り戻してファイルのサイズを削減するには、OPTIMIZE
TABLE
ステートメントまたは
myisamchk
ユーティリティを使用してテーブルを再編成します。
この場合、OPTIMIZE TABLE
の方が簡単ですが、myisamchk
の方が処理が迅速です。項4.6.1. 「OPTIMIZE TABLE
構文」
および 項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
これらの例では、テーブル t1
と
t2
内の一致するレコードだけが削除されます。
上の例ではカンマ演算子を使用した内部結合を示していますが、複数テーブルの
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 BY
と LIMIT
はいずれも使用できません。
TRUNCATE TABLE table_name
3.23 では、TRUNCATE TABLE
は
COMMIT; DELETE FROM table_name
にマップされる。 See 項6.4.5. 「DELETE
構文」。
TRUNCATE TABLE
は次の点で
DELETE FROM ...
と異なります。
切り捨て操作では、テーブルが破棄され、再作成される。この操作は、レコードを 1 つずつ削除するよりはるかに迅速に処理される。
切り捨て操作はトランザクションセーフではない。アクティブなトランザクションやアクティブなテーブルのロックがあると、エラーになる。
削除されたレコード数は返されない。
テーブル定義ファイル
table_name.frm
が有効である限り、データやインデックスのファイルが破損しても、この方法でテーブルを再作成できる。
TRUNCATE TABLE
は Oracle の SQL
拡張です。 このステートメントは MySQL 3.23.28
で追加されました。ただし、3.23.28 〜 3.23.32
では、キーワード TABLE
を省略する必要があります。
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,...
REPLACE
は INSERT
とほぼ同じように動作しますが、唯一異なる点として、UNIQUE
インデックスまたは PRIMARY KEY
に関して新しいレコードと同じ値がテーブル内の以前のレコードに含まれていると、以前のレコードが削除されてから新しいレコードが挿入されます。
See 項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
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
権限が必要になります。
MySQL 3.23.49 と MySQL 4.0.2(Windows では
4.0.13)以降では、LOCAL
はサーバとサーバクライアントの両方でこれが有効として設定されている場合にのみ機能します。たとえば、--local-infile=0
を指定して mysqld
を起動した場合、LOCAL
は機能しません。 See
項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 項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 項4.5.6. 「myisamchk
を使用したテーブルの保守とクラッシュのリカバリ」。
LOAD DATA INFILE
は SELECT ... INTO
OUTFILE
の逆です。 See
項6.4.1. 「SELECT
構文」。
テーブルからファイルにデータを書き込むには、SELECT
... INTO OUTFILE
を使用します。
ファイルを再びテーブルに読み取るには、LOAD
DATA INFILE
を使用します。
FIELDS
節と LINES
節の構文は、どちらのコマンドでも同じです。どちらの節もオプションとして指定できますが、これらの節を両方とも指定する場合は、FIELDS
を LINES
より前に指定する必要があります。
FIELDS
節を指定する場合は、その節の従属節(TERMINATED
BY
、[OPTIONALLY] ENCLOSED
BY
、ESCAPED 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
は入力データの読み取り時に次のように動作します。
改行文字では、行の境界を探す。
LINES STARTING BY prefix
が指定されている場合、プリフィックスが検出されるまで読み取り、プリフィックスの後ろにある文字から再び読み取りを開始する。行にプリフィックスが含まれていない場合は、その行をスキップする。
タブ文字では、行をフィールドに区切る。
フィールドはどの引用文字にも囲まれていないとみなす。
‘\
’
に続くタブ、改行、‘\
’
の各文字は、フィールド値の一部を成すリテラル文字として解釈する。
逆に、デフォルトの 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 OUTFILE
と LOAD
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 BY
と FIELDS ESCAPED
BY
の値は単一の文字でなければなりません。FIELDS
TERMINATED BY
と LINES 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 [OPTIONALLY] ENCLOSED BY
指定文字
FIELDS TERMINATED BY
と LINES
TERMINATED BY
に指定された値の最初の文字
ASCII
0
(エスケープ文字に続いて実際に記述されるのは、ゼロ値のバイトではなく
ASCII '0'
)
FIELDS ESCAPED BY
の指定が空の場合、どの文字もエスケープ処理されません。
データのフィールド値に上記の文字が含まれている場合は特に、エスケープ文字として空文字は指定すべきではありません。
入力では、FIELDS ESCAPED BY
に空以外の文字が指定されている場合、その文字は除去され、それに続く文字がフィールド値の一部として通常の文字と同じように解釈されます。ただし、‘0
’
または ‘N
’
がエスケープされている場合(たとえば、エスケープ文字が
‘\
’ の場合の
\0
または
\N
)は例外です。これらの文字列は
ASCII 0
(ゼロ値のバイト)および
NULL
として解釈されます。下記の
NULL
の処理に関する規則を参照してください。
‘\
’
を使用したエスケープ構文の詳細については、項6.1.1. 「リテラル:文字列と数値の記述方法」
を参照してください。
場合によっては、次に示すように、フィールドと行の各処理オプションが相互に作用することがあります。
LINES TERMINATED BY
に空の文字列が指定されていて、FIELDS
TERMINATED BY
に空以外の文字列が指定されている場合、行の終端も
FIELDS TERMINATED BY
指定文字列によって示される。
FIELDS TERMINATED BY
と FIELDS
ENCLOSED BY
の値がどちらも空(''
)の場合、固定レコード(区切りなし)の形式が使用される。
固定長レコードの形式では、フィールド間に区切り記号は使用されない(行終端記号は使用可能)。代わりに、カラムの
``表示''
幅に基づいてカラム値が読み書きされる。たとえば、カラムが
INT(7)
として宣言されている場合、そのカラムの値は
7
文字のフィールドを使用して書き込まれる。人力時には、そのカラムの値は、7
文字を読み取ることによって取得される。
この場合も、各行の分離には、LINES
TERMINATED BY
が使用される。1
行にすべてのフィールドが含まれていない場合、残りのフィールドにはそれぞれのデフォルト値が設定される。行終端記号がない場合は、終端記号を
''
として指定するようにする。この場合、テキストファイルに各レコードのすべてのフィールドが含まれていなければならない。
固定長レコード形式は、NULL
値の処理にも影響します。下記を参照。
注意:
マルチバイト文字のキャラクタセットを使用している場合、固定サイズ形式は機能しない。
NULL
値の処理は、使用されている
FIELDS
オプションと
LINES
オプションによって異なります。
FIELDS
と LINES
の値がデフォルトの場合、出力では
NULL
が \N
として書き込まれ、入力では
\N
が NULL
として読み取られる(ESCAPED BY
指定文字が ‘\
’
の場合)。
FIELDS ENCLOSED BY
に空以外の文字が指定されている場合、リテラルの
NULL
を値として持つフィールドは
NULL
値として読み取られる(これは、FIELDS
ENCLOSED BY
指定文字で囲まれた語
NULL
が、文字列
'NULL'
として読み取られるのと異なる)。
FIELDS ESCAPED BY
の指定が空の場合、NULL
は
NULL
という語として書き込まれる。
固定長レコード形式(FIELDS TERMINATED
BY
と FIELDS ENCLOSED BY
の両方の指定が空の場合)では、NULL
は空の文字列として書き込まれる。注意:
それによって、ファイルへの書き込み時に、テーブル内の
NULL
値と空の文字列の両方が空の文字列として書き込まれるため、それらを区別できなくなる。ファイルを再び読み取るときにこれらを区別できるようにする必要がある場合は、固定レコード形式は使用しないようにする。
次に示すケースは LOAD DATA INFILE
でサポートしていません。
固定長サイズのレコード(FIELDS
TERMINATED BY
と FIELDS ENCLOSED
BY
の指定がどちらも空)と
BLOB
または TEXT
型のカラム。
1
つの区切り記号が別の区切り文字とまったく同じか、別の区切り記号の先頭の部分と同じである場合、LOAD
DATA INFILE
は入力を正しく解釈できない。たとえば、次の
FIELDS
節では問題が発生する。
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
FIELDS ESCAPED BY
の指定が空の場合、FIELDS ENCLOSED
BY
または LINES TERMINATED
BY
の指定文字に続いて FIELDS
TERMINATED BY
指定値があると、LOAD DATA INFILE
はフィールドまたは行の読み取りを誤って早く停止する。
これは、フィールドまたは行の値の終端を
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 で認識できません。
レコードに含まれているフィールドの数が足りない場合、入力フィールドが欠落しているカラムにはデフォルト値が設定されます。デフォルト値の割り当てについては、項6.5.3. 「CREATE TABLE
構文」
で説明しています。
空のフィールド値はフィールド値が欠落している場合とは異なる解釈をされます。
文字列型のカラムの場合は、値として空の文字列が設定される。
数値型のカラムの場合は、値として
0
が設定される。
日付と時刻型のカラムの場合は、値として、その型に対応する ``ゼロ'' 値が設定される。 See 項6.2.2. 「日付と時刻型」。
注意: これらは、INSERT
や
UPDATE
ステートメントで文字列型、数値型、日付または時刻型のカラムに空白の文字列を明示的に割り当てた場合と同じ値です。
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
項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 項4.6.8.9. 「SHOW WARNINGS | ERRORS
」。
INSERT
と LOAD DATA
INFILE
の効率性の比較や、LOAD DATA
INFILE
の迅速化の詳細については、See
項5.2.10. 「INSERT
クエリの速度」。
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_a
、col_b
、col_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 KEY
の
HANDLER
インタフェースを使用している場合は、HANDLER
tbl READ `PRIMARY` > (...)
のように、キーワード PRIMARY
をバッククォート記号で必ず囲みます。
HANDLER
は、やや低レベルのステートメントです。たとえば、整合性は確保されません。つまり、HANDLER
... OPEN
はテーブルのスナップショットを取るものではなく、テーブルのロックも行いません。そのため、HANDLER
... OPEN
の発行後に、テーブルデータが変更される(そのスレッドまたは他のスレッドによって)可能性があります。このような変更は
HANDLER ... NEXT
スキャンや
HANDLER ... PREV
スキャンでは部分的にしか示されないことがあります。
通常の SQL の代わりにこのインタフェースを使用する理由は、次のとおりです。
次の理由で、SELECT
より処理が迅速。
HANDLER OPEN
では、指定したストレージエンジンがスレッドに割り当てられる。
実行される解析が少ない。
オプティマイザやクエリチェックのオーバヘッドがない。
2 つのハンドラ要求間で、使用テーブルをロックする必要がない。
ハンドラインタフェースでは、整合性のあるデータの提供は重要とされていないため(たとえば、ダーティリードが可能)、SQL によって通常許可されない最適化をストレージエンジンで実行することができる。
ISAM のような MySQL インタフェースを使用するアプリケーションの移植をはるかに容易に実行できる。
SQL では難しい(場合によっては不可能な)方法で、データベースをスキャンできる。データベースの対話式ユーザインタフェースを提供するアプリケーションを処理する場合には、データを参照する方法としてハンドラインタフェースを使用したほうがより自然である。
CREATE DATABASE [IF NOT EXISTS] db_name
CREATE DATABASE
では、指定した名前のデータベースが作成されます。
使用可能なデータベース名の規則は、項6.1.2. 「データベース名、テーブル名、インデックス名、カラム名、エイリアス名」
で説明しています。IF NOT EXISTS
を指定していないときに、データベースが既に存在していると、エラーが発生します。
MySQL
では、データベースは、対応するファイルをその内部に含むディレクトリとして実装されます。作成当初のデータベースにはテーブルは何もないため、CREATE
DATABASE
ステートメントの実行では、MySQL
データディレクトリの下にディレクトリが作成されるだけです。
データベースの作成は mysqladmin
でも可能です。 See
項4.9. 「MySQL クライアントサイドのスクリプトとユーティリティ」。
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
項4.9. 「MySQL クライアントサイドのスクリプトとユーティリティ」。
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
では、指定した名前のテーブルが作成されます。
使用可能なテーブル名の規則は、項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 以降では、属性
SERIAL
を BIGINT 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
DIRECTORY
や INDEX DIRECTORY
のテーブルオプションはいずれもコピーされません。
データベースディレクトリ内の一部のファイルには、各テーブルの
tbl_name
が反映されます。MyISAM
型のテーブルの場合、次のようになります。
ファイル | 用途 |
tbl_name.frm | テーブル形式(定義)ファイル |
tbl_name.MYD | データファイル |
tbl_name.MYI | インデックスファイル |
さまざまなカラム型の特性の詳細については、項6.2. 「カラム型」 を参照してください。
NULL
も NOT NULL
も指定されていない場合、カラムは
NULL
が指定されているときと同じように処理される。
整数型カラムは追加属性
AUTO_INCREMENT
を持つことができる。 インデックス付きの
AUTO_INCREMENT
カラムに
NULL
(推奨)または
0
を挿入すると、そのカラムには連続値の次の値が設定される。
通常、これは value+1
になる(value
はテーブルに現在格納されているそのカラムの最大値)。
AUTO_INCREMENT
は 1
から開始される。 See
項11.1.3.32. 「mysql_insert_id()
」。
MySQL 4.1.1 以降では、--sql-mode
サーバオプションまたは
sql_mode
サーバ変数に対して
NO_AUTO_VALUE_ON_ZERO
フラグを指定することによって、新しい連続値を生成する代わりに、AUTO_INCREMENT
カラムに 0
を 0
として格納することができる。 See
項4.1.1. 「mysqld
コマンドラインオプション」。
AUTO_INCREMENT
カラムの最大値が入ったレコードを削除した場合、その値は
ISAM
テーブルや
BDB
テーブルでは再利用されるが、MyISAM
テーブルや InnoDB
テーブルでは再利用されない。DELETE
FROM table_name
(WHERE
節なし)を AUTOCOMMIT
モードで実行してテーブル内のすべてのレコードを削除した場合、InnoDB
を除くすべてのテーブル型で、連続値が初めから開始される。
See 項7.5.12.5. 「InnoDB での AUTO_INCREMENT
カラムの仕組み」。
注意:
AUTO_INCREMENT
カラムはテーブルごとに 1
つだけ存在できる。このカラムにはインデックスを付ける必要があり、また
DEFAULT
値は設定できない。 MySQL
バージョン 3.23
では、AUTO_INCREMENT
カラムは、正の値だけを持つ場合にのみ正しく機能する。負の数値が挿入されると、その値はきわめて大きな正数としてみなされる。
これは、数値が正の数から負の数に
``折り返す''
ときに発生する精度の問題を回避するためと、0
が入った AUTO_INCREMENT
カラムが誤って取得されないようにするためである。
MyISAM
テーブルと
BDB
テーブルでは、複合インデックスで
AUTO_INCREMENT
セカンダリカラムを指定できる。 See
項3.6.9. 「AUTO_INCREMENT
の使用」。
MySQL と一部の ODBC
アプリケーションとの互換性を確保するため、最後に挿入されたレコードの
AUTO_INCREMENT
値を次のクエリで検出することができる。
SELECT * FROM tbl_name WHERE auto_col IS NULL
TIMESTAMP
型カラムでは、他のカラム型とは異なる方法で
NULL
値が処理される。TIMESTAMP
型カラムには、NULL
は格納できない。カラムに NULL
を挿入すると、カラムの値として現在の日時が設定される。TIMESTAMP
型のカラムはこのように動作するため、NULL
属性と NOT NULL
属性は通常どおりには適用されず、それらを指定しても無視される。
その一方で、TIMESTAMP
型のカラムを MySQL
クライアントにとって使用しやすくするために、サーバは、(実際には、TIMESTAMP
型カラムには NULL
値は格納されないにもかかわらず)TIMESTAMP
型カラムについて、NULL
値の割り当てが可能(true)と報告する。DESCRIBE
tbl_name
を使用してテーブルに関する記述を取得すると、これを確認できる。
注意: TIMESTAMP
型のカラムに、値として 0
を設定するのは、NULL
を設定するのとは異なる。0
は
TIMESTAMP
型の有効な値である。
DEFAULT
値は定数でなければならず、関数や式を使用することはできない。
DEFAULT
値が指定されていない場合、そのカラムには、次の方法で、MySQL
によって DEFAULT
値が自動的に割り当てられる。
値として NULL
を取れるカラムの場合、デフォルト値は
NULL
になる。
NOT NULL
として宣言されているカラムの場合、デフォルト値はそれぞれのカラム型によって決まる。
AUTO_INCREMENT
属性を持つと宣言されていない数値型カラムの場合、デフォルトは
0
。AUTO_INCREMENT
カラムの場合、デフォルト値は連続値の次の値になる。
TIMESTAMP
型以外の日付と時刻型の場合、デフォルトはその型に対応するゼロ値。テーブル内の最初の
TIMESTAMP
型カラムのデフォルト値は、現在の日時になる。
See 項6.2.2. 「日付と時刻型」。
ENUM
型以外の文字列型の場合、デフォルト値は空の文字列。ENUM
の場合、デフォルト値は最初の列挙値になる。
デフォルト値は定数でなければならない。したがって、日付カラムのデフォルト値として、NOW()
や CURRENT_DATE
などの関数を設定することはできない。
COMMENT
オプションでは、カラムに関するコメントを指定することができる。
コメントは SHOW CREATE TABLE
ステートメントと SHOW FULL
COLUMNS
で表示される。
このオプションは MySQL 4.1
から利用可能(それ以前のバージョンでは、使用は可能だが無視される)。
KEY
は、通常 INDEX
のシノニム。 バージョン 4.1 以降、キー属性
PRIMARY KEY
は単に
KEY
として指定することもできる。この機能は他のデータベースとの互換性を考慮して実装された。
MySQL では、UNIQUE
キーには重複のない値以外は格納できない。
既存のレコードのキーと同じキーを持つ新しいレコードを追加しようとすると、エラーが発生する。
PRIMARY KEY
は、すべてのキーカラムが NOT
NULL
として定義されていなければならないユニーク
KEY
である。NOT
NULL
として明示的に定義されていないと、暗黙的(かつ自動的)に
NOT NULL
に設定される。MySQL
において、このキーは PRIMARY
と呼ばれる。個々のテーブルは PRIMARY
KEY
を 1 つだけ持つことができる。
PRIMARY KEY
がない場合に、何らかのアプリケーションがテーブルの
PRIMARY KEY
を要求すると、MySQL
では、NULL
カラムをまったく持たない最初の
UNIQUE
キーが PRIMARY
KEY
として返される。
複合インデックスを PRIMARY KEY
にすることもできる。しかし、カラムの仕様で
PRIMARY KEY
キー属性を使用して複合インデックスは作成することはできない。そのようにしても、単一のカラムがプライマリとしてマークされるにすぎない。
この場合、別に PRIMARY KEY(index_col_name,
...)
節を使用する必要がある。
UNIQUE
インデックスでは、インデックスのすべての値に重複がない状態でなければならない。ただし、例外として、そのインデックスのカラムの
1 つで NULL
値が格納可能な場合、複数の
NULL
値を格納できる。
この例外は BDB
型のテーブルには適用されない。BDB
型のテーブルには単一の NULL
のみ格納可能。
PRIMARY
キーまたは
UNIQUE
キーが単一のカラムで構成されていて、そのカラム型が整数型の場合、そのキーは
_rowid
として参照することもできる(バージョン
3.23.11 の新機能)。
PRIMARY KEY
でないインデックスに名前を割り当てないと、そのインデックスは
index_col_name
の最初のカラム名と同じ名前が割り当てられ、そのインデックスを一意(ユニーク)なものとするためのオプションのサフィックス(_2
、_3
、...
)が付けられる。テーブルのインデックス名は
SHOW INDEX FROM tbl_name
を使用して確認できる。 See
項4.6.8.1. 「データベース、テーブル、カラム、およびインデックスに関する情報の取得」。
NULL
値を持つことができるカラムに対するインデックスの作成は、MyISAM
、InnoDB
、BDB
の各テーブル型でのみサポートしている。その他のテーブルでは、カラムが
NOT NULL
と宣言されていないとエラーになる。
インデックスの指定で
col_name(length)
構文を使用することによって、CHAR
型または VARCHAR
型カラムの最初から length
に指定した長さのバイトのみを使用するインデックスを作成できる。この方法で、インデックスファイルのサイズをかなり小さくすることができる。
See 項5.4.4. 「カラムインデックス」。
BLOB
型と TEXT
型のカラムのインデックスの作成は、MyISAM
テーブルと(MySQL 4.0.14
以降の)InnoDB
テーブルでのみサポートしている。BLOB
型または TEXT
型のカラムにインデックスを付けるときには、インデックスの長さ(最大
255
バイト)を必ず指定する必要がある。次に例を示す。
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
index_col_name
の指定では、最後に ASC
または
DESC
を付けることができる。
これらのキーワードは、昇順または降順によるインデックス値の格納を指定できるようにする今後の拡張に対応している。現時点では、これらのキーワードは解析されるが無視される。インデックス値は常に昇順で格納される。
TEXT
型または BLOB
型のカラムで ORDER BY
または
GROUP BY
が使用されていると、サーバは、最初の部分の、
max_sort_length
サーバ変数が示す数のバイトのみを使用して値をソートする。
See 項6.2.3.2. 「BLOB
型と TEXT
型」。
MySQL バージョン 3.23.23 以降では、特殊な
FULLTEXT
インデックスも作成できる。これは全文検索に使用される。FULLTEXT
インデックスは、MyISAM
テーブルでのみサポートしている。このインデックスは、CHAR
型、VARCHAR
型、TEXT
型のカラムからのみ作成できる。
インデックスの作成は常にカラム全体に対して行われる。部分的なインデックスの作成は行われない。処理の詳細については、項6.8. 「MySQL 全文検索」
を参照。
MySQL バージョン 3.23.44
以降では、InnoDB
テーブルで外部キー制約のチェックをサポートしている。See
項7.5. 「InnoDB
テーブル」。 注意:
InnoDB
での FOREIGN
KEY
構文は上に示した構文より制限されている。参照テーブルのカラム名は、必ず明示的に指定する必要がある。
InnoDB では、MySQL
3.23.50以降、外部キーに対する ON
DELETE
アクションを、また MySQL 4.0.8
以降では ON UPDATE
アクションをサポートしている。
正確な構文については、このマニュアルの
InnoDB
のセクションを参照。 See
項7.5.5.2. 「FOREIGN KEY
制約」。
他のテーブル型については、MySQL サーバは
CREATE TABLE
コマンドの
FOREIGN
KEY
、CHECK
、REFERENCES
の各構文を解析するが、それ以上の処理は行わない。
See 項1.8.4.5. 「外部キー」。
MyISAM
テーブルと
ISAM
テーブルの場合、各
NULL
カラムは 1
ビット余分に使用して、最も近いバイトに切り上げられる。
バイトでの最大レコード長は次のように計算される。
レコード長 = 1 + (カラム長の合計) + (NULL カラムの数 + delete_flag + 7)/8 + (可変長カラムの数)
静的レコード形式のテーブルでは、delete_flag
は
1。静的テーブルでは、行レコードで、そのレコードが削除されたものであるかを示すフラグ用に
1
ビットが使用される。動的テーブルでは、このフラグは可変長レコードの頭に格納されるため、delete_flag
は 0 になる。
これらの計算は InnoDB
テーブルには適用されない。InnoDB
テーブルでは、NULL
カラムの格納サイズは NOT NULL
カラムと比較して変わらない。
table_options
オプションと
SELECT
オプションは MySQL
バージョン 3.23 以降でのみ実装されている。
テーブル型を指定する TYPE
オプションは次の値を取る。
テーブル型 | 説明 |
BDB または BerkeleyDB | ページのロックを行う、トランザクションセーフテーブル。
See 項7.6. 「BDB または BerkeleyDB テーブル」。 |
HEAP | このテーブルのデータはメモリにしか格納されない。
See 項7.4. 「HEAP テーブル」。 |
ISAM | 元のストレージエンジン。 See 項7.3. 「ISAM テーブル」。 |
InnoDB | 行ロックを行う、トランザクションセーフテーブル。
See 項7.5. 「InnoDB テーブル」。 |
MERGE | 1 つのテーブルとして使用される MyISAM
テーブルの集まり。 See
項7.2. 「MERGE テーブル」。 |
MRG_MyISAM | MERGE のエイリアス。 |
MyISAM | ISAM
に代わる、バイナリの移植が可能な新しいストレージエンジン。
See 項7.1. 「MyISAM テーブル」。 |
See 章 7. MySQL のテーブル型。
テーブル型が指定されているときに、そのテーブル型が使用できない場合、MySQL
では、代わりに MyISAM
が使用される。 たとえば、テーブル定義に
TYPE=BDB
オプションが含まれているときに、BDB
型のテーブルを MySQL
サーバでサポートしていない場合、テーブルは
MyISAM
テーブルとして作成される。そのため、マスタにトランザクションテーブルがありながら、スレーブでは非トランザクションテーブルを作成する(速度を上げるため)といった、レプリケーション設定が可能になる。MySQL
4.1.1
では、指定したテーブル型が受け付けられないと警告が出力される。
その他のテーブルオプションは、テーブルの動作を最適化するために使用される。ほとんどの場合、これらはいずれも指定しなくてよい。 これらのオプションは、特に断りがない限り、すべてのテーブル型に適用される。
オプション | 説明 |
AUTO_INCREMENT | テーブルに設定する次の AUTO_INCREMENT
値(MyISAM
テーブルのみ。InnoDB
テーブルの最初の AUTO_INCREMENT
値を設定するには、1
つ少ない値を持つダミーレコードを挿入し、後からそのダミーレコードを削除する)。 |
AVG_ROW_LENGTH | テーブルのレコードの長さの平均の近似値。可変サイズレコードを持つ大きなテーブル以外では、この値を設定する必要はない。 |
CHECKSUM | すべてのローのチェクサムを MySQL
に維持させるには、この値を 1
に設定する(それにより、テーブルの更新速度はやや遅くなるが、破損したテーブルを見つけやすくなる)(MyISAM
テーブルのみ)。 |
COMMENT | テーブルに関する、60 文字のコメント。 |
MAX_ROWS | テーブルに格納する予定の最大レコード数。 |
MIN_ROWS | テーブルに格納する予定の最小レコード数。 |
PACK_KEYS | インデックスのサイズを小さくするには、この値を 1
に設定する。通常、それにより、更新速度が遅くなるが、読み取りは速くなる(MyISAM
テーブルと ISAM
テーブルのみ)。この値を 0
に設定すると、キーのパックがすべて無効化される。この値を
DEFAULT
に設定すると(MySQL 4.0
の場合)、ストレージエンジンによって、CHAR
型または VARCHAR
型の長いカラムのみがパックされる。 |
PASSWORD | パスワードを使用して .frm
ファイルを暗号化する。標準の MySQL
バージョンでは、このオプションを指定しても何も行われない。 |
DELAY_KEY_WRITE | テーブルが閉じられるまでキーテーブルの更新を遅らせるには、この値を1
に設定する(MyISAM
テーブルのみ)。 |
ROW_FORMAT | レコードの格納方法を定義する。現在、このオプションは、形式として
DYNAMIC と
FIXED をサポートしている
MyISAM
テーブルに対してのみ機能する。 See
項7.1.2. 「MyISAM テーブル形式」。 |
MyISAM
テーブルの使用時には、MySQL
で、MAX_ROWS * AVG_ROW_LENGTH
の積によって、結果のテーブルがどれくらいのサイズになるかの計算が行われる。上記のオプションのどれも指定しないと、テーブルの最大サイズは
4G(使用しているオペレーティングシステムで
2G
のテーブルしかサポートされていないときは
2G)になる。その理由は、単に大きなファイルが必要でない場合に、ポインタのサイズを抑制することによって、インデックスをより小さく、より迅速化することにある。
PACK_KEYS
を指定しないと、デフォルトでは、文字列のパックのみ行われ、数値のパックは行われない。PACK_KEYS=1
と指定すると、数値もパックされる。
バイナリ数値キーのパック時には、MySQL
によってプリフィックスの圧縮が行われる。
つまり、これによって大きな利益を得られるのは、同じ数値が数多く存在する場合に限られる。プリフィックスの圧縮では、前のキーの何バイトが次のキーと同じであるかを示す追加の
1 バイトが各キーで必要になる(注意:
圧縮のパフォーマンスを良くするため、キーの直後に、レコードのポインタが上位バイトから下位バイトの順に格納される)。したがって、連続する
2
つのレコードに同じキーが数多くあるとき、通常、``同じ''
キーの後に続くものはいずれも 2
バイト(レコードのポインタも含めて)しか取らない。それに比べて通常の場合は、後に続くキーで
storage_size_for_key + pointer_size 分(通常 4
バイト)必要になる。その一方、すべてのキーがまったく異なる場合は、NULL
値を持てない各キーで 1
バイト余分に使用される(この場合、パックされたキーの長さは、キーが
NULL
であるかどうかを示すバイトと同じバイトに格納される)。
MySQL 3.23 以降では、CREATE
ステートメントの後に SELECT
を指定すると、SELECT
のすべての要素に対応する新しいフィールドが
MySQL によって作成される。次に例を示す。
mysql>CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
->PRIMARY KEY (a), KEY(b))
->TYPE=MyISAM SELECT b,c FROM test2;
この場合、a、b、c の 3 つのカラムを持つ
MyISAM
テーブルが作成される。
注意: SELECT
ステートメントからのカラムは、テーブルの上に重ねられるのではなく、テーブルの右側に追加される。次に例を示す。
mysql>SELECT * FROM foo;
+---+ | n | +---+ | 1 | +---+ mysql>CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM bar;
+------+---+ | m | n | +------+---+ | NULL | 1 | +------+---+ 1 row in set (0.00 sec)
テーブル foo
の各レコードに対応するレコードが、foo
からの値と新しいカラムのデフォルト値とともに
bar
に挿入される。
CREATE TABLE ... SELECT
では、インデックスの作成は自動では行われない。これは、このコマンドをできるだけ柔軟なものにするためである。作成するテーブルにインデックスが必要な場合は、SELECT
ステートメントの前にインデックスを指定する。
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
テーブルへのデータのコピー時にエラーが発生した場合、データは自動で削除される。
SELECT
の前に
IGNORE
または
REPLACE
を付けることで、ユニークキー値が重複するレコードの処理方法を指定できる。
IGNORE
の場合、新しいレコードのユニークキー値が既存のレコードの値と重複していると、その新しいレコードは破棄される。REPLACE
の場合、新しいレコードによって、同じユニークキー値を持つ既存のレコードが置換される。IGNORE
と REPLACE
のどちらも指定していない場合、ユニークキー値の重複が検出されるとエラーになる。
更新ログやバイナリログを使用して元のテーブルを確実に再作成できるようにするため、MySQL
では CREATE TABLE ... SELECT
実行中の同時挿入は行えない。
RAID_TYPE
オプションでは、大きなファイルをサポートしていないオペレーティングシステムで
MyISAM
データファイル(インデックスファイルではなく)に対する
2G または 4G
の制限を超すことができる。注意:
このオプションは大きなファイルをサポートしているファイルシステムでは推奨されない。
異なる物理ディスク上に RAID
ディレクトリを配置することによって I/O
のボトルネックを迅速化することができる。RAID_TYPE
はあらゆるオペレーティングシステムで機能するが、MySQL
のコンフィギャを --with-raid
として行っておく必要がある。現時点で使用可能な
RAID_TYPE
は
STRIPED
(1
と
RAID0
はこのエイリアス)。
MyISAM
テーブルに対して
RAID_TYPE=STRIPED
と指定すると、データベースディレクトリに、00、01、02
という RAID_CHUNKS
サブディレクトリが MyISAM
によって作成される。これらのディレクトリのそれぞれで、table_name.MYD
が MyISAM
によって作成される。データファイルへのデータの書き込み時、RAID
ハンドラによって、最初の
RAID_CHUNKSIZE
*1024
バイトが最初のファイルにマップされ、次の
RAID_CHUNKSIZE
*1024
バイトが次のファイルにマップされる(以下同様)。
UNION
は、同一テーブルのコレクションを 1
つのものとして使用する場合に指定する。これは、MERGE
テーブルに対してのみ機能する。 See
項7.2. 「MERGE
テーブル」。
現在のところ、MERGE
テーブルにマップするテーブルに対する
SELECT
、UPDATE
、DELETE
の各権限が必要になる。
マップ対象のテーブルはいずれも
MERGE
テーブルと同じデータベースに存在しなければならない。
MERGE
テーブルにデータを挿入するには、レコードの挿入先とするテーブルを
INSERT_METHOD
で指定する必要がある。
INSERT_METHOD
は
MERGE
テーブルのみに使用できるオプションである。See
項7.2. 「MERGE
テーブル」。このオプションは MySQL
4.0.0 で導入された。
作成されたテーブルでは、最初に
PRIMARY
キーが置かれ、続いてすべての
UNIQUE
キー、通常キーの順に配置される。そのため、MySQL
オプティマイザで使用するキーを優先させることができ、また重複する
UNIQUE
キーをより迅速に検出できる。
DATA DIRECTORY='directory'
または
INDEX DIRECTORY='directory'
を使用することによって、ストレージエンジンのデータファイルとインデックスファイルの格納場所を指定できる。注意:
この directory
には、対象のディレクトリのフルパス(相対パスではなく)を指定する。
これは、MySQL
4.0
において、--skip-symlink
オプションは指定しないときの
MyISAM
テーブルに対してのみ機能する。 See
項5.6.1.2. 「Unix 上のテーブルに対するシンボリックリンクの使用」。
場合によっては、CREATE TABLE
ステートメントで指定されているカラムの型、属性が、MySQL
によって暗黙的に変更されることがあります(このような変更は
ALTER TABLE
でも発生する場合があります)。
長さが 4 文字に満たない
VARCHAR
型のカラムは
CHAR
型に変更される。
テーブルのいずれかのカラムが可変長である場合は、結果的にそのレコード全体が可変長になる。したがって、テーブルに可変長のカラム(VARCHAR
、TEXT
、BLOB
)が含まれている場合、長さが
3 文字を超す CHAR
型のカラムはいずれも VARCHAR
型カラムに変更される。これはカラムの使用方法には影響しない。MySQL
では、VARCHAR
型は単に文字を格納するもう 1
つの手段として使用されている。MySQL
でこの変換が実行される理由は、スペースを節約し、テーブル処理を迅速化するためである。
See 章 7. MySQL のテーブル型。
バージョン 4.1.0 以降では、255
文字を超える長さを持つ CHAR
型または VARCHAR
型のフィールドはいずれも
TEXT
型に変換される。
これは互換性を考慮した機能。
TIMESTAMP
型の表示サイズは 2
〜 14 の範囲の偶数でなければならない。
表示サイズとして14 を超す数値や 0
を指定すると、サイズは強制的に 14
に設定される。1 〜 13
の範囲の奇数値を指定すると、サイズは強制的に
1 つ上の偶数に設定される。
TIMESTAMP
型のカラムにはリテラルの
NULL
は格納できない。このカラムに
NULL
を挿入すると、値として現在の日時が設定される。TIMESTAMP
型のカラムはこのように動作するため、NULL
属性と NOT NULL
属性は通常どおりには適用されず、それらを指定しても無視される。DESCRIBE
tbl_name
では、TIMESTAMP
型のカラムは常に NULL
値の割り当てが可能と報告される。
MySQL では、他の SQL データベースベンダが使用している一部のカラム型が MySQL のカラム型にマップされる。 See 項6.2.5. 「他のデータベースエンジンのカラム型の使用」。
指定した以外のカラム型が MySQL
によって使用されたかどうか確認するには、テーブルの作成または変更後に、DESCRIBE
tbl_name
ステートメントを発行します。
myisampack
を使用してテーブルを圧縮すると、特定の他のカラム型の変更が発生する場合があります。
See 項7.1.2.3. 「圧縮テーブルの特性」。
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 項6.5.3. 「CREATE TABLE
構文」。
ALTER TABLE
を使用してカラムの仕様を変更したにもかかわらず、カラムが変更されていないと
DESCRIBE tbl_name
で示された場合は、項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
を使用するためには、対象のテーブルに対する
ALTER
、INSERT
、CREATE
の各権限が必要。
IGNORE
は SQL-92 に対する MySQL
の拡張。 IGNORE
では、重複するユニークキーが新しいテーブルに存在する場合の
ALTER TABLE
の動作が制御される。 IGNORE
を指定しない場合は、コピー処理が中断され、ロールバックされる。
IGNORE
を指定すると、重複するユニークキーを持つレコードがある場合、最初のレコードのみが使用され、その他のレコードが削除される。
1 つの ALTER TABLE
ステートメントで、複数の
ADD
、ALTER
、DROP
、CHANGE
節を発行できる。これは SQL-92 に対する MySQL
の拡張。SQL-92 では、1 つの ALTER
TABLE
ステートメントでこれらのいずれか 1
つの節しか使用できない。
CHANGE col_name
, DROP
col_name
と DROP INDEX
は
SQL-92 に対する MySQL の拡張。
MODIFY
は ALTER TABLE
に対する Oracle の拡張。
オプションの語 COLUMN
は純粋なノイズワードであり、省略可能。
その他のオプションを指定しないで
ALTER TABLE tbl_name RENAME TO new_name
を使用すると、単にテーブル
tbl_name
に対応するファイルの名前が MySQL
によって変更される。テンポラリテーブルを作成する必要はない。
See 項6.5.5. 「RENAME TABLE
構文」。
create_definition
節では、ADD
および
CHANGE
用に CREATE
TABLE
と同じ構文が使用される。注意:
この構文には、カラム型だけでなく、カラム名が含まれる。
See 項6.5.3. 「CREATE TABLE
構文」。
カラム名の変更には、CHANGE old_col_name
create_definition
節を使用できる。この変更を行うには、元のカラム名と新しいカラム名を指定し、さらに現在のこのカラムの型を指定する。たとえば、INTEGER
型のカラム a
の名前を
b
に変更するには、次のようにする。
mysql> ALTER TABLE t1 CHANGE a b INTEGER;
CHANGE
構文では、カラムの名前ではなく型を変更する場合にも、元のカラム名と新しいカラム名の両方を(たとえ同じであっても)指定する必要がある。
次に例を示す。
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
ただし、MySQL バージョン 3.22.16a
以降では、MODIFY
を使用することで、カラムの名前を変更することなく、カラムの型変更を実行できる。
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
カラムの一部に関するインデックスがある場合(たとえば、VARCHAR
型カラムの最初の 10
文字のインデックスがある場合など)、CHANGE
または MODIFY
を使用してそのカラムを短縮するときには、カラムの長さを、インデックスが作成されている文字の数より短くすることはできない。
CHANGE
または
MODIFY
を使用してカラムの型を変更する際には、MySQL
によって、新しい型へのデータの変換ができる限り実行される。
MySQL バージョン 3.22
以降では、FIRST
または
ADD ... AFTER col_name
を使用して、テーブルレコード内の特定の位置にカラムを追加することができる。デフォルトでは、レコードの最後にカラムが追加される。
MySQL バージョン 4.0.1
以降では、CHANGE
や
MODIFY
でも、FIRST
および AFTER
キーワードを使用できる。
ALTER COLUMN
では、カラムの新しいデフォルト値を指定するか、または以前のデフォルト値を削除できる。
以前のデフォルトを削除した場合、そのカラムで
NULL
の格納が可能なら、新しいデフォルト値は
NULL
になる。そのカラムで
NULL
の格納が不可能な場合は、項6.5.3. 「CREATE TABLE
構文」
で説明しているデフォルト値が MySQL
によって割り当てられる。
DROP INDEX
では、インデックスが削除される。これは、SQL-92
に対する MySQL の拡張。See
項6.5.8. 「DROP INDEX
構文」。
カラムがテーブルから破棄された場合、そのカラムは構成要素となっているすべてのインデックスからも削除される。インデックスを構成するすべてのカラムが破棄された場合は、そのインデックス自体も破棄される。
テーブルにカラムが 1
つしか含まれない場合、そのカラムを破棄することはできない。
テーブルの削除を実行することが目的である場合は、カラムを破棄するのではなく、DROP
TABLE
を実行する。
DROP PRIMARY KEY
では、プライマリインデックスが破棄される。プライマリインデックスが存在しない場合は、そのテーブルの最初の
UNIQUE
インデックスが破棄される(明示的に指定された
PRIMARY KEY
がまったく存在しない場合は、MySQL
によって、最初の UNIQUE
キーが
PRIMARY KEY
としてマークされる)。
テーブルに UNIQUE INDEX
または
PRIMARY KEY
を追加すると、その値は非
UNIQUE
なあらゆるインデックスの前に格納される。これは、MySQL
で重複キーをできる限り迅速に検出できるようにするためである。
ORDER BY
では、レコードを特定の順序で並べた新しいテーブルを作成できる。注意:
挿入や削除を行った後は、テーブル内の元の順序は維持されない。場合によっては、後でテーブル内の順序付けの基準とするカラムに基づいて、テーブル内の順序を設定しておくと、MySQL
でのソートがより容易化されることがある。このオプションは主に、レコードのクエリをたいてい特定の順序で行うことが明らかな場合に役立つ。テーブルを大幅に変更した後にこのオプションを使用することによって、パフォーマンスが良くなる場合がある。
MyISAM
テーブルに対して
ALTER TABLE
を使用すると、非ユニークなインデックスのすべてが別のバッチに作成される(REPAIR
の場合と同様)。
インデックスが数多くある場合は、これによって
ALTER TABLE
の処理がはるかに迅速化される。
MySQL 4.0
以降では、上記の機能を明示的に有効化することができる。
そのためには、ALTER TABLE ... DISABLE
KEYS
によって、MySQL による
MyISAM
テーブルの非ユニークなインデックスの更新を停止する。
その後、ALTER TABLE ... ENABLE KEYS
によって、欠落しているインデックスを再作成する。MySQL
において、この処理は 1
つずつキーを挿入する処理よりはるかに早い特殊アルゴリズムを使用して実行されるため、大量の挿入ではキーを無効化することによって処理が大幅に迅速化される。
C API 関数 mysql_info()
を使用すると、コピーされたレコードの数と、ユニークキー値の重複により削除されたレコードの数(IGNORE
を指定した場合)を確認できる。
... ADD [CONSTRAINT [symbol]] FOREIGN KEY (...)
REFERENCES ... (...)
と ... DROP FOREIGN
KEY ...
をサポートしている InnoDB
型のテーブルを対象としている場合を除いて、FOREIGN
KEY
、CHECK
、REFERENCES
の各節では実際には何も行われない。 See
項7.5.5.2. 「FOREIGN KEY
制約」。
他のテーブル型に関しては、この構文は互換性を確保する目的で提供されている。つまり、他の
SQL
サーバにコードを移植し、参照を含むテーブルを作成するアプリケーションを実行しやすくするためである。
See 項1.8.4. 「MySQL と SQL-92 との違い」。
ALTER TABLE
では、テーブルオプション DATA
DIRECTORY
と INDEX DIRECTORY
は無視される。
CHAR 型、VARCHAR 型、TEXT 型のすべてのカラムを新しいキャラクタセットに変更するには(たとえば、MySQL 4.0.x から 4.1.1 にアップグレードした後などに)、次のようにする。
ALTER TABLE table_name CHARACTER SET character_set_name;
注意: 次のコマンドでは、テーブルの
default character set
しか変更されない。
ALTER TABLE table_name DEFAULT CHARACTER SET character_set_name;
default character set
とは、テーブルに追加する(ALTER TABLE
... ADD column
などで)新しいカラムに対してキャラクタセットを指定しなかった場合に使用されるキャラクタセット。
以下に、ALTER TABLE
に使用例をいくつか示します。まず、次のコマンドでテーブル
t1
を作成するとします。
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
このテーブルの名前を t1
から
t2
に変更するには、次のようにします。
mysql> ALTER TABLE t1 RENAME t2;
カラム a
を INTEGER
から TINYINT NOT NULL
に変更し(名前は変えずに)、さらにカラム
b
を CHAR(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
カラムにはインデックスが必要なためです。また、c
を NOT NULL
として宣言しているのは、インデックス付きカラムは値として
NULL
を取れないためです。
AUTO_INCREMENT
カラムを追加すると、カラム値として連続番号が自動的に挿入されます。最初の連続番号を設定するには、ALTER
TABLE
の前に SET INSERT_ID=value
を実行するか、または
AUTO_INCREMENT=value
テーブルオプションを指定します。 See
項5.5.6. 「SET
構文」。
MyISAM テーブルでは、AUTO_INCREMENT
カラムを変更しない限り、連続番号は影響されません。AUTO_INCREMENT
カラムを破棄した後に別の
AUTO_INCREMENT
カラムを追加すると、再び 1
から採番されます。
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
で追加されました。
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
項4.6.8.9. 「SHOW WARNINGS | ERRORS
」。
RESTRICT
と CASCADE
は、移植を容易化するためのものです。
現在のところ、これらを指定しても何も行われません。
注意: DROP
TABLE
では、現在のアクティブなトランザクションが自動的にコミットされます(4.1
を使用していて、TEMPORARY
キーワードを指定した場合を除く)。
オプション TEMPORARY
は、4.0
では無視されます。4.1
では、このオプションは次のように動作します。
テンポラリテーブルの破棄のみ行う。
実行中のトランザクションは終了されない。
アクセス権のチェックは行われない。
TEMPORARY
は、実際のテーブルが誤って廃棄されないようにするための手段として役立ちます。
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
ステートメントにマップされています。
通常、テーブルのインデックスはすべて、テーブル自体を
CREATE TABLE
で作成するときに一緒に作成します。 See
項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 以降で
MyISAM
、InnoDB
、BDB
のいずれかのテーブル型を使用している場合にのみ可能です。
BLOB
型や TEXT
型のカラムに対するインデックスの追加は、MySQL
バージョン 3.23.2 以降で MyISAM
または BDB
のいずれかのテーブル型を使用している場合か、MySQL
バージョン 4.0.14 以降で InnoDB
テーブル型を使用している場合にのみ可能です。
BLOB
型や TEXT
型カラムのインデックスでは、プリフィックスの長さを必ず指定する必要があります。
index_col_name
の指定では、最後に
ASC
または DESC
を付けることができます。
これらのキーワードは、昇順または降順によるインデックス値の格納を指定できるようにする今後の拡張に対応するものです。現時点では、これらのキーワードは解析されても無視され、インデックス値は常に昇順で格納されます。
MySQL でのインデックスの使用方法の詳細については、項5.4.3. 「MySQL でのインデックスの使用」 を参照してください。
FULLTEXT
インデックスでは、MyISAM
テーブルにおける CHAR
型、VARCHAR
型、TEXT
型のカラムに対してのみ、インデックスを作成することができます。FULLTEXT
インデックスは MySQL バージョン 3.23.23
以降で使用できます。
項6.8. 「MySQL 全文検索」。
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
項6.5.4. 「ALTER TABLE
構文」。
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
との互換性を確保するためのものです。
{DESCRIBE | DESC} tbl_name [col_name | wild]
DESCRIBE
は SHOW COLUMNS
FROM
の簡略形です。
See 項4.6.8.1. 「データベース、テーブル、カラム、およびインデックスに関する情報の取得」。
DESCRIBE
では、テーブルのカラムに関する情報が出力されます。col_name
には、カラム名を指定する他に、SQL
のワイルドカード文字
‘%
’ と
‘_
’
を含む文字列を指定できます。この場合、この文字列に一致する名前を持つカラム名のみが出力されます。文字列を引用符でエスケープする必要はありません。
カラム情報で示されたカラムの型は、そのカラムの
CREATE TABLE
ステートメントで指定したものと異なっている場合があります。これは、カラムの型が
MySQL
によって自動で変更されることがあるためです。
See 項6.5.3.1. 「カラムの暗黙的な変更」。
このステートメントは Oracle との互換性を確保するためのものです。
SHOW
ステートメントでも、同様の情報が出力されます。
See 項4.6.8. 「SHOW
構文」。
デフォルトでは、MySQL は自動コミットモードで稼動します。この場合、テーブルを更新(変更)するステートメントを実行すると、MySQL によって直ちにその更新がディスクに格納されます。
トランザクションセーフテーブル(InnoDB
や
BDB
)を使用している場合は、次のコマンドを使用して
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
の代わりに BEGIN
と BEGIN 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 項4.10.4. 「バイナリログ」。
トランザクションの分離レベルを変更するには、SET
TRANSACTION ISOLATION LEVEL
を使用します。 See
項6.7.6. 「SET TRANSACTION
構文」。
一部のステートメントはロールバックできません。通常、このようなステートメントとして、データベースの作成や破棄を行うステートメントや、テーブルの作成、破棄、変更を行うステートメントなどのデータ定義言語(DDL)ステートメントがあります。
場合によっては、このようなステートメントを組み込まないよう、トランザクションを設計する必要があります。
ロールバックできないステートメントをトランザクションの始めの方で発行したときに、その後別のステートメントでエラーが発生した場合、トランザクションの結果全体を
ROLLBACK
ステートメントでロールバックすることはできません。
次のコマンドでは、トランザクションが(コマンドの実行前に
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
の影響によるものです。
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
を実行すると、現在のトランザクションのセーブポイントがすべて削除されます。
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
では、関連するテーブルに対する
SELECT
、insert
、DELETE
、UPDATE
の各権限が必要です。
LOCK TABLES
を使用する主な理由は、トランザクションをエミュレートしたり、テーブルの更新時に処理を迅速化したりするためです。これについては、詳しく後述します。
あるスレッドがテーブルに対する
READ
ロックを取得すると、そのスレッド(および他のすべてのスレッド)はそのテーブルからの読み取りのみ実行できるようになります。あるスレッドがテーブルに対する
WRITE
ロックを取得すると、ロックを保有しているスレッドだけがそのテーブルからの読み取りやテーブルへの書き込みを実行できるようになります。他のスレッドはブロックされます。
READ LOCAL
と READ
の違いは、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 つのテーブルをロックし、スレッドがすべてのロックを取得するまでロック処理を繰り返す。
このポリシーによって、テーブルのロックでデッドロックの発生が回避されます。ただし、このスキーマに関しては注意すべき点が他にもあります。
MySQL でテーブルに対して LOW_PRIORITY
WRITE
ロックを使用した場合、そのスレッドは
READ
ロックを要求する他のスレッドがなくなるまでの間のみ待機し、READ
を要求する他のスレッドがなくなった時点でロックを取得します。そのスレッドで
WRITE
ロックを取得した後に、ロックテーブルリストの次のテーブルのロックを取得しようと待機しているときには、他のスレッドの方がいずれも
WRITE
ロックが解除されるまで待つことになります。これによってアプリケーションで深刻な問題が発生する場合は、一部のテーブルをトランザクションセーフテーブルに変換することを検討してください。
テーブルのロックを取得しようと待機しているスレッドを、安全な方法で強制終了するには、KILL
を使用します。 See 項4.6.7. 「KILL
構文」。
注意: INSERT DELAYED
で使用しているテーブルは、ロックすべきではありません。なぜなら、この場合、INSERT
が独立したスレッドで実行されるためです。
個々の UPDATE
ステートメントでは、いずれも処理が原子的に行われるため、通常、テーブルをロックする必要はありません。現在実行中の
SQL
ステートメントが、他のスレッドによって妨害されることはまったくありません。しかし、次に示すように、テーブルをロックする必要が生じる場合もいくつかあります。
一連のテーブルに対して多くの操作を実行する場合、使用するテーブルをロックした方が処理がはるかに迅速になる。当然ながら、この場合の短所は、READ
ロックされているテーブルについては、どのスレッドも(ロックを保有しているスレッドも含む)このテーブルを更新できなくなり、WRITE
ロックされているテーブルについては、ロックを保有しているスレッド以外、どのスレッドもこのテーブルを読み取れなくなることである。
LOCK TABLES
の使用時にいくつかの面で処理が迅速になる理由は、MySQL
でキーのキャッシュが UNLOCK
TABLES
が呼び出されるまでフラッシュされないためである(通常、キーのキャッシュは各
SQL
ステートメントの後にフラッシュされる)。それによって、MyISAM
テーブルに対する挿入、更新、削除処理が迅速化される。
トランザクションをサポートしていないストレージエンジンを
MySQL
で使用している場合、SELECT
と
UPDATE
の間に他のスレッドに割り込まれないようにするには、LOCK
TABLES
を使用する必要がある。次の例では、安全に処理を実行するために
LOCK TABLES
を発行する必要がある。
mysql>LOCK TABLES trans READ, customer WRITE;
mysql>SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql>UPDATE customer SET total_value=sum_from_previous_statement
->WHERE customer_id=some_id;
mysql>UNLOCK TABLES;
LOCK TABLES
を発行しないと、SELECT
ステートメントと UPDATE
ステートメントの実行の間に別のスレッドが
trans
テーブルに新しいレコードを挿入してしまう可能性がある。
多くの場合、自身の加算を行う更新(UPDATE
customer SET value=value+new_value
)や
LAST_INSERT_ID()
関数の使用により、LOCK TABLES
の使用を避けることができます。
また、ユーザレベルのロック関数
GET_LOCK()
と
RELEASE_LOCK()
を使用して問題を解決できる場合もあります。これらのロックはサーバのハッシュテーブルに保存され、高速にするため
pthread_mutex_lock()
と
pthread_mutex_unlock()
で実装されます。 See
項6.3.6.2. 「その他の各種関数」。
ロックポリシーの詳細については、項5.3.1. 「MySQL のテーブルロック方法」 を参照してください。
全データベースの全テーブルを読み取りロックでロックするには、FLUSH
TABLES WITH READ LOCK
コマンドを使用します。See
項4.6.4. 「FLUSH
構文」。特定の時点のスナップショットを取ることができる、Veritas
などのファイルシステムを使用している場合には、このコマンドがバックアップを作成するときに非常に役立ちます。
注意: LOCK
TABLES
はトランザクションセーフではありません。アクティブなトランザクションは、テーブルロックの試行前に暗黙的にコミットされます。
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
この構文では、トランザクションの分離レベルが、グローバルなセッション全体または次のトランザクションのどちらかとして設定されます。
デフォルトの動作では、次の(まだ開始されていない)トランザクションの分離レベルが設定されます。このステートメントに
GLOBAL
キーワードを使用すると、それ以降に作成されるすべての新しい接続(既存の接続は対象外)に対してグローバルにデフォルトのトランザクションレベルが設定されます。
これを行うには、SUPER
権限が必要です。SESSION
キーワードを使用すると、現在の接続で実行されるすべての新しいトランザクションに対してデフォルトのトランザクションレベルが設定されます。
InnoDB
トランザクションの各分離レベルについては、項7.5.9.1. 「InnoDB と SET ... TRANSACTION ISOLATION LEVEL ...
」
を参照してください。MySQL 4.0.5 以降、InnoDB
ではこれらの各レベルをサポートしています。デフォルトのレベルは
REPEATABLE READ
です。
mysqld
のデフォルトのグローバル分離レベルは、--transaction-isolation=...
で設定することができます。 See
項4.1.1. 「mysqld
コマンドラインオプション」。
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 TABLE
か
CREATE 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 文字です。この長さは
項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'' とは一致しない。
全文検索は MyISAM
テーブルでのみ可能。
全文検索は UCS-2 では使用できない(しかし、MySQL 4.1.1 以降では、UTF-8 で機能する)。
MATCH()
関数のパラメータはすべて、同じ
FULLTEXT
インデックスの一部を成す同じテーブルのカラムでなければならない(IN
BOOLEAN MODE
で MATCH()
を実行する場合を除く)。
FULLTEXT
インデックスのカラムはすべて同じキャラクタセットを使用していなければならない。
MATCH()
のカラムリストはテーブルの一部の
FULLTEXT
インデックス定義のカラムリストと正確に一致していなければならない(IN
BOOLEAN MODE
で MATCH()
を実行する場合を除く)。
AGAINST()
の引数は定数文字列でなければならない。
残念ながら、ユーザによる調整が可能な全文検索のパラメータは現在のところ少ししかありません。しかし、調整可能なパラメータの追加は、TODO リストにおいて優先度の高い位置にランクされています。MySQL ソースディストリビューション(see 項2.3. 「MySQL ソースディストリビューションのインストール」)がある場合は、全文検索の動作をより詳細に制御できます。
注意: 全文検索は検索の効率を良くするよう入念に調整されています。デフォルトの動作を変更すると、多くの場合、結果的に検索結果が悪くなります。MySQL のソースは、十分な知識がない限り変更しないでください。
以下に説明するフルテキスト変数は、サーバの起動時に設定されていなければなりません。サーバの稼動中にこれらの変数を動的に変更することはできません。
インデックスを作成するワードの最小長は、MySQL
変数 ft_min_word_len
で定義される。 See
項4.6.8.4. 「SHOW VARIABLES
」。 (この変数は MySQL
バージョン 4.0 以降でのみ使用できる)。
デフォルト値は 4 文字。
この値を必要な値に変更して、FULLTEXT
インデックスを再ビルドする。 たとえば、3
文字のワードを検索可能にするには、オプションファイルに以下の行を書き込むことによってこの変数を設定する。
[mysqld] ft_min_word_len=3
その後、サーバを再起動して、FULLTEXT
インデックスを再ビルドする。
ストップワードリストは、ft_stopword_file
変数に指定したファイルからロードすることができる。
See 項4.6.8.4. 「SHOW VARIABLES
」。
ストップワードリストを変更した後、FULLTEXT
インデックスを再ビルドする(この変数は
MySQL バージョン 4.0.10
以降でのみ使用できる)。
50%
のしきい値は、選択されている特定の重み付け設定で決められている。
これを無効にするには、myisam/ftdefs.h
の次の行を変更する。
#define GWS_IN_USE GWS_PROB
次のように変更する。
#define GWS_IN_USE GWS_FREQ
その後、MySQL を再コンパイルする。
この場合、インデックスを再ビルドする必要はない。
注意:
この設定によって、MATCH()
関数で適切な関連性を示す値が得られるようにする
MySQL
の機能が大幅に弱くなる。
実際にこのような一般的な語を検索する必要がある場合は、むしろ、IN
BOOLEAN MODE
を使用して検索を行う方が良い。この場合、50%
のしきい値が考慮されない。
検索エンジンの管理者が、ブール値のフルテキスト検索に使用する演算子を変更したくなることもある。これらの演算子は
ft_boolean_syntax
変数で定義される。 See
項4.6.8.4. 「SHOW VARIABLES
」。
しかし、この変数は読み取り専用であり、値は
myisam/ft_static.c
に設定されている。
FULLTEXT
インデックスの再構築が必要になるフルテキスト関連の変更の場合、MyISAM
テーブルに対してこれを行う最も簡単な方法は、インデックスファイルを再ビルドする次のステートメントを使用することです。
mysql> REPAIR TABLE tbl_name QUICK;
FULLTEXT
インデックスを使用するすべての操作の迅速化。
近接演算子。
"常にインデックスワード" のサポート。これは、"C++"、"AS/400"、"TCP/IP" など、ユーザがワードとして認識させたい任意の文字列である。
MERGE
テーブルでの全文検索のサポート。
UCS-2 のサポート。
ストップワードリストをデータの言語に依存させる。
ステミング(= 語幹の抽出。言うまでもなく、データの言語に依存する抽出)。
ユーザによる提供が可能な汎用 UDF プリパーサ。
モデルのよりいっそうの柔軟化(CREATE/ALTER
TABLE
の FULLTEXT
に調整可能なパラメータをいくつか追加する)。
バージョン 4.0.1 以降、MySQL サーバ
には Query Cache
機能があります。
クエリキャッシュの使用時、このキャッシュには、SELECT
クエリのテキストと、クライアントに送られたその結果が格納されます。
後でまったく同じクエリを受け取ると、サーバはそのクエリの解析と実行をもう一度繰り返す代わりに、クエリキャッシュから結果を取り出します。
注意:クエリキャッシュから古いデータが返されることはありません。データが変更されると、クエリキャッシュの関連するエントリがすべてフラッシュされます。
(一部の)テーブルがそれほど頻繁には変更されず、同じクエリが何度も実行される環境では、クエリキャッシュが非常に役立ちます。 動的コンテンツを大量に持つ多くの Web サーバでは、このような状況が一般的です。
クエリキャッシュのパフォーマンスに関するデータの一部を、以下に示します(これらの結果は、2 GB の RAM、64 MB のクエリキャッシュを搭載する Linux Alpha 2 x 500 MHz での MySQL ベンチマークスィートの実行により生成されたものです):
実行しているクエリがすべて単純なもの(レコードが 1 つしかないテーブルからレコードを 1 つ選択するなど)でありながら互いに異なるために、クエリをキャッシュすることができない場合、クエリキャッシュをアクティブにしておくことによるオーバーヘッドは 13%。 これは最悪の場合のシナリオとみなすことができる。現実には、クエリはこの例よりもはるかに複雑なため、通常オーバーヘッドはかなり低くなる。
レコードが 1 つだけのテーブルでの 1 つのレコードの検索は 238% 迅速化される。 これは、キャッシュに格納されているクエリで想定される迅速化の最小値に近い数値である。
クエリキャッシュのコードを無効にするには、query_cache_size=0
として設定する。
クエリキャッシュコードを無効にすると、目立ったオーバーヘッドはなくなる(クエリキャッシュは、コンフィギャオプション
--without-query-cache
を使用してコードから除外できる)。
クエリは解析前に比較されるため、
SELECT * FROM tbl_name
と
Select * from tbl_name
は、クエリキャッシュで別のクエリとみなされます。完全に一致する(各バイトが)クエリ以外、同一とはみなされません。 また、たとえば、あるクライアントで新しい形式の通信プロトコルを使用している場合や、別のクライアントが使用しているものとは異なるキャラクタセットを使用している場合も、同じものであるはずのクエリが異なるものとして認識されることがあります。
異なるデータベースを使用するクエリや、使用プロトコルのバージョンが異なるクエリ、またデフォルトのキャラクタセットが異なるクエリは、いずれも異なるクエリとして認識され、別々にキャッシュされます。
キャッシュは SELECT SQL_CALC_FOUND_ROWS
...
および SELECT FOUND_ROWS()
...
型のクエリでも機能します。これは、検出されたレコードの数もキャッシュに格納されるためです。
クエリの結果がクエリキャッシュから返された場合、ステータス変数
Com_select
の値は増加しませんが、Qcache_hits
の値は増加します。 See
項6.9.4. 「クエリキャッシュのステータスと保守」。
テーブルが変更されると(INSERT
、UPDATE
、DELETE
、TRUNCATE
、ALTER
、DROP
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 MODE
、SELECT ... INTO OUTFILE
...
、SELECT ... INTO DUMPFILE ...
のいずれかの形式のクエリ、および SELECT
* FROM AUTOINCREMENT_FIELD IS NULL
形式のクエリ(最後に挿入された ID の取り出し
- ODBC
回避策)についても、キャッシュできません。
ただし、FOUND_ROWS()
は、先行するクエリがキャッシュからフェッチされたものであっても正しい値を返します。
クエリでテーブルを何も使用しない、またはテンポラリテーブルを使用する場合や、関連するテーブルのいずれかに対するカラムのアクセス権限をユーザが持っていない場合、クエリはキャッシュされません。
MySQL では、クエリをクエリキャッシュから読み取る前に、関連するすべてのデータベースとテーブルに対する SELECT 権限をユーザが持っているかチェックします。この権限をユーザが持っていない場合、キャッシュに格納されている結果は使用されません。
mysqld
の起動時には、コマンドラインで
mysqld
の少数の MySQL
システム変数がクエリキャッシュにより追加されます。これらのシステム変数はオプション設定ファイルで設定することができます。
query_cache_limit
これより大きい結果はキャッシュしない(デフォルト
1M)。
query_cache_min_res_unit
この変数はバージョン 4.1 以降で利用できる。
クエリの結果(クライアントにも送られるデータ)は結果の取り出し時にクエリキャッシュに格納される。したがって、通常、データは
1
つの大きなまとまりとして処理されるのではない。クエリキャッシュでは、データを格納するブロックが要求に応じて割り当てられる。1
つのブロックがいっぱいになると、新しいブロックが割り当てられる。
メモリ割り当て処理はコストが高い(時間的に)ため、クエリキャッシュでのブロックの割り当ては、query_cache_min_res_unit
に指定された最小サイズで行われる。
クエリが実行されると、最後の結果ブロックは実際のデータサイズに切り捨てられ、使用していないメモリが解放される。
query_cache_min_res_unit
のデフォルト値は 4
KB。ほとんどの場合、これで十分である。
結果が小さいクエリが数多くある場合は、デフォルトのブロックサイズを使用するとメモリがフラグメント化することがある(これは空きブロック(Qcache_free_blocks
)の数が多くなることでわかる。フラングメント化すると、メモリ不足によってキャッシュからクエリが削除される(Qcache_lowmem_prunes
)ことがある)。その場合は、query_cache_min_res_unit
の値を小さくする。
結果が大きいクエリが大半を占める場合は(Qcache_total_blocks
および Qcache_queries_in_cache
を参照)、query_cache_min_res_unit
の値を大きくすることによって、パフォーマンスを良くすることができる。ただし、あまり大きくしすぎないよう注意すること(上記を参照)。
query_cache_size
以前のクエリの結果を格納するために割り当てるメモリ量(バイト単位で指定)。この値を
0
にすると、クエリキャッシュは無効(デフォルト)になる。
query_cache_type
次のいずれかの値(数値のみ)を設定できる。
オプション | 説明 |
0 | (OFF - キャッシュへの格納、結果の取り出しをいずれも行わない) |
1 | (ON。SELECT SQL_NO_CACHE ...
クエリを除くすべての結果をキャッシュする) |
2 | (DEMAND。SELECT SQL_CACHE ...
クエリのみキャッシュする) |
クエリキャッシュの動作は、スレッド(接続)内でデフォルトから変更することができます。構文は次のとおりです。
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 ...
クエリのみキャッシュする。 |
SELECT
クエリでは、クエリキャッシュ関連の次の 2
つのパラメータを指定することができます。
オプション | 説明 |
SQL_CACHE | QUERY_CACHE_TYPE が DEMAND
の場合、クエリをキャッシュ可能にする。
QUERY_CACHE_TYPE が
ON
の場合、これがデフォルト。
QUERY_CACHE_TYPE が
OFF の場合、何もしない。 |
SQL_NO_CACHE | このクエリをキャッシュ不可にする。このクエリをキャッシュに格納しない。 |
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_blocks
と Qcache_free_blocks
によって、クエリキャッシュメモリのフラグメント化が示されることがあります。
FLUSH QUERY CACHE
を実行すると、1
つの(大きな)空きブロックだけが残ります。
注意:各クエリには、最低でも 2 ブロック必要です(クエリテキスト用に 1 ブロック、クエリ結果用に 1 ブロック以上)。また、クエリで使用される各テーブル用にも 1 ブロック必要です。ただし、複数のクエリで同じテーブルを使用している場合は、1 ブロックの割り当てですみます。
クエリのキャッシュサイズは、Qcache_lowmem_prunes
ステータス変数に基づいて調整できます。この値は、新しいクエリを格納できるようメモリを解放するためにキャッシュから削除されたクエリ数を示します。クエリキャッシュでは、使用されたうち最も古い
(LRU
)方針に従って、キャッシュから削除するクエリが決定されます。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.