第6章 MySQL SQL言語リファレンス

目次

6.1. 言語構造
6.1.1. リテラル:文字列と数値の記述方法
6.1.2. データベース名、テーブル名、インデックス名、カラム名、エイリアス名
6.1.3. 名前におけるケース依存
6.1.4. ユーザ変数
6.1.5. システム変数
6.1.6. コメント構文
6.1.7. MySQL での予約語の扱い
6.2. カラム型
6.2.1. 数値型
6.2.2. 日付と時刻型
6.2.3. 文字列型
6.2.4. 正しいカラム型の選択
6.2.5. 他のデータベースエンジンのカラム型の使用
6.2.6. 各カラム型に必要な記憶容量
6.3. SELECT 節と WHERE 節で使用する関数
6.3.1. 各データ型共通の演算子と関数
6.3.2. 文字列関数
6.3.3. 数値関数
6.3.4. 日付と時刻関数
6.3.5. キャスト関数
6.3.6. その他の関数
6.3.7. GROUP BY 節で使用する関数と修飾子
6.4. データの操作: SELECTINSERTUPDATEDELETE
6.4.1. SELECT 構文
6.4.2. サブクエリ構文
6.4.3. INSERT 構文
6.4.4. UPDATE 構文
6.4.5. DELETE 構文
6.4.6. TRUNCATE 構文
6.4.7. REPLACE 構文
6.4.8. LOAD DATA INFILE 構文
6.4.9. HANDLER 構文
6.4.10. DO 構文
6.5. データ定義: CREATEDROPALTER
6.5.1. CREATE DATABASE 構文
6.5.2. DROP DATABASE 構文
6.5.3. CREATE TABLE 構文
6.5.4. ALTER TABLE 構文
6.5.5. RENAME TABLE 構文
6.5.6. DROP TABLE 構文
6.5.7. CREATE INDEX 構文
6.5.8. DROP INDEX 構文
6.6. MySQL 基本ユーザユーティリティコマンド
6.6.1. USE 構文
6.6.2. DESCRIBE 構文(カラムに関する情報の取得)
6.7. MySQL トランザクションコマンドとロックコマンド
6.7.1. START TRANSACTIONCOMMITROLLBACK の各構文
6.7.2. ロールバックできないステートメント
6.7.3. 暗黙的なコミットを引き起こすステートメント
6.7.4. SAVEPOINT および ROLLBACK TO SAVEPOINT 構文
6.7.5. LOCK TABLES および UNLOCK TABLES 構文
6.7.6. SET TRANSACTION 構文
6.8. MySQL 全文検索
6.8.1. 全文検索における制約
6.8.2. MySQL 全文検索の調整
6.8.3. 全文検索に関連する TODO 項目
6.9. MySQL クエリキャッシュ
6.9.1. クエリキャッシュの動作
6.9.2. クエリキャッシュの設定
6.9.3. SELECT でのクエリキャッシュオプション
6.9.4. クエリキャッシュのステータスと保守

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

6.1. 言語構造

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

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

6.1.1.1. 文字列

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

'a string'
"another string"

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

  • \0

    ASCII 0(NUL)文字。

  • \'

    単一引用符(‘'’)。

  • \"

    二重引用符(‘"’)。

  • \b

    バックスペース文字。

  • \n

    改行文字(LF)。

  • \r

    復帰改行文字(CR)。

  • \t

    タブ文字。

  • \z

    ASCII(26)(Control-Z)。この文字をコード化することによって、ASCII(26) が Windows では END-OF-FILE を表すという問題を回避することができる(ASCII(26) では、mysql database < filename を使用する場合に問題が発生する)。

  • \\

    バックスラッシュ(‘\’)文字。

  • \%

    %’ 文字。これは、‘%’ をそのまま使用したときにワイルドカード文字として解釈されてしまうコンテキストで ‘%’ 自体を検索する場合に使用する。 See 項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 によって自動で行われます。

6.1.1.2. 数値

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

有効な整数の例:

1221
0
-32

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

294.42
-32032.6809e+10
148.00

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

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

6.1.1.3. 16 進値

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

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

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

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

6.1.1.4. NULL

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

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

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

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;

See 項6.1.7. 「MySQL での予約語の扱い」

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

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

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

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

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

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

6.1.4. ユーザ変数

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

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

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

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

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

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

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

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

6.1.5. システム変数

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

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

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

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

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

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

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

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

LOCALSESSION のシノニムです。

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

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

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

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

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

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

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

変数名値のデータ型タイプ
autocommitboolSESSION
big_tablesboolSESSION
binlog_cache_sizenumGLOBAL
bulk_insert_buffer_sizenumGLOBAL | SESSION
concurrent_insertboolGLOBAL
connect_timeoutnumGLOBAL
convert_character_setstringSESSION
delay_key_writeOFF | ON | ALLGLOBAL
delayed_insert_limitnumGLOBAL
delayed_insert_timeoutnumGLOBAL
delayed_queue_sizenumGLOBAL
error_countnumSESSION
flushboolGLOBAL
flush_timenumGLOBAL
foreign_key_checksboolSESSION
identitynumSESSION
insert_idboolSESSION
interactive_timeoutnumGLOBAL | SESSION
join_buffer_sizenumGLOBAL | SESSION
key_buffer_sizenumGLOBAL
last_insert_idboolSESSION
local_infileboolGLOBAL
log_warningsboolGLOBAL
long_query_timenumGLOBAL | SESSION
low_priority_updatesboolGLOBAL | SESSION
max_allowed_packetnumGLOBAL | SESSION
max_binlog_cache_sizenumGLOBAL
max_binlog_sizenumGLOBAL
max_connect_errorsnumGLOBAL
max_connectionsnumGLOBAL
max_error_countnumGLOBAL | SESSION
max_delayed_threadsnumGLOBAL
max_heap_table_sizenumGLOBAL | SESSION
max_join_sizenumGLOBAL | SESSION
max_relay_log_sizenumGLOBAL
max_sort_lengthnumGLOBAL | SESSION
max_tmp_tablesnumGLOBAL
max_user_connectionsnumGLOBAL
max_write_lock_countnumGLOBAL
myisam_max_extra_sort_file_sizenumGLOBAL | SESSION
myisam_repair_threadsnumGLOBAL | SESSION
myisam_max_sort_file_sizenumGLOBAL | SESSION
myisam_sort_buffer_sizenumGLOBAL | SESSION
net_buffer_lengthnumGLOBAL | SESSION
net_read_timeoutnumGLOBAL | SESSION
net_retry_countnumGLOBAL | SESSION
net_write_timeoutnumGLOBAL | SESSION
query_cache_limitnumGLOBAL
query_cache_sizenumGLOBAL
query_cache_typeenumGLOBAL
read_buffer_sizenumGLOBAL | SESSION
read_rnd_buffer_sizenumGLOBAL | SESSION
rpl_recovery_ranknumGLOBAL
safe_show_databaseboolGLOBAL
server_idnumGLOBAL
slave_compressed_protocolboolGLOBAL
slave_net_timeoutnumGLOBAL
slow_launch_timenumGLOBAL
sort_buffer_sizenumGLOBAL | SESSION
sql_auto_is_nullboolSESSION
sql_big_selectsboolSESSION
sql_big_tablesboolSESSION
sql_buffer_resultboolSESSION
sql_log_binlogboolSESSION
sql_log_offboolSESSION
sql_log_updateboolSESSION
sql_low_priority_updatesboolGLOBAL | SESSION
sql_max_join_sizenumGLOBAL | SESSION
sql_quote_show_createboolSESSION
sql_safe_updatesboolSESSION
sql_select_limitboolSESSION
sql_slave_skip_counternumGLOBAL
sql_warningsboolSESSION
table_cachenumGLOBAL
table_typeenumGLOBAL | SESSION
thread_cache_sizenumGLOBAL
timestampboolSESSION
tmp_table_sizeenumGLOBAL | SESSION
tx_isolationenumGLOBAL | SESSION
wait_timeoutnumGLOBAL | SESSION
warning_countnumSESSION
unique_checksboolSESSION

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

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

変数説明
identitylast_insert_id のエイリアス(Sybase との互換性を確保するため)
sql_low_priority_updateslow_priority_updates のエイリアス
sql_max_join_sizemax_join_size のエイリアス
versionVERSION() のエイリアス(Sybase(?)との互換性を確保するため)

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

6.1.6. コメント構文

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

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

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

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

  • 単一引用符と二重引用符は、コメント内であっても、引用文字列の開始を示すものとして解釈される。そのコメント内に、最初の引用符と一致するもう 1 つの引用符がない場合、パーサはそのコメントの終了を認識しない。mysql を対話的に実行している場合は、プロンプトが mysql> から '> または "> に変わるため、パーサがコメントの終了を認識できずにいることがわかる。

  • セミコロンは、現在の SQL ステートメントの終了を表すものとして解釈され、セミコロンの後は、次のステートメントの開始を表すものとして解釈される。

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

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

6.1.7. MySQL での予約語の扱い

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

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

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

ADDALLALTER
ANALYZEANDAS
ASCBEFOREBETWEEN
BIGINTBINARYBLOB
BOTHBYCASCADE
CASECHANGECHAR
CHARACTERCHECKCOLLATE
COLUMNCOLUMNSCONSTRAINT
CONVERTCREATECROSS
CURRENT_DATECURRENT_TIMECURRENT_TIMESTAMP
CURRENT_USERDATABASEDATABASES
DAY_HOURDAY_MICROSECONDDAY_MINUTE
DAY_SECONDDECDECIMAL
DEFAULTDELAYEDDELETE
DESCDESCRIBEDISTINCT
DISTINCTROWDIVDOUBLE
DROPDUALELSE
ENCLOSEDESCAPEDEXISTS
EXPLAINFALSEFIELDS
FLOATFLOAT4FLOAT8
FORFORCEFOREIGN
FROMFULLTEXTGRANT
GROUPHAVINGHIGH_PRIORITY
HOUR_MICROSECONDHOUR_MINUTEHOUR_SECOND
IFIGNOREIN
INDEXINFILEINNER
INSERTINTINT1
INT2INT3INT4
INT8INTEGERINTERVAL
INTOISJOIN
KEYKEYSKILL
LEADINGLEFTLIKE
LIMITLINESLOAD
LOCALTIMELOCALTIMESTAMPLOCK
LONGLONGBLOBLONGTEXT
LOW_PRIORITYMATCHMEDIUMBLOB
MEDIUMINTMEDIUMTEXTMIDDLEINT
MINUTE_MICROSECONDMINUTE_SECONDMOD
NATURALNOTNO_WRITE_TO_BINLOG
NULLNUMERICON
OPTIMIZEOPTIONOPTIONALLY
ORORDEROUTER
OUTFILEPRECISIONPRIMARY
PRIVILEGESPROCEDUREPURGE
READREALREFERENCES
REGEXPRENAMEREPLACE
REQUIRERESTRICTREVOKE
RIGHTRLIKESECOND_MICROSECOND
SELECTSEPARATORSET
SHOWSMALLINTSONAME
SPATIALSQL_BIG_RESULTSQL_CALC_FOUND_ROWS
SQL_SMALL_RESULTSSLSTARTING
STRAIGHT_JOINTABLETABLES
TERMINATEDTHENTINYBLOB
TINYINTTINYTEXTTO
TRAILINGTRUEUNION
UNIQUEUNLOCKUNSIGNED
UPDATEUSAGEUSE
USINGUTC_DATEUTC_TIME
UTC_TIMESTAMPVALUESVARBINARY
VARCHARVARCHARACTERVARYING
WHENWHEREWITH
WRITEXORYEAR_MONTH
ZEROFILL??

以下はMySQL 4.0で登場する新規の予約語です。

CHECKFORCELOCALTIME
LOCALTIMESTAMPREQUIRESQL_CALC_FOUND_ROWS
SSLXOR?

以下はMySQL 4.1で登場する新規の予約語です。

BEFORECOLLATECONVERT
CURRENT_USERDAY_MICROSECONDDIV
DUALFALSEHOUR_MICROSECOND
MINUTE_MICROSECONDMODNO_WRITE_TO_BINLOG
SECOND_MICROSECONDSEPARATORSPATIAL
TRUEUTC_DATEUTC_TIME
UTC_TIMESTAMPVARCHARACTER?

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

  • ACTION

  • BIT

  • DATE

  • ENUM

  • NO

  • TEXT

  • TIME

  • TIMESTAMP

6.2. カラム型

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. 「不整合レコードの問題解決」

    この構文は ODBC との互換性を確保するために提供されている。

  • FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

    単精度浮動小数点数。使用可能な値は -3.402823466E+38 ? -1.175494351E-380、および 1.175494351E-38 ? 3.402823466E+38UNSIGNED を指定した場合、負数は使用できない。M は表示幅で、D は小数部桁数。引数のない FLOAT や、X が 24 以下の FLOAT(X) は、単精度浮動小数点数を表す。

  • DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

    倍精度浮動小数点数。 使用可能な値は -1.7976931348623157E+308 ? -2.2250738585072014E-3080、および 2.2250738585072014E-308 ? 1.7976931348623157E+308UNSIGNED を指定した場合、負数は使用できない。M は表示幅で、D は小数部桁数。引数のない DOUBLE や、X が 25 以上 53 以下である FLOAT(X) は、倍精度浮動小数点数を表す。

  • DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL] , REAL[(M,D)] [UNSIGNED] [ZEROFILL]

    いずれも DOUBLE のシノニム。

  • DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

    アンパック浮動小数点数。CHAR カラムのように動作する。``アンパック'' とは、その数値が、各桁に 1 文字ずつ使用して文字列として格納されることを意味する。M では、小数点と、負数に使用される ‘-’ 記号はカウントされない(しかし、これらのためのスペースは確保される)。D が 0 の場合、値は小数点も小数部も持たない。DECIMAL 値の最大範囲は、DOUBLE と同じだが、個々の DECIMAL カラムの実際の範囲は、MD の値によって制限される。UNSIGNED を指定した場合、負数は使用できない。

    D を省略した場合、デフォルトは 0。M を省略した場合、デフォルトは 10。

    MySQL バージョン 3.23 より前のバージョンでは、M 引数に、符号と小数点に必要なスペースを含める必要がある。

  • DEC[(M[,D])] [UNSIGNED] [ZEROFILL] , NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL] , FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]

    いずれも DECIMAL のシノニム。

    FIXED エイリアスは、他のサーバとの互換性を確保する目的で、バージョン 4.1.0 で追加された。

  • DATE

    日付。サポートしている範囲は、'1000-01-01' ? '9999-12-31'。MySQL では、DATE 値は 'YYYY-MM-DD' 形式で表示されるが、DATE カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。 See 項6.2.2.2. 「DATETIMEDATETIMESTAMP 型」

  • DATETIME

    日付と時刻の組み合わせ。サポートしている範囲は、'1000-01-01 00:00:00' ? '9999-12-31 23:59:59'。MySQL では、DATETIME 値は 'YYYY-MM-DD HH:MM:SS' 形式で表示されるが、DATETIME カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。

    See 項6.2.2.2. 「DATETIMEDATETIMESTAMP 型」

  • TIMESTAMP[(M)]

    タイムスタンプ。範囲は '1970-01-01 00:00:00' ? 2037 年の一定の時点。

    MySQL 4.0 以前のバージョンでは、TIMESTAMP 値は、M14(または指定なし)、128、または 6 のどれであるかに応じて、YYYYMMDDHHMMSSYYMMDDHHMMSSYYYYMMDD、または YYMMDD 形式で表示されるが、TIMESTAMP カラムへの値の割り当てには文字列または数値のいずれかを使用することができる。

    MySQL 4.1 以降では、TIMESTAMP'YYYY-MM-DD HH:MM:SS' 形式の文字列として返される。数値として返されるようにするには、タイムスタンプカラムに +0 を追加する。異なるタイムスタンプ長はサポートしていない。バージョン 4.0.12 以降、--new オプションを使用することで、バージョン 4.1 と同じようにサーバを動作させることができる。

    TIMESTAMP カラムに値を指定しないと、最後に行われた操作の日付と時刻が自動的に設定されるため、このカラムは INSERT 操作や UPDATE 操作の日付と時刻を記録するのに役立つ。また、このカラムに NULL 値を割り当てることによって、現在の日付と時刻をカラムに設定することができる。 See 項6.2.2. 「日付と時刻型」

    M 引数は、TIMESTAMP カラムの表示方法にのみ作用する。 この値は常に 4 バイトで格納される。

    M が 8 または 14 の TIMESTAMP(M) カラムは数値として報告され、その他の TIMESTAMP(M) カラムは文字列として報告されることに注意する。これは単に、これらのデータ型のテーブルのダンプとリストアを確実に実行できるようにすることを目的としている。 See 項6.2.2.2. 「DATETIMEDATETIMESTAMP 型」

  • 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 ? 21550000、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 では、これはデフォルト。

    CHARCHARACTER の省略形。

    バージョン 4.1.0 以降では、latin1 キャラクタセットを CHAR カラムに割り当てる ASCII 属性を指定することができる。

    バージョン 4.1.1 以降では、ucs2 キャラクタセットを CHAR カラムに割り当てる UNICODE 属性を指定することができる。

    MySQL では、CHAR(0) 型のカラムを作成することができる。これは、主に、カラム自体は必要とするが、そのカラムの値を実際に使用することはない、というような古いアプリケーションに対応する必要があるときに役立つ。また、2 つの値しか取らないカラムが必要な場合にも非常に役立つ。 CHAR(0)NOT NULL としては定義されず、1 ビットのみ占め、NULL または "" の 2 つの値しか取らない。 See 項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 型に変換される。 これは互換性を考慮した機能。

    VARCHARCHARACTER VARYING の省略形。

    See 項6.2.3.1. 「CHAR 型と VARCHAR 型」

  • 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 型」

6.2.1. 数値型

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

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

    salary DECIMAL(5,2)

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

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

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

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

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

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

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

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

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

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

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

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

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

バイト最小値最大値
TINYINT1-128127
SMALLINT2-3276832767
MEDIUMINT3-83886088388607
INT4-21474836482147483647
BIGINT8-92233720368547758089223372036854775807

6.2.2. 日付と時刻型

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

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

  • 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'
    TIMESTAMP00000000000000(長さは表示サイズに依存)
    TIME'00:00:00'
    YEAR0000
  • ``ゼロ'' 値は特殊な値だが、上の表に示した値を使用することによって、``ゼロ'' 値を明示的に格納または参照することができる。また、この他に、より簡単に記述できる値 '0' または 0 も、``ゼロ'' 値の格納または参照に使用できる。

  • ODBC では、日付または時刻型の値 ``ゼロ'' を処理できないため、MyODBC バージョン 2.50.12 以降では、MyODBC を通して日付または時刻型の値 ``ゼロ'' を使用すると、自動的に NULL に変換される。

6.2.2.1. 西暦 2000 年問題と日付型

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)) のようなものを使用します。

6.2.2.2. DATETIMEDATETIMESTAMP

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

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

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

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

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

MySQL を MAXDB モードで実行している場合、TIMESTAMPDATETIME と同じように動作します。TIMESTAMP カラムの自動更新(次の段落で説明)は行われません。MySQL の MAXDB モードでの実行は、バージョン 4.1.1 以降で可能です。See 項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 モードで実行している場合、TIMESTAMPDATETIME とまったく変わりません。格納と表示には同じ形式が使用され、また値の範囲も同じです。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' 形式の文字列として返されます。その他のタイムスタンプ長のサポートは中止されました。

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

  • '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 形式の数値(日付として適切なもの)として指定。たとえば、19830905132800830905132800'1983-09-05 13:28:00' として解釈される。

  • YYYYMMDD または YYMMDD 形式の数値(日付として適切なもの)として指定。たとえば、19830905830905'1983-09-05' として解釈される。

  • DATETIMEDATE、または TIMESTAMP 型のコンテキストで許容される値を返す、NOW()CURRENT_DATE などの関数の結果として指定。

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

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

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

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

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

  • カラム型が 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 型には時刻情報が格納されないため、結果の値の時刻部分は削除される。

  • DATETIMEDATE、および 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 に変換

6.2.2.3. TIME

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

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

  • 'D HH:MM:SS.fraction' 形式の文字列として指定(注意: MySQL では、小数部は今のところ時刻カラムに格納されない)。``柔軟'' な構文として、HH:MM:SS.fractionHH:MM:SSHH:MMD HH:MM:SSD HH:MMD HHSS のいずれかも使用できる。この場合、D は 0 ? 33 の間の日。

  • 区切り記号のない、'HHMMSS' 形式の文字列(時刻として適切なもの)として指定。たとえば、'101112''10:11:12' として認識されるが、'109712' は正しくないため(分部分が不適切)、'00:00:00' になる。

  • HHMMSS 形式の数値(時刻として適切なもの)として指定。 たとえば、101112'10:11:12' として認識される。代替形式として、SSMMSSHHMMSSHHMMSS.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' 値から見分けることはできないことに注意してください。

6.2.2.4. YEAR

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

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

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

  • 範囲 '1901' ? '2155' の、4 桁の文字列として指定。

  • 範囲 1901 ? 2155 の、4 桁の数値として指定。

  • 範囲 '00' ? '99' の、2 桁の文字列として指定。範囲 '00' ? '69''70' ? '99' の値は、それぞれ範囲 2000 ? 20691970 ? 1999YEAR 値に変換される。

  • 範囲 1 ? 99 の、2 桁の数値として指定。範囲 1 ? 6970 ? 99 の値は、それぞれ範囲 2001 ? 20691970 ? 1999YEAR 値に変換される。注意: 2 桁の数値の範囲は、2 桁の文字列の範囲と多少異なる。数値として指定した場合、ゼロを直接入力して 2000 と解釈させることはできない。2000 と解釈させるには、必ず文字列の '0' または '00' として指定する必要がある。数値として指定すると、0000 として解釈される。

  • YEAR 型のコンテキストで許容される値を返す、NOW() などの関数の結果として指定。

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

6.2.3. 文字列型

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

最大サイズバイト
TINYTEXT または TINYBLOB2^8-1255
TEXT または BLOB2^16-1(64K-1)65535
MEDIUMTEXT または MEDIUMBLOB2^24-1(16M-1)16777215
LONGBLOB2^32-1(4G-1)4294967295

6.2.3.1. CHAR 型と VARCHAR

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

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

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

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

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

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

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

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

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

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

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

6.2.3.2. BLOB 型と TEXT

BLOB 型は、可変長のデータを格納できる、大きなバイナリオブジェクトです。TINYBLOBBLOBMEDIUMBLOBLONGBLOB の 4 つの BLOB 型では、格納可能な値の最大長のみが異なります。

See 項6.2.6. 「各カラム型に必要な記憶容量」

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

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

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

  • MySQL バージョン 3.23.2 以降では、BLOB 型と TEXT 型のカラムには、インデックスを付けることができる。それより前の MySQL バージョンでは、インデックスはサポートしていない。

  • VARCHAR 型のカラムでは値の格納時に後続のスペースが削除されるが、BLOB 型と TEXT 型のカラムではこの削除は行われない。

  • BLOB 型と TEXT 型のカラムには、DEFAULT 値は設定できない。

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

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

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

  • GROUP BY または ORDER BYBLOB 型または 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 度だけ記憶領域が割り当てられます。

6.2.3.3. ENUM

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") として指定されたカラムの場合、次の値のいずれかを取ります。それぞれの値では、対応するインデックスも示しています。

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

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

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

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

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

mysql> SELECT enum_col+0 FROM tbl_name;

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

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

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

6.2.3.4. SET

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

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

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

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

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

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

mysql> SELECT set_col+0 FROM tbl_name;

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

SET 要素10 進数2 進数
a10001
b20010
c40100
d81000

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

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

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

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

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

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

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

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

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

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

6.2.4. 正しいカラム型の選択

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

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

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

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

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

他のベンダの型MySQL の型
BINARY(NUM)CHAR(NUM) BINARY
CHAR VARYING(NUM)VARCHAR(NUM)
FLOAT4FLOAT
FLOAT8DOUBLE
INT1TINYINT
INT2SMALLINT
INT3MEDIUMINT
INT4INT
INT8BIGINT
LONG VARBINARYMEDIUMBLOB
LONG VARCHARMEDIUMTEXT
MIDDLEINTMEDIUMINT
VARBINARY(NUM)VARCHAR(NUM) BINARY

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

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

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

数値型に必要な記憶容量

カラム型必要な記憶容量
TINYINT1 バイト
SMALLINT2 バイト
MEDIUMINT3 バイト
INT4 バイト
INTEGER4 バイト
BIGINT8 バイト
FLOAT(X)X <= 24 の場合は 4 バイト、25 <= X <= 53 の場合は 8 バイト
FLOAT4 バイト
DOUBLE8 バイト
DOUBLE PRECISION8 バイト
REAL8 バイト
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 バイト)

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

カラム型必要な記憶容量
DATE3 バイト
DATETIME8 バイト
TIMESTAMP4 バイト
TIME3 バイト
YEAR1 バイト

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

カラム型必要な記憶容量
CHAR(M)M バイト(1 <= M <= 255
VARCHAR(M)L+1 バイト(L <= M で、かつ 1 <= M <= 255
TINYBLOBTINYTEXTL+1 バイト(L < 2^8)
BLOBTEXTL+2 バイト(L < 2^16)
MEDIUMBLOBMEDIUMTEXTL+3 バイト(L < 2^24)
LONGBLOBLONGTEXTL+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 バイトしか占有しません。

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

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

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

6.3.1.1. かっこ

( ... )

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

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

6.3.1.2. 比較演算子

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

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

  • どちらかまたは両方の引数が NULL の場合、<=> 演算子を使用しているときを除いて、比較結果は NULL になる。

  • 比較演算の両方の引数が文字列の場合、それらは文字列として比較される。

  • 両方の引数が整数の場合、それらは整数として比較される。

  • 16 進値は、数値と比較する場合を除いて、バイナリ文字列として扱われる。

  • 引数のどちらかが TIMESTAMP または DATETIME 型のカラムで、もう一方が定数の場合、定数は比較の実行前にタイムスタンプに変換される。これは ODBC との互換性を確保するために行われる。

  • その他のすべての場合には、引数は浮動小数点数(実数)として比較される。

デフォルトでは、文字列の比較は、現在のキャラクタセット(デフォルトでは 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

    exprmin 以上で、max 以下の場合は 1 を返す。それ以外の場合は、0 を返す。すべての引数が同じ型の場合、これは式 (min <= expr AND expr <= max) と同じ。引数の型が異なる場合、前述の規則にもとづいて型変換が実行される。この場合、型変換は 3 つすべての引数に適用される。注意: 4.0.5 より前のバージョンでは、引数は expr の型に変換されていた。

    mysql> SELECT 1 BETWEEN 2 AND 3;
            -> 0
    mysql> SELECT 'b' BETWEEN 'a' AND 'c';
            -> 1
    mysql> SELECT 2 BETWEEN 2 AND '3';
            -> 1
    mysql> SELECT 2 BETWEEN 2 AND 'x-3';
            -> 0
    

  • expr NOT BETWEEN min AND max

    NOT (expr BETWEEN min AND max) と同じ。

  • expr IN (value,...)

    exprIN リストのいずれかの値のときは 1 を返す。それ以外の場合は 0 を返す。すべての値が定数なら、値はすべて expr の型に基づいて評価され、ソートされる。その後、バイナリ検索によってアイテムが検索される。したがって、IN の値リストが定数だけで構成されている場合、IN は非常に迅速に行われる。expr がケース依存の文字列式の場合、文字列の比較はケース依存方式で行われる。

    mysql> SELECT 2 IN (0,3,5,'wefwf');
            -> 0
    mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
            -> 1
    

    IN リストの値の数は、max_allowed_packet 値のみによって制限される。

    4.1 以降(SQL-99 標準に準拠するため)、IN では、左側の式が NULL の場合だけでなく、リストに一致するものが見つからず、リスト内の式の 1 つが NULL の場合にも NULL が返る。

    MySQL バージョン 4.1 以降では、IN() 節にサブクエリを組み込むこともできる。 See 項6.4.2.3. 「ANYINSOME とともに使用したサブクエリ」

  • expr NOT IN (value,...)

    NOT (expr IN (value,...)) と同じ。

  • ISNULL(expr)

    exprNULL の場合は 1 を返す。それ以外の場合は 0 を返す。

    mysql> SELECT ISNULL(1+1);
            -> 0
    mysql> SELECT ISNULL(1/0);
            -> 1
    

    注意: = を使用した NULL 値の比較は常に false になる。

  • COALESCE(list)

    リスト内の最初の非 NULL 要素を返す。

    mysql> SELECT COALESCE(NULL,1);
            -> 1
    mysql> SELECT COALESCE(NULL,NULL,NULL);
            -> NULL
    

  • INTERVAL(N,N1,N2,N3,...)

    N < N1 の場合は 0N < N2 の場合は 1(以下同様)というように値を返す。NNULL の場合は -1 を返す。引数はすべて整数として扱われる。この関数で N1 < N2 < N3 < ... < Nn を正しく動作させるには、引数を整数として扱う必要がある。これはバイナリ検索(非常に迅速)が使用されるからである。

    mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
            -> 3
    mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
            -> 2
    mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
            -> 0
    

6.3.1.3. 論理演算子

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

  • NOT , !

    論理 NOT。 オペランドが 0 の場合は 1 を返し、ゼロでない場合は 0 を返し、NOT NULL の場合は NULL を返す。

    mysql> SELECT NOT 10;
            -> 0
    mysql> SELECT NOT 0;
            -> 1
    mysql> SELECT NOT NULL;
            -> NULL
    mysql> SELECT ! (1+1);
            -> 0
    mysql> SELECT ! 1+1;
            -> 1
    

    最後の例の場合、式が (!1)+1 と同様に評価されるため、1 が返る。

  • AND , &&

    論理積。 すべてのオペランドがゼロでも NULL でもない場合は 1 を返し、1 つ以上のオペランドが 0 の場合は 0 を返す。それ以外の場合は NULL を返す。

    mysql> SELECT 1 && 1;
            -> 1
    mysql> SELECT 1 && 0;
            -> 0
    mysql> SELECT 1 && NULL;
            -> NULL
    mysql> SELECT 0 && NULL;
            -> 0
    mysql> SELECT NULL && 0;
            -> 0
    

    注意: 4.0.5 より前のバージョンの MySQL では、NULL が検出されると、使用可能な 0 値をチェックするプロセスが継続されずに、評価が停止される。そのため、これらのバージョンの場合、SELECT (NULL AND 0) では 0 ではなく NULL が返る。 バージョン 4.0.5 では、引き続き可能な限り最適化を図る一方で、常に SQL標準で規定されたとおりの結果になるようコードが再設計されている。

  • OR , ||

    論理和。 いずれかのオペランドが非ゼロの場合は 1 を返し、いずれかのオペランドが NULL の場合は NULL を返します。それ以外の場合は 0 を返す。

    mysql> SELECT 1 || 1;
            -> 1
    mysql> SELECT 1 || 0;
            -> 1
    mysql> SELECT 0 || 0;
            -> 0
    mysql> SELECT 0 || NULL;
            -> NULL
    mysql> SELECT 1 || NULL;
            -> 1
    

  • XOR

    排他論理和。 いずれかのオペランドが NULL の場合は NULL を返す。 NULL 以外のオペランドに対しては、奇数個のオペランドが非ゼロの場合は 1 を返し、それ以外の場合は 0 を返す。

    mysql> SELECT 1 XOR 1;
            -> 0
    mysql> SELECT 1 XOR 0;
            -> 1
    mysql> SELECT 1 XOR NULL;
            -> NULL
    mysql> SELECT 1 XOR 1 XOR 1;
            -> 1
    

    a XOR b は数学的に (a AND (NOT b)) OR ((NOT a) and b) と等価。

    XOR はバージョン 4.0.2 で追加された。

6.3.1.4. フロー制御関数

  • CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...][ELSE result] END , CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...][ELSE result] END

    最初の式では、value=compare-value である result を返す。2 番目の式では、最初の条件が true なら、その result 値を返す。一致する結果が検出されない場合は、ELSE 後の result 値を返す。ELSE 部分がない場合は、NULL を返す。

    mysql> SELECT CASE 1 WHEN 1 THEN "one"
               WHEN 2 THEN "two" ELSE "more" END;
           -> "one"
    mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
           -> "true"
    mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
           -> NULL
    

    戻り値の型(INTEGERDOUBLE、または STRING)は最初の戻り値(最初の THEN 後の式)の型と同じ。

  • IF(expr1,expr2,expr3)

    expr1 が TRUE(expr1 <> 0 および expr1 <> NULL)の場合 IF()expr2 を返し、それ以外の場合は expr3 を返す。 IF() は、使用されているコンテキストに応じて、数値または文字列を返す。

    mysql> SELECT IF(1>2,2,3);
            -> 3
    mysql> SELECT IF(1<2,'yes','no');
            -> 'yes'
    mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
            -> 'no'
    

    expr2 または expr3 が明示的に NULL の場合、IF() 関数の結果の型は NULL 以外のカラムの型になる(この動作は MySQL 4.0.3 で新たに導入された)。

    expr1 は整数値として評価される。したがって、浮動小数点型または文字列型の値をテストする場合は、比較演算を使用するようにする。

    mysql> SELECT IF(0.1,1,0);
            -> 0
    mysql> SELECT IF(0.1<>0,1,0);
            -> 1
    

    上の最初の式では、IF(0.1)0 を返す。これは、0.1 が整数型の値に変換されることによって、IF(0) のテストが行われるためである。これでは期待した結果が得られない場合がある。2 番目の式では、元の浮動小数点値がゼロ以外の値かどうか比較によってテストされる。比較の結果は整数として使用される。

    IF() のデフォルトの戻り値型は、MySQL バージョン 3.23 では次のように計算される(デフォルトの戻り値型はテンポラリテーブルへの格納時に重要になる場合がある)。

    戻り値
    expr2 または expr3 が文字列を返す。文字列
    expr2 または expr3 が浮動小数点値を返す。浮動小数点
    expr2 または expr3 が整数を返す。整数

    expr2 と expr3 が文字列の場合、両方の文字列がケース非依存のときは結果もケース非依存になる(バージョン 3.23.51 以降)。

  • IFNULL(expr1,expr2)

    expr1NULL でない場合は expr1 を返し、それ以外の場合は expr2 を返す。IFNULL() は、使用されているコンテキストに応じて、数値または文字列を返す。

    mysql> SELECT IFNULL(1,0);
            -> 1
    mysql> SELECT IFNULL(NULL,10);
            -> 10
    mysql> SELECT IFNULL(1/0,10);
            -> 10
    mysql> SELECT IFNULL(1/0,'yes');
            -> 'yes'
    

    MySQL 4.0.6 以降では、IFNULL(expr1,expr2) のデフォルトの結果値は、2 つの式のより ``一般的'' な方(STRINGREAL または INTEGER の順)になる。それ以前の MySQL バージョンとの違いは、式に基づくテーブルの作成時や、IFNULL() から得られた値を MySQL で内部的にテンポラリテーブルに格納する必要があるときに最も顕著である。

    CREATE TABLE foo SELECT IFNULL(1,"test") as test;
    

    MySQL 4.0.6 では、カラム 'テスト' の型は CHAR(4) だが、それ以前のバージョンでは、BIGINT

  • NULLIF(expr1,expr2)

    expr1 = expr2 が TRUE の場合は NULL を返し、それ以外の場合は expr1 を返す。 これは CASE WHEN x = y THEN NULL ELSE x END と同じ。

    mysql> SELECT NULLIF(1,1);
            -> NULL
    mysql> SELECT NULLIF(1,2);
            -> 1
    

    注意: MySQL では、引数が等しくない場合、expr1 は 2 回評価される。

6.3.2. 文字列関数

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

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

  • ASCII(str)

    文字列 str の左端の文字の ASCII コード値を返す。str が空の文字列のときは 0 を返す。strNULL のときは NULL を返す。

    mysql> SELECT ASCII('2');
            -> 50
    mysql> SELECT ASCII(2);
            -> 50
    mysql> SELECT ASCII('dx');
            -> 100
    

    ORD() 関数も参照。

  • BIN(N)

    longlong (BIGINT)型の数値である N のバイナリの文字列式を返す。これは CONV(N,10,2) と同じ。NNULL のときは NULL を返す。

    mysql> SELECT BIN(12);
            -> '1100'
    

  • BIT_LENGTH(str)

    文字列 str の長さをビットで返す。

    mysql> SELECT BIT_LENGTH('text');
            -> 32
    

  • CHAR(N,...)

    引数を整数として解釈し、それらの整数の ASCII コード値で表現された文字から成る文字列を返す。NULL 値はスキップされる。

    mysql> SELECT CHAR(77,121,83,81,'76');
            -> 'MySQL'
    mysql> SELECT CHAR(77,77.3,'77.3');
            -> 'MMM'
    

  • CHAR_LENGTH(str)

    文字列 str の長さ(文字数)を返す。 マルチバイト文字は 1 文字とみなされる。 したがって、5 個のマルチバイト文字で構成される文字列の場合、LENGTH() では 10 が返るが、CHAR_LENGTH() では 5 が返る。

  • CHARACTER_LENGTH(str)

    CHARACTER_LENGTH()CHAR_LENGTH() のシノニム。

  • CONCAT(str1,str2,...)

    引数を連結した結果の文字列を返す。いずれかの引数が NULL のときは NULL を返す。3 つ以上の引数の指定が可能。 数値型の引数は同等の文字列形式に変換される。

    mysql> SELECT CONCAT('My', 'S', 'QL');
            -> 'MySQL'
    mysql> SELECT CONCAT('My', NULL, 'QL');
            -> NULL
    mysql> SELECT CONCAT(14.3);
            -> '14.3'
    

  • CONCAT_WS(separator, str1, str2,...)

    CONCAT_WS()CONCAT() の特殊型で、区切り文字付きの CONCAT(CONCAT With Separator)。最初の引数は残りの引数の区切り文字である。 この区切り文字は連結する各文字列の間に挿入される。 区切り文字は残りの引数同様、文字列として指定することができる。区切り文字が NULL の場合、結果は NULL になる。 区切り文字引数の後の NULL 値はスキップされる。

    mysql> SELECT CONCAT_WS(",","First name","Second name","Last Name");
           -> 'First name,Second name,Last Name'
    mysql> SELECT CONCAT_WS(",","First name",NULL,"Last Name");
           -> 'First name,Last Name'
    

    MySQL 4.1.1 より前のバージョンの CONCAT_WS() では、NULL 値だけでなく、空の文字列もスキップされる。

  • CONV(N,from_base,to_base)

    数値を、進数の異なる数値に変換する。数値 Nfrom_base 進数から to_base 進数に変換した数値の文字列表現を返す。いずれかの引数が NULL のときは NULL を返す。 引数 N は整数として解釈されるが、整数または文字列として指定することができる。最小の進数は 2 で、最大の進数は 36to_base が負数の場合、N は符号付きの数値とみなされる。それ以外の場合、N は符号なしの数値として処理される。CONV は 64 ビットの精度で動作する。

    mysql> SELECT CONV("a",16,2);
            -> '1010'
    mysql> SELECT CONV("6E",18,8);
            -> '172'
    mysql> SELECT CONV(-17,10,-18);
            -> '-H'
    mysql> SELECT CONV(10+"10"+'10'+0xa,10,10);
            -> '40'
    

  • ELT(N,str1,str2,str3,...)

    N = 1 のときは str1 を返し、N = 2 のときは str2 を返す(以下同様)。N1 より小さいか、引数の数より大きい場合は、NULL を返す。ELT()FIELD() の逆。

    mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
            -> 'ej'
    mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
            -> 'foo'
    

  • EXPORT_SET(bits,on,off,[separator,[number_of_bits]])

    'bits' に指定された数値に対し、1 のビットを 'on' で指定された文字列で表現し、0 のビットを 'off' で指定された文字列で表現した文字列を返す。各文字列の間は 'separator' に指定された区切り文字'(デフォルトは ',')で区切られ、'number_of_bits' に指定されたビット数(デフォルトは 64)だけが表示される。

    mysql> SELECT EXPORT_SET(5,'Y','N',',',4)
            -> Y,N,Y,N
    

  • FIELD(str,str1,str2,str3,...)

    str1, str2, str3, ... リスト内の str のインデックスを返す。 str が検出されない場合は 0 を返す。 FIELD()ELT() の逆。

    mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 2
    mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
            -> 0
    

  • FIND_IN_SET(str,strlist)

    N 個の部分文字列で構成されるリスト strlist に、文字列 str が含まれている場合は、1 から N までのいずれかの値を返す。文字列のリストは、それぞれの間を ‘,’ 文字で区切られた各部分文字列で構成される文字列である。最初の引数が定数文字列で、2 番目の引数が SET 型のカラムの場合、FIND_IN_SET() 関数はビット演算を使用するよう最適化される。 strstrlist に含まれていない場合や、strlist が空の文字列の場合は、0 を返す。どちらの引数も NULL の場合は、NULL を返す。 最初の引数にカンマ ‘,’ が含まれていると、この関数は正しく動作しない。

    mysql> SELECT FIND_IN_SET('b','a,b,c,d');
            -> 2
    

  • HEX(N_or_S)

    N_OR_S が数値の場合、longlong(BIGINT)型の数値である N の 16 進値の文字列表現を返す。 これは CONV(N,10,16) と同じ。

    N_OR_S が文字列の場合は、N_OR_S の各文字を 2 桁の 16 進数に変換した N_OR_S の 16 進文字列を返す。これは 0xff 文字列の逆。

    mysql> SELECT HEX(255);
            -> 'FF'
    mysql> SELECT HEX("abc");
            -> 616263
    mysql> SELECT 0x616263;
            -> "abc"
    mysql> SELECT HEX('あ');
            -> 'A4A2'   ; # 注意 EUC-JP コードでの結果
    

  • INSERT(str,pos,len,newstr)

    str 内の、位置 pos から始まる長さ len の部分文字列を文字列 newstr に置き換えた文字列を返す。

    mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
            -> 'QuWhattic'
    mysql> SELECT INSERT('あいうえお', 3, 2, 'か');
            -> あいかお
    

    この関数はマルチバイト文字に対応している。

  • INSTR(str,substr)

    文字列 str に最初に出現する部分文字列 substr の位置を返す。これは LOCATE() の 2 つの引数を使用する形式と同じだが、引数の順序が入れ替わっている。

    mysql> SELECT INSTR('foobarbar', 'bar');
            -> 4
    mysql> SELECT INSTR('xbar', 'foobar');
            -> 0
    mysql> SELECT INSTR('あいうえお', 'う');
            -> 3
    

    この関数はマルチバイト文字に対応している。 MySQL 3.23 では、この関数では大文字と小文字が区別されるが(ケース依存)、バージョン 4.0 では、どちらかの引数がバイナリ文字列の場合にのみケース依存になる。

  • LCASE(str)

    LCASE()LOWER() のシノニム。

  • LEFT(str,len)

    文字列 str の左端にある長さ len の文字を返す。

    mysql> SELECT LEFT('foobarbar', 5);
            -> 'fooba'
    mysql> SELECT LEFT('あいうえお', 2);
            -> 'あい'
    

  • LENGTH(str)

    文字列 str の長さ(バイト)を返す。1個のマルチバイト文字は複数バイトになる。 したがって、5 個の 2 バイト文字で構成される文字列の場合、LENGTH() では 10 が返るが、CHAR_LENGTH() では 5 が返る。

    mysql> SELECT LENGTH('text');
            -> 4
    mysql> SELECT LENGTH('あいうえお');
            -> 10
    

  • LOAD_FILE(file_name)

    ファイルを読み取り、ファイルの内容を文字列として返す。ファイルはサーバ上に存在しなければならず、ファイルのフルパス名を指定する必要がある。また、FILE 権限が必要となる。ファイルは全ユーザが読み取り可能でなければならず、max_allowed_packet より小さいサイズでなければならない。

    ファイルが存在しない場合や、上記の理由のいずれかによって読み取り不可能な場合、この関数は NULL を返す。

    mysql> UPDATE tbl_name
               SET blob_column=LOAD_FILE("/tmp/picture")
               WHERE id=1;
    

    MySQL バージョン 3.23 以外のバージョンを使用している場合は、ファイルの読み取りをアプリケーション内で行い、その後 INSERT/UPDATE ステートメントを作成して、アプリケーションからデータベースにファイルの内容を書き出す必要がある。MySQL++ ライブラリを使用している場合は、これを行う方法の 1 つを http://www.mysql.com/documentation/mysql++/mysql++-examples.html で参照できる。

  • LOCATE(substr,str) , LOCATE(substr,str,pos)

    最初の構文は、文字列 str に最初に出現する部分文字列 substr の位置を返す。 2 番目の構文は、文字列 str の位置 pos 以降に最初に出現する部分文字列 substr の位置を返す。 str 内に substr が存在しない場合は 0 を返す。

    mysql> SELECT LOCATE('bar', 'foobarbar');
            -> 4
    mysql> SELECT LOCATE('xbar', 'foobar');
            -> 0
    mysql> SELECT LOCATE('bar', 'foobarbar',5);
            -> 7
    mysql> SELECT LOCATE('え', 'あいうえおうえ');
            -> 4
    mysql> SELECT LOCATE('え', 'あいうえおうえ', 5);
            -> 7
    

    この関数はマルチバイト文字に対応している。 MySQL 3.23 では、この関数では大文字と小文字が区別されるが(ケース依存)、バージョン 4.0 では、どちらかの引数がバイナリ文字列の場合にのみケース依存になる。

  • LOWER(str)

    str のすべての文字を現在のキャラクタセット(デフォルトは ISO-8859-1 Latin1)のマッピングに基づいて小文字に変更した文字列を返す。

    mysql> SELECT LOWER('QUADRATICALLY');
            -> 'quadratically'
    mysql> SELECT LOWER('あいうえお');
            -> 'あいうえお'
    

    この関数はマルチバイト文字に対応している。

  • LPAD(str,len,padstr)

    文字列 strlen に指定された長さの文字になるよう、str の左側に文字列 padstr を埋め込んだ文字列を返す。strlen より長い場合は、戻り値は len の長さの文字に縮められる。

    mysql> SELECT LPAD('hi',4,'??');
            -> '??hi'
    
    #バージョン4.1以上では以下のようになります。
    mysql> SELECT LPAD('あいう', 5 , 'X');
            -> 'XXあいう'
    
    #バージョン4.1未満では以下のようになります。
    mysql> SELECT LPAD('あいう', 8 , 'X');
            -> 'XXあいう'
    mysql> SELECT LPAD('あいう', 8 , 'お');
            -> 'おあいう'
    mysql> SELECT LPAD('あいう', 5 , 'X');
            -> 'あい ' ; #注意。最後は1byte
    

  • LTRIM(str)

    文字列 str から先頭のスペース文字を削除した文字列を返す。

    mysql> SELECT LTRIM('  barbar');
            -> 'barbar'
    

  • MAKE_SET(bits,str1,str2,...)

    bits に指定されたビットのセットに対応するビットを持つ文字列から成るセット(‘,’ 文字で間を区切られた各部分文字列を含む文字列)を返す。str1 はビット 0 に対応し、str2 はビット 1 に対応する(以下同様に続く)。str1, str2, ... 内の NULL 文字列は結果には組み込まれない。

    mysql> SELECT MAKE_SET(1,'a','b','c');
            -> 'a'
    mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
            -> 'hello,world'
    mysql> SELECT MAKE_SET(0,'a','b','c');
            -> ''
    

  • MID(str,pos,len)

    MID(str,pos,len)SUBSTRING(str,pos,len) のシノニム。

  • OCT(N)

    longlong 型の数値である N の 8 進値の文字列表現を返す。これは CONV(N,10,8) と同じ。 NNULL のときは NULL を返す。

    mysql> SELECT OCT(12);
            -> '14'
    

  • OCTET_LENGTH(str)

    OCTET_LENGTH()LENGTH() のシノニム。

  • ORD(str)

    文字列 str の左端の文字がマルチバイト文字の場合に、次の式を使用して計算した、その文字を構成する各文字の ASCII コード値を返す。((最初のバイトの ASCII コード)*256+(2 番目のバイトの ASCII コード))[*256+3 番目のバイトの ASCII コード...] 左端の文字がマルチバイト文字でないときは、ASCII() 関数を使用した場合と同じ値を返す。

    mysql> SELECT ORD('2');
            -> 50
    mysql> SELECT ORD('あ');
            -> 42146   ; #注意 EUC-JP コードでの結果
    

  • POSITION(substr IN str)

    POSITION(substr IN str)LOCATE(substr,str) のシノニム。

  • QUOTE(str)

    指定された文字列を、SQL ステートメントで正しいエスケープデータ値として使用できるように引用符で囲んだ文字列を返す。結果の文字列は単一引用符で囲まれ、文字列内に単一引用符(‘'’)、バックスラッシュ(‘\’)、ASCII NUL、Control-Z が含まれている場合はその直前にバックスラッシュが挿入される。引数が NULL の場合は、``NULL'' という語が単一引用符で囲まれずに返される。 QUOTE() 関数は MySQL バージョン 4.0.3 で追加された。

    mysql> SELECT QUOTE("Don't");
            -> 'Don\'t!'
    mysql> SELECT QUOTE(NULL);
            -> NULL
    

  • REPEAT(str,count)

    文字列 str を、count に指定された回数だけ繰り返した文字列を返す。count <= 0 の場合は、空の文字列を返す。str または countNULL の場合は、NULL を返す。

    mysql> SELECT REPEAT('MySQL', 3);
            -> 'MySQLMySQLMySQL'
    mysql> SELECT REPEAT('げ', 3);
            -> 'げげげ'
    

  • REPLACE(str,from_str,to_str)

    文字列 str に含まれる文字列 from_str をすべて文字列 to_str に置換した文字列を返す。

    mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
            -> 'WwWwWw.mysql.com'
    mysql> SELECT REPLACE('あいあいうえお', 'い', 'す');
            -> 'あすあすうえお'
    

    この関数はマルチバイト文字に対応している。

  • REVERSE(str)

    文字列 str 内の文字の順序を逆にした文字列を返す。

    mysql> SELECT REVERSE('abc');
            -> 'cba'
    mysql> SELECT REVERSE('あいうえお');
            -> 'おえういあ'
    

    この関数はマルチバイト文字に対応している。

  • RIGHT(str,len)

    文字列 str の右端にある長さ len の文字を返す。

    mysql> SELECT RIGHT('foobarbar', 4);
            -> 'rbar'
    mysql> SELECT RIGHT('あいうえお', 4);
            -> 'いうえお'
    

    この関数はマルチバイト文字に対応している。

  • RPAD(str,len,padstr)

    文字列 strlen に指定された長さの文字になるよう、str の右側に文字列 padstr を埋め込んだ文字列を返す。strlen より長い場合は、戻り値は len の長さの文字に縮められる。

    mysql> SELECT RPAD('hi',5,'?');
            -> 'hi???'
    
    #バージョン4.1以上では以下のようになります。
    mysql> SELECT RPAD('あい', 5, 'う');
            -> 'あいううう'
    
    #バージョン4.1未満では以下のようになります。
    mysql> SELECT RPAD('あい', 5, 'X');
            -> 'あいX'
    mysql> SELECT RPAD('あい', 5, 'う');
            -> 'あい '  ; # 注意: 最後はマルチバイト文字の上位1byte
    

  • RTRIM(str)

    文字列 str から後続のスペース文字を削除した文字列を返す。

    mysql> SELECT RTRIM('barbar   ');
            -> 'barbar'
    

    この関数はマルチバイト文字に対応している。

  • SOUNDEX(str)

    文字列 str の soundex 文字列を返す。発音が似通った 2 つの文字列の soundex 文字列は同じものになる。標準の soundex 文字列の長さは 4 文字だが、SOUNDEX() 関数は任意の長さの文字列を返す。返された値に対して SUBSTRING() を使用すると、標準の soundex 文字列が得られる。指定された文字列内の英数字以外の文字は無視される。A ? Z の範囲外の各国語のアルファベット文字はすべて母音として扱われる。

    mysql> SELECT SOUNDEX('Hello');
            -> 'H400'
    mysql> SELECT SOUNDEX('Quadratically');
            -> 'Q36324'
    

  • expr1 SOUNDS LIKE expr2

    SOUNDEX(expr1)=SOUNDEX(expr2) と同じ(バージョン 4.1 以降でのみ利用可能)。

  • SPACE(N)

    N に指定された数のスペース文字で構成される文字列を返す。

    mysql> SELECT SPACE(6);
            -> '      '
    

  • SUBSTRING(str,pos) , SUBSTRING(str FROM pos) , SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)

    len 引数のない形式の場合は、文字列 str 内の位置 pos 以降の部分文字列を返す。 len 引数のある形式の場合は、文字列 str の位置 pos 以降の、len に指定された長さの部分文字列を返す。 FROM を使用する形式は SQL-92 の構文。

    mysql> SELECT SUBSTRING('Quadratically',5);
            -> 'ratically'
    mysql> SELECT SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'
    mysql> SELECT SUBSTRING('Quadratically',5,6);
            -> 'ratica'
    mysql> SELECT SUBSTRING('あいうえおかきくけこ', 5);
            -> 'おかきくけこ'
    

    この関数はマルチバイト文字に対応している。

  • SUBSTRING_INDEX(str,delim,count)

    文字列 str から、delim に指定された区切り記号の count 個目の出現位置の直前までの部分文字列を返す。 count に指定された数が正数の場合は、(左から数えて)指定された数の最後の区切り記号の左側にあるすべての文字を返す。 count に指定された数が負数の場合は、(右から数えて)指定された数の最後の区切り記号の右側にあるすべての文字を返す。

    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
            -> 'www.mysql'
    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
            -> 'mysql.com'
    mysql> SELECT SUBSTRING_INDEX('あいんうえおんかき', 'ん', 2);
            -> 'あいんうえお'
    mysql> SELECT SUBSTRING_INDEX('あいんうえおんかき', 'ん', -2);
            -> 'うえおんかき'
    

    この関数はマルチバイト文字に対応している。

  • TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)

    remstr に指定されたすべてのプリフィックスまたはサフィックス(あるいはその両方)を、文字列 str から削除した文字列を返す。指定子 BOTHLEADINGTRAILING がいずれも指定されていない場合は、BOTH が指定されたとみなされる。remstr が指定されていない場合は、スペースが削除される。

    mysql> SELECT TRIM('  bar   ');
            -> 'bar'
    mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
            -> 'barxxx'
    mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
            -> 'bar'
    mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
            -> 'barx'
    mysql> SELECT TRIM(BOTH 'お' FROM 'おあいうえお');
            -> 'あいうえ'
    

    この関数はマルチバイト文字に対応している。

  • UCASE(str)

    UCASE()UPPER() のシノニム。

  • UPPER(str)

    str のすべての文字を現在のキャラクタセット(デフォルトは ISO-8859-1 Latin1)のマッピングに基づいて大文字に変更した文字列を返す。

    mysql> SELECT UPPER('Hej');
            -> 'HEJ'
    mysql> SELECT UPPER('へい');
            -> 'へい'
    

    この関数はマルチバイト文字に対応している。

6.3.2.1. 文字列比較関数

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

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

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

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

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

  • expr LIKE pat [ESCAPE 'escape-char']

    SQL の単純な正規表現比較を使用したパターンマッチ。1(TRUE)または 0(FALSE)を返す。LIKE では、次の 2 つのワイルドカード文字をパターン内で使用できる。

    文字説明
    %任意の数の文字(ゼロ文字を含む)と一致する。
    _厳密に 1 つの文字と一致する。

    mysql> SELECT 'David!' LIKE 'David_';
            -> 1
    mysql> SELECT 'David!' LIKE '%D%v%';
            -> 1
    

    ワイルドカード文字を通常の文字として扱う場合は、直前にエスケープ文字を付ける。特定の ESCAPE 文字を指定しないと、‘\’ をエスケープ文字として使用するものとみなされる。

    文字列説明
    \%1 つの % 文字と一致する。
    \_1 つの _ 文字と一致する。

    mysql> SELECT 'David!' LIKE 'David\_';
            -> 0
    mysql> SELECT 'David_' LIKE 'David\_';
            -> 1
    

    別のエスケープ文字を指定する場合は、次のように、ESCAPE 節を使用する。

    mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
            -> 1
    

    次の 2 つのステートメントは、オペランドのどちらか一方がバイナリ文字列の場合、文字列の比較がケース依存方式で行われることを示している。

    mysql> SELECT 'abc' LIKE 'ABC';
            -> 1
    mysql> SELECT 'abc' LIKE BINARY 'ABC';
            -> 0
    

    LIKE は数値式で使用できる(これは SQL-99 の LIKE に対する MySQL の拡張)。

    mysql> SELECT 10 LIKE '1%';
            -> 1
    mysql> SELECT 'いあ' LIKE '%い%';
            -> 1
    mysql> SELECT 'イあ' LIKE '%い%';
            -> 0
    # 注意: EUC-JP コードで、'イあ' は 0xA5A4A4A2。'い' は 0xA4A4。
    

    注意:MySQL では文字列で C のエスケープ構文('\n' など)を使用するため、LIKE の文字列に ‘\’ を挿入するときは、2 倍の数の ‘\’ を使用する必要がある。たとえば、'\n' を検索する場合は、'\\n' と指定する。また、‘\’ を検索する場合は、'\\\\' と指定する(バックスラッシュはパーサによって一度取り除かれ、パターンマッチの実行時にもう一度取り除かれる。そして、残った 1 つのバックスラッシュがマッチングの対象となる)。

  • MATCH (col1,col2,...)AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION] )

    MATCH ... AGAINST() は全文検索に使用され、カラム (col1,col2,...) のテキストと、クエリ expr のテキストとの関連性(類似度)を返す。関連性は正の浮動小数点数で表現される。関連性がゼロのときは、類似性がまったくないことを意味する。 MATCH ... AGAINST() は MySQL バージョン 3.23.23 以降で利用できる。IN BOOLEAN MODE 拡張はバージョン 4.0.1 で追加され、WITH QUERY EXPANSION は 4.1.1 で追加された。 詳細および使用例については、項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 の正規表現exprpat とマッチする場合は 1 を返し、マッチしない場合は 0 を返す。RLIKE は、mSQL との互換性を確保するための、REGEXP のシノニム。 注意:MySQL では、文字列で C のエスケープ構文('\n' など)を使用するため、REGEXP の文字列に ‘\’ を挿入するときは、2 倍の数の ‘\’ を使用する必要がある。 MySQL バージョン 3.23.4 以降では、REGEXP は通常(非バイナリ)の文字列に対してはケース非依存。

    mysql> SELECT 'Monty!' REGEXP 'm%y%%';
            -> 0
    mysql> SELECT 'Monty!' REGEXP '.*';
            -> 1
    mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
            -> 1
    mysql> SELECT "a" REGEXP "A", "a" REGEXP BINARY "A";
            -> 1  0
    mysql> SELECT "a" REGEXP "^[a-d]";
            -> 1
    

    REGEXPRLIKE では、現在のキャラクタセット(デフォルトでは ISO-8859-1 Latin1)に基づいて文字の型が決定される。

  • STRCMP(expr1,expr2)

    STRCMP() 両方の文字列が同じものである場合は 0 を返し、現在のソート順で最初の引数が 2 番目の引数より小さい場合は -1 を返し、それ以外の場合は -1 を返す。

    mysql> SELECT STRCMP('text', 'text2');
            -> -1
    mysql> SELECT STRCMP('text2', 'text');
            -> 1
    mysql> SELECT STRCMP('text', 'text');
            -> 0
    

6.3.2.2. ケース依存性

  • BINARY

    BINARY 演算子はこの演算子の後に続く文字列をバイナリ文字列にキャストする。 この演算子を使用すれば、BINARY または BLOB として定義されていないカラムに対しても、強制的にケース依存にしたカラムの比較を簡単に行うことができる。

    mysql> SELECT "a" = "A";
            -> 1
    mysql> SELECT BINARY "a" = "A";
            -> 0
    

    BINARY stringCAST(string AS BINARY) の省略形。 See 項6.3.5. 「キャスト関数」BINARY は MySQL バージョン 3.23.0 で導入された。

    注意: MySQL の一部のコンテキストでは、インデックス付きのカラムを BINARY にキャストすると、インデックスを効率的に使用できなくなる。

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

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

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

6.3.3. 数値関数

6.3.3.1. 算術演算

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

  • +

    加算

    mysql> SELECT 3+5;
            -> 8
    

  • -

    減算

    mysql> SELECT 3-5;
            -> -2
    

  • *

    乗算

    mysql> SELECT 3*5;
            -> 15
    mysql> SELECT 18014398509481984*18014398509481984.0;
            -> 324518553658426726783156020576256.0
    mysql> SELECT 18014398509481984*18014398509481984;
            -> 0
    

    最後の式の結果は正しくない。これは、この整数乗算の結果が BIGINT 計算の 64 ビットの範囲を超えるため。

  • /

    除算

    mysql> SELECT 3/5;
            -> 0.60
    

    ゼロで割ると結果は NULL になる。

    mysql> SELECT 102/(1-1);
            -> NULL
    

    除算が BIGINT 演算で計算されるのは、結果が整数に変換されるコンテキストでその演算が実行された場合に限られる。

6.3.3.2. 数学関数

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

  • -

    単項マイナス。引数の符号を変更する。

    mysql> SELECT - 2;
            -> -2
    

    注意: BIGINT 型の値に対してこの演算子を使用すると、戻り値は BIGINT になる。したがって、値が -2^63 になる可能性がある整数に対しては - の使用を避ける。

  • ABS(X)

    X の絶対値を返す。

    mysql> SELECT ABS(2);
            -> 2
    mysql> SELECT ABS(-32);
            -> 32
    

    この関数は BIGINT 型の値に対して使用しても問題ない。

  • ACOS(X)

    X のアークコサイン(つまり、コサインが X である値)を返す。X-1 から 1 の範囲にないときは NULL を返す。

    mysql> SELECT ACOS(1);
            -> 0.000000
    mysql> SELECT ACOS(1.0001);
            -> NULL
    mysql> SELECT ACOS(0);
            -> 1.570796
    

  • ASIN(X)

    X のアークサイン(つまり、サインが X である値)を返す。X-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 つの変数 XY のアークタンジェントを返す。これは Y / X によるアークタンジェントの計算と似ているが、異なる点として、この場合、両方の引数の符号に基づいて結果の四分円が決定される。

    mysql> SELECT ATAN(-2,2);
            -> -0.785398
    mysql> SELECT ATAN2(PI(),0);
            -> 1.570796
    

  • CEILING(X) , CEIL(X)

    X 以上の最も小さい整数値を返す。

    mysql> SELECT CEILING(1.23);
            -> 2
    mysql> SELECT CEIL(-1.23);
            -> -1
    

    CEIL() エイリアスはバージョン 4.0.6 で追加された。

    注意: 戻り値は BIGINT に変換される。

  • COS(X)

    X(ラジアン)のコサインを返す。

    mysql> SELECT COS(PI());
            -> -1.000000
    

  • COT(X)

    X のコタンジェントを返す。

    mysql> SELECT COT(12);
            -> -1.57267341
    mysql> SELECT COT(0);
            -> NULL
    

  • CRC32(expr)

    巡回冗長検査値を計算し、32 ビットの符号なしの値を返す。 引数が NULL の場合、結果は NULL になる。引数では、文字列の指定が前提となる。文字列以外の値を指定しても、文字列として扱われる。

    mysql> SELECT CRC32('MySQL');
            -> 3259397556
    

    CRC32() は MySQL 4.1.0 以降で利用できる。

  • DEGREES(X)

    引数 X をラジアンから度に変換して返す。

    mysql> SELECT DEGREES(PI());
            -> 180.000000
    

  • DIV

    整数の除算。 FLOOR() と同様。ただし、BIGINT 型の値に対応している。

    mysql> SELECT 5 DIV 2
            -> 2
    

    DIV は MySQL 4.1.0 の新機能。

  • EXP(X)

    e(自然対数の底)を X 乗した値を返す。

    mysql> SELECT EXP(2);
            -> 7.389056
    mysql> SELECT EXP(-2);
            -> 0.135335
    

  • FLOOR(X)

    X 以下の最も大きい整数値を返す。

    mysql> SELECT FLOOR(1.23);
            -> 1
    mysql> SELECT FLOOR(-1.23);
            -> -2
    

    注意: 戻り値は BIGINT に変換される。

  • GREATEST(X,Y,...)

    最も大きい(つまり、最も大きい値を指定された)引数を返す。 各引数の比較は LEAST の場合と同じ規則に基づいて行われる。

    mysql> SELECT GREATEST(2,0);
            -> 2
    mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
            -> 767.0
    mysql> SELECT GREATEST("B","A","C");
            -> "C"
    

    バージョン 3.22.5 より前の MySQL では、GREATEST の代わりに MAX() を使用できる。

  • LEAST(X,Y,...)

    指定された 2 つ以上の引数の中で、最も小さい(つまり、最も小さい値を指定された)引数を返す。 各引数の比較は、次の規則に基づいて行われる。

    • 戻り値が INTEGER のコンテキストで使用される場合、またはすべての引数に整数値が指定されている場合は、各引数は整数として比較される。

    • 戻り値が REAL のコンテキストで使用される場合、またはすべての引数に実数が指定されている場合は、各引数は実数として比較される。

    • いずれかの引数がケース依存文字列である場合は、各引数はケース依存文字列として比較される。

    • その他の場合、引数はケース非依存文字列として比較される。

    mysql> SELECT LEAST(2,0);
            -> 0
    mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
            -> 3.0
    mysql> SELECT LEAST("B","A","C");
            -> "A"
    

    バージョン 3.22.5 より前の MySQL では、LEAST の代わりに MIN() を使用できる。

  • LN(X)

    X の自然対数を返す。

    mysql> SELECT LN(2);
            -> 0.693147
    mysql> SELECT LN(-2);
            -> NULL
    

    この関数は MySQL バージョン 4.0.3 で追加された。 MySQL における LOG(X) のシノニム。

  • LOG(X) , LOG(B,X)

    パラメータ 1 つで呼び出された場合、この関数は X の自然対数を返す。

    mysql> SELECT LOG(2);
            -> 0.693147
    mysql> SELECT LOG(-2);
            -> NULL
    

    パラメータ 2 つで呼び出された場合、この関数は任意の底 B に対する X の自然対数を返す。

    mysql> SELECT LOG(2,65536);
            -> 16.000000
    mysql> SELECT LOG(1,100);
            -> NULL
    

    任意の底を指定できるオプションは MySQL バージョン 4.0.3 で追加された。 LOG(B,X)LOG(X)/LOG(B) と同じ。

  • LOG2(X)

    2 を底とする X の自然対数を返す。

    mysql> SELECT LOG2(65536);
            -> 16.000000
    mysql> SELECT LOG2(-100);
            -> NULL
    

    LOG2() は、特定の数値の格納に何ビット必要か調べるのに役立つ。 この関数は MySQL バージョン 4.0.3 で追加された。 それより前のバージョンでは、代わりに LOG(X)/LOG(2) を使用できる。

  • LOG10(X)

    10 を底とする X の自然対数を返す。

    mysql> SELECT LOG10(2);
            -> 0.301030
    mysql> SELECT LOG10(100);
            -> 2.000000
    mysql> SELECT LOG10(-100);
            -> NULL
    

  • MOD(N,M) , %

    モジュロ(C の % 演算子に類する)。 NM で割ったときの余りを返す。

    mysql> SELECT MOD(234, 10);
            -> 4
    mysql> SELECT 253 % 7;
            -> 1
    mysql> SELECT MOD(29,9);
            -> 2
    mysql> SELECT 29 MOD 9;
            -> 2
    

    この関数は BIGINT 型の値に使用しても問題ない。 最後の例は MySQL 4.1 でのみ有効。

  • PI()

    π の値を返す。小数部の表示桁数はデフォルトで 5 桁だが、MySQL の内部では、π に完全な倍精度が使用される。

    mysql> SELECT PI();
            -> 3.141593
    mysql> SELECT PI()+0.000000000000000000;
            -> 3.141592653589793116
    

  • POW(X,Y) , POWER(X,Y)

    XY 乗した値を返す。

    mysql> SELECT POW(2,2);
            -> 4.000000
    mysql> SELECT POW(2,-2);
            -> 0.250000
    

  • RADIANS(X)

    引数 X を度からラジアンに変換して返す。

    mysql> SELECT RADIANS(90);
            -> 1.570796
    

  • RAND() , RAND(N)

    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 が負数か、ゼロか、正数かに応じて、この引数の符号を -10、または 1 として返す。

    mysql> SELECT SIGN(-32);
            -> -1
    mysql> SELECT SIGN(0);
            -> 0
    mysql> SELECT SIGN(234);
            -> 1
    

  • SIN(X)

    X(ラジアン)のサインを返す。

    mysql> SELECT SIN(PI());
            -> 0.000000
    

  • SQRT(X)

    X の負数でない平方根を返す。

    mysql> SELECT SQRT(4);
            -> 2.000000
    mysql> SELECT SQRT(20);
            -> 4.472136
    

  • TAN(X)

    X(ラジアン)のタンジェントを返す。

    mysql> SELECT TAN(PI()+1);
            -> 1.557408
    

  • TRUNCATE(X,D)

    数値 X の小数部を D に指定された桁数に切り捨てた値を返す。D0 の場合、結果の値は小数点も小数部も持たない。

    mysql> SELECT TRUNCATE(1.223,1);
            -> 1.2
    mysql> SELECT TRUNCATE(1.999,1);
            -> 1.9
    mysql> SELECT TRUNCATE(1.999,0);
            -> 1
    mysql> SELECT TRUNCATE(-1.999,1);
            -> -1.9
    

    MySQL 3.23.51 以降、すべての数値はゼロ方向に丸められる。

    D が負数の場合、その数値の小数部以外の部分もゼロになる。

    mysql> SELECT TRUNCATE(122,-2);
           -> 100
    

    注意: 小数は通常、正確な数値としてではなく、倍精度の値としてコンピュータに格納されるため、次のようなおかしな結果が出ることがある。

    mysql> SELECT TRUNCATE(10.28*100,0);
           -> 1027
    

    これは、10.28 が実際には 10.2799999999999999 のような値として格納されることによって発生する。

6.3.4. 日付と時刻関数

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

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

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

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

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

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

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

  • ADDDATE(date,INTERVAL expr type) , ADDDATE(expr,days)

    2 番目の引数の INTERVAL を指定する形式で呼び出した場合、ADDDATE()DATE_ADD() とシノニムになる。関連する関数 SUBDATE()DATE_SUB() のシノニム。

    mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
            -> '1998-02-02'
    mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
            -> '1998-02-02'
    

    2 番目の構文は MySQL 4.1.1 以降で使用できる。expr には日付式か日付時刻式を指定し、days には expr に加える日数を指定する。

    mysql> SELECT ADDDATE('1998-01-02', 31);
            -> '1998-02-02'
    

  • ADDTIME(expr,expr2)

    ADDTIME() では、exprexpr2 を加えた結果が返される。 expr には日付式か日付時刻式を指定し、expr2 には時刻式を指定する。

    mysql> SELECT ADDTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
            -> '1998-01-02 01:01:01.000001'
    mysql> SELECT ADDTIME("01:00:00.999999", "02:00:00.999998");
            -> '03:00:01.999997'
    

    ADDTIME() は MySQL 4.1.1 で追加された。

  • CURDATE()

    文字列と数値のどちらのコンテキストで使用されているかに応じて、'YYYY-MM-DD' または YYYYMMDD 形式の値として、現在の日付を返す。

    mysql> SELECT CURDATE();
            -> '1997-12-15'
    mysql> SELECT CURDATE() + 0;
            -> 19971215
    

  • CURRENT_DATE , CURRENT_DATE()

    CURRENT_DATECURRENT_DATE()CURDATE() のシノニム。

  • CURTIME()

    文字列と数値のどちらのコンテキストで使用されているかに応じて、'HH:MM:SS' または HHMMSS 形式の値として、現在の時刻を返す。

    mysql> SELECT CURTIME();
            -> '23:50:26'
    mysql> SELECT CURTIME() + 0;
            -> 235026
    

  • CURRENT_TIME , CURRENT_TIME()

    CURRENT_TIMECURRENT_TIME()CURTIME() のシノニム。

  • CURRENT_TIMESTAMP , CURRENT_TIMESTAMP()

    CURRENT_TIMESTAMPCURRENT_TIMESTAMP()NOW() のシノニム。

  • DATE(expr)

    日付式または日付時刻式 expr の日付部分を取り出す。

    mysql> SELECT DATE('2003-12-31 01:02:03');
            -> '2003-12-31'
    

    DATE() は MySQL 4.1.1 以降で使用できる。

  • DATEDIFF(expr,expr2)

    DATEDIFF() は開始日 expr と終了日 expr2 との間の日数を返す。 exprexpr2 には、日付式か、日付時刻式を指定する。 計算は値の日付部分のみに基づいて行われる。

    mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
            -> 1
    mysql> SELECT DATEDIFF('1997-11-31 23:59:59','1997-12-31');
            -> -30
    

    DATEDIFF() は MySQL 4.1.1 で追加された。

  • DATE_ADD(date,INTERVAL expr type) , DATE_SUB(date,INTERVAL expr type)

    これらの関数では日付演算が実行される。

    MySQL バージョン 3.23 以降では、+ 演算子のどちらかの側にINTERVAL expr type を使用できる。この場合、もう一方の側の式には日付値または日付時刻値を指定する。 - 演算子を使用する場合は、演算子の右側にのみ INTERVAL expr type を使用できる。これは、日付値または日付時刻値を間隔から差し引いても意味がないため(下の例を参照)。

    date には、開始日とする DATETIME または DATE 値を指定する。expr には、開始日に加える、または開始日から差し引く間隔値を表す式を文字列として指定する。先頭に ‘-’ を付けて負の間隔を表すこともできる。type には、式の解釈方法を示すキーワードを指定する。

    次の表に、type 引数と expr 引数がどのように関連するかを示す。

    type 前提となる expr形式
    SECONDSECONDS
    MINUTEMINUTES
    HOURHOURS
    DAYDAYS
    MONTHMONTHS
    YEARYEARS
    MINUTE_SECOND'MINUTES:SECONDS'
    HOUR_MINUTE'HOURS:MINUTES'
    DAY_HOUR'DAYS HOURS'
    YEAR_MONTH'YEARS-MONTHS'
    HOUR_SECOND'HOURS:MINUTES:SECONDS'
    DAY_MINUTE'DAYS HOURS:MINUTES'
    DAY_SECOND'DAYS HOURS:MINUTES:SECONDS'
    DAY_MICROSECOND'DAYS.MICROSECONDS'
    HOUR_MICROSECOND'HOURS.MICROSECONDS'
    MINUTE_MICROSECOND'MINUTES.MICROSECONDS'
    SECOND_MICROSECOND'SECONDS.MICROSECONDS'
    MICROSECOND'MICROSECONDS'

    typeDAY_MICROSECONDHOUR_MICROSECONDMINUTE_MICROSECONDSECOND_MICROSECONDMICROSECOND は、MySQL 4.1.1 以降で使用できる。

    MySQL では、expr の形式で任意の句読記号を使用できる。 上の表では、これらの句読記号の一部を示している。date 引数に DATE 型の値を指定し、計算に YEARMONTHDAY 部分のみを組み込む(つまり、時刻部分は含めない)場合、結果は DATE 型の値になる。それ以外の場合、DATETIME 型の値が返される。

    mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;
            -> '1998-01-01 00:00:00'
    mysql> SELECT INTERVAL 1 DAY + '1997-12-31';
            -> '1998-01-01'
    mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND;
            -> '1997-12-31 23:59:59'
    mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
        ->                 INTERVAL 1 SECOND);
            -> '1998-01-01 00:00:00'
    mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
        ->                 INTERVAL 1 DAY);
            -> '1998-01-01 23:59:59'
    mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
        ->                 INTERVAL '1:1' MINUTE_SECOND);
            -> '1998-01-01 00:01:00'
    mysql> SELECT DATE_SUB('1998-01-01 00:00:00',
        ->                 INTERVAL '1 1:1:1' DAY_SECOND);
            -> '1997-12-30 22:58:59'
    mysql> SELECT DATE_ADD('1998-01-01 00:00:00',
        ->                 INTERVAL '-1 10' DAY_HOUR);
            -> '1997-12-30 14:00:00'
    mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
            -> '1997-12-02'
    mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
        ->                 INTERVAL '1.999999' SECOND_MICROSECOND);
            -> '1993-01-01 00:00:01.000001'
    

    指定した間隔値が短すぎる場合(つまり、type キーワードによって想定される間隔部分の一部を含んでいない場合)、MySQL では、間隔値の左端の部分がないとみなされる。たとえば、typeDAY_SECOND として指定すると、expr の値は、日、時、分、秒の各部で構成されると想定される。この場合、'1:10' のような値を指定すると、値は日部分と時間部分を持たず、分と秒を表すと解釈される。つまり、'1:10' DAY_SECOND と指定した場合、'1:10' MINUTE_SECOND と指定した場合と同じように解釈されることになる。これは、MySQL で TIME 値が 1 日の時刻ではなく経過時間として解釈されるのに類する。

    注意:時刻部分を持つ値を日付値に加えたり、日付値から差し引いたりすると、結果は自動的に日付時刻型の値に変換される。

    mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);
            -> '1999-01-02'
    mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);
            -> '1999-01-01 01:00:00'
    

    誤った日付を使用すると、結果は NULL になる。MONTHYEAR_MONTHYEAR のいずれかを加えた結果の日付が、新しい月の最大日数より大きい場合、新しい月の最大日数に調整される。

    mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);
            -> '1998-02-28'
    

    注意: 上記の例で、キーワード INTERVALtype 指定子はケース非依存。

  • DATE_FORMAT(date,format)

    format 文字列に合わせて、date 値を形式設定する。format 文字列では、次の指定子を使用できる。

    指定子説明
    %M月の名前(January..December)。
    %W曜日名(Sunday..Saturday)。
    %D英語のサフィックス付きの日付(0th1st2nd3rd など)。
    %Y4 桁の数値で表した年。
    %y2 桁の数値で表した年。
    %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)。
    %r12 時間形式の時刻(hh:mm:ss に続けて AM または PM)。
    %T24 時間形式の時刻(hh:mm:ss)。
    %S秒(00..59)。
    %s秒(00..59)。
    %fマイクロ秒(000000..999999)。
    %pAM または 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_FORMATTIME_FORMATDATETIME_FORMAT を設定したりするときに役立つ。最初の引数には 3 つの入力可能値があり、2 番目の引数には 5 つの入力可能値があるため、結果として返されるフォーマット文字列は全部で 15 通りある(使用される指定子については、DATE_FORMAT() 関数の説明に含まれている表を参照)。

    関数呼び出し結果
    GET_FORMAT(DATE,'USA')'%m.%d.%Y'
    GET_FORMAT(DATE,'JIS')'%Y-%m-%d'
    GET_FORMAT(DATE,'ISO')'%Y-%m-%d'
    GET_FORMAT(DATE,'EUR')'%d.%m.%Y'
    GET_FORMAT(DATE,'INTERNAL')'%Y%m%d'
    GET_FORMAT(TIMESTAMP,'USA')'%Y-%m-%d-%H.%i.%s'
    GET_FORMAT(TIMESTAMP,'JIS')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(TIMESTAMP,'ISO')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(TIMESTAMP,'EUR')'%Y-%m-%d-%H.%i.%s'
    GET_FORMAT(TIMESTAMP,'INTERNAL')'%Y%m%d%H%i%s'
    GET_FORMAT(TIME,'USA')'%h:%i:%s %p'
    GET_FORMAT(TIME,'JIS')'%H:%i:%s'
    GET_FORMAT(TIME,'ISO')'%H:%i:%s'
    GET_FORMAT(TIME,'EUR')'%H.%i.%S'
    GET_FORMAT(TIME,'INTERNAL')'%H%i%s'

    ISO 形式は ISO 8601 ではなく、ISO 9075。

    mysql> SELECT DATE_FORMAT('2003-10-03', GET_FORMAT(DATE, 'EUR')
            -> '03.10.2003'
    mysql> SELECT STR_TO_DATE('10.31.2003', GET_FORMAT(DATE, 'USA'))
            -> 2003-10-31
    mysql> SET DATE_FORMAT=GET_FORMAT(DATE, 'USA'); SELECT '2003-10-31';
            -> 10-31-2003
    

    GET_FORMAT() は MySQL 4.1.1 以降で使用できる。 See 項5.5.6. 「SET 構文」 を参照。

  • HOUR(time)

    time に指定された時刻の時間部分の値を返す。戻り値の範囲は、1 日の時間を示す値の場合は 0 から 23

    mysql> SELECT HOUR('10:05:03');
            -> 10
    

    しかし、TIME 値の範囲は、実際にはこれよりずっと広いため、23 より大きい値が HOUR として返ることがある。

    mysql> SELECT HOUR('272:59:59');
            -> 272
    

  • LAST_DAY(date)

    指定された日付または日付時刻の値に対し、その値が含まれる月の最後の日にちを返す。引数が無効な場合は、NULL を返す。

    mysql> SELECT LAST_DAY('2003-02-05'), LAST_DAY('2004-02-05');
            -> '2003-02-28', '2004-02-29'
    mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
            -> '2004-01-31'
    mysql> SELECT LAST_DAY('2003-03-32');
            -> NULL
    

    LAST_DAY() は MySQL 4.1.1 以降で使用できる。

  • LOCALTIME , LOCALTIME()

    LOCALTIMELOCALTIME()NOW() のシノニム。

  • LOCALTIMESTAMP , LOCALTIMESTAMP()

    LOCALTIMESTAMPLOCALTIMESTAMP()NOW() のシノニム。

  • MAKEDATE(year,dayofyear)

    指定された年の値と年間を通した日にちの値に対応する日付を返す。 dayofyear には、0 より大きい値を指定する必要がある。0 以下の値を指定すると、結果として NULL が返される。

    mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);
            -> '2001-01-31', '2001-02-01'
    mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
            -> '2001-12-31', '2004-12-30'
    mysql> SELECT MAKEDATE(2001,0);
            -> NULL
    

    MAKEDATE() は MySQL 4.1.1 以降で使用できる。

  • MAKETIME(hour,minute,second)

    引数 hourminutesecond に指定された値から計算した時刻値を返す。

    mysql> SELECT MAKETIME(12,15,30);
            -> '12:15:30'
    

    MAKETIME() は MySQL 4.1.1 以降で使用できる。

  • MICROSECOND(expr)

    時刻式または日付時刻式 expr からマイクロ秒を、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 に指定された月数を期間 PYYMM または YYYYMM の形式)に加える。戻り値は YYYYMM の形式で返る。

    注意: 期間引数 P には、日付値を指定しないようにする。

    mysql> SELECT PERIOD_ADD(9801,2);
            -> 199803
    

  • PERIOD_DIFF(P1,P2)

    期間 P1P2 の間の月数を返す。 P1P2 の指定は YYMM または YYYYMM 形式で行う。

    注意: 期間引数 P1P2 には、日付値を指定しないようにする。

    mysql> SELECT PERIOD_DIFF(9802,199703);
            -> 11
    

  • QUARTER(date)

    date に指定された日付に対応する四半期を、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 の間の時間が返される。 exprexpr2 には、時刻式か日付時刻式を指定できるが、どちらも同じ型にしなければならない。

    mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00.000001');
            -> '-00:00:00.000001'
    mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001','1997-12-30 01:01:01.000002');
            -> '46:58:57.999999'
    

    TIMEDIFF() は MySQL 4.1.1 で追加された。

  • TIMESTAMP(expr) , TIMESTAMP(expr,expr2)

    引数が 1 つの場合は、日付式または日付時刻式 expr を日付時刻値として返す。 引数が 2 つの場合は、日付式または日付時刻式 expr に時刻式 expr2 を加えた結果を日付時刻値として返す。

    mysql> SELECT TIMESTAMP('2003-12-31');
            -> '2003-12-31 00:00:00'
    mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
            -> '2004-01-01 00:00:00'
    

    TIMESTAMP() は MySQL 4.1.1 以降で使用できる。

  • TIME_FORMAT(time,format)

    この関数の使用法は DATE_FORMAT() 関数と同様だが、この関数の場合、format に指定できる文字列は、時、分、秒を処理する形式指定子に限られる。その他の指定子を指定した場合は、NULL 値または 0 が返される。

    time 値の時間部分が 23 より大きい場合、時間形式指定子 %H%k では、通常の範囲 0..23 より大きい値が生成される。その他の時間形式指定子では、時間値のモジュロ 12 が生成される。

    mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');
            -> '100 100 04 04 4'
    

  • TIME_TO_SEC(time)

    time 引数に指定された時刻を秒数に変換して返す。

    mysql> SELECT TIME_TO_SEC('22:23:00');
            -> 80580
    mysql> SELECT TIME_TO_SEC('00:39:38');
            -> 2378
    

  • TO_DAYS(date)

    date に指定された日付を日数(年 0 からの通し日数)に変換して返す。

    mysql> SELECT TO_DAYS(950501);
            -> 728779
    mysql> SELECT TO_DAYS('1997-10-07');
            -> 729669
    

    TO_DAYS() では、グレゴリオ暦(1582 年)より前の値の指定は想定していない。これは、カレンダが変更されたときに失われた日数が考慮されないため。

  • UNIX_TIMESTAMP() , UNIX_TIMESTAMP(date)

    引数なしで呼び出された場合、Unix タイムスタンプ('1970-01-01 00:00:00' GMT からの秒数)を符号なしの整数として返す。date 引数を指定して呼び出された場合、UNIX_TIMESTAMP() は引数に指定された日付を '1970-01-01 00:00:00' GMT からの秒数として返す。引数 date には、DATE 型文字列、DATETIME 型文字列、TIMESTAMP 型の値、YYMMDD または YYYYMMDD の形式の現地時間のいずれかを指定できる。

    mysql> SELECT UNIX_TIMESTAMP();
            -> 882226357
    mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
            -> 875996580
    

    UNIX_TIMESTAMPTIMESTAMP 型のカラムに使用すると。``文字列から Unix タイムスタンプへの'' 暗黙的な変換を行わずに、内部のタイムスタンプ値が直接返される。 UNIX_TIMESTAMP() に範囲外の日付を渡すと、0 が返されるが、この場合、実行されるチェックは基本チェック(年 1970 ? 2037、月 01 ? 12、日 01 ? 31)に限られる。

    UNIX_TIMESTAMP() カラム値を差し引く場合、結果を符号付き整数にキャストする必要がある場合がある。 See 項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() 関数では、指定した年のコンテキストで週数が返される。

6.3.5. キャスト関数

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 では、DATEDATETIMETIME 型のカラムに CAST() 操作を行った場合、カラムが特定の型としてマークされるだけで、カラム値が変わるわけではありません。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

SELECT CONVERT('abc' USING utf8);

6.3.6. その他の関数

6.3.6.1. ビット関数

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

  • |

    ビットごとの OR。

    mysql> SELECT 29 | 15;
            -> 31
    

    結果は符合なしの 64 ビット整数。

  • &

    ビットごとの AND。

    mysql> SELECT 29 & 15;
            -> 13
    

    結果は符合なしの 64 ビット整数。

  • ^

    ビットごとの XOR。

    mysql> SELECT 1 ^ 1;
            -> 0
    mysql> SELECT 1 ^ 0;
            -> 1
    mysql> SELECT 11 ^ 3;
            -> 8
    

    結果は符合なしの 64 ビット整数。

    XOR はバージョン 4.0.2 で追加された。

  • <<

    longlong(BIGINT)値のビットを左にシフトする。

    mysql> SELECT 1 << 2;
            -> 4
    

    結果は符合なしの 64 ビット整数。

  • >>

    longlong(BIGINT)値のビットを右にシフトする。

    mysql> SELECT 4 >> 2;
            -> 1
    

    結果は符合なしの 64 ビット整数。

  • ~

    すべてのビットを反転させる。

    mysql> SELECT 5 & ~1;
            -> 4
    

    結果は符合なしの 64 ビット整数。

  • BIT_COUNT(N)

    引数 N に指定された数値を 2 進表記したときに 1 に設定されるビット数を返す。

    mysql> SELECT BIT_COUNT(29);
            -> 4
    

6.3.6.2. その他の各種関数

  • AES_ENCRYPT(string,key_string) , AES_DECRYPT(string,key_string)

    これらの関数では、公式の AES(Advanced Encryption Standard)アルゴリズム(以前、Rijndael と呼ばれていたもの)を使用してデータの暗号化と解読を実行できる。 エンコードに使用されるキー長は 128 ビットだが、ソースを変更することによって、256 ビットまで拡張できる。MySQL では 128 ビットを選択している。その理由は、そのほうが迅速で、かつ通常、安全性も十分に確保できるため。

    入力引数は任意の長さにすることができる。どちらかの引数として NULL を指定した場合、この関数の結果も NULL になる。

    AES はブロックレベルのアルゴリズムであるため、不揃いの長さの文字列のエンコード時には埋め込みが行われる。したがって、結果の文字列の長さは 16*(trunc(string_length/16)+1) として計算することができる。

    AES_DECRYPT() では、無効なデータや誤った埋め込みが検出されると、NULL が返される。しかし、入力データやキーが無効でも、AES_DECRYPT() から NULL 以外の値(ガベージなど)が返されることがある。

    クエリを次のように変更することによって、AES 関数を使用して暗号形式でデータを格納できる。

    INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'));
    

    各クエリの接続を通したキーの転送を行わないようにすれば、さらにセキュリティを強化することができる。この場合、キーは接続時にサーバ側の変数に格納する。

    SELECT @password:='my password';
    INSERT INTO t VALUES (1,AES_ENCRYPT('text',@password));
    

    AES_ENCRYPT()AES_DECRYPT() はバージョン 4.0.2 で追加された。この 2 つは、現在のところ MySQL で使用可能な、暗号化方式として最も安全性の高い暗号化関数としてみなすことができる。

  • BENCHMARK(count,expr)

    BENCHMARK() 関数は、expr に指定された式を count に指定された回数だけ繰り返し実行する。この関数は、MySQL での式の処理速度を計測するために使用できる。結果の値としては、常に 0 が返る。この関数を mysql クライアントで使用することによって、クエリの実行時間をレポートすることができる。

    mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
    +----------------------------------------------+
    | BENCHMARK(1000000,ENCODE("hello","goodbye")) |
    +----------------------------------------------+
    |                                            0 |
    +----------------------------------------------+
    1 row in set (4.74 sec)
    

    レポートされる時間は、サーバ側の CPU 時間ではなく、クライアント側の経過時間である。BENCHMARK() を数回実行し、結果を分析することによって、サーバマシンの負荷がどれくらいか調べることができる。

  • COMPRESS(string_to_compress)

    文字列を圧縮する。

    mysql> SELECT LENGTH(COMPRESS(REPEAT("a",1000)));
            -> 21
    mysql> SELECT LENGTH(COMPRESS(""));
            -> 0
    mysql> SELECT LENGTH(COMPRESS("a"));
            -> 13
    mysql> SELECT LENGTH(COMPRESS(REPEAT("a",16)));
            -> 15
    

    COMPRESS() は MySQL バージョン 4.1.1 で追加された。 この関数を使用するためには、zlib などの圧縮ライブラリを使用して MySQL をコンパイルしておく必要がある。コンパイルを行っていないと、戻り値は常に NULL になる。

    圧縮した文字列の内容は次の方法で格納される。

    • 空の文字列は空の文字列として格納される。

    • 空以外の文字列は、まず 4 バイトの長さの非圧縮文字列として格納され(下位バイトが先)、その後 gzip によって文字列が圧縮される。文字列がスペースで終わっている場合は、追加の ‘.’ が挿入される。これは、結果を CHAR 型または VARCHAR 型のカラムに格納する場合に末尾のスペースの切り取りで問題が発生しないようにするため。しかし、CHAR 型や VARCHAR 型カラムへの圧縮文字列の格納は推奨されない。代わりに、BLOB 型のカラムを使用するようにする。

  • CONNECTION_ID()

    接続の接続 ID(スレッド ID)を返す。 各接続にはその接続固有の一意な ID が割り当てられる。

    mysql> SELECT CONNECTION_ID();
            -> 23786
    

  • CURRENT_USER()

    現在のセッションの認証に使用されたユーザ名とホスト名を返す。この値はアクセス権限の評価に使用されるアカウントに対応している。USER() の値とは異なる場合がある。

    mysql> SELECT USER();
            -> 'davida@localhost'
    mysql> SELECT * FROM mysql.user;
            -> ERROR 1044: Access denied for user: '@localhost' to database 'mysql'
    mysql> SELECT CURRENT_USER();
            -> '@localhost'
    

    上の例では、クライアントがユーザ名として davida を指定している(USER() の値により)にもかかわらず、サーバは匿名ユーザアカウントでクライアントの認証を行っている(CURRENT_USER() 値のユーザ名の部分が空)のがわかる。このようなことが起こる原因の 1 つとして、davida の権限テーブルにアカウントが登録されていない場合が考えられる。

  • DATABASE()

    カレントデータベース名を返す。

    mysql> SELECT DATABASE();
            -> 'test'
    

    カレントデータベースがない場合、DATABASE() は、MySQL 4.1.1 以降では NULL を返し、それ以前のバージョンでは空の文字列を返す。

  • DECODE(crypt_str,pass_str)

    pass_str に指定された文字列をパスワードとして使用して、暗号化された文字列 crypt_str を解読する。crypt_strENCODE() から返された文字列でなければならない。

  • ENCODE(str,pass_str)

    pass_str に指定された文字列をパスワードとして使用して、str を暗号化する。 暗号化された結果を解読するには、 DECODE() を使用する。

    結果として、string と同じ長さのバイナリ文字列が返される。 この文字列をカラムに保存するには、BLOB 型のカラムを使用する。

  • DES_DECRYPT(string_to_decrypt [, key_string])

    DES_ENCRYPT() で暗号化された文字列を解読する。

    注意: この関数は、MySQL で SSL のサポートが組み込まれている場合にのみ機能する。 See 項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 に指定された桁数に丸めて、'#,###,###.##' のような形式に設定し、結果を文字列として返す。 D0 の場合、結果の値は小数点も小数部も持たない。

    mysql> SELECT FORMAT(12332.123456, 4);
            -> '12,332.1235'
    mysql> SELECT FORMAT(12332.1,4);
            -> '12,332.1000'
    mysql> SELECT FORMAT(12332.2,0);
            -> '12,332'
    

  • FOUND_ROWS()

    SELECT ステートメントに LIMIT 節を組み込むことによって、サーバがクライアントに返すレコード数を制限できる。 状況によっては、LIMIT を指定しなかった場合にいくつのレコードが返されるかを、ステートメントを再度実行することなく確認したいことがある。 このレコード数を確認するには SELECT ステートメントに SQL_CALC_FOUND_ROWS オプションを指定し、その後 FOUND_ROWS() を呼び出す。

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
           WHERE id > 100 LIMIT 10;
    mysql> SELECT FOUND_ROWS();
    

    2 番目の SELECT では、最初の SELECTLIMIT 節なしで実行した場合に返されるレコード数を示す数が返る(先行する SELECT ステートメントに SQL_CALC_FOUND_ROWS オプションが含まれていないと、FOUND_ROWS()LIMIT が使用されない場合とは異なる、LIMIT が使用されたときの結果を返す)。

    注意: SELECT SQL_CALC_FOUND_ROWS ... を使用した場合、MySQL では完全な結果セットに含まれるレコード数を計算する必要が生じる。しかし、この場合、結果セットをクライアントに送る必要がないため、LIMIT なしで再度クエリを実行するより時間がかからない。

    SQL_CALC_FOUND_ROWSFOUND_ROWS() は、クエリで返されるレコード数を制限する必要がある場合に、完全な結果セットに含まれるレコード数を(クエリを再実行することなく)確認したいときに役立つ。例として、検索結果の別のセクションを示すページへのリンクを含むページ画面を表示する Web スクリプトを挙げることができる。FOUND_ROWS() を使用すると、結果の残りの部分を表示するのにあと何ページ必要か確認できる。

    SQL_CALC_FOUND_ROWSFOUND_ROWS()UNION クエリで使用した場合、単純な SELECT ステートメントで使用した場合よりも複雑になる。これは、LIMITUNION 内の複数の場所で起こり得るためである。LIMIT は、UNION 内の個々の SELECT ステートメントに適用することも、UNION の結果全体にグローバルに適用することもできる。

    UNION に対して SQL_CALC_FOUND_ROWS を使用する目的は、このオプションによって、グローバルな LIMIT を指定しなかった場合に返されるレコード数を確認できることにある。 UNION での SQL_CALC_FOUND_ROWS の使用には、以下の条件が適用される。

    • UNION の最初の SELECTSQL_CALC_FOUND_ROWS キーワードが指定されていなければならない。

    • FOUND_ROWS() の値は UNION ALL の使用時のみ正確になる。 ALL なしで UNION を使用した場合、重複の削除が行われるため、FOUND_ROWS() の値は近似値にすぎない。

    • UNION 内に LIMIT が存在しない場合、SQL_CALC_FOUND_ROWS は無視され、UNION を処理するために作成されたテンポラリテーブル内のレコード数が返される。

    SQL_CALC_FOUND_ROWSFOUND_ROWS() は MySQL バージョン 4.0.0 以降で使用できる。

  • GET_LOCK(str,timeout)

    str に指定された名前のロックを取得しようと試みる。この場合、timeout に指定された秒数をタイムアウトとする。正常にロックが取得されたときは 1 を返し、ロックの取得がタイムアウトになった(指定された名前が別のクライアントによってすでにロックされている場合など)ときは 0 を返し、エラーが発生した(メモリ不足や、mysqladmin kill でスレッドが強制終了された場合など)ときは NULL を返す。ロックは、RELEASE_LOCK() が実行されるか、新しい GET_LOCK() が実行されるか、またはスレッドが終了する(正常終了または異常終了)と解除される。

    この関数はアプリケーションのロックを実行したり、レコードのロックをシミュレーションしたりする目的で使用できる。名前はサーバ全体の範囲で有効である。 1 つのクライアントがある名前のロックを得ている場合、GET_LOCK() は、その名前のロックに対する、別のクライアントからのすべての要求をブロックする。 ある名前のロックをもとにすれば、各クライアント間での同期をとらせるような動作が可能である:

    mysql> SELECT GET_LOCK("lock1",10);
            -> 1
    mysql> SELECT IS_FREE_LOCK("lock2");
            -> 1
    mysql> SELECT GET_LOCK("lock2",10);
            -> 1
    mysql> SELECT RELEASE_LOCK("lock2");
            -> 1
    mysql> SELECT RELEASE_LOCK("lock1");
            -> NULL
    

    注意: 2 番目の RELEASE_LOCK() 呼び出しでは NULL が返される。これは、ロック "lock1" が 2 番目の GET_LOCK() 呼び出しによって自動的に解除されるため。

  • INET_ATON(expr)

    文字列として指定された、ドット 10 進表記のネットワークアドレスを、そのアドレスの数値を表す整数として返す。 アドレスとして、4 バイトまたは 8 バイトのアドレスを指定できる。

    mysql> SELECT INET_ATON("209.207.224.40");
           ->  3520061480
    

    生成される数値は、常にネットワークバイトオーダーで生成される。たとえば、上の例の数値は、209*256^3 + 207*256^2 + 224*256 +40 として計算される。

  • INET_NTOA(expr)

    数値として表現されたネットワークアドレス(4 または 8 バイト)を、ドット 10 進表記のアドレス(文字列)として返す。

    mysql> SELECT INET_NTOA(3520061480);
           ->  "209.207.224.40"
    

  • IS_FREE_LOCK(str)

    str に指定された名前をもつロックが解放されているかどうか(つまり、ロックされていないかどうか)確認する。 ロックが解放されている(誰もそのロックを使用していない)場合は 1 を返し、そのロックが使用されている場合は 0 を返し、エラーが発生した(引数に誤りがあるなど)場合は NULL を返す。

  • LAST_INSERT_ID([expr])

    AUTO_INCREMENT カラムに挿入された値のうち、最後に自動生成された値を返す。

    mysql> SELECT LAST_INSERT_ID();
            -> 195
    

    生成された最後の ID は、接続ごとにサーバで維持される。したがって、この関数から個々のクライアントに返される値は、そのクライアントによって生成された最新の AUTO_INCREMENT 値である。この値は、他のクライアントがそれぞれの AUTO_INCREMENT 値を生成しても、それによって影響されることはない。この動作によって、他のクライアントの活動にかかわりなく、また、ロックやトランザクションを必要とすることなく、自分の ID を確実に取り出すことができる。

    非マジック値(つまり、NULL でも 0 でもない値)を持つレコードの AUTO_INCREMENT カラムを更新しても、LAST_INSERT_ID() の値は変更されない。

    INSERT ステートメントで同時に複数のレコードを挿入した場合、LAST_INSERT_ID() は最初に挿入されたレコードの値を返す。これは、同じ INSERT ステートメントを他のいずれかのサーバに対して簡単に再生成できるようにするためである。

    LAST_INSERT_ID() の引数として expr を指定した場合、引数の値が関数から返され、この値が LAST_INSERT_ID() によって返される次の値として設定される。これはシーケンスのシミュレーションに使用できる。

    まず、テーブルを作成する。

    mysql> CREATE TABLE sequence (id INT NOT NULL);
    mysql> INSERT INTO sequence VALUES (0);
    

    その後、このテーブルを使用してシーケンス番号を次のように生成できる。

    mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
    

    シーケンスの生成は LAST_INSERT_ID() を呼び出さなくても可能だが、この関数をこのように使用した場合、ID 値が最後に自動生成された値としてサーバに維持される(マルチユーザ対応)。 新しい ID は、MySQL で通常の AUTO_INCREMENT 値を読み取るときと同じように取り出せる。たとえば、LAST_INSERT_ID()(引数はいずれもなし)では、新しい ID が返される。C API 関数 mysql_insert_id() もこの ID 値の取得に使用できる。

    注意: mysql_insert_id() が更新されるのは、INSERT ステートメントや UPDATE ステートメントの後になるため、SELECTSET などの他の SQL ステートメントの実行後に、C API 関数を使用して LAST_INSERT_ID(expr) の値を取り出すことはできない。 See 項11.1.3.32. 「mysql_insert_id()

  • MASTER_POS_WAIT(log_name, log_pos [, timeout])

    スレーブがマスタログの指定された位置に達する(つまり、指定された位置まで更新をすべて読み取って適用する)までブロックする。マスタ情報が初期化されていない場合や、引数に誤りがある場合は、NULL を返す。スレーブが実行されていない場合は、スレーブが開始され、指定された位置まで到達するか、これを通過するまで、ブロックして待機する。スレーブが指定された位置をすでに通過している場合、この関数は直ちに戻る。

    timeout(4.0.10 で導入)が指定されている場合は、timeout に指定された秒数が経過すると待機を中止する。timeout 値は 0 より大きくなければならない。ゼロや負の timeout 値はタイムアウトなしを意味する。戻り値として、指定された位置に到達するまでに待機しなければならかったログイベントの数が返される。エラー時には、NULL が返され、タイムアウトを超過した場合は -1 が返される。

    このコマンドはマスタとスレーブの同期化に役立つ。

  • MD5(string)

    指定された文字列の MD5 128 ビットチェックサムを計算する。値は 32 ビットの 16 進数として返される。この値は、ハッシュキーなどとして使用できる。

    mysql> SELECT MD5("testing");
            -> 'ae2b1fca515949e5d54fb22b8ed95575'
    

    これは "RSA Data Security, Inc. の MD5 Message-Digest Algorithm"。

  • PASSWORD(str) , OLD_PASSWORD(str)

    平文テキストのパスワード str からパスワード文字列を計算する。これは、user 権限テーブルの Password カラムに格納する MySQL パスワードの暗号化に使用される関数。

    mysql> SELECT PASSWORD('badpwd');
            -> '7f84554057dd964b'
    

    PASSWORD() の暗号化は可逆ではない。

    PASSWORD() は、パスワードの暗号化を Unix パスワードの暗号化と同じ方法では行わない。ENCRYPT() を参照。

    注意: PASSWORD() 関数は、MySQL サーバの認証システムで使用される。アプリケーションでは使用しないこと。 アプリケーション用には、MD5()SHA1() を代わりに使用する。 アプリケーションでのパスワードと認証の安全な処理の詳細については、 RFC-2195 も参照。

  • RELEASE_LOCK(str)

    GET_LOCK() によって取得された、文字列 str を名前として持つロックを解除する。そのロックが解除された場合は 1 を返し、そのロックがこのスレッドによってロックされているのでない場合は 0 を返し(この場合、ロックは解除されない)、指定されたロックが存在しない場合は NULL を返す(そのロックが GET_LOCK() を呼び出して取得されたのでない場合や、すでに解除されている場合、そのロックは存在しないことになる)。

    DO ステートメントを RELEASE_LOCK() で使用すると便利である。 See 項6.4.10. 「DO 構文」

  • SESSION_USER()

    SESSION_USER()USER() のシノニム。

  • SHA1(string) , SHA(string)

    指定された文字列に対して、RFC 3174(Secure Hash Algorithm)に定義された SHA1 160 ビットチェックサムを計算する。値は 40 桁の 16 進数として返される。入力引数が NULL の場合は、NULL が返される。 この関数の用途の 1 つとして、戻り値をハッシュキーとして使用できる。また、この関数は、パスワードを格納するための安全な暗号化関数としても使用できる。

    mysql> SELECT SHA1("abc");
            -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
    

    SHA1() はバージョン 4.0.2 で追加された。この関数は MD5() よりもさらに安全度が高い暗号化関数とみなすことができる。 SHA()SHA1() のシノニム。

  • SYSTEM_USER()

    SYSTEM_USER()USER() のシノニム。

  • UNCOMPRESS(string_to_uncompress)

    COMPRESS() 関数によって圧縮された文字列の圧縮を解除する。

    mysql> SELECT UNCOMPRESS(COMPRESS("any string"));
            -> 'any string'
    

    UNCOMPRESS() は MySQL バージョン 4.1.1 で追加された。 この関数を使用するためには、zlib などの圧縮ライブラリを使用して MySQL をコンパイルしておく必要がある。コンパイルを行っていないと、戻り値は常に NULL になる。

  • UNCOMPRESSED_LENGTH(compressed_string)

    圧縮文字列の圧縮前の長さを返す。

    mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT("a",30)));
            -> 30
    

    UNCOMPRESSED_LENGTH() は MySQL バージョン 4.1.1 で追加された。

  • USER()

    現在の MySQL ユーザ名とホスト名を返す。

    mysql> SELECT USER();
            -> 'davida@localhost'
    

    戻り値は、サーバへの接続時に指定したユーザ名と、接続元のクライアントホストを表す(MySQL バージョン 3.22.11 より前のバージョンでは、この関数の戻り値にはクライアントホスト名は含まれない)。

    次のようにした場合、値にホスト名の部分が含まれているかどうかにかかわらず、ユーザ名の部分だけを取り出すこともできる。

    mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
            -> 'davida'
    

  • VERSION()

    MySQL サーバのバージョンを示す文字列を返す。

    mysql> SELECT VERSION();
            -> '3.23.13-log'
    

    注意: バージョンの後ろに -log が付いている場合、ログが有効になっていることを表す。

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

6.3.7.1. GROUP BY 関数

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

  • AVG(expr)

    expr の平均値を返す。

    mysql> SELECT student_name, AVG(test_score)
        ->        FROM student
        ->        GROUP BY student_name;
    

  • BIT_AND(expr)

    expr のすべてのビットに対するビットごとの AND を返す。この計算は 64 ビット(BIGINT)の精度で実行される。

    MySQL 4.0.17 以降では、マッチするレコードがない場合、この関数は 18446744073709551615 を返す(これはすべてのビットを 1 に設定した、符号なしの BIGINT 値)。 4.0.17 より前のバージョンでは、マッチするレコードがない場合、この関数は -1 を返す。

  • BIT_OR(expr)

    expr のすべてのビットに対するビットごとの OR を返す。この計算は 64 ビット(BIGINT)の精度で実行される。

    マッチするレコードがない場合、この関数は 0 を返す。

  • BIT_XOR(expr)

    expr のすべてのビットに対するビットごとの XOR を返す。この計算は 64 ビット(BIGINT)の精度で実行される。

    マッチするレコードがない場合、この関数は 0 を返す。

    この関数は MySQL 4.1.1 以降で使用できる。

  • COUNT(expr)

    SELECT ステートメントで取り出されたレコードのうち、NULL 以外の値の数のカウントを返す。

    mysql> SELECT student.student_name,COUNT(*)
        ->        FROM student,course
        ->        WHERE student.student_id=course.student_id
        ->        GROUP BY student_name;
    
    

    COUNT(*) は、レコードに NULL 値が含まれているかどうかにかかわらず、取り出されたレコード数のカウントを返すという点で多少異なる。

    SELECT で 1 つのテーブルから値を取り出し、他のカラムからは値を取り出さず、かつ WHERE 節がない場合、COUNT(*) は迅速に戻るよう最適化される。次に例を示す。

    mysql> SELECT COUNT(*) FROM student;
    

    この最適化は、MyISAM テーブルと ISAM テーブルにのみ適用される。これは、この 2 つのテーブル型では正確なレコードカウントが格納され、迅速にアクセスできるためである。トランザクションストレージエンジン(InnodB, BDB)の場合、複数のトランザクションが発生し、それぞれがカウントに影響する場合があるため、正確なレコードカウントの格納はより難しくなる。

  • COUNT(DISTINCT expr,[expr...])

    NULL 以外の異なる各値の数のカウントを返す。

    mysql> SELECT COUNT(DISTINCT results) FROM student;
    

    MySQL では、式のリストを指定することによって、NULL を含まない、重複のない式の組み合せの数を得ることができる。 SQL-99 では、COUNT(DISTINCT ...) 内ですべての式を連結する必要がある。

  • GROUP_CONCAT(expr)

    完全な構文

    GROUP_CONCAT([DISTINCT] expr [,expr ...]
                 [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
                 [SEPARATOR str_val])
    

    この関数は MySQL バージョン 4.1 で追加された。 この関数はグループ内の値を連結した結果の文字列を返す。

    mysql> SELECT student_name,
        ->        GROUP_CONCAT(test_score)
        ->        FROM student 
        ->        GROUP BY student_name;
    または
    mysql> SELECT student_name,
        ->        GROUP_CONCAT(DISTINCT test_score
        ->                     ORDER BY test_score DESC SEPARATOR " ")
        ->        FROM student
        ->        GROUP BY student_name;
    

    MySQL では、式の組み合わせの連結値を得ることができる。 DISTINCT を使用することで、重複する値は排除できる。 結果の値をソートするには、ORDER BY 節を使用する。 逆の順序でソートするには、ORDER BY 節でソートキーとするカラムの名前に DESC(降順)キーワードを付ける。デフォルトは昇順だが、昇順を明示的に指定するには、ASC キーワードを指定する。 SEPARATOR は結果の値と値の間に挿入する文字列値を表す。デフォルトはカンマ('","')。区切り記号をまったく使用しない場合は、SEPARATOR "" と指定する。

    使用可能な最大長は、変数 group_concat_max_len をオプション設定ファイルに記述することで設定できる。 設定を SQL クエリで行う構文は次のとおり。

    SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
    

    最大長が設定されている場合、結果はこの最大長に合わせて切り捨てられる。

    GROUP_CONCAT() 関数は、Sybase SQL Anywhere でサポートされている基本の LIST() 関数を拡張した実装である。 カラムが 1 つだけで、その他のオプションが指定されていない場合、GROUP_CONCAT() は機能がかなり制限されている LIST() と下位互換になる。ただし、LIST() にはデフォルトのソート順序はある。

  • MIN(expr) , MAX(expr)

    expr の最小値または最大値を返す。MIN()MAX() は文字列引数を取ることができる。その場合、最小または最大の文字列値を返す。 See 項5.4.3. 「MySQL でのインデックスの使用」

    mysql> SELECT student_name, MIN(test_score), MAX(test_score)
        ->        FROM student
        ->        GROUP BY student_name;
    

    MySQL では、現在のところ、MIN()MAX() やその他の集約関数において ENUM 型と SET 型のカラムの比較を、セット内での文字列の相対的な位置ではなくそれぞれの文字列値に基づいて行っている。 これは改正される予定。

  • STD(expr) , STDDEV(expr)

    expr の標準偏差(VARIANCE() の平方根)を返す。これは SQL-99 に対する拡張。この関数の STDDEV() の形式は Oracle との互換性を確保するために提供されている。

  • SUM(expr)

    expr の合計を返す。注意: 戻り値のセットにレコードが含まれていない場合、NULL を返す。

  • VARIANCE(expr)

    expr の標準偏差を返す(レコードはサンプルではなく、母集団全体とみなされる。そのため、この関数はレコード数を分母として取る)。これは SQL-99 に対する拡張(バージョン 4.1 以降で使用可能)。

6.3.7.2. GROUP BY の修飾子

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 特定の年度と国に対応する各製品レコードセットの後に、製品ごとのすべて値の合計を示す追加の集計レコードが 1 つずつ生成される。これらのレコードでは、product カラムの値が NULL に設定される。

  • 特定の年度に対応する各レコードセットの後に、国ごと、製品ごとのすべての値の合計を示す追加の集計レコードが 1 つずつ生成される。これらのレコードでは、country カラムと products カラムの値が NULL に設定される。

  • 最後に、他のすべてのレコードの後に、年度ごと、国ごと、製品ごとのすべての値の総計を示す追加の集計レコードが 1 つ生成される。このレコードでは、yearcountryproducts の各カラムの値が NULL に設定される。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6.4. データの操作: SELECTINSERTUPDATEDELETE

6.4.1. SELECT 構文

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

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

次に例を示します。

mysql> SELECT 1 + 1;
         -> 2

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

  • 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 KEYUSE/IGNORE/FORCE INDEX のシノニム。

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

    MySQL 4.0.14 では、MySQL にテーブルのスキャンよりもキーのスキャンを優先させるための代替方法として、SET MAX_SEEKS_FOR_KEY=value も使用できる。

  • テーブルは(カレントデータベース内のものなら)tbl_name として参照できる。データベースを明示的に指定する場合は、dbname.tbl_name として参照する。 カラムは、col_nametbl_name.col_name、または db_name.tbl_name.col_name として参照できる。SELECT ステートメントでカラムを参照するときには、その参照があいまいにならない限り、カラム名の前に tbl_namedb_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 で指定した任意のカラムまたはエイリアスを参照することができる。この節は、処理の終わり近くになって(項目がクライアントに送られる直前)、最適化されることなく適用される(LIMITHAVING の後に適用)。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;
    
  • DISTINCTDISTINCTROWALL の各オプションでは、重複レコードを返すかどうかを指定する。デフォルト(ALL)では、マッチするすべてのレコードが返される。DISTINCTDISTINCTROW はシノニムで、これらを指定した場合、結果セットから重複レコードが削除される。

  • STRAIGHT_JOINHIGH_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=2DEMAND)を使用した場合に、クエリの結果をクエリキャッシュに格納するよう 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 節を拡張しており、この節で指定したカラムの後に ASCDESC のいずれかを指定することができる。

    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 nLIMIT 0,n と指定するのと同じである。

  • SELECT ... INTO OUTFILE 'file_name' 形式の SELECT では、SELECT したレコードがファイルに書き込まれる。ファイルはサーバホスト上に作成される。既存のファイルを指定することはできない(この制限は、特に、/etc/passwd などのデータベーステーブルやファイルが破壊されないようにするため)。この形式の SELECT を使用するには、サーバホストに対する FILE 権限が必要となる。

    SELECT ... INTO OUTFILE ステートメントの用途は、主に、サーバマシン上のテーブルのダンプをきわめて迅速に実行できるようにすることである。サーバホスト以外のホストに結果のファイルを作成する必要があるときには、SELECT ... INTO OUTFILE は使用できない。この場合、代わりに、mysqldump --tabmysql -e "SELECT ..." > outfile などのクライアントプログラムを使用してファイルを生成する。

    SELECT ... INTO OUTFILELOAD 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 BYESCAPED BYLINES 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 OUTFILEINTO DUMPFILE で作成されるファイルは、サーバホスト上にあるアカウントで書き込み可能であるかもしれない。その理由は、MySQL サーバを実行しているアカウントで、それらファイルを作成するからであり、作成されたファイルはそのアカウントがオーナーになっているからである(mysqldroot として実行すべきでない)。 ファイルの内容を操作できるようにするには、ファイルを全ユーザ書き込み可能にする必要がある。

  • PROCEDURE 節には、結果セット内のデータの処理に使用するプロシージャを指定する。例については、項13.3.1. 「プロシージャの分析」を参照。

  • ページロックまたは行ロック機能があるストレージエンジンに対して FOR UPDATE を使用すると、現在のトランザクションが終了するまで、検査対象のレコードは書き込みに対してロックされる。

6.4.1.1. JOIN 構文

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

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

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

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

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

ON conditional_expr |
USING (column_list)

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

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

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

  • テーブル参照では、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 JOINON または 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.idNOT NULL として宣言されていることが前提となる。 See 項5.2.7. 「MySQL による LEFT JOINRIGHT 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 JOINLEFT JOIN の類似機能。コードをデータベース間で移植可能にするには、RIGHT JOIN ではなく LEFT JOIN を使用するようにする。

  • STRAIGHT_JOINJOIN と同様のものだが、異なる点として、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 KEYUSE/IGNORE INDEX のシノニム。

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

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

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

See 項5.2.7. 「MySQL による LEFT JOINRIGHT JOIN の最適化」

6.4.1.2. UNION 構文

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

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

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

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

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

  • 最後の 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    |
+---------------+

6.4.2. サブクエリ構文

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

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

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

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

  • クエリの各部分が互いに分離されるように、クエリを記述することができる。

  • 複雑な結合や集合処理を必要とする操作を、それらの処理を行わずに実行できる。

  • (多くの人々の意見として)判読しやすい。 事実、初期の 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 バージョンに合わせたサブクエリの書き換え」

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

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

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

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

  • サブクエリの外側のステートメントとしては、SELECTINSERTUPDATEDELETESETDO のいずれかを使用できる。

  • サブクエリには、通常の SELECT に組み込める任意のキーワードまたは節(DISTINCTGROUP BYORDER BYLIMIT、結合、ヒント、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;

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

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

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

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

= > < >= <= <>

次に例を示します。

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

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

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

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

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

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

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

構文

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

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

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

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

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

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

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

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

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

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

構文

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

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

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

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

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

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

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

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

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

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

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

6.4.2.5. 相関副問い合わせ

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

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

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

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

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

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

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

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

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

6.4.2.6. EXISTSNOT EXISTS

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

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

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

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

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

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

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

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

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

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

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

6.4.2.7. 行副問い合わせ

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

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

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

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

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

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

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

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

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

6.4.2.8. FROM 節のサブクエリ

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

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

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

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

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

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

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

結果: 2、'2'、4.0

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

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

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

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

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

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

6.4.2.9. サブクエリのエラー

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

  • 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)を使用することはできません。

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

6.4.2.10. サブクエリの最適化

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

  • サブクエリのレコード数やレコードの順序に影響するサブクエリ節を使用する。次はその例。

    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. 非相関副問い合わせは 1 度しか実行されない(EXPLAIN を使用して、指定されたサブクエリが実際に非相関副問い合わせかどうか確認できる)

  2. IN/ALL/ANY/SOME サブクエリは、サブクエリ内の選択リストカラムがインデックス付きである可能性があるため、書き直される。

  3. 次の形式のサブクエリはインデックスルックアップ関数と置き換えられる。

    ... IN (SELECT indexed_column FROM single_table ...)
    

    インデックスルックアップ関数は、EXPLAIN では特殊な結合型として記述される。

  4. 次の形式の式は、MIN または MAX を含む式で拡張される(NULL 値や空のセットが含まれている場合を除く)。

    value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
    

    WHERE 5 > ALL (SELECT x FROM t)
    

    上の式は次のように処理される。

    WHERE 5 > (SELECT MAX(x) FROM t)
    

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

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

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

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

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

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

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

次のクエリの場合、

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

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

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

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

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

  • 第 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 ステートメントもサポートしています。

6.4.3. INSERT 構文

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

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

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

  • INSERT ... 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;
    

    このコマンドでは、aUNIQUE として宣言されていて、かつすでに 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 型のカラムへの、そのカラムの最大長を超える文字列の挿入。この場合、値はカラムの最大長に合わせて切り捨てられる。

  • 日付または時刻型のカラムへの、そのカラム型に不適切な値の挿入。この場合、カラムの値はその型に対応するゼロ値に設定される。

6.4.3.1. INSERT ... SELECT 構文

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

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

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

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

  • 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 を使用します。以前のレコードの値と重複するユニークキー値を持つ新しいレコードの処理に関して、REPLACEINSERT IGNORE に対立する働きをします。つまり、新しいレコードが廃棄されるのではなく、新しいレコードによって以前のレコードが置き換えられます。

6.4.3.2. INSERT DELAYED 構文

INSERT DELAYED ...

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

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

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

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

注意: 現在のところ、キューに入れられたレコードは、テーブルに挿入されるまでは単にメモリに格納されているに過ぎません。つまり、mysqldkill -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_writesINSERT DELAYED で書き込まれたレコード数
    Not_flushed_delayed_rows書き込み待ちのレコード数

    これらの変数を表示するには、SHOW STATUS ステートメントを発行するか、または mysqladmin extended-status コマンドを実行する。

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

6.4.4. UPDATE 構文

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

または

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

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

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

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

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

mysql> UPDATE persondata SET age=age+1;

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

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

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

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

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

  • 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 BYLIMIT はいずれも使用できません。

6.4.5. DELETE 構文

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

または

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

または

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

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

WHERE 節が指定されていない DELETE では、すべてのレコードが削除されます。AUTOCOMMIT モードで実行された場合、WHERE 節なしの DELETETRUNCATE と同じように動作します。See 項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

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

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

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

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

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

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

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

6.4.6. TRUNCATE 構文

TRUNCATE TABLE table_name

3.23 では、TRUNCATE TABLECOMMIT; DELETE FROM table_name にマップされる。 See 項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 を省略する必要があります。

6.4.7. REPLACE 構文

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

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

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

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

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

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

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

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

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

6.4.8. LOAD DATA INFILE 構文

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

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

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

See 項4.3.7. 「MySQL が提供する権限」

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

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

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

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

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

LINES TERMINATED BY '\n'

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

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

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

  • 改行文字では、行の境界を探す。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • FIELDS ESCAPED BY 指定文字自体

  • FIELDS [OPTIONALLY] ENCLOSED BY 指定文字

  • FIELDS TERMINATED BYLINES 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 BYFIELDS ENCLOSED BY の値がどちらも空('')の場合、固定レコード(区切りなし)の形式が使用される。 固定長レコードの形式では、フィールド間に区切り記号は使用されない(行終端記号は使用可能)。代わりに、カラムの ``表示'' 幅に基づいてカラム値が読み書きされる。たとえば、カラムが INT(7) として宣言されている場合、そのカラムの値は 7 文字のフィールドを使用して書き込まれる。人力時には、そのカラムの値は、7 文字を読み取ることによって取得される。

    この場合も、各行の分離には、LINES TERMINATED BY が使用される。1 行にすべてのフィールドが含まれていない場合、残りのフィールドにはそれぞれのデフォルト値が設定される。行終端記号がない場合は、終端記号を '' として指定するようにする。この場合、テキストファイルに各レコードのすべてのフィールドが含まれていなければならない。

    固定長レコード形式は、NULL 値の処理にも影響します。下記を参照。 注意: マルチバイト文字のキャラクタセットを使用している場合、固定サイズ形式は機能しない。

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

  • FIELDSLINES の値がデフォルトの場合、出力では NULL\N として書き込まれ、入力では \NNULL として読み取られる(ESCAPED BY 指定文字が ‘\’ の場合)。

  • FIELDS ENCLOSED BY に空以外の文字が指定されている場合、リテラルの NULL を値として持つフィールドは NULL 値として読み取られる(これは、FIELDS ENCLOSED BY 指定文字で囲まれた語 NULL が、文字列 'NULL' として読み取られるのと異なる)。

  • FIELDS ESCAPED BY の指定が空の場合、NULLNULL という語として書き込まれる。

  • 固定長レコード形式(FIELDS TERMINATED BYFIELDS ENCLOSED BY の両方の指定が空の場合)では、NULL は空の文字列として書き込まれる。注意: それによって、ファイルへの書き込み時に、テーブル内の NULL 値と空の文字列の両方が空の文字列として書き込まれるため、それらを区別できなくなる。ファイルを再び読み取るときにこれらを区別できるようにする必要がある場合は、固定レコード形式は使用しないようにする。

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

  • 固定長サイズのレコード(FIELDS TERMINATED BYFIELDS 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. 「日付と時刻型」

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

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

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

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

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

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

Warnings(警告)は、INSERT ステートメント(see 項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

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

6.4.9. HANDLER 構文

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

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

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

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

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

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

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

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

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

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

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

  • 次の理由で、SELECT より処理が迅速。

    • HANDLER OPEN では、指定したストレージエンジンがスレッドに割り当てられる。

    • 実行される解析が少ない。

    • オプティマイザやクエリチェックのオーバヘッドがない。

    • 2 つのハンドラ要求間で、使用テーブルをロックする必要がない。

    • ハンドラインタフェースでは、整合性のあるデータの提供は重要とされていないため(たとえば、ダーティリードが可能)、SQL によって通常許可されない最適化をストレージエンジンで実行することができる。

  • ISAM のような MySQL インタフェースを使用するアプリケーションの移植をはるかに容易に実行できる。

  • SQL では難しい(場合によっては不可能な)方法で、データベースをスキャンできる。データベースの対話式ユーザインタフェースを提供するアプリケーションを処理する場合には、データを参照する方法としてハンドラインタフェースを使用したほうがより自然である。

6.4.10. DO 構文

DO expression, [expression, ...]

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

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

6.5. データ定義: CREATEDROPALTER

6.5.1. CREATE DATABASE 構文

CREATE DATABASE [IF NOT EXISTS] db_name

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

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

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

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

6.5.2. DROP DATABASE 構文

DROP DATABASE [IF EXISTS] db_name

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

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

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

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

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

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

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

6.5.3. CREATE TABLE 構文

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

または

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

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

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

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

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

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

table_options: table_option [table_option] ...

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

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

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

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

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

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

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

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

CREATE TABLE new_tbl SELECT * FROM orig_tbl;

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

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

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

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

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

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

CREATE TABLE new_tbl LIKE orig_tbl;

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

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

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

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

  • NULLNOT NULL も指定されていない場合、カラムは NULL が指定されているときと同じように処理される。

  • 整数型カラムは追加属性 AUTO_INCREMENT を持つことができる。 インデックス付きの AUTO_INCREMENT カラムに NULL(推奨)または 0 を挿入すると、そのカラムには連続値の次の値が設定される。 通常、これは value+1 になる(value はテーブルに現在格納されているそのカラムの最大値)。 AUTO_INCREMENT1 から開始される。 See 項11.1.3.32. 「mysql_insert_id()

    MySQL 4.1.1 以降では、--sql-mode サーバオプションまたは sql_mode サーバ変数に対して NO_AUTO_VALUE_ON_ZERO フラグを指定することによって、新しい連続値を生成する代わりに、AUTO_INCREMENT カラムに 00 として格納することができる。 See 項4.1.1. 「mysqld コマンドラインオプション」

    AUTO_INCREMENT カラムの最大値が入ったレコードを削除した場合、その値は ISAM テーブルや BDB テーブルでは再利用されるが、MyISAM テーブルや InnoDB テーブルでは再利用されない。DELETE FROM table_nameWHERE 節なし)を 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 を設定するのとは異なる。0TIMESTAMP 型の有効な値である。

  • DEFAULT 値は定数でなければならず、関数や式を使用することはできない。

    DEFAULT 値が指定されていない場合、そのカラムには、次の方法で、MySQL によって DEFAULT 値が自動的に割り当てられる。

    値として NULL を取れるカラムの場合、デフォルト値は NULL になる。

    NOT NULL として宣言されているカラムの場合、デフォルト値はそれぞれのカラム型によって決まる。

    • AUTO_INCREMENT 属性を持つと宣言されていない数値型カラムの場合、デフォルトは 0AUTO_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 値を持つことができるカラムに対するインデックスの作成は、MyISAMInnoDBBDB の各テーブル型でのみサポートしている。その他のテーブルでは、カラムが 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 KEYCHECKREFERENCES の各構文を解析するが、それ以上の処理は行わない。 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 テーブル」
    MERGE1 つのテーブルとして使用される MyISAM テーブルの集まり。 See 項7.2. 「MERGE テーブル」
    MRG_MyISAMMERGE のエイリアス。
    MyISAMISAM に代わる、バイナリの移植が可能な新しいストレージエンジン。 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レコードの格納方法を定義する。現在、このオプションは、形式として DYNAMICFIXED をサポートしている 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 の場合、新しいレコードによって、同じユニークキー値を持つ既存のレコードが置換される。IGNOREREPLACE のどちらも指定していない場合、ユニークキー値の重複が検出されるとエラーになる。

    更新ログやバイナリログを使用して元のテーブルを確実に再作成できるようにするため、MySQL では CREATE TABLE ... SELECT 実行中の同時挿入は行えない。

  • RAID_TYPE オプションでは、大きなファイルをサポートしていないオペレーティングシステムで MyISAM データファイル(インデックスファイルではなく)に対する 2G または 4G の制限を超すことができる。注意: このオプションは大きなファイルをサポートしているファイルシステムでは推奨されない。

    異なる物理ディスク上に RAID ディレクトリを配置することによって I/O のボトルネックを迅速化することができる。RAID_TYPE はあらゆるオペレーティングシステムで機能するが、MySQL のコンフィギャを --with-raid として行っておく必要がある。現時点で使用可能な RAID_TYPESTRIPED1RAID0 はこのエイリアス)。

    MyISAM テーブルに対して RAID_TYPE=STRIPED と指定すると、データベースディレクトリに、00、01、02 という RAID_CHUNKS サブディレクトリが MyISAM によって作成される。これらのディレクトリのそれぞれで、table_name.MYDMyISAM によって作成される。データファイルへのデータの書き込み時、RAID ハンドラによって、最初の RAID_CHUNKSIZE *1024 バイトが最初のファイルにマップされ、次の RAID_CHUNKSIZE *1024 バイトが次のファイルにマップされる(以下同様)。

  • UNION は、同一テーブルのコレクションを 1 つのものとして使用する場合に指定する。これは、MERGE テーブルに対してのみ機能する。 See 項7.2. 「MERGE テーブル」

    現在のところ、MERGE テーブルにマップするテーブルに対する SELECTUPDATEDELETE の各権限が必要になる。 マップ対象のテーブルはいずれも MERGE テーブルと同じデータベースに存在しなければならない。

  • MERGE テーブルにデータを挿入するには、レコードの挿入先とするテーブルを INSERT_METHOD で指定する必要がある。 INSERT_METHODMERGE テーブルのみに使用できるオプションである。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 上のテーブルに対するシンボリックリンクの使用」

6.5.3.1. カラムの暗黙的な変更

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

  • 長さが 4 文字に満たない VARCHAR 型のカラムは CHAR 型に変更される。

  • テーブルのいずれかのカラムが可変長である場合は、結果的にそのレコード全体が可変長になる。したがって、テーブルに可変長のカラム(VARCHARTEXTBLOB)が含まれている場合、長さが 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. 「圧縮テーブルの特性」

6.5.4. ALTER TABLE 構文

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

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

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

See 項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 を使用するためには、対象のテーブルに対する ALTERINSERTCREATE の各権限が必要。

  • IGNORE は SQL-92 に対する MySQL の拡張。 IGNORE では、重複するユニークキーが新しいテーブルに存在する場合の ALTER TABLE の動作が制御される。 IGNORE を指定しない場合は、コピー処理が中断され、ロールバックされる。 IGNORE を指定すると、重複するユニークキーを持つレコードがある場合、最初のレコードのみが使用され、その他のレコードが削除される。

  • 1 つの ALTER TABLE ステートメントで、複数の ADDALTERDROPCHANGE 節を発行できる。これは SQL-92 に対する MySQL の拡張。SQL-92 では、1 つの ALTER TABLE ステートメントでこれらのいずれか 1 つの節しか使用できない。

  • CHANGE col_name, DROP col_nameDROP INDEX は SQL-92 に対する MySQL の拡張。

  • MODIFYALTER 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 以降では、CHANGEMODIFY でも、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 KEYCHECKREFERENCES の各節では実際には何も行われない。 See 項7.5.5.2. 「FOREIGN KEY 制約」。 他のテーブル型に関しては、この構文は互換性を確保する目的で提供されている。つまり、他の SQL サーバにコードを移植し、参照を含むテーブルを作成するアプリケーションを実行しやすくするためである。 See 項1.8.4. 「MySQL と SQL-92 との違い」

  • ALTER TABLE では、テーブルオプション DATA DIRECTORYINDEX 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;

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

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

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

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

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

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

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

mysql> ALTER TABLE t2 DROP COLUMN c;

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

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

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

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

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

See 項A.7.1. 「ALTER TABLE の問題」

6.5.5. RENAME TABLE 構文

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

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

:

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

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

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

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

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

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

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

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

6.5.6. DROP TABLE 構文

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

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

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

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

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

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

  • テンポラリテーブルの破棄のみ行う。

  • 実行中のトランザクションは終了されない。

  • アクセス権のチェックは行われない。

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

6.5.7. CREATE INDEX 構文

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

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

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

See 項6.5.4. 「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 以降で MyISAMInnoDBBDB のいずれかのテーブル型を使用している場合にのみ可能です。 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 全文検索」

6.5.8. DROP INDEX 構文

DROP INDEX index_name ON tbl_name

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

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

6.6.1. USE 構文

USE db_name

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

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

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

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

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

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

{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBESHOW COLUMNS FROM の簡略形です。

See 項4.6.8.1. 「データベース、テーブル、カラム、およびインデックスに関する情報の取得」

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

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

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

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

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

6.7.1. START TRANSACTIONCOMMITROLLBACK の各構文

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

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

SET AUTOCOMMIT=0

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

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

:

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

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

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

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

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

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

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

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

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

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

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

コマンドコマンドコマンド
ALTER TABLEBEGINCREATE INDEX
DROP DATABASEDROP INDEXDROP TABLE
LOAD MASTER DATALOCK TABLESRENAME TABLE
SET AUTOCOMMIT=1START TRANSACTIONTRUNCATE

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

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

6.7.4. SAVEPOINT および ROLLBACK TO SAVEPOINT 構文

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

SAVEPOINT identifier

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

ROLLBACK TO SAVEPOINT identifier

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

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

ERROR 1181: Got error 153 during ROLLBACK

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

6.7.5. LOCK TABLES および UNLOCK TABLES 構文

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

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

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

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

あるスレッドがテーブルに対する READ ロックを取得すると、そのスレッド(および他のすべてのスレッド)はそのテーブルからの読み取りのみ実行できるようになります。あるスレッドがテーブルに対する WRITE ロックを取得すると、ロックを保有しているスレッドだけがそのテーブルからの読み取りやテーブルへの書き込みを実行できるようになります。他のスレッドはブロックされます。

READ LOCALREAD の違いは、READ LOCAL の場合、ロックの保有中に、コンフクリトを発生させない INSERT ステートメントを実行できることです。しかし、ロックの保有中にデータベースを MySQL の外部で操作しようとする場合は、この機能を使用できません。

LOCK TABLES の使用時には、使用するテーブルをすべてロックし、またクエリで使用するエイリアスと同じ名前を使用する必要があります。1 つのクエリで同じテーブルを何度も指定する(エイリアスを使用して)場合は、各エイリアスに対してロックを取得しなければなりません。

更新をできるだけ早く処理するために、WRITE ロックは、通常、READ ロックより優先されます。そのため、あるスレッドが READ ロックを取得し、別のスレッドが WRITE ロックを要求している場合、後続の READ ロック要求は、WRITE スレッドがロックを取得し、その後そのロックを解除するまで待機します。LOW_PRIORITY WRITE ロックでは、そのスレッドが WRITE ロックを取得する前に、他のスレッドが READ ロックを取得することができます。その間、LOW_PRIORITY WRITE ロックを発行したスレッドは待機します。LOW_PRIORITY WRITE は、READ ロックを取得しようとするスレッドが皆無になるときがあるとわかっている場合にのみ使用してください。

LOCK TABLES は次のように機能します。

  1. ロックするテーブルを内部定義された順序(ユーザから見た場合は未定義)でソートする。

  2. 読み取りロックと書き込みロックでテーブルがロックされる場合は、読み取りロックより書き込みロックを優先する。

  3. 一度に 1 つのテーブルをロックし、スレッドがすべてのロックを取得するまでロック処理を繰り返す。

このポリシーによって、テーブルのロックでデッドロックの発生が回避されます。ただし、このスキーマに関しては注意すべき点が他にもあります。

MySQL でテーブルに対して LOW_PRIORITY WRITE ロックを使用した場合、そのスレッドは READ ロックを要求する他のスレッドがなくなるまでの間のみ待機し、READ を要求する他のスレッドがなくなった時点でロックを取得します。そのスレッドで WRITE ロックを取得した後に、ロックテーブルリストの次のテーブルのロックを取得しようと待機しているときには、他のスレッドの方がいずれも WRITE ロックが解除されるまで待つことになります。これによってアプリケーションで深刻な問題が発生する場合は、一部のテーブルをトランザクションセーフテーブルに変換することを検討してください。

テーブルのロックを取得しようと待機しているスレッドを、安全な方法で強制終了するには、KILL を使用します。 See 項4.6.7. 「KILL 構文」

注意: INSERT DELAYED で使用しているテーブルは、ロックすべきではありません。なぜなら、この場合、INSERT が独立したスレッドで実行されるためです。

個々の UPDATE ステートメントでは、いずれも処理が原子的に行われるため、通常、テーブルをロックする必要はありません。現在実行中の SQL ステートメントが、他のスレッドによって妨害されることはまったくありません。しかし、次に示すように、テーブルをロックする必要が生じる場合もいくつかあります。

  • 一連のテーブルに対して多くの操作を実行する場合、使用するテーブルをロックした方が処理がはるかに迅速になる。当然ながら、この場合の短所は、READ ロックされているテーブルについては、どのスレッドも(ロックを保有しているスレッドも含む)このテーブルを更新できなくなり、WRITE ロックされているテーブルについては、ロックを保有しているスレッド以外、どのスレッドもこのテーブルを読み取れなくなることである。

    LOCK TABLES の使用時にいくつかの面で処理が迅速になる理由は、MySQL でキーのキャッシュが UNLOCK TABLES が呼び出されるまでフラッシュされないためである(通常、キーのキャッシュは各 SQL ステートメントの後にフラッシュされる)。それによって、MyISAM テーブルに対する挿入、更新、削除処理が迅速化される。

  • トランザクションをサポートしていないストレージエンジンを MySQL で使用している場合、SELECTUPDATE の間に他のスレッドに割り込まれないようにするには、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 はトランザクションセーフではありません。アクティブなトランザクションは、テーブルロックの試行前に暗黙的にコミットされます。

6.7.6. SET TRANSACTION 構文

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 コマンドラインオプション」

6.8. MySQL 全文検索

MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION] )

バージョン 3.23.23 以降、MySQL ではフルテキストインデックスと全文検索をサポートしています。 MySQL のフルテキストインデックスは FULLTEXT 型のインデックスです。 FULLTEXT インデックスは MyISAM テーブルにのみ使用され、CHAR 型、VARCHAR 型、TEXT 型のいずれかのカラムから作成することができます。この作成は CREATE TABLE 時に行えますが、ALTER TABLECREATE INDEX を使用して後から追加することも可能です。データセットのサイズが大きい場合は、FULLTEXT インデックスを持たないテーブルにデータをロードしてから、ALTER TABLE(または CREATE INDEX)を使用してインデックスを作成する方が処理がはるかに迅速です。すでに FULLTEXT インデックスを持っているテーブルにデータをロードすると、処理がかなり遅くなることがあります。

全文検索を実行するには、MATCH() 関数を使用します。

mysql> CREATE TABLE articles (
    ->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    ->   title VARCHAR(200),
    ->   body TEXT,
    ->   FULLTEXT (title,body)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
    -> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
    -> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
    -> (NULL,'Optimizing MySQL','In this tutorial we will show ...'),
    -> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    -> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
    -> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles
    ->          WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

MATCH() 関数では、テキストのコレクション(FULLTEXT インデックスに含まれる 1 つ以上のカラムのセット)に対して、文字列の自然言語検索が実行されます。検索文字列は AGAINST() の引数として指定します。検索はケース非依存方式で実行されます。 MATCH() からは、テーブルの各レコードについて、関連性を示す値(つまり、検索文字列と、そのレコードの MATCH() リストに指定したカラムのテキストとの間の類似度)が返されます。

MATCH()WHERE 節で使用すると(上の例を参照)、返されるレコードは関連性が最も高いレコードから低いレコードの順に自動でソートされます。 関連性を示す値は負の数でない浮動小数点数です。関連性がゼロのときは、類似性がまったくないことを意味します。関連性は、レコードに含まれるワード数、そのレコードに含まれる一意のワード数、コレクションに含まれる合計ワード数、特定のワードを含むドキュメント(レコード)数に基づいて計算されます。

ブール値モードの検索も実行できます。これについては後述します。

上記の例は、MATCH() 関数の基本的な使用方法を示したものです。レコードは関連性が高いものから低いものの順に返されます。

次の例は、関連値を明示的に取り出す方法を示したものです。 WHERE 節も ORDER BY 節もないので、返されるレコードは順序付けられていません。

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
|  1 |                        0.64840710366884 |
|  2 |                                       0 |
|  3 |                        0.66266459031789 |
|  4 |                                       0 |
|  5 |                                       0 |
|  6 |                                       0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

次の例はより複雑です。このクエリでは、関連性が返され、関連性の高いものから低いものの順にレコードがソートされます。この結果を出力するためには、MATCH() を 2 回指定します。それによって追加のオーバーヘッドが発生することはありません。なぜなら、MySQL のオプティマイザは 2 つの MATCH() 呼び出しが同じものであると認識し、全文検索コードを 1 度しか起動しないためです。

mysql> SELECT id, body, MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root') AS score
    -> FROM articles WHERE MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
|  6 | When configured properly, MySQL ... |   1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

バージョン 4.1.1 以降、全文検索ではクエリの拡張(特に、その異型の ``ブラインドクエリ拡張'')をサポートしています。通常、これは、検索語句が短すぎるときに役立ちます。検索語句が短い場合、その語句を指定したユーザが暗黙的な知識に頼っていることがよくあります。暗黙的な知識といったものは、通常、全文検索エンジンは備えていません。たとえば、ユーザが ``データベース'' という語句を検索している場合、実際にはそのユーザは、単に ``データベース'' だけでなく、``MySQL''、``Oracle''、``DB2''、``RDBMS'' といった語句もすべて ``データベース'' に一致し、返されるはずだと想定していることがあります。暗黙的な知識とは、このようなことを意味します。

ブラインドクエリ拡張(自動関連性フィードバック)では、検索が 2 回実行されます。2 回目の検索の検索語句には、元の検索語句に、最初の検索で上位に検出された少数のドキュメントが結び付けられたものが使用されます。したがって、たとえば、これらのドキュメントの 1 つに ``データベース'' という語と ``MySQL'' という語が含まれている場合、2 回目の検索では、``MySQL'' という語を含み、``データベース'' という語は含まないドキュメントが検索されます。また、たとえば、Georges Simenonの著書で ``Maigret'' 警視に関する本を検索しようとするときに、``Maigret'' のスペルが正確にわからないとします。この場合、``Megre and the reluctant witnesses'' を検索語句として指定すると、クエリの拡張を使用しなければ ``Maigret and the Reluctant Witnesses'' しか検出されません。しかし、クエリの拡張を使用すると、2 回目の検索で ``Maigret'' という語が含まれるすべての本が検出されます。注意:ブラインドクエリ拡張では、関連しないドキュメントが返されることでノイズが大幅に増加しがちです。そのため、この機能を使用する意味があるのは、検索語句が比較的短い場合に限られます。

MySQL では、非常に単純なパーサを使用してテキストをワード(語)に分割します。``ワード'' とは、文字、数字、‘'’、‘_’ で構成される文字列です。ストップワードリストに含まれる ``ワード'' や短すぎるものは無視されます。全文検索で検出されるワードのデフォルトの最小長は 4 文字です。この長さは 項6.8.2. 「MySQL 全文検索の調整」 の説明に従って変更可能です。

コレクションおよびクエリに含まれる正しい各ワードには、そのクエリまたはコレクションでのそのワードの重要度に基づいて重みが設定されます。そのため、多くのドキュメントに存在するワードは低く重み付けされます(重みがゼロの場合もあります)。なぜなら、そのワードはそのコレクションにおいて意味値が低いためです。そのワードがまれにしか存在しない場合は、高く重み付けされます。その後、各ワードの重みが結合されてレコードの関連性が計算されます。

このようなテクニックは、サイズの大きなコレクションの場合に最も効果があります(実際に、それを目的として入念に調整されています)。小さいテーブルでは、ワードの分布はそれぞれの意味値を正しく反映するものとはならず、このモデルを使用した場合、奇妙な結果が出ることがあります。

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

上の例では、MySQL というワードの検索で何も結果が生成されません。これは、このワードが半分以上のレコードに存在するためです。したがって、このワードは事実上ストップワード(意味値がゼロのワード)として扱われます。これは最も望ましい動作です。自然言語のクエリの場合 、1 GB のテーブルから 1 つおきにレコードが返されるのは適切ではありません。

ワードがテーブルの半分を占めるレコードに一致する場合、関連するドキュメントが検出される見込みはあまりありません。むしろ、無関係のドキュメントが大量に検出される可能性が多分にあります。 これは、検索エンジンを使用してインターネットで検索をするときに誰もが頻繁に経験することです。このようなレコードに該当のデータセットにおいて低い意味値が設定されている理由は、ここにあります。

バージョン 4.0.1 以降、MySQL では、IN BOOLEAN MODE 修飾子を使用してブール値の全文検索も実行できます。

mysql> SELECT * FROM articles WHERE MATCH (title,body)
    ->     AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title                        | body                                |
+----+------------------------------+-------------------------------------+
|  1 | MySQL Tutorial               | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Efficiently | After you went through a ...        |
|  3 | Optimizing MySQL             | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security               | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

このクエリでは、MySQL というワードを含み(注意: 50% のしきい値は使用されません)、YourSQL というワードは含まないすべてのレコードが取り出されます。注意: ブール値モードの検索では、関連値の高いもの順のレコードの自動ソートは行われません。これは上のクエリの結果を見るとわかります。上のクエリでは、関連性が最も高いレコード(MySQL というワードを 2 つ含むレコード)が最初ではなく最後にリストされています。また、ブール値の全文検索は FULLTEXT インデックスがなくても機能します。ただし、この場合、処理速度は遅くなります。

ブール値の全文検索機能では、次の演算子をサポートしています。

  • +

    先行するプラス記号は、返される各レコードにそのワードが存在しなければならないことを表す。

  • -

    先行するマイナス記号は、返される各レコードにそのワードが存在してはならないことを表す。

  • デフォルト(プラスもマイナスも指定しない場合)では、そのワードは必ずしも存在する必要はないが、そのワードを含むレコードは高く評価される。これは、IN BOOLEAN MODE 修飾子を指定していない MATCH() ... AGAINST() の動作に類似する。

  • < >

    これら 2 つの演算子は、各レコードに割り当てられる関連性の値に対する個々のワードの貢献度を変更するために使用される。< 演算子は貢献度を減少させ、> 演算子は貢献度を増加させる。 下の例を参照。

  • ( )

    かっこは、ワードを副次式にグループ化するために使用される。

  • ~

    先行するチルダは否定演算子として機能し、レコードの関連性に対するワードの貢献度をマイナスにする。これはノイズワードをマークするのに役立つ。このようなワードを含むレコードは、他のワードより低く評価されるが、- 演算子を使用したときのように完全に除外されるわけではない。

  • *

    アスタリスクは切り捨て演算子。他の演算子と異なり、これはワードの前ではなく後ろに付ける。

  • "

    二重引用符 " で囲んだ語句は、この語句とまったく同じ語句を含むレコードにのみ一致する。

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

  • apple banana

    これらのワードの最低 1 つを含むレコードが検索される。

  • +apple +juice

    ... 両方のワードを含むレコードを検索。

  • +apple macintosh

    ... ワード ``apple'' を含むレコードを検索。``apple'' に加えて ``macintosh'' というワードも含んでいれば、高く評価される。

  • +apple -macintosh

    ... ワード ``apple'' を含み、``macintosh'' は含まないレコードを検索。

  • +apple +(>turnover <strudel)

    ... ``apple'' と ``turnover''、または ``apple'' と ``strudel'' を含むレコード(2 つのワードの順序は問わない)を検索。ただし、``apple pie'' は ``apple strudel'' より高く評価される。

  • apple*

    ... ``apple''、``apples''、``applesauce''、``applet'' はいずれもこれと一致する。

  • "some words"

    ... ``some words of wisdom'' とは一致するが、``some noise words'' とは一致しない。

6.8.1. 全文検索における制約

  • 全文検索は MyISAM テーブルでのみ可能。

  • 全文検索は UCS-2 では使用できない(しかし、MySQL 4.1.1 以降では、UTF-8 で機能する)。

  • MATCH() 関数のパラメータはすべて、同じ FULLTEXT インデックスの一部を成す同じテーブルのカラムでなければならない(IN BOOLEAN MODEMATCH() を実行する場合を除く)。

  • FULLTEXT インデックスのカラムはすべて同じキャラクタセットを使用していなければならない。

  • MATCH() のカラムリストはテーブルの一部の FULLTEXT インデックス定義のカラムリストと正確に一致していなければならない(IN BOOLEAN MODEMATCH() を実行する場合を除く)。

  • AGAINST() の引数は定数文字列でなければならない。

6.8.2. MySQL 全文検索の調整

残念ながら、ユーザによる調整が可能な全文検索のパラメータは現在のところ少ししかありません。しかし、調整可能なパラメータの追加は、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;

6.8.3. 全文検索に関連する TODO 項目

  • FULLTEXT インデックスを使用するすべての操作の迅速化

  • 近接演算子。

  • "常にインデックスワード" のサポート。これは、"C++"、"AS/400"、"TCP/IP" など、ユーザがワードとして認識させたい任意の文字列である。

  • MERGE テーブルでの全文検索のサポート。

  • UCS-2 のサポート。

  • ストップワードリストをデータの言語に依存させる。

  • ステミング(= 語幹の抽出。言うまでもなく、データの言語に依存する抽出)。

  • ユーザによる提供が可能な汎用 UDF プリパーサ。

  • モデルのよりいっそうの柔軟化(CREATE/ALTER TABLEFULLTEXT に調整可能なパラメータをいくつか追加する)。

6.9. MySQL クエリキャッシュ

バージョン 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 を使用してコードから除外できる)。

6.9.1. クエリキャッシュの動作

クエリは解析前に比較されるため、

SELECT * FROM tbl_name

Select * from tbl_name

は、クエリキャッシュで別のクエリとみなされます。完全に一致する(各バイトが)クエリ以外、同一とはみなされません。 また、たとえば、あるクライアントで新しい形式の通信プロトコルを使用している場合や、別のクライアントが使用しているものとは異なるキャラクタセットを使用している場合も、同じものであるはずのクエリが異なるものとして認識されることがあります。

異なるデータベースを使用するクエリや、使用プロトコルのバージョンが異なるクエリ、またデフォルトのキャラクタセットが異なるクエリは、いずれも異なるクエリとして認識され、別々にキャッシュされます。

キャッシュは SELECT SQL_CALC_FOUND_ROWS ... および SELECT FOUND_ROWS() ... 型のクエリでも機能します。これは、検出されたレコードの数もキャッシュに格納されるためです。

クエリの結果がクエリキャッシュから返された場合、ステータス変数 Com_select の値は増加しませんが、Qcache_hits の値は増加します。 See 項6.9.4. 「クエリキャッシュのステータスと保守」

テーブルが変更されると(INSERTUPDATEDELETETRUNCATEALTERDROP TABLE|DATABASE のいずれかによって)、そのテーブルを(場合によっては、MRG_MyISAM テーブルを通して)使用したキャッシュ内のクエリはすべて無効になり、キャッシュから削除されます。

変更された InnoDB トランザクションテーブルは、COMMIT が実行されると無効化されます。

MySQL 4.0 では、クエリキャッシュはトランザクション内では無効です(結果は返されません)。MySQL 4.1.1 以降では、InnoDB テーブルの使用時、クエリキャッシュはトランザクション内でも機能します(テーブルのバージョン番号に基づいて、データがまだカレントかどうかが検出されます)。

MySQL 5.0 より前のバージョンでは、先行するコメントで始まるクエリの場合、キャッシュへの格納は可能でも、キャッシュから取得できませんでした。この問題は MySQL 5.0 で修正されています。

次の関数のいずれかを含んでいるクエリは、キャッシュできません。

関数関数関数
User-Defined FunctionsCONNECTION_IDFOUND_ROWS
GET_LOCKRELEASE_LOCKLOAD_FILE
MASTER_POS_WAITNOWSYSDATE
CURRENT_TIMESTAMPCURDATECURRENT_DATE
CURTIMECURRENT_TIMEDATABASE
ENCRYPT (パラメータを 1 つ持つもの)LAST_INSERT_IDRAND
UNIX_TIMESTAMP (パラメータなし)USERBENCHMARK

また、ユーザ変数を含んでいるクエリ、mysql システムデータベースを参照しているクエリ、SELECT ... IN SHARE MODESELECT ... INTO OUTFILE ...SELECT ... INTO DUMPFILE ... のいずれかの形式のクエリ、および SELECT * FROM AUTOINCREMENT_FIELD IS NULL 形式のクエリ(最後に挿入された ID の取り出し - ODBC 回避策)についても、キャッシュできません。

ただし、FOUND_ROWS() は、先行するクエリがキャッシュからフェッチされたものであっても正しい値を返します。

クエリでテーブルを何も使用しない、またはテンポラリテーブルを使用する場合や、関連するテーブルのいずれかに対するカラムのアクセス権限をユーザが持っていない場合、クエリはキャッシュされません。

MySQL では、クエリをクエリキャッシュから読み取る前に、関連するすべてのデータベースとテーブルに対する SELECT 権限をユーザが持っているかチェックします。この権限をユーザが持っていない場合、キャッシュに格納されている結果は使用されません。

6.9.2. クエリキャッシュの設定

mysqld の起動時には、コマンドラインで mysqld の少数の MySQL システム変数がクエリキャッシュにより追加されます。これらのシステム変数はオプション設定ファイルで設定することができます。

  • query_cache_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 または ONSELECT SQL_NO_CACHE ... クエリを除くすべての結果をキャッシュする。
2 または DEMANDSELECT SQL_CACHE ... クエリのみキャッシュする。

6.9.3. SELECT でのクエリキャッシュオプション

SELECT クエリでは、クエリキャッシュ関連の次の 2 つのパラメータを指定することができます。

オプション説明
SQL_CACHEQUERY_CACHE_TYPEDEMAND の場合、クエリをキャッシュ可能にする。 QUERY_CACHE_TYPEON の場合、これがデフォルト。 QUERY_CACHE_TYPEOFF の場合、何もしない。
SQL_NO_CACHEこのクエリをキャッシュ不可にする。このクエリをキャッシュに格納しない。

6.9.4. クエリキャッシュのステータスと保守

FLUSH QUERY CACHE コマンドでは、クエリキャッシュをデフラグメント化して、メモリの使用効率を良くすることができます。このコマンドを発行しても、キャッシュからクエリが削除されることはありません。 FLUSH TABLES でも、クエリキャッシュがフラッシュされます。

RESET QUERY CACHE コマンドでは、すべてのクエリ結果がクエリキャッシュから削除されます。

使用している MySQL バージョンにクエリキャッシュがあるかどうかは、次のコマンドで確認できます。

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

クエリキャッシュのパフォーマンスは、SHOW STATUS で監視できます。

変数説明
Qcache_queries_in_cacheキャッシュに登録されているクエリ数
Qcache_insertsキャッシュに追加されたクエリ数
Qcache_hitsキャッシュヒット数
Qcache_lowmem_prunesメモリ不足のためにキャッシュから削除されたクエリ数
Qcache_not_cachedキャッシュされていない(キャッシュ不可、または QUERY_CACHE_TYPE により)クエリ数
Qcache_free_memoryクエリキャッシュの空きメモリ量
Qcache_free_blocksクエリキャッシュ内の空きメモリブロック数
Qcache_total_blocksクエリキャッシュ内の合計ブロック数

合計クエリ数 = Qcache_inserts + Qcache_hits + Qcache_not_cached

クエリキャッシュでは可変長ブロックが使用されるため、Qcache_total_blocksQcache_free_blocks によって、クエリキャッシュメモリのフラグメント化が示されることがあります。 FLUSH QUERY CACHE を実行すると、1 つの(大きな)空きブロックだけが残ります。

注意:各クエリには、最低でも 2 ブロック必要です(クエリテキスト用に 1 ブロック、クエリ結果用に 1 ブロック以上)。また、クエリで使用される各テーブル用にも 1 ブロック必要です。ただし、複数のクエリで同じテーブルを使用している場合は、1 ブロックの割り当てですみます。

クエリのキャッシュサイズは、Qcache_lowmem_prunes ステータス変数に基づいて調整できます。この値は、新しいクエリを格納できるようメモリを解放するためにキャッシュから削除されたクエリ数を示します。クエリキャッシュでは、使用されたうち最も古いLRU)方針に従って、キャッシュから削除するクエリが決定されます。


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.

アダルトレンタルサーバー