第 12 章 関数と演算子

目次

12.1 関数と演算子のリファレンス
12.2 式評価での型変換
12.3 演算子
12.3.1 演算子の優先順位
12.3.2 比較関数と演算子
12.3.3 論理演算子
12.3.4 割り当て演算子
12.4 制御フロー関数
12.5 文字列関数
12.5.1 文字列比較関数
12.5.2 正規表現
12.6 数値関数と演算子
12.6.1 算術演算子
12.6.2 数学関数
12.7 日付および時間関数
12.8 MySQL で使用されるカレンダー
12.9 全文検索関数
12.9.1 自然言語全文検索
12.9.2 ブール全文検索
12.9.3 クエリー拡張を使用した全文検索
12.9.4 全文ストップワード
12.9.5 全文制限
12.9.6 MySQL の全文検索の微調整
12.9.7 全文インデックス作成用の照合順序の追加
12.10 キャスト関数と演算子
12.11 XML 関数
12.12 ビット関数
12.13 暗号化関数と圧縮関数
12.14 情報関数
12.15 空間分析関数
12.15.1 空間関数のリファレンス
12.15.2 空間関数による引数処理
12.15.3 WKT 値から幾何値を作成する関数
12.15.4 WKB 値から幾何値を作成する関数
12.15.5 幾何値を作成する MySQL 固有の関数
12.15.6 幾何形式変換関数
12.15.7 幾何プロパティー関数
12.15.8 空間演算子関数
12.15.9 幾何オブジェクト間の空間関係をテストする関数
12.16 グローバルトランザクション ID とともに使用される関数
12.17 MySQL Enterprise Encryption の関数
12.17.1 Enterprise Encryption のインストール
12.17.2 Enterprise Encryption の使用法と例
12.17.3 Enterprise Encryption 関数のリファレンス
12.17.4 Enterprise Encryption 関数の説明
12.18 その他の関数
12.19 GROUP BY 句で使用される関数と修飾子
12.19.1 GROUP BY (集約) 関数
12.19.2 GROUP BY 修飾子
12.19.3 MySQL での GROUP BY の処理
12.20 高精度計算
12.20.1 数値の型
12.20.2 DECIMAL データ型の特性
12.20.3 式の処理
12.20.4 丸め動作
12.20.5 高精度計算の例

SQL ステートメントのいくつかのポイント (SELECT ステートメントの ORDER BY または HAVING 句、SELECTDELETE、または UPDATE ステートメントの WHERE 句、SET ステートメントなど) では、式を使用できます。式は、リテラル値、カラム値、NULL、組み込み関数、ストアドファンクション、ユーザー定義関数、および演算子を使用して作成できます。この章では、MySQL で式を記述する際に許可されている関数および演算子について説明します。ストアドファンクションおよびユーザー定義関数を作成する手順については、セクション20.2「ストアドルーチン (プロシージャーと関数) の使用」およびセクション24.3「MySQL への新しい関数の追加」で説明されています。各種の関数への参照をサーバーが解釈する方法を記述したルールについては、セクション9.2.4「関数名の構文解析と解決」を参照してください。

NULL を含む式では、その関数または演算子に関するドキュメントで明記されていないかぎり、常に NULL 値が生成されます。

注記

デフォルトでは、関数名とそれに続く丸括弧の間には空白を入れることはできません。これは、MySQL パーサーが、関数呼び出しと、偶然に関数と同じ名前を持つテーブルまたはカラムへの参照を区別するのに役立ちます。ただし、関数の引数の前後にスペースを入れることは許可されています。

最初に --sql-mode=IGNORE_SPACE オプションを付けると、関数名のあとの空白文字を受け入れるように MySQL サーバーに指示できます。(セクション5.1.7「サーバー SQL モード」を参照してください。)各クライアントプログラムで mysql_real_connect()CLIENT_IGNORE_SPACE オプションを使用すると、この動作をリクエストできます。どちらの場合でも、すべての関数名は予約語になります。

簡略化のため、この章で示すほとんどの例では、mysql プログラムからの出力が省略形で表示されています。例は次の書式で表示されません。

mysql> SELECT MOD(29,9);+-----------+
| mod(29,9) |
+-----------+
| 2 |
+-----------+
1 rows in set (0.00 sec)

代わりに、次の書式が使用されます。

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

12.1 関数と演算子のリファレンス

表 12.1 関数/演算子

名前説明
ABS() 絶対値を返します
ACOS() アークコサインを返します
ADDDATE() 日付値に時間値 (間隔) を加算します
ADDTIME() 時間を加算します
AES_DECRYPT() AES を使用して復号化します
AES_ENCRYPT() AES を使用して暗号化します
AND, && 論理 AND
Area() Polygon または MultiPolygon 領域を返します
AsBinary(), AsWKB() 内部幾何形式から WKB に変換します
ASCII() 左端の文字の数値を返します
ASIN() アークサインを返します
= (SET ステートメントの一部として、または UPDATE ステートメントの SET 句の一部として) 値を割り当てます
:= 値を割り当てます
AsText(), AsWKT() 内部幾何形式から WKT に変換します
ASYMMETRIC_DECRYPT() 秘密鍵または公開鍵を使用して暗号文を復号化します
ASYMMETRIC_DERIVE() 非対称鍵から対称鍵を導出します
ASYMMETRIC_ENCRYPT() 秘密鍵または公開鍵を使用してプレーンテキストを暗号化します
ASYMMETRIC_SIGN() ダイジェストから署名を生成します
ASYMMETRIC_VERIFY() 署名がダイジェストと一致することを確認します
ATAN() アークタンジェントを返します
ATAN2(), ATAN() 2 つの引数のアークタンジェントを返します
AVG() 引数の平均値を返します
BENCHMARK() 式を繰り返し実行します
BETWEEN ... AND ... 値が値の範囲内に含まれているかどうかを確認します
BIN() 数値のバイナリ表現を含む文字列を返します
BINARY 文字列をバイナリ文字列にキャストします
BIT_AND() ビット単位の And を返します
BIT_COUNT() 設定されているビット数を返します
BIT_LENGTH() ビット単位で引数の長さを返します
BIT_OR() ビット単位の OR を返します
BIT_XOR() ビット単位の XOR を返します
& ビット単位の AND
~ ビットを反転します
| ビット単位の OR
^ ビット単位の XOR
Buffer() 幾何図形から指定された距離内にある点の幾何図形を返します
CASE CASE 演算子
CAST() 値を特定の型としてキャストします
CEIL() 引数以上のもっとも小さな整数値を返します
CEILING() 引数以上のもっとも小さな整数値を返します
Centroid() 重心を Point として返します
CHAR() 渡された各整数の文字を返します
CHAR_LENGTH() 引数の文字数を返します
CHARACTER_LENGTH() CHAR_LENGTH() のシノニムです
CHARSET() 引数の文字セットを返します
COALESCE() NULL 以外の最初の引数を返します
COERCIBILITY() 文字列引数の照合順序強制性値を返します
COLLATION() 文字列引数の照合順序を返します
COMPRESS() バイナリ文字列として結果を返します
CONCAT() 連結された文字列を返します
CONCAT_WS() 連結されたものをセパレータ付きで返します
CONNECTION_ID() 接続のための接続 ID (スレッド ID) を返します
Contains() ある幾何図形に別の幾何図形が含まれているかどうか
CONV() 数値を異なる基数間で変換します
CONVERT() 値を特定の型としてキャストします
CONVERT_TZ() あるタイムゾーンから別のタイムゾーンに変換します
COS() コサインを返します
COT() コタンジェントを返します
COUNT() 返された行数のカウントを返します
COUNT(DISTINCT) 異なる値のカウントを返します
CRC32() 巡回冗長検査値を計算します
CREATE_ASYMMETRIC_PRIV_KEY() 秘密鍵を作成します
CREATE_ASYMMETRIC_PUB_KEY() 公開鍵を作成します
CREATE_DH_PARAMETERS() 共有 DH シークレットを生成します
CREATE_DIGEST() 文字列からダイジェストを生成します
Crosses() ある幾何図形が別の幾何図形と交差しているかどうか
CURDATE() 現在の日付を返します
CURRENT_DATE(), CURRENT_DATE CURDATE() のシノニムです
CURRENT_TIME(), CURRENT_TIME CURTIME() のシノニムです
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP NOW() のシノニムです
CURRENT_USER(), CURRENT_USER 認証済みユーザー名とホスト名
CURTIME() 現在の時間を返します
DATABASE() デフォルト (現在) のデータベース名を返します
DATE() 日付または日付時間式の日付部分を抽出します
DATE_ADD() 日付値に時間値 (間隔) を加算します
DATE_FORMAT() 日付を指定された書式に設定します
DATE_SUB() 日付から時間値 (間隔) を引きます
DATEDIFF() 2 つの日付の差を求めます
DAY() DAYOFMONTH() のシノニムです
DAYNAME() 曜日の名前を返します
DAYOFMONTH() 月の日を返します (0 - 31)
DAYOFWEEK() 引数の曜日インデックスを返します
DAYOFYEAR() 年の日を返します (1 - 366)
DECODE() ENCODE() を使用して暗号化された文字列をデコードします
DEFAULT() テーブルカラムのデフォルト値を返します
DEGREES() ラジアンを角度に変換します
DES_DECRYPT() 文字列を復号化します
DES_ENCRYPT() 文字列を暗号化します
Dimension() 幾何図形の次元
Disjoint() ある幾何図形が別の幾何図形から切り離されているかどうか
DIV 整数除算
/ 除算演算子
ELT() インデックス番号位置の文字列を返します
ENCODE() 文字列をエンコードします
ENCRYPT() 文字列を暗号化します
EndPoint() LineString の終点
Envelope() 幾何図形の MBR を返します
= 等価 (等しい) 演算子
<=> NULL 安全等価演算子
Equals() ある幾何図形が別の幾何図形に等しいかどうか
EXP() 累乗します
EXPORT_SET() 値 bits 内の各ビットが設定されている場合は on 文字列を取得し、各ビットが設定されていない場合には off 文字列を取得するように、文字列を返します
ExteriorRing() Polygon の外側のリングを返します
EXTRACT() 日付の一部を抽出します
ExtractValue() XPath 表記法を使用して、XML 文字列から値を抽出します
FIELD() 後続の引数内で第 1 引数のインデックス (位置) を返します
FIND_IN_SET() 第 2 引数内で第 1 引数のインデックス位置を返します
FLOOR() 引数以下のもっとも大きな整数値を返します
FORMAT() 指定された小数点以下桁数に書式設定された数値を返します
FOUND_ROWS() LIMIT 句付き SELECT で、LIMIT 句がない場合に戻される可能性がある行の数です
FROM_BASE64() base 64 文字列にデコードして結果を返します
FROM_DAYS() 日数を日付に変換します
FROM_UNIXTIME() UNIX タイムスタンプを日付として書式設定します
GeomCollFromText(), GeometryCollectionFromText() WKT からジオメトリコレクションを返します
GeomCollFromWKB(), GeometryCollectionFromWKB() WKB からジオメトリコレクションを返します
GeometryCollection() 幾何図形からジオメトリコレクションを構築します
GeometryN() ジオメトリコレクションから N 番目の幾何図形を返します
GeometryType() 幾何型の名前を返します
GeomFromText(), GeometryFromText() WKT から幾何図形を返します
GeomFromWKB() WKB から幾何図形を返します
GET_FORMAT() 日付書式文字列を返します
GET_LOCK() 名前付きロックを取得します
GLength() LineString の長さを返します
> 右不等 (より多い) 演算子
>= 以上 (より多いか等しい) 演算子
GREATEST() 最大の引数を返します
GROUP_CONCAT() 連結された文字列を返します
GTID_SUBSET() サブセット内のすべての GTID がセット内にもある場合は、true を返します。そうでない場合は、false を返します。
GTID_SUBTRACT() セット内の GTID のうち、サブセット内にないものをすべてを返します。
HEX() 10 進値または文字列値の 16 進表現を返します
HOUR() 時を抽出します
IF() If/else 構文
IFNULL() Null if/else 構文
IN() ある値が値セット内に含まれているかどうかを確認します
INET_ATON() IP アドレスの数値を返します
INET_NTOA() 数値から IP アドレスを返します
INET6_ATON() IPv6 アドレスの数値を返します
INET6_NTOA() 数値から IPv6 アドレスを返します
INSERT() 部分文字列を、指定された位置に指定された文字数だけ挿入します
INSTR() 部分文字列が最初に出現する位置のインデックスを返します
InteriorRingN() Polygon の N 番目の内側のリングを返します
Intersects() ある幾何図形が別の幾何図形と交差しているかどうか
INTERVAL() 第 1 引数より小さい引数のインデックスを返します
IS ブーリアンに対して値をテストします
IS_FREE_LOCK() 名前付きロックが解放されているかどうかを確認します
IS_IPV4() 引数が IPv4 アドレスの場合、true を返します
IS_IPV4_COMPAT() 引数が IPv4 互換アドレスの場合、true を返します
IS_IPV4_MAPPED() 引数が IPv4 マップアドレスの場合、true を返します
IS_IPV6() 引数が IPv6 アドレスの場合、true を返します
IS NOT ブーリアンに対して値をテストします
IS NOT NULL NOT NULL 値テスト
IS NULL NULL 値テスト
IS_USED_LOCK() 名前付きロックが使用中かどうかを確認します。true の場合は接続識別子を返します。
IsClosed() 幾何図形が閉じていて単純かどうか
IsEmpty() プレースホルダ関数
ISNULL() 引数が NULL かどうかをテストします
IsSimple() 幾何図形が単純かどうか
LAST_DAY 引数の月の最終日を返します
LAST_INSERT_ID() 前回の INSERT での AUTOINCREMENT カラムの値です
LCASE() LOWER() のシノニムです
LEAST() 最小の引数を返します
LEFT() 左端から指定された数の文字を返します
<< 左シフト
LENGTH() 文字列の長さをバイト単位で返します
< 左不等 (より少ない) 演算子
<= 以下 (より少ないか等しい) 演算子
LIKE 単純なパターン一致
LineFromText() WKT から LineString を構築します
LineFromWKB(), LineStringFromWKB() WKB から LineString を構築します
LineString() Point 値から LineString を構築します
LN() 引数の自然対数を返します
LOAD_FILE() 指定されたファイルをロードします
LOCALTIME(), LOCALTIME NOW() のシノニムです
LOCALTIMESTAMP, LOCALTIMESTAMP() NOW() のシノニムです
LOCATE() 部分文字列が最初に出現する位置を返します
LOG() 最初の引数の自然対数を返します
LOG10() 引数の底 10 の対数を返します
LOG2() 引数の底 2 の対数を返します
LOWER() 引数を小文字で返します
LPAD() 指定された文字列で左からパディングした文字列引数を返します
LTRIM() 先頭の空白を削除します
MAKE_SET() bits セット内の対応するビットを持つ、カンマ区切り文字列のセットを返します
MAKEDATE() 年と年間通算日から日付を作成します
MAKETIME() 時、分、秒から時間を作成します
MASTER_POS_WAIT() スレーブが指定された位置まですべての更新を読み取って適用するまで、ブロックします
MATCH 全文検索を実行します
MAX() 最大値を返します
MBRContains() ある幾何図形の MBR に、別の幾何図形の MBR が含まれているかどうか
MBRDisjoint() 2 つの幾何図形の MBR が切り離されているかどうか
MBREqual() 2 つの幾何図形の MBR が等しいかどうか
MBRIntersects() 2 つの幾何図形の MBR が交差しているかどうか
MBROverlaps() 2 つの幾何図形の MBR がオーバーラップしているかどうか
MBRTouches() 2 つの幾何図形の MBR が接しているかどうか
MBRWithin() ある幾何図形の MBR が、別の幾何図形の MBR の内部にあるかどうか
MD5() MD5 チェックサムを計算します
MICROSECOND() 引数からマイクロ秒を返します
MID() 指定された位置から始まる部分文字列を返します
MIN() 最小値を返します
- 減算演算子
MINUTE() 引数から分を返します
MLineFromText(), MultiLineStringFromText() WKT から MultiLineString を構築します
MLineFromWKB(), MultiLineStringFromWKB() WKB から MultiLineString を構築します
MOD() 余りを返します
%, MOD モジュロ演算子
MONTH() 渡された日付から月を返します
MONTHNAME() 月の名前を返します
MPointFromText(), MultiPointFromText() WKT から MultiPoint を構築します
MPointFromWKB(), MultiPointFromWKB() WKB から MultiPoint を構築します
MPolyFromText(), MultiPolygonFromText() WKT から MultiPolygon を構築します
MPolyFromWKB(), MultiPolygonFromWKB() WKB から MultiPolygon を構築します
MultiLineString() LineString 値から MultiLineString を構築します
MultiPoint() Point 値から MultiPoint を構築します
MultiPolygon() Polygon 値から MultiPolygon を構築します
NAME_CONST() 指定された名前がカラムに付けられます
NOT, ! 値を否定します
NOT BETWEEN ... AND ... 値が値の範囲内に含まれていないかどうかを確認します
!=, <> 不等価 (等しくない) 演算子
NOT IN() 値が値セット内に含まれていないかどうかを確認します
NOT LIKE 単純なパターン一致の否定
NOT REGEXP REGEXP の否定
NOW() 現在の日付と時間を返します
NULLIF() expr1 = expr2 の場合に NULL を返します
NumGeometries() ジオメトリコレクション内の幾何図形数を返します
NumInteriorRings() Polygon 内の内側のリング数を返します
NumPoints() LineString 内の Point の数を返します
OCT() 数値の 8 進数表現を含む文字列を返します
OCTET_LENGTH() LENGTH() のシノニムです
OLD_PASSWORD() (deprecated 5.6.5) 4.1 より前の PASSWORD 実装の値を返します
||, OR 論理 OR
ORD() 引数の左端の文字の文字コードを返します
Overlaps() ある幾何図形が別の幾何図形とオーバーラップしているかどうか
PASSWORD() パスワード文字列を計算して返します
PERIOD_ADD() 年月に期間を加算します
PERIOD_DIFF() 期間内の月数を返します
PI() pi の値を返します
+ 加算演算子
Point() 座標から Point を構築します
PointFromText() WKT から Point を構築します
PointFromWKB() WKB から Point を構築します
PointN() LineString から N 番目の Point を返します
PolyFromText(), PolygonFromText() WKT から Polygon を構築します
PolyFromWKB(), PolygonFromWKB() WKB から Polygon を構築します
Polygon() LineString 引数から Polygon を構築します
POSITION() LOCATE() のシノニムです
POW() 指定した指数で累乗された引数を返します
POWER() 指定した指数で累乗された引数を返します
PROCEDURE ANALYSE() クエリーの結果を解析します
QUARTER() 日付引数から四半期を返します
QUOTE() SQL ステートメント内で使用するために引数をエスケープします
RADIANS() ラジアンに変換された引数を返します
RAND() ランダムな浮動小数点値を返します
RANDOM_BYTES() ランダムなバイトベクトルを返します
REGEXP 正規表現を使用したパターン一致
RELEASE_LOCK() 名前付きロックを解放します
REPEAT() 文字列を指定された回数だけ繰り返します
REPLACE() 指定された文字列の出現箇所を置き換えます
REVERSE() 文字列内の文字を逆順に並べ替えます
RIGHT() 右端から指定された数の文字を返します
>> 右シフト
RLIKE REGEXP のシノニムです
ROUND() 引数を丸めます
ROW_COUNT() 更新された行数
RPAD() 指定された回数だけ文字列を追加します
RTRIM() 末尾の空白を削除します
SCHEMA() DATABASE() のシノニムです
SEC_TO_TIME() 秒を「HH:MM:SS」形式に変換します
SECOND() 秒 (0-59) を返します
SESSION_USER() USER() のシノニムです
SHA1(), SHA() SHA-1 160 ビットチェックサムを計算します
SHA2() SHA-2 チェックサムを計算します
SIGN() 引数の符号を返します
SIN() 引数のサインを返します
SLEEP() ある秒数間スリープ状態にします
SOUNDEX() soundex 文字列を返します
SOUNDS LIKE 音声を比較します
SPACE() 指定された数の空白で構成される文字列を返します
SQL_THREAD_WAIT_AFTER_GTIDS() (deprecated 5.6.9) 廃止: WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() に置き換わりました
SQRT() 引数の平方根を返します
SRID() 幾何図形の空間参照システム ID を返します
ST_Area() Polygon または MultiPolygon 領域を返します
ST_Centroid() 重心を Point として返します
ST_Contains() ある幾何図形に別の幾何図形が含まれているかどうか
ST_Crosses() ある幾何図形が別の幾何図形と交差しているかどうか
ST_Difference() 2 つの幾何図形の点集合の差集合を返します
ST_Disjoint() ある幾何図形が別の幾何図形から切り離されているかどうか
ST_Distance() ある幾何図形の別の幾何図形からの距離
ST_Envelope() 幾何図形の MBR を返します
ST_Equals() ある幾何図形が別の幾何図形に等しいかどうか
ST_Intersection() 2 つの幾何図形の点集合の積集合を返します
ST_Intersects() ある幾何図形が別の幾何図形と交差しているかどうか
ST_Overlaps() ある幾何図形が別の幾何図形とオーバーラップしているかどうか
ST_SymDifference() 2 つの幾何図形の点集合の対称差を返します
ST_Touches() ある幾何図形が別の幾何図形に接しているかどうか
ST_Union() 2 つの幾何図形の点集合の和集合を返します
ST_Within() ある幾何図形が別の幾何図形の内部にあるかどうか
StartPoint() LineString の始点
STD() 母標準偏差を返します
STDDEV() 母標準偏差を返します
STDDEV_POP() 母標準偏差を返します
STDDEV_SAMP() 標本標準偏差を返します
STR_TO_DATE() 文字列を日付に変換します
STRCMP() 2 つの文字列を比較します
SUBDATE() 3 つの引数で呼び出されるときは DATE_SUB() のシノニムです
SUBSTR() 指定された部分文字列を返します
SUBSTRING() 指定された部分文字列を返します
SUBSTRING_INDEX() 文字列から、区切り文字が指定された回数出現する前の部分文字列を返します
SUBTIME() 時間の差を求めます
SUM() 集計を返します
SYSDATE() この関数が実行される時間を返します
SYSTEM_USER() USER() のシノニムです
TAN() 引数のタンジェントを返します
TIME() 渡された式の時部分を抽出します
TIME_FORMAT() 時間として書式設定します
TIME_TO_SEC() 秒に変換された引数を返します
TIMEDIFF() 時間の差を求めます
* 乗算演算子
TIMESTAMP() 引数が 1 つの場合、この関数は日付または日付時間式を返します。引数が 2 つの場合、引数の合計を返します
TIMESTAMPADD() 日付時間式に間隔を加算します
TIMESTAMPDIFF() 日付時間式から間隔を減算します
TO_BASE64() base 64 文字列に変換された引数を返します
TO_DAYS() 日に変換された日付引数を返します
TO_SECONDS() 0 年以降の秒数に変換された日付または日付時間引数を返します
Touches() ある幾何図形が別の幾何図形に接しているかどうか
TRIM() 先頭と末尾にある空白を削除します
TRUNCATE() 指定された小数点以下の桁数に切り捨てます
UCASE() UPPER() のシノニムです
- 引数の符号を変更します
UNCOMPRESS() 圧縮された文字列を圧縮解除します
UNCOMPRESSED_LENGTH() 圧縮前の文字列長を返します
UNHEX() 数値の 16 進数表現を含む文字列を返します
UNIX_TIMESTAMP() UNIX タイムスタンプを返します
UpdateXML() 置換後 XML フラグメントを返します
UPPER() 大文字に変換します
USER() ユーザー名と、クライアントによって提供されるホスト名です
UTC_DATE() 現在の UTC 日付を返します
UTC_TIME() 現在の UTC 時間を返します
UTC_TIMESTAMP() 現在の UTC 日付と時間を返します
UUID() ユニバーサル固有識別子 (UUID) を返します
UUID_SHORT() 整数値のユニバーサル識別子を返します
VALIDATE_PASSWORD_STRENGTH() パスワードの強度を判断します
VALUES() INSERT で使用される値を定義します
VAR_POP() 母標準分散を返します
VAR_SAMP() 標本分散を返します
VARIANCE() 母標準分散を返します
VERSION() MySQL サーバーのバージョンを示す文字列を返します
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() 指定された GTID がスレーブで実行されるまで待ちます。
WEEK() 週番号を返します
WEEKDAY() 曜日インデックスを返します
WEEKOFYEAR() 日付の暦週を返します (0 - 53)
WEIGHT_STRING() 文字列の重み文字列を返します
Within() ある幾何図形が別の幾何図形の内部にあるかどうか
X() Point の X 座標を返します
XOR 論理 XOR
Y() Point の Y 座標を返します
YEAR() 年を返します
YEARWEEK() 年と週を返します

12.2 式評価での型変換

演算子が別の型のオペランドとともに使用されると、オペランドの互換性を保つために型変換が発生します。一部の変換は暗黙的に発生します。たとえば、MySQL では必要に応じて数字が文字列 (またはその逆) に自動的に変換されます。

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

また、CAST() 関数を明示的に使用して、数字を文字列に変換することもできます。CONCAT() 関数では文字列の引数が要求されるため、使用すると暗黙的に変換が発生します。

mysql> SELECT 38.8, CAST(38.8 AS CHAR); -> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8); -> 38.8, '38.8'

文字セットの数字から文字列への暗黙的な変換について、および CREATE TABLE ... SELECT ステートメントに適用される変更済みのルールについては、このセクションの後半を参照してください。

次のルールでは、比較演算の際にどのように変換が発生するのかについて説明します。

  • NULL-safe <=> 等価比較演算子の場合を除いて、一方または両方の引数が NULL の場合は、比較の結果も NULL になります。NULL <=> NULL の場合は、結果が true になります。変換は必要ありません。

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

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

  • 16 進値が数字と比較されない場合は、バイナリ文字列として処理されます。

  • 引数の一方が TIMESTAMP または DATETIME カラムで他方が定数の場合は、比較が実行される前に定数がタイムスタンプに変換されます。これは、ODBC により適合させるために実行されます。これは、IN() への引数には実行されません。念のため、比較を行う際は、常に完全な日付時間、日付、または時間文字列を使用してください。たとえば、日付または時間の値とともに BETWEEN を使用したときの結果を最適にするには、CAST() を使用して、明示的に値を目的のデータ型に変換します。

    テーブル (複数可) からの単一行のサブクエリーは、定数とみなされません。たとえば、サブクエリーで DATETIME 値と比較される整数が返される場合は、比較が 2 つの整数として実行されます。整数は時間値には変換されません。オペランドを DATETIME 値として比較するには、CAST() を使用して、明示的にサブクエリーの値を DATETIME に変換します。

  • 引数のいずれかが 10 進値の場合、比較はその他の引数に依存します。その他の引数が 10 進値または整数値の場合、引数は 10 進値として比較され、その他の引数が浮動小数点値の場合、引数は浮動小数点値として比較されます。

  • ほかのすべてのケースでは、引数は浮動小数点 (実) 数として比較されます。

別の時間型への値の変換については、セクション11.3.7「日付と時間型間での変換」を参照してください。

次の例は、比較演算での文字列から数字への変換を示しています。

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

文字列カラムと数字との比較では、MySQL はカラム上のインデックスを使用して、値をすばやく検索できません。str_col がインデックスの付いた文字列カラムである場合は、次のステートメントで検索を実行するときに、そのインデックスを使用できません。

SELECT * FROM tbl_name WHERE str_col=1;

その理由は、'1'' 1''1a' のように、値 1 に変換できるさまざまな文字列があるためです。

このような数字は不正確であるため、浮動小数点数 (または浮動小数点数に変換される値) を使用する比較は概算になります。これにより、整合性のない結果が表示される可能性があります。

mysql> SELECT '18015376320243458' = 18015376320243458; -> 1
mysql> SELECT '18015376320243459' = 18015376320243459; -> 0

このような結果は、53 ビットの精度しか持たない浮動小数点数に値が変換され、丸めの対象になるために発生する可能性があります。

mysql> SELECT '18015376320243459'+0.0; -> 1.8015376320243e+16

さらに、文字列から浮動小数点への変換および整数から浮動小数点への変換は、必ずしも同様に発生するとはかぎりません。整数は、CPU によって浮動小数点に変換される可能性があります。一方、文字列は、浮動小数点の乗算を伴う演算で 1 桁ずつ変換されます。

表示される結果はシステムによって異なり、コンピュータのアーキテクチャーやコンパイラのバージョンなどの要因、または最適化レベルの影響を受ける可能性があります。このような問題を回避する方法の 1 つは、値が暗黙的に浮動小数点値に変換されないように、CAST() を使用することです。

mysql> SELECT CAST('18015376320243459' AS UNSIGNED) = 18015376320243459; -> 1

浮動小数点の比較についての詳細は、セクションB.5.5.8「浮動小数点値に関する問題」を参照してください。

MySQL 5.6 では、サーバーに dtoa が含まれています。これは、文字列または DECIMAL 値と近似値 (FLOAT/DOUBLE) の数値間の変換を改善するための基礎を提供する変換ライブラリです。

  • Unix と Windows 間の変換の相違などが除去された、プラットフォーム間で整合性のある変換結果。

  • 以前の結果に十分な精度がなかった場合 (IEEE の制限に近い値など) の正確な値の表示。

  • 最大限の精度を持つ文字列書式への数字の変換。dtoa の精度は、常に標準の C ライブラリ関数の精度と同じか、それ以上です。

このライブラリで生成された変換は、dtoa 以外の結果とは異なる場合があるため、以前の結果に依存するアプリケーションとの互換性が保たれない可能性があります。たとえば、以前の変換からの特定の正確な結果に依存するアプリケーションでは、追加の精度に対応するように調整が必要となる場合があります。

dtoa ライブラリでは、次のプロパティーを使用した変換が提供されます。DDECIMAL または文字列表現を含む値を表し、F はネイティブバイナリ (IEEE) 書式の浮動小数点数を表します。

  • F -> D の変換は、最大限の精度で実行され、読み取り時に F が生成されるもっとも短い文字列として D が返され、IEEE で指定されているネイティブバイナリ形式でもっとも近い値に丸められます。

  • D -> F の変換は、F が入力された 10 進文字列 D にもっとも近いネイティブバイナリの数字になるように実行されます。

F-inf+inf、または NaN の場合を除いて、これらのプロパティーは、F -> D -> F の変換が可逆であることを暗黙的に示しています。後者の値は、SQL 標準では FLOAT または DOUBLE の無効な値として定義されているため、サポートされていません。

D -> F -> D の変換では、D が 15 桁以下の精度を使用し、非正規値 (-inf+inf、または NaN) でないことが可逆のための十分な条件となります。D の精度が 15 桁よりも大きい場合でも、変換が可逆であるケースもありますが、常に該当するとはかぎりません。

MySQL 5.6 では、暗黙的に数値または時間値を文字列に変換すると、character_set_connection および collation_connection システム変数で決定された文字セットおよび照合順序を含む値が生成されます。(一般に、これらの変数は SET NAMES を使用して設定されます。接続文字セットについては、セクション10.1.4「接続文字セットおよび照合順序」を参照してください。)

つまり、接続文字セットが binary に設定されている場合を除いて、このような変換では、(非バイナリ) 文字列 (CHARVARCHAR、または LONGTEXT 値) が生成されます。この場合、変換の結果はバイナリ文字列 (BINARYVARBINARY、または LONGBLOB 値) になります。

整数式では、式の評価に関する上記の備考は、式の割り当てには多少異なる方法で適用されます。次のようなステートメントでの例を示します。

CREATE TABLE t SELECT integer_expr;

この場合、式の結果として生成されるカラム内のテーブルの型は、整数式の長さに応じて、INT または BIGINT になります。式の最大長が INT に収まらない場合は、代わりに BIGINT が使用されます。長さは、SELECT 結果セットメタデータの max_length 値から取得されます (セクション23.8.5「C API データ構造」を参照してください)。つまり、十分に長い式を使用することで、INT ではなく、BIGINT を強制的に適用できます。

CREATE TABLE t SELECT 000000000000000000000;

12.3 演算子

表 12.2 演算子

名前説明
AND, && 論理 AND
= (SET ステートメントの一部として、または UPDATE ステートメントの SET 句の一部として) 値を割り当てます
:= 値を割り当てます
BETWEEN ... AND ... 値が値の範囲内に含まれているかどうかを確認します
BINARY 文字列をバイナリ文字列にキャストします
& ビット単位の AND
~ ビットを反転します
| ビット単位の OR
^ ビット単位の XOR
CASE CASE 演算子
DIV 整数除算
/ 除算演算子
= 等価 (等しい) 演算子
<=> NULL 安全等価演算子
> 右不等 (より多い) 演算子
>= 以上 (より多いか等しい) 演算子
IS ブーリアンに対して値をテストします
IS NOT ブーリアンに対して値をテストします
IS NOT NULL NOT NULL 値テスト
IS NULL NULL 値テスト
<< 左シフト
< 左不等 (より少ない) 演算子
<= 以下 (より少ないか等しい) 演算子
LIKE 単純なパターン一致
- 減算演算子
%, MOD モジュロ演算子
NOT, ! 値を否定します
NOT BETWEEN ... AND ... 値が値の範囲内に含まれていないかどうかを確認します
!=, <> 不等価 (等しくない) 演算子
NOT LIKE 単純なパターン一致の否定
NOT REGEXP REGEXP の否定
||, OR 論理 OR
+ 加算演算子
REGEXP 正規表現を使用したパターン一致
>> 右シフト
RLIKE REGEXP のシノニムです
SOUNDS LIKE 音声を比較します
* 乗算演算子
- 引数の符号を変更します
XOR 論理 XOR

12.3.1 演算子の優先順位

次のリストには、演算子の優先順位をもっとも高いものから順番に示しています。同じ行に並んで記載されている演算子は、優先順位が同じものです。

INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
&&, AND
XOR
||, OR
= (assignment), :=

= の優先順位は、比較演算子 (=) として使用されるのか、割り当て演算子 (=) として使用されるのかによって異なります。比較演算子として使用される場合は、優先順位が <=>>=><=<<>!=ISLIKEREGEXP、および IN と同じです。割り当て演算子として使用される場合は、優先順位が := と同じです。セクション13.7.4「SET 構文」およびセクション9.4「ユーザー定義変数」では、適用される = の解釈が MySQL でどのように決定されるのかについて説明されています。

一部の演算子の意味は、SQL モードによって異なります。

  • デフォルトでは、|| は論理 OR 演算子です。PIPES_AS_CONCAT が有効になっている場合は、||^ と単項演算子間の優先順位を持つ文字列連結です。

  • デフォルトでは、!NOT よりも高い優先順位です。HIGH_NOT_PRECEDENCE が有効になっている場合は、!NOT の優先順位は同じです。

セクション5.1.7「サーバー SQL モード」を参照してください。

演算子の優先順位によって、式の項の評価順序が決まります。この順序をオーバーライドし、明示的に項をグループ化するには、丸括弧を使用します。例:

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

12.3.2 比較関数と演算子

表 12.3 比較演算子

名前説明
BETWEEN ... AND ... 値が値の範囲内に含まれているかどうかを確認します
COALESCE() NULL 以外の最初の引数を返します
= 等価 (等しい) 演算子
<=> NULL 安全等価演算子
> 右不等 (より多い) 演算子
>= 以上 (より多いか等しい) 演算子
GREATEST() 最大の引数を返します
IN() ある値が値セット内に含まれているかどうかを確認します
INTERVAL() 第 1 引数より小さい引数のインデックスを返します
IS ブーリアンに対して値をテストします
IS NOT ブーリアンに対して値をテストします
IS NOT NULL NOT NULL 値テスト
IS NULL NULL 値テスト
ISNULL() 引数が NULL かどうかをテストします
LEAST() 最小の引数を返します
< 左不等 (より少ない) 演算子
<= 以下 (より少ないか等しい) 演算子
LIKE 単純なパターン一致
NOT BETWEEN ... AND ... 値が値の範囲内に含まれていないかどうかを確認します
!=, <> 不等価 (等しくない) 演算子
NOT IN() 値が値セット内に含まれていないかどうかを確認します
NOT LIKE 単純なパターン一致の否定
STRCMP() 2 つの文字列を比較します

比較演算の結果は、1 (TRUE)、0 (FALSE)、または NULL の値になります。これらの演算は、数字と文字列の両方で機能します。必要に応じて、文字列は数字に、数字は文字列に自動的に変換されます。

次の関係比較演算子を使用すれば、スカラーオペランドだけでなく行オペランドも比較できます。

= > < >= <= <> !=

行比較の例については、セクション13.2.10.5「行サブクエリー」を参照してください。

このセクションで示す関数の一部では、1 (TRUE)、0 (FALSE)、または NULL 以外の値が返されます。たとえば、LEAST()GREATEST() です。ただし、返される値は、セクション12.2「式評価での型変換」で説明したルールに従って実行された比較演算に基づきます。

CAST() 関数を使用すると、比較目的で値を特定の型に変換できます。CONVERT() を使用すると、文字列値を別の文字セットに変換できます。セクション12.10「キャスト関数と演算子」を参照してください。

デフォルトでは、文字列の比較では大文字と小文字が区別されず、現在の文字セットが使用されます。デフォルトは latin1 (cp1252 西ヨーロッパ言語) であり、英語でも正常に機能します。

  • =

    等しい:

    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
  • <=>

    NULL - 安全等価。この演算子では、= 演算子のように等価比較が実行されますが、両方のオペランドが NULL であれば、NULL でなく 1 が返され、一方のオペランドが NULL の場合は、NULL でなく 0 が返されます。

    mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1, 1, 0
    mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL; -> 1, NULL, NULL
  • <>, !=

    等しくない:

    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
  • IS boolean_value

    boolean_valueTRUEFALSE、または UNKNOWN にすることができるブール値に対して値をテストします。

    mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN; -> 1, 1, 1
  • IS NOT boolean_value

    boolean_valueTRUEFALSE、または UNKNOWN にすることができるブール値に対して値をテストします。

    mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN; -> 1, 1, 0
  • IS NULL

    値が NULL かどうかをテストします。

    mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL; -> 0, 0, 1

    ODBC プログラムとの連携が正しく機能するように、MySQL では IS NULL の使用時に次の追加機能がサポートされます。

    • sql_auto_is_null 変数が 1 に設定されている場合は、自動的に生成された AUTO_INCREMENT 値を正常に挿入するステートメントのあとに、次の形式のステートメントを発行すれば、その値を検索できます。

      SELECT * FROM tbl_name WHERE auto_col IS NULL

      ステートメントが行を返す場合、返される値は LAST_INSERT_ID() 関数を呼び出した場合と同じです。複数行の挿入後の戻り値などについての詳細は、セクション12.14「情報関数」を参照してください。AUTO_INCREMENT 値を正常に挿入できなかった場合、SELECT ステートメントは行を返しません。

      IS NULL の比較を使用して AUTO_INCREMENT 値を取得する動作は、sql_auto_is_null = 0 を設定すると無効にできます。セクション5.1.4「サーバーシステム変数」を参照してください。

      MySQL 5.6 では sql_auto_is_null のデフォルト値は 0 です。

    • NOT NULL として宣言された DATE および DATETIME カラムでは、次のようなステートメントを使用することで、特殊な日付 '0000-00-00' を検索できます。

      SELECT * FROM tbl_name WHERE date_column IS NULL

      ODBC では '0000-00-00' 日付値がサポートされていないため、一部の ODBC アプリケーションを取得する際に、これが必要になります。

      Obtaining Auto-Increment Values、およびConnector/ODBC Connection ParametersFLAG_AUTO_IS_NULL オプションについての説明を参照してください。

  • IS NOT NULL

    値が NULL でないかどうかをテストします。

    mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL; -> 1, 1, 0
  • expr BETWEEN min AND max

    exprmin より多いか等しく、exprmax より少ないか等しい場合、BETWEEN1 を返し、それ以外では 0 を返します。すべての引数の型が同じであれば、これは式 (min <= expr AND expr <= max) と同等です。それ以外の場合は、セクション12.2「式評価での型変換」に記載したルールに従って型変換が実行されますが、3 つのすべての引数に適用されます。

    mysql> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1; -> 1, 0
    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

    日付または時間の値とともに BETWEEN を使用したときの結果を最適にするには、CAST() を使用して明示的に値を目的のデータ型に変換します。例 : DATETIME を 2 つの DATE 値と比較する場合は、DATE 値を DATETIME 値に変換します。DATE との比較で '2001-1-1' などの文字列定数を使用する場合は、文字列を DATE にキャストします。

  • expr NOT BETWEEN min AND max

    これは、NOT (expr BETWEEN min AND max) と同じです。

  • COALESCE(value,...)

    リストの最初の非 NULL 値を返します。非 NULL 値がない場合は、NULL を返します。

    mysql> SELECT COALESCE(NULL,1); -> 1
    mysql> SELECT COALESCE(NULL,NULL,NULL); -> NULL
  • GREATEST(value1,value2,...)

    2 つ以上の引数がある場合は、最大の (最大値の) 引数を返します。引数は、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'

    引数のいずれかが NULL である場合、GREATEST()NULL を返します。

  • expr IN (value,...)

    exprIN リストのいずれかの値と等しい場合は 1 を返し、それ以外の場合は 0 を返します。すべての値が定数の場合は、expr の型に従って評価され、ソートされます。その際の項目の検索は、バイナリ検索を使って行われます。つまり、IN 値のリストがすべて定数で構成されている場合、IN は非常に高速です。それ以外の場合は、セクション12.2「式評価での型変換」で説明したルールに従って型変換が実行されますが、すべての引数に適用されます。

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

    引用符で囲まれた値 (文字列など) と囲まれていない値 (数字など) の比較ルールは異なるため、IN リストの引用符で囲まれた値と囲まれていない値を決して混同しないでください。したがって、型を混同すると、整合性のない結果になる可能性があります。たとえば、IN 式を次のように記述しないでください。

    SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');

    代わりに、次のように記述してください。

    SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');

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

    SQL の標準に準拠するために、左側の式が NULL である場合だけでなく、リストに一致が見つからない場合やリストの式のいずれかが NULL である場合にも、INNULL を返します。

    IN() 構文は、特定のタイプのサブクエリーを作成する際にも使用できます。セクション13.2.10.3「ANY、IN、または SOME を使用したサブクエリー」を参照してください。

  • expr NOT IN (value,...)

    これは、NOT (expr IN (value,...)) と同じです。

  • ISNULL(expr)

    exprNULL の場合、ISNULL()1 を返し、それ以外の場合は 0 を返します。

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

    = の代わりに ISNULL() を使用すると、値が NULL であるかどうかをテストできます。(= を使用して値を NULL と比較すると、常に false が発生します。)

    ISNULL() 関数は IS NULL 比較演算子と、いくつかの特殊な動作を共有します。IS NULL の説明を参照してください。

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

    N < N1 の場合は 0 を返し、N < 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
  • LEAST(value1,value2,...)

    2 つ以上の引数がある場合は、最小の (最小値の) 引数を返します。引数は、次のルールを使用して比較されます。

    • 引数が NULL である場合、結果は NULL になります。比較は必要ありません。

    • 戻り値が 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'

    一部のボーダーラインケースでは、前述の変換ルールで異常な結果が生成される可能性があります。

    mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED); -> -9223372036854775808

    これは、MySQL が 9223372036854775808.0 を整数のコンテキストで読み取ることが原因で発生します。整数表記では値を保持するのに十分でないため、符号付き整数にラップします。

12.3.3 論理演算子

表 12.4 論理演算子

名前説明
AND, && 論理 AND
NOT, ! 値を否定します
||, OR 論理 OR
XOR 論理 XOR

SQL では、すべての論理演算子は TRUEFALSE、または NULL (UNKNOWN) に評価されます。MySQL では、これらは 1 (TRUE)、0 (FALSE)、および NULL として実装されます。この大部分は、さまざまな SQL データベースサーバーに共通のものです。ただし、一部のサーバーは TRUE にゼロ以外の任意の値を返す場合があります。

MySQL では、ゼロ以外の任意の非 NULL 値が TRUE に評価されます。たとえば、次のステートメントはすべて TRUE に評価されます。

mysql> SELECT 10 IS TRUE;-> 1
mysql> SELECT -10 IS TRUE;-> 1
mysql> SELECT 'string' IS NOT NULL;-> 1
  • 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&&

    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
  • OR||

    論理 OR。両方のオペランドが非 NULL であれば、オペランドのいずれかがゼロ以外である場合の結果は 1、それ以外の場合は 0 になります。NULL オペランドが 1 つあれば、ほかのオペランドがゼロ以外である場合の結果は 1、それ以外の場合は NULL になります。両方のオペランドが NULL であれば、結果は NULL になります。

    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

    論理 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) に等しくなります。

12.3.4 割り当て演算子

表 12.5 割り当て演算子

名前説明
= (SET ステートメントの一部として、または UPDATE ステートメントの SET 句の一部として) 値を割り当てます
:= 値を割り当てます

  • :=

    割り当て演算子。演算子の左側にあるユーザー変数が右側にある値に代入されます。右側の値は、リテラル値、値を格納する別の変数、またはクエリーの結果を含むスカラー値を生成する任意の有効な式 (この値がスカラー値の場合) である可能性があります。同じ SET ステートメントで、複数の割り当てを実行できます。同じステートメントで、複数の割り当てを実行できます。

    = とは異なり、:= 演算子は比較演算子として解釈されません。つまり、(SET ステートメントだけでなく) 有効な任意の SQL ステートメントで := を使用すれば、値を変数に割り当てることができます。

    mysql> SELECT @var1, @var2; -> NULL, NULL
    mysql> SELECT @var1 := 1, @var2; -> 1, NULL
    mysql> SELECT @var1, @var2; -> 1, NULL
    mysql> SELECT @var1, @var2 := @var1; -> 1, 1
    mysql> SELECT @var1, @var2; -> 1, 1
    mysql> SELECT @var1:=COUNT(*) FROM t1; -> 4
    mysql> SELECT @var1; -> 4

    次に示すように、SELECT 以外のステートメント (UPDATE など) でも、:= を使用して値の割り当てを実行できます。

    mysql> SELECT @var1; -> 4
    mysql> SELECT * FROM t1; -> 1, 3, 5, 7
    mysql> UPDATE t1 SET c1 = 2 WHERE c1 = @var1:= 1;Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    mysql> SELECT @var1; -> 1
    mysql> SELECT * FROM t1; -> 2, 3, 5, 7

    := 演算子を使用すれば、単一の SQL ステートメントで同じ変数の値の設定と読み取りの両方を行うこともできますが、これは推奨されていません。セクション9.4「ユーザー定義変数」では、これを回避するべき理由について説明されています。

  • =

    この演算子は、次の 2 つのパラグラフで説明する 2 つのケースで値の割り当てを実行する際に使用されます。

    SET ステートメントでは、= は、演算子の左側にあるユーザー変数を右側にある値に代入する割り当て演算子として処理されます。(言い換えると、SET ステートメントで使用されると、=:= と同じように処理されます。)右側の値は、リテラル値、値を格納する別の変数、またはクエリーの結果を含むスカラー値を生成する任意の有効な式 (この値がスカラー値の場合) である可能性があります。同じ SET ステートメントで、複数の割り当てを実行できます。

    UPDATE ステートメントの SET 句では、= は割り当て演算子としても機能します。ただし、この場合、UPDATE の一部である WHERE 条件に一致していれば、演算子の左側で指定されたカラムが右側に指定された値であるとみなされます。UPDATE ステートメントの同じ SET 句で、複数の割り当てを実行できます。

    その他のコンテキストでは、=比較演算子として処理されます。

    mysql> SELECT @var1, @var2; -> NULL, NULL
    mysql> SELECT @var1 := 1, @var2; -> 1, NULL
    mysql> SELECT @var1, @var2; -> 1, NULL
    mysql> SELECT @var1, @var2 := @var1; -> 1, 1
    mysql> SELECT @var1, @var2; -> 1, 1

    詳細は、セクション13.7.4「SET 構文」セクション13.2.11「UPDATE 構文」、およびセクション13.2.10「サブクエリー構文」を参照してください。

12.4 制御フロー関数

表 12.6 フロー制御演算子

名前説明
CASE CASE 演算子
IF() If/else 構文
IFNULL() Null if/else 構文
NULLIF() expr1 = expr2 の場合に NULL を返します

  • 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

    1 番目のバージョンでは、value=compare_value の場合に result が返されます。2 番目のバージョンでは、true である最初の条件の結果が返されます。一致する結果値がなかった場合は、ELSE のあとの結果が返され、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

    CASE 式の戻り型は、すべての戻り値の互換性のある集約型ですが、使用されるコンテキストにも依存します。文字列のコンテキストで使用される場合は、結果は文字列として返されます。数値のコンテキストで使用される場合は、結果が 10 進数値、実数値、または整数値として返されます。

    注記

    ここで示す CASEの構文は、ストアドプログラム内部で使用するために、セクション13.6.5.1「CASE 構文」で説明した SQL CASEステートメントの構文とはわずかに異なります。CASE ステートメントは ELSE NULL 句を持つことができず、END でなく、END CASE で終了します。

  • IF(expr1,expr2,expr3)

    expr1TRUE (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'

    expr2expr3 の一方のみが明示的に NULL である場合は、IF() 関数の結果型は非 NULL 式の型になります。

    IF() のデフォルトの戻り値 (一時テーブルに格納されるときに重要となる場合があります) は、次のように計算されます。

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

    expr2expr3 の両方が文字列で、どちらかの文字列で大文字と小文字が区別される場合は、結果でも大文字と小文字が区別されます。

    注記

    IFステートメントもありますが、ここで説明されている IF()関数とは異なります。セクション13.6.5.2「IF 構文」を参照してください。

  • IFNULL(expr1,expr2)

    expr1NULL でない場合、IFNULL()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'

    IFNULL(expr1,expr2) のデフォルトの結果値は、STRINGREAL、または INTEGER の順に、2 つの式のよりも一般的です。式や MySQL が一時テーブルの IFNULL() で返された値を内部に格納する必要のある場所に基づいて、テーブルの大文字と小文字を考慮してください。

    mysql> CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;mysql> DESCRIBE tmp;+-------+--------------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | test | varbinary(4) | NO | | | |
    +-------+--------------+------+-----+---------+-------+

    この例では、test カラムの型は VARBINARY(4) です。

  • NULLIF(expr1,expr2)

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

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

    引数が等しくない場合は、MySQL で expr1 が 2 回評価されます。

12.5 文字列関数

表 12.7 文字列演算子

名前説明
ASCII() 左端の文字の数値を返します
BIN() 数値のバイナリ表現を含む文字列を返します
BIT_LENGTH() ビット単位で引数の長さを返します
CHAR() 渡された各整数の文字を返します
CHAR_LENGTH() 引数の文字数を返します
CHARACTER_LENGTH() CHAR_LENGTH() のシノニムです
CONCAT() 連結された文字列を返します
CONCAT_WS() 連結されたものをセパレータ付きで返します
ELT() インデックス番号位置の文字列を返します
EXPORT_SET() 値 bits 内の各ビットが設定されている場合は on 文字列を取得し、各ビットが設定されていない場合には off 文字列を取得するように、文字列を返します
FIELD() 後続の引数内で第 1 引数のインデックス (位置) を返します
FIND_IN_SET() 第 2 引数内で第 1 引数のインデックス位置を返します
FORMAT() 指定された小数点以下桁数に書式設定された数値を返します
FROM_BASE64() base 64 文字列にデコードして結果を返します
HEX() 10 進値または文字列値の 16 進表現を返します
INSERT() 部分文字列を、指定された位置に指定された文字数だけ挿入します
INSTR() 部分文字列が最初に出現する位置のインデックスを返します
LCASE() LOWER() のシノニムです
LEFT() 左端から指定された数の文字を返します
LENGTH() 文字列の長さをバイト単位で返します
LIKE 単純なパターン一致
LOAD_FILE() 指定されたファイルをロードします
LOCATE() 部分文字列が最初に出現する位置を返します
LOWER() 引数を小文字で返します
LPAD() 指定された文字列で左からパディングした文字列引数を返します
LTRIM() 先頭の空白を削除します
MAKE_SET() bits セット内の対応するビットを持つ、カンマ区切り文字列のセットを返します
MATCH 全文検索を実行します
MID() 指定された位置から始まる部分文字列を返します
NOT LIKE 単純なパターン一致の否定
NOT REGEXP REGEXP の否定
OCT() 数値の 8 進数表現を含む文字列を返します
OCTET_LENGTH() LENGTH() のシノニムです
ORD() 引数の左端の文字の文字コードを返します
POSITION() LOCATE() のシノニムです
QUOTE() SQL ステートメント内で使用するために引数をエスケープします
REGEXP 正規表現を使用したパターン一致
REPEAT() 文字列を指定された回数だけ繰り返します
REPLACE() 指定された文字列の出現箇所を置き換えます
REVERSE() 文字列内の文字を逆順に並べ替えます
RIGHT() 右端から指定された数の文字を返します
RLIKE REGEXP のシノニムです
RPAD() 指定された回数だけ文字列を追加します
RTRIM() 末尾の空白を削除します
SOUNDEX() soundex 文字列を返します
SOUNDS LIKE 音声を比較します
SPACE() 指定された数の空白で構成される文字列を返します
STRCMP() 2 つの文字列を比較します
SUBSTR() 指定された部分文字列を返します
SUBSTRING() 指定された部分文字列を返します
SUBSTRING_INDEX() 文字列から、区切り文字が指定された回数出現する前の部分文字列を返します
TO_BASE64() base 64 文字列に変換された引数を返します
TRIM() 先頭と末尾にある空白を削除します
UCASE() UPPER() のシノニムです
UNHEX() 数値の 16 進数表現を含む文字列を返します
UPPER() 大文字に変換します
WEIGHT_STRING() 文字列の重み文字列を返します

文字列値の関数は、結果の長さが max_allowed_packet システム環境変数の値よりも長くなると、NULL を返します。セクション8.11.2「サーバーパラメータのチューニング」を参照してください。

文字列の位置を操作する関数では、最初の位置には数値 1 が付けられます。

長さの引数を取る関数では、整数以外の引数はもっとも近い整数に丸められます。

  • ASCII(str)

    文字列 str の左端の文字の数値を返します。str が空の文字列である場合は、0 を返します。strNULL である場合は NULL を返します。ASCII() は、8 ビット文字の場合に動作します。

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

    ORD() 関数も参照してください。

  • BIN(N)

    N のバイナリ値の文字列表現を返します。N は longlong (BIGINT) 数字です。これは、CONV(N,10,2) と同等です。NNULL である場合は NULL を返します。

    mysql> SELECT BIN(12); -> '1100'
  • BIT_LENGTH(str)

    文字列 str の長さをビット単位で返します。

    mysql> SELECT BIT_LENGTH('text'); -> 32
  • CHAR(N,... [USING charset_name])

    CHAR() は各 N 引数を整数として解釈し、それらの整数のコード値で指定された文字を構成している文字列を返します。NULL 値はスキップされます。

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

    255 よりも大きい CHAR() 引数は、複数の結果バイトに変換されます。たとえば、CHAR(256)CHAR(1,0) に同等で、CHAR(256*256)CHAR(1,0,0) に同等です。

    mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256));+----------------+----------------+
    | HEX(CHAR(1,0)) | HEX(CHAR(256)) |
    +----------------+----------------+
    | 0100 | 0100 |
    +----------------+----------------+
    mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));+------------------+--------------------+
    | HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) |
    +------------------+--------------------+
    | 010000 | 010000 |
    +------------------+--------------------+

    デフォルトでは、CHAR() はバイナリ文字列を返します。指定された文字セットで文字列を生成するには、オプションの USING 句を使用します。

    mysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));+---------------------+--------------------------------+
    | CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |
    +---------------------+--------------------------------+
    | binary | utf8 |
    +---------------------+--------------------------------+

    USING が指定され、結果文字列が指定された文字セットで不正である場合は、警告が発行されます。また、厳密な SQL モードが有効になっている場合は、CHAR() からの結果は NULL になります。

  • CHAR_LENGTH(str)

    文字で測定された文字列 str の長さを返します。マルチバイト文字は、単一の文字としてカウントされます。つまり、5 つの 2 バイト文字を含む文字列では、LENGTH()10 を返し、CHAR_LENGTH()5 を返します。

  • CHARACTER_LENGTH(str)

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

  • CONCAT(str1,str2,...)

    引数を連結することで生成される文字列を返します。1 つ以上の引数を持つ場合があります。すべての引数が非バイナリ文字列の場合は、結果も非バイナリ文字列になります。引数にバイナリ文字列が含まれる場合は、結果はバイナリ文字列になります。数値の引数は、同等の非バイナリ文字列形式に変換されます。

    引数のいずれかかが NULL である場合、CONCAT()NULL を返します。

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

    引用符で囲まれた文字列では、文字列を並べて配置することで連結が実行されます。

    mysql> SELECT 'My' 'S' 'QL'; -> 'MySQL'
  • CONCAT_WS(separator,str1,str2,...)

    CONCAT_WS() は Concatenate With Separator (区切り文字を使用した連結) を表し、CONCAT() の特殊な形式です。最初の引数は、残りの引数の区切り文字です。区切り文字は、連結される文字列の間に追加されます。区切り文字は、残りの引数と同様に文字列にすることができます。区切り文字が 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'

    CONCAT_WS() では、空の文字列がスキップされません。ただし、区切り文字引数のあとの NULL 値はすべてスキップされます。

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

    ELT() は、文字列リストの N 番目の要素を返します。N = 1 の場合は str1N = 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 内で各ビットが設定されている場合には on 文字列を取得し、値内で各ビットが設定されていない場合には off 文字列を取得するように、文字列を返します。bits のビットは、右から左 (下位ビットから上位ビット) へと検証されます。文字列は、separator 文字列 (デフォルトはカンマ文字 ,) で区切られた結果に左から右へと追加されます。検証されるビット数は、number_of_bits で指定されます。指定されない場合のデフォルトは 64 です。number_of_bits が 64 よりも大きい場合は、警告なしで 64 に短縮されます。符号なし整数として処理されるため、値 −1 は実際には 64 と同じです。

    mysql> SELECT EXPORT_SET(5,'Y','N',',',4); -> 'Y,N,Y,N'
    mysql> SELECT EXPORT_SET(6,'1','0',',',10); -> '0,1,1,0,0,0,0,0,0,0'
  • FIELD(str,str1,str2,str3,...)

    str1str2str3... リスト内で str のインデックス (位置) を返します。str が見つからない場合は、0 を返します。

    FIELD() へのすべての引数が文字列の場合は、すべての引数が文字列として比較されます。すべての引数が数値の場合は、数字として比較されます。それ以外の場合は、引数が倍精度として比較されます。

    NULL ではどの値との等価比較にも失敗するため、strNULL である場合は、戻り値が 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)

    文字列 strN 部分文字列で構成される文字列リスト strlist 内にある場合は、1 から N までの範囲内の値を返します。文字列リストは、, 文字で区切られた部分文字列で構成された文字列です。最初の引数が定数文字列で、2 番目が SET 型のカラムの場合、FIND_IN_SET() 関数はビット演算を使用するために最適化されます。strstrlist 内にない場合、または strlist が空の文字列の場合は、0 を返します。引数のいずれかが NULL である場合は、NULL を返します。最初の引数にカンマ (,) 文字が含まれる場合は、この関数が正しく動作しません。

    mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2
  • FORMAT(X,D[,locale])

    数値 X'#,###,###.##' のような書式に変換し、小数点第 D 位に丸めて、その結果を文字列として返します。D0 の場合は、結果に小数点または小数部が含まれません。

    オプションの 3 番目のパラメータを使用すると、結果数の小数点、3 桁の区切り文字、および区切り文字間のグループ化に使用されるロケールを指定できます。許可されるロケール値は、lc_time_names システム変数の有効な値と同じです (セクション10.7「MySQL Server のロケールサポート」を参照してください)。ロケールが指定されていない場合のデフォルトは、'en_US' です。

    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'
    mysql> SELECT FORMAT(12332.2,2,'de_DE'); -> '12.332,20'
  • FROM_BASE64(str)

    TO_BASE64() で使用される base-64 でエンコードされたルールでエンコードされた文字列が指定され、デコードされた結果をバイナリ文字列として返します。引数が NULL の場合または有効な base-64 文字列でない場合は、結果が NULL になります。ルールのエンコードおよびデコードについての詳細は、TO_BASE64() の説明を参照してください。

    この関数は、MySQL 5.6.1 で追加されました。

    mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc')); -> 'JWJj', 'abc'
  • HEX(str), HEX(N)

    文字列の引数 str では、HEX()str の 16 進数文字列表現を返します。str 内の各文字の各バイトは、2 つの 16 進数字に変換されます。(したがって、マルチバイト文字は 2 桁よりも大きくなります。)この演算の逆は、UNHEX() 関数で実行されます。

    数値の引数 N では、HEX() は、longlong (BIGINT) 数字として処理される N の 16 進数文字列表現を返します。これは、CONV(N,10.16) と同等です。この演算の逆は、CONV(HEX(N),16,10) で実行されます。

    mysql> SELECT 0x616263, HEX('abc'), UNHEX(HEX('abc')); -> 'abc', 616263, 'abc'
    mysql> SELECT HEX(255), CONV(HEX(255),16,10); -> 'FF', 255
  • INSERT(str,pos,len,newstr)

    位置 pos で始まる部分文字列と、文字列 newstr で置換された len 文字長とともに、文字列 str を返します。pos が文字列の長さに収まらない場合は、元の文字列を返します。len が残りの文字列の長さに収まらない場合は、位置 pos からの残りの文字列を置換します。引数のいずれかが NULL である場合は、NULL を返します。

    mysql> SELECT INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic'
    mysql> SELECT INSERT('Quadratic', -1, 4, 'What'); -> 'Quadratic'
    mysql> SELECT INSERT('Quadratic', 3, 100, 'What'); -> 'QuWhat'

    この関数はマルチバイトセーフです。

  • INSTR(str,substr)

    文字列 str 内で部分文字列 substr が最初に出現する位置を返します。これは、引数の順序が逆になる点を除いて、2 つの引数形式の LOCATE() と同じです。

    mysql> SELECT INSTR('foobarbar', 'bar'); -> 4
    mysql> SELECT INSTR('xbar', 'foobar'); -> 0

    この関数はマルチバイトセーフであり、1 つ以上の引数がバイナリ文字列である場合にのみ大文字と小文字が区別されます。

  • LCASE(str)

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

  • LEFT(str,len)

    文字列 str から左端の len 文字を返し、引数が NULL である場合は NULL を返します。

    mysql> SELECT LEFT('foobarbar', 5); -> 'fooba'

    この関数はマルチバイトセーフです。

  • LENGTH(str)

    バイトで測定された文字列 str の長さを返します。マルチバイト文字は、複数のバイトとしてカウントされます。つまり、5 つの 2 バイト文字を含む文字列では、LENGTH()10 を返し、CHAR_LENGTH()5 を返します。

    mysql> SELECT LENGTH('text'); -> 4
    注記

    Length() OpenGIS 空間関数は、MySQL では GLength() という名前です。

  • LOAD_FILE(file_name)

    ファイルを読み取り、ファイルの内容を文字列として返します。この関数を使用するには、ファイルがサーバーホストに配置されている必要があり、ファイルへのフルパス名を指定し、FILE 権限を持つ必要があります。ファイルはすべてのユーザーから読み取り可能で、max_allowed_packet バイトよりも小さなサイズである必要があります。secure_file_priv システム変数が空でないディレクトリ名に設定されている場合は、そのディレクトリ内にロード対象のファイルが配置されている必要があります。

    ファイルが存在しない場合、または上記の条件が満たされていないために、ファイルを読み取ることができない場合、この関数は NULL を返します。

    character_set_filesystem システム変数では、リテラル文字列として指定されているファイル名の解釈が制御されます。

    mysql> UPDATE t SET blob_col=LOAD_FILE('/tmp/picture') WHERE id=1;
  • LOCATE(substr,str), LOCATE(substr,str,pos)

    1 番目の構文は、文字列 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

    この関数はマルチバイトセーフであり、1 つ以上の引数がバイナリ文字列である場合にのみ大文字と小文字が区別されます。

  • LOWER(str)

    現在の文字セットのマッピングに従って、すべての文字が小文字に変更された文字列 str を返します。デフォルトは latin1 (cp1252 西ヨーロッパ言語) です。

    mysql> SELECT LOWER('QUADRATICALLY'); -> 'quadratically'

    LOWER() (および UPPER()) をバイナリ文字列 (BINARYVARBINARYBLOB) に適用しても、何の効果もありません。大文字/小文字の変換を実行するには、バイナリ文字列を非バイナリ文字列に変換します。

    mysql> SET @str = BINARY 'New York';mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));+-------------+-----------------------------------+
    | LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |
    +-------------+-----------------------------------+
    | New York | new york |
    +-------------+-----------------------------------+

    Unicode 文字セットの場合、xxx_unicode_520_ci 照合順序およびそれらから派生した言語固有の照合順序では、LOWER() および UPPER() は Unicode 照合順序アルゴリズム (UCA) 5.2.0 に従って動作します。その他の Unicode 照合では、LOWER() および UPPER() は Unicode 照合アルゴリズム (UCA) 4.0.0 に従って動作します。セクション10.1.14.1「Unicode 文字セット」を参照してください。

    この関数はマルチバイトセーフです。

  • LPAD(str,len,padstr)

    len 文字の長さになるように文字列 padstr で左にパディングされた文字列 str を返します。strlen よりも長い場合は、戻り値は len 文字に短縮されます。

    mysql> SELECT LPAD('hi',4,'??'); -> '??hi'
    mysql> SELECT LPAD('hi',1,'??'); -> 'h'
  • LTRIM(str)

    先頭の空白文字が削除された文字列 str を返します。

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

    この関数はマルチバイトセーフです。

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

    bits セット内の対応するビットを持つ文字列で構成されるセット値 (, 文字で区切られた部分文字列を含む文字列) を返します。str1 はビット 0 に対応し、str2 はビット 1 に対応する、などとなります。str1str2... 内の 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(1 | 4,'hello','nice',NULL,'world'); -> 'hello'
    mysql> SELECT MAKE_SET(0,'a','b','c'); -> ''
  • MID(str,pos,len)

    MID(str,pos,len) は、SUBSTRING(str,pos,len) のシノニムです。

  • OCT(N)

    N の 8 進数の文字列表現を返します。N は longlong (BIGINT) 数字です。これは、CONV(N,10.8) と同等です。NNULL である場合は NULL を返します。

    mysql> SELECT OCT(12); -> '14'
  • OCTET_LENGTH(str)

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

  • ORD(str)

    文字列 str の左端の文字がマルチバイト文字である場合は、その文字のコードを返します。コードは、次の計算式を使用して、その構成要素の数値から計算されます。

     (1st byte code)
    + (2nd byte code * 256)
    + (3rd byte code * 2562) ...

    左端の文字がマルチバイト文字でない場合は、ORD()ASCII() 関数と同じ値を返します。

    mysql> SELECT ORD('2'); -> 50
  • POSITION(substr IN str)

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

  • QUOTE(str)

    SQL ステートメントで、適切にエスケープされたデータ値として使用できる結果を生成する文字列を引用符で囲みます。一重引用符で囲まれ、バックスラッシュの後ろにバックスラッシュ (\)、一重引用符 (')、ASCII NUL、および Control+Z の各インスタンスが続く文字列が返されます。引数が NULL の場合の戻り値は、一重引用符で囲まれていない単語 NULL です。

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

    比較するために、セクション9.1.1「文字列リテラル」およびセクション23.8.7.54「mysql_real_escape_string()」で、リテラル文字列に対する引用ルールと C API 内の引用ルールを参照してください。

  • REPEAT(str,count)

    count 回繰り返された文字列 str で構成される文字列を返します。count が 1 よりも小さい場合は、空の文字列を返します。str または countNULL である場合は NULL を返します。

    mysql> SELECT REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL'
  • REPLACE(str,from_str,to_str)

    文字列 from_str のすべての出現箇所が文字列 to_str で置換された、文字列 str を返します。REPLACE() は、from_str を検索する際に、大文字と小文字を区別した一致を実行します。

    mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww'); -> 'WwWwWw.mysql.com'

    この関数はマルチバイトセーフです。

  • REVERSE(str)

    文字の順序が逆になった文字列 str を返します。

    mysql> SELECT REVERSE('abc'); -> 'cba'

    この関数はマルチバイトセーフです。

  • RIGHT(str,len)

    文字列 str から右端の len 文字を返し、引数が NULL である場合は NULL を返します。

    mysql> SELECT RIGHT('foobarbar', 4); -> 'rbar'

    この関数はマルチバイトセーフです。

  • RPAD(str,len,padstr)

    len 文字の長さになるように文字列 padstr で右にパディングされた文字列 str を返します。strlen よりも長い場合は、戻り値は len 文字に短縮されます。

    mysql> SELECT RPAD('hi',5,'?'); -> 'hi???'
    mysql> SELECT RPAD('hi',1,'?'); -> 'h'

    この関数はマルチバイトセーフです。

  • RTRIM(str)

    末尾の空白文字が削除された文字列 str を返します。

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

    この関数はマルチバイトセーフです。

  • SOUNDEX(str)

    str から soundex 文字列を返します。ほぼ同じ発音の 2 つの文字列は、同じ soundex 文字列を持つはずです。標準の soundex 文字列の長さは 4 文字ですが、SOUNDEX() 関数は任意の長さの文字列を返します。結果で SUBSTRING() を使用すると、標準の soundex 文字列を取得できます。str 内のアルファベット以外の文字はすべて無視されます。A から Z までの範囲外の国際アルファベット文字はすべて、母音として処理されます。

    重要

    SOUNDEX() の使用時には、次の制限に注意してください。

    • 現在実装されているこの関数は、文字列の言語が英語である場合にのみ機能するように設計されています。その他の言語の文字列では、信頼できる結果が生成されない可能性があります。

    • この関数では、文字列でマルチバイト文字セット (utf-8 など) が使用されている場合に、整合性のある結果が生成されることは保証されません。

      今後のリリースで、このような制限が解除されることを期待しています。詳細は、Bug #22638 を参照してください。

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

    この関数には、オリジナルの Soundex アルゴリズムが実装されています。より人気のある拡張バージョンではありません (この作成者も D. Knuth です)。相違点としては、元のバージョンではまず母音が破棄されてから複製が破棄されますが、拡張バージョンではまず複製が破棄されてから母音が破棄されます。

  • expr1 SOUNDS LIKE expr2

    これは、SOUNDEX(expr1) = SOUNDEX(expr2) と同じです。

  • SPACE(N)

    N 空白文字で構成される文字列を返します。

    mysql> SELECT SPACE(6); -> ' '
  • SUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str FROM pos FOR len)

    SUBSTR()SUBSTRING() のシノニムです。

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

    len 引数を付けない形式では、位置 pos で始まる文字列 str からの部分文字列が返されます。len 引数を付けた形式では、位置 pos で始まる文字列 str からの部分文字列 len 文字長が返されます。FROM を使用する形式は、標準の SQL 構文です。また、pos に負の値を使用することもできます。その場合、部分文字列の先頭は文字列の先頭でなく、文字列の末尾からの pos 文字になります。この関数のどの形式でも、pos で負の値を使用できます。

    すべての形式の SUBSTRING() で、部分文字列の抽出が開始される文字列内の最初の文字の位置が 1 とみなされます。

    mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically'
    mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar'
    mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica'
    mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila'
    mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki'
    mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki'

    この関数はマルチバイトセーフです。

    len が 1 よりも小さい場合は、結果が空の文字列になります。

  • SUBSTRING_INDEX(str,delim,count)

    文字列 str から、区切り文字 delimcount 回出現する前の部分文字列を返します。count が正の値の場合は、(左から数えて) 最後の区切り文字の左側にあるすべてが返されます。count が負の値の場合は、(右から数えて) 最後の区切り文字の右側にあるすべてが返されます。SUBSTRING_INDEX() は、delim を検索する際に、大文字と小文字を区別した一致を実行します。

    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2); -> 'www.mysql'
    mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2); -> 'mysql.com'

    この関数はマルチバイトセーフです。

  • TO_BASE64(str)

    文字列の引数を base-64 でエンコードされた形式に変換し、その結果を接続文字セットと照合順序が含まれる文字列として返します。引数が文字列でない場合は、変換が実行される前に文字列に変換されます。引数が NULL である場合は、結果も NULL になります。FROM_BASE64() 関数を使用すると、base-64 でエンコードされた文字列をデコードできます。

    この関数は、MySQL 5.6.1 で追加されました。

    mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc')); -> 'JWJj', 'abc'

    さまざまな base-64 エンコードスキームが存在します。これらは、TO_BASE64() および FROM_BASE64() で使用されるエンコードおよびデコードのルールです。

    • アルファベット値 62 のエンコードは '+' です。

    • アルファベット値 63 のエンコードは '/' です。

    • エンコードされた出力は、出力可能な 4 文字のグループで構成されます。入力データの各 3 バイトは、4 文字を使用してエンコードされます。最後のグループが不完全な場合は、長さが 4 になるまで '=' 文字でパディングされます。

    • 長い出力を複数の行に分割するために、エンコードされた出力の各 76 文字の後ろに改行が追加されます。

    • デコードでは改行、復帰改行、タブ、および空白が認識および無視されます。

  • TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([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'

    この関数はマルチバイトセーフです。

  • UCASE(str)

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

  • UNHEX(str)

    文字列の引数 str では、UNHEX(str) は引数の各文字ペアを 16 進数として解釈し、その数字で表されたバイトに変換します。戻り値はバイナリ文字列です。

    mysql> SELECT UNHEX('4D7953514C'); -> 'MySQL'
    mysql> SELECT 0x4D7953514C; -> 'MySQL'
    mysql> SELECT UNHEX(HEX('string')); -> 'string'
    mysql> SELECT HEX(UNHEX('1267')); -> '1267'

    引数文字列内の文字は、正当な 16 進数である必要があります: '0' .. '9''A' ..'F''a' .. 'f'。引数に 16 進以外の数字が含まれている場合は、結果が NULL になります。

    mysql> SELECT UNHEX('GG');+-------------+
    | UNHEX('GG') |
    +-------------+
    | NULL |
    +-------------+

    UNHEX() への引数が BINARY カラムである場合は、格納時に値に 0x00 バイトがパディングされますが、それらのバイトは取得時に削除されないため、結果が NULL になる可能性があります。たとえば、'41''41 ' として CHAR(3) カラムに格納され、(末尾にパディングされた空白文字が削除された) '41' として取得されるため、カラム値に対する UNHEX() では 'A' が返されます。反対に、'41''41\0' として BINARY(3) カラムに格納され、(末尾にパディングされた 0x00 バイトが削除されない) '41\0' として取得されます。'\0' は不正な 16 進数であるため、カラム値に対する UNHEX() では NULL が返されます。

    数値の引数 N の場合、HEX(N) の逆は UNHEX() では実行されません。代わりに、CONV(HEX(N),16,10) を使用してください。HEX() の説明を参照してください。

  • UPPER(str)

    現在の文字セットのマッピングに従って、すべての文字が大文字に変更された文字列 str を返します。デフォルトは latin1 (cp1252 西ヨーロッパ言語) です。

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

    UPPER() にも適用される情報については、LOWER() の説明を参照してください。これには、現在は機能が無効になっているバイナリ文字列 (BINARYVARBINARYBLOB) の大文字と小文字の変換を実行する方法に関する情報、および Unicode 文字セットの大文字と小文字の変換に関する情報が含まれていました。

    この関数はマルチバイトセーフです。

  • WEIGHT_STRING(str [AS {CHAR|BINARY}(N)] [LEVEL levels] [flags])

    levels: N [ASC|DESC|REVERSE] [, N [ASC|DESC|REVERSE]] ...

    この関数は、入力文字列の重み文字列を返します。戻り値は、文字列のソートおよび比較の値を表すバイナリ文字列です。これらのプロパティーがあります。

    • WEIGHT_STRING(str1) = WEIGHT_STRING(str2) の場合は、str1 = str2 です (str1str2 は等しいとみなされます)。

    • WEIGHT_STRING(str1) < WEIGHT_STRING(str2) の場合は、str1 < str2 です (str1str2 の前にソートされます)。

    WEIGHT_STRING() は、照合順序のテストおよびデバッグを行う際、特に新しい照合順序を追加する場合に使用できます。セクション10.4「文字セットへの照合順序の追加」を参照してください。

    入力文字列 str は文字列式です。入力が非バイナリ (文字) 文字列 (CHARVARCHARTEXT 値など) である場合は、戻り値に文字列の照合順序重みが含まれます。入力がバイナリ (バイト) 文字列 (BINARYVARBINARYBLOB 値など) である場合は、戻り値は入力と同じです (バイナリ文字列のバイトごとの重みはバイト値です)。入力が NULL である場合は、WEIGHT_STRING()NULL を返します。

    例:

    mysql> SET @s = _latin1 'AB' COLLATE latin1_swedish_ci;mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));+------+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +------+---------+------------------------+
    | AB | 4142 | 4142 |
    +------+---------+------------------------+
    mysql> SET @s = _latin1 'ab' COLLATE latin1_swedish_ci;mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));+------+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +------+---------+------------------------+
    | ab | 6162 | 4142 |
    +------+---------+------------------------+
    mysql> SET @s = CAST('AB' AS BINARY);mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));+------+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +------+---------+------------------------+
    | AB | 4142 | 4142 |
    +------+---------+------------------------+
    mysql> SET @s = CAST('ab' AS BINARY);mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));+------+---------+------------------------+
    | @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
    +------+---------+------------------------+
    | ab | 6162 | 6162 |
    +------+---------+------------------------+

    上記の例では、HEX() を使用して WEIGHT_STRING() の結果を表示しています。結果はバイナリ値であるため、結果に出力されない値が含まれるときに出力可能な形式で表示する際に、HEX() が特に役立ちます。

    mysql> SET @s = CONVERT(0xC39F USING utf8) COLLATE utf8_czech_ci;mysql> SELECT HEX(WEIGHT_STRING(@s));+------------------------+
    | HEX(WEIGHT_STRING(@s)) |
    +------------------------+
    | 0FEA0FEA |
    +------------------------+

    NULL の戻り値では、長さが VARBINARY の最大長内である場合は、値のデータ型が VARBINARY であり、その他の場合はデータ型は BLOB です。

    入力文字列を非バイナリまたはバイナリの文字列にキャストし、強制的に指定した長さになるように、AS 句が指定されている場合があります。

    • AS CHAR(N) は、文字列を非バイナリ文字列にキャストし、N 文字の長さになるように空白文字で右側をパディングします。N は少なくとも 1 にする必要があります。N が入力文字列の長さよりも小さい場合は、文字列が N 文字まで切り捨てられます。切り捨てられても警告は発生しません。

    • AS BINARY(N) は、文字列がバイナリ文字列にキャストされ、N が (文字単位ではなく) バイト単位で測定され、パディングで (空白文字でななく) 0x00 バイトが使用される点を除いて同様です。

    mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));+-------------------------------------+
    | HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
    +-------------------------------------+
    | 41422020 |
    +-------------------------------------+
    mysql> SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4)));+---------------------------------------+
    | HEX(WEIGHT_STRING('ab' AS BINARY(4))) |
    +---------------------------------------+
    | 61620000 |
    +---------------------------------------+

    戻り値に特定の照合順序レベルに合った重みが含まれるように指定するために、LEVEL 句が指定される場合があります。

    カンマで区切られた 1 つ以上の整数のリストとして、またはダッシュで区切られた 2 つの整数の範囲として、LEVEL キーワードの後ろに levels 指定子が指定される場合があります。句読文字の前後の空白の有無は影響しません。

    例:

    LEVEL 1
    LEVEL 2, 3, 5
    LEVEL 1-3

    1 よりも低いレベルは 1 として処理されます。入力文字列照合順序の最大値よりも高いレベルは、照合順序の最大値として処理されます。最大値は照合順序ごとに異なりますが、6 よりも大きい値にはなりません。

    レベルのリストでは、レベルを小さい順に指定する必要があります。レベルの範囲では、2 番目の数字が 1 番目よりも小さい場合は、1 番目の数字として処理されます (たとえば、4-2 は 4-4 と同じになります)。

    LEVEL 句が省略された場合は、MySQL では LEVEL 1 - max であるとみなされます。ここで、max は照合順序の最大レベルです。

    LEVEL が (範囲構文ではなく) リスト構文を使用して指定されている場合は、レベルの数字のあとに次の修飾子を指定できます。

    • ASC: 変更なしで重みを返します。これはデフォルトです。

    • DESC: ビット反転された重みを返します (たとえば、0x78f0 DESC = 0x870f です)。

    • REVERSE: 逆順で重み (つまり、最初の文字を最後に、最後の文字を最後にと、逆に並べた文字列の重み) を返します。

    例:

    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1));+--------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1)) |
    +--------------------------------------+
    | 007FFF |
    +--------------------------------------+
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC));+-------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC)) |
    +-------------------------------------------+
    | FF8000 |
    +-------------------------------------------+
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 REVERSE));+----------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 REVERSE)) |
    +----------------------------------------------+
    | FF7F00 |
    +----------------------------------------------+
    mysql> SELECT HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC REVERSE));+---------------------------------------------------+
    | HEX(WEIGHT_STRING(0x007fff LEVEL 1 DESC REVERSE)) |
    +---------------------------------------------------+
    | 0080FF |
    +---------------------------------------------------+

    現在、flags 句は使用されていません。

12.5.1 文字列比較関数

表 12.8 文字列比較演算子

名前説明
LIKE 単純なパターン一致
NOT LIKE 単純なパターン一致の否定
STRCMP() 2 つの文字列を比較します

文字列関数に引数としてバイナリ文字列が指定されている場合は、結果の文字列もバイナリ文字列になります。文字列に変換された数字は、バイナリ文字列として処理されます。比較のみがこの影響を受けます。

通常、文字列比較の式で大文字と小文字が区別される場合は、大文字と小文字が区別される方法で比較が実行されます。

  • expr LIKE pat [ESCAPE 'escape_char']

    SQL の単純な正規表現比較を使用したパターンマッチング。1 (TRUE) または 0 (FALSE) を返します。expr または pat のいずれかが NULL である場合は、結果も NULL になります。

    パターンはリテラル文字列である必要はありません。たとえば、文字列式やテーブルカラムとして指定できます。

    SQL 標準では、LIKE は文字ごとに一致を実行するため、= 比較演算子とは異なる結果が生成される可能性があります。

    mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;+-----------------------------------------+
    | 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
    +-----------------------------------------+
    | 0 |
    +-----------------------------------------+
    mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;+--------------------------------------+
    | 'ä' = 'ae' COLLATE latin1_german2_ci |
    +--------------------------------------+
    | 1 |
    +--------------------------------------+

    特に、末尾の空白は重要です。ただし、= 演算子を使って実行される CHARVARCHAR の比較には当てはまりません。

    mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';+------------+---------------+
    | 'a' = 'a ' | 'a' LIKE 'a ' |
    +------------+---------------+
    | 1 | 0 |
    +------------+---------------+
    1 row in set (0.00 sec)

    LIKE では、パターンで次の 2 つのワイルドカード文字を使用できます。

    文字説明
    %0 個の文字も含めて、任意の数の文字に一致します
    _正確に 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

    エスケープシーケンスは空にするか、1 文字の長さにするようにしてください。実行時に、式は定数として評価される必要があります。NO_BACKSLASH_ESCAPES SQL モードが有効になっている場合は、シーケンスを空にできません。

    次の 2 つのステートメントは、オペランドのいずれかがバイナリ文字列である場合を除いて、文字列の比較では大文字と小文字が区別されないことを示しています。

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

    MySQL では、数値式で LIKE が許可されます。(これは、標準 SQL の LIKE の拡張機能です。)

    mysql> SELECT 10 LIKE '1%'; -> 1
    注記

    MySQL では文字列で C のエスケープ構文 (たとえば、改行文字を表すために \n) が使用されているため、LIKE 文字列で使用される \ はすべて二重に指定する必要があります。たとえば、\n を検索するには、\\n と指定します。\ を検索するには、\\\\ と指定します。これは、バックスラッシュはパーサーによって一度削除され、パターン一致が実行されるときにも再度削除される結果、一致対象のバックスラッシュは 1 つしか残らないためです。

    例外: パターン文字列の末尾では、バックスラッシュを \\ と指定できます。文字列の末尾では、エスケープの後ろに何もないため、バックスラッシュはそれ自体を表します。テーブルに次の値が含まれると仮定します。

    mysql> SELECT filename FROM t1;+--------------+
    | filename |
    +--------------+
    | C: |
    | C:\ |
    | C:\Programs |
    | C:\Programs\ |
    +--------------+

    バックスラッシュで終わる値をテストするには、次のパターンのいずれかを使用すると値をマッチングできます。

    mysql> SELECT filename, filename LIKE '%\\' FROM t1;+--------------+---------------------+
    | filename | filename LIKE '%\\' |
    +--------------+---------------------+
    | C: | 0 |
    | C:\ | 1 |
    | C:\Programs | 0 |
    | C:\Programs\ | 1 |
    +--------------+---------------------+
    mysql> SELECT filename, filename LIKE '%\\\\' FROM t1;+--------------+-----------------------+
    | filename | filename LIKE '%\\\\' |
    +--------------+-----------------------+
    | C: | 0 |
    | C:\ | 1 |
    | C:\Programs | 0 |
    | C:\Programs\ | 1 |
    +--------------+-----------------------+
  • expr NOT LIKE pat [ESCAPE 'escape_char']

    これは、NOT (expr LIKE pat [ESCAPE 'escape_char']) と同じです。

    注記

    NULL を含むカラムとの NOT LIKE 比較を伴う集計クエリーでは、予想外の結果が生成される可能性があります。たとえば、次のテーブルとデータを検討してください。

    CREATE TABLE foo (bar VARCHAR(10));
    INSERT INTO foo VALUES (NULL), (NULL);

    クエリー SELECT COUNT(*) FROM foo WHERE bar LIKE '%baz%';0 を返します。SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%';2 を返すと想定しています。ただし、事実は異なります。2 番目のクエリーは 0 を返します。これは、expr の値に関係なく、NULL NOT LIKE expr は常に NULL を返すためです。NULL を伴う集計クエリー、および NOT RLIKE または NOT REGEXP を使用する比較でも、同じことが当てはまります。このような場合は、次に示すように、(AND ではなく) OR を使用して NOT NULL を明示的にテストする必要があります。

    SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%' OR bar IS NULL;
  • STRCMP(expr1,expr2)

    STRCMP() は、文字列が同じ場合は 0 を返し、現在のソート順に従って 1 番目の引数が 2 番目よりも小さい場合は -1、それ以外の場合は 1 を返します。

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

    STRCMP() は、引数の照合順序を使用して比較を実行します。

    mysql> SET @s1 = _latin1 'x' COLLATE latin1_general_ci;mysql> SET @s2 = _latin1 'X' COLLATE latin1_general_ci;mysql> SET @s3 = _latin1 'x' COLLATE latin1_general_cs;mysql> SET @s4 = _latin1 'X' COLLATE latin1_general_cs;mysql> SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4);+------------------+------------------+
    | STRCMP(@s1, @s2) | STRCMP(@s3, @s4) |
    +------------------+------------------+
    | 0 | 1 |
    +------------------+------------------+

    照合順序の互換性がない場合は、その他との互換性を保つために、引数のいずれかを変換する必要があります。セクション10.1.7.5「式の照合順序」を参照してください。

    mysql> SELECT STRCMP(@s1, @s3);ERROR 1267 (HY000): Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_general_cs,IMPLICIT) for operation 'strcmp'
    mysql> SELECT STRCMP(@s1, @s3 COLLATE latin1_general_ci);+--------------------------------------------+
    | STRCMP(@s1, @s3 COLLATE latin1_general_ci) |
    +--------------------------------------------+
    | 0 |
    +--------------------------------------------+

12.5.2 正規表現

表 12.9 文字列正規表現演算子

名前説明
NOT REGEXP REGEXP の否定
REGEXP 正規表現を使用したパターン一致
RLIKE REGEXP のシノニムです

正規表現は、複雑な検索でパターンを指定する強力な方法です。

MySQL では、POSIX 1003.2 に準拠することを目的とした Henry Spencer 氏による正規表現の実装が使用されます。MySQL では、SQL ステートメントで REGEXP 演算子とともに実行されるパターンマッチング演算をサポートするために、拡張バージョンが使用されています。

このセクションでは、MySQL の REGEXP 演算で使用できる特殊な文字や構造を例を示して要約しています。Henry Spencer 氏の regex(7) マニュアルページで検索できる詳細がすべて含まれているわけではありません。そのマニュアルページは、MySQL のソース配布の regex ディレクトリにある regex.7 ファイルに含まれています。セクション3.3.4.7「パターンマッチング」も参照してください。

正規表現演算子

  • expr NOT REGEXP pat, expr NOT RLIKE pat

    これは、NOT (expr REGEXP pat) と同じです。

  • expr REGEXP patexpr RLIKE pat

    パターン pat と比較して、文字列式 expr のパターン一致を実行します。パターンは、拡張正規表現にすることができます。構文については、このセクションの後半で説明します。exprpat と一致する場合は 1 を返し、それ以外の場合は 0 を返します。expr または pat のいずれかが NULL である場合は、結果も NULL になります。RLIKE は、mSQL との互換性を確保するために用意された REGEXP のシノニムです。

    パターンはリテラル文字列である必要はありません。たとえば、文字列式やテーブルカラムとして指定できます。

    注記

    MySQL では文字列で C のエスケープ構文 (たとえば、改行文字を表すために \n) が使用されているため、REGEXP 文字列で使用される \ はすべて二重に指定する必要があります。

    REGEXP では、バイナリ文字列で使用される場合を除いて、大文字と小文字が区別されません。

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

    REGEXP および RLIKE では、文字の型を決定する際および比較を実行する際に、引数の文字セットおよび照合順序が使用されます。引数にさまざまな文字セットまたは照合順序が含まれる場合は、セクション10.1.7.5「式の照合順序」で説明するとおりに、型変換属性ルールが適用されます。

    警告

    REGEXP および RLIKE 演算子はバイト単位で機能するため、マルチバイトセーフではなく、マルチバイト文字セットを使用すると想定外の結果が生成される可能性があります。さらに、これらの演算子ではそのバイト値に基づいて文字が比較されるため、アクセント記号付き文字は、指定された照合順序では等しいとみなされた場合でも、等しいとして比較されない可能性があります。

正規表現の構文

正規表現では、文字列のセットが記述されます。もっとも単純な正規表現は、特殊文字を使用していないものです。たとえば、正規表現 hellohello にのみ一致します。

重要な正規表現では、複数の文字列に一致できるように特定の特殊構造が使用されます。たとえば、正規表現 hello|word は、文字列 hello または文字列 word に一致します。

さらに複雑な例として、正規表現 B[an]*s は、文字列 BananasBaaaaasBs のいずれか、および B で始まり、s で終わり、その間に任意の数字の a または n 文字が含まれるその他の文字列に一致します。

REGEXP 演算子の正規表現では、次の特殊文字および構造のいずれかが使用される場合があります。

  • ^

    文字列の先頭に一致します。

    mysql> SELECT 'fo\nfo' REGEXP '^fo$'; -> 0
    mysql> SELECT 'fofo' REGEXP '^fo'; -> 1
  • $

    文字列の末尾に一致します。

    mysql> SELECT 'fo\no' REGEXP '^fo\no$'; -> 1
    mysql> SELECT 'fo\no' REGEXP '^fo$'; -> 0
  • .

    任意の文字 (復帰改行および改行を含む) に一致します。

    mysql> SELECT 'fofo' REGEXP '^f.*$'; -> 1
    mysql> SELECT 'fo\r\nfo' REGEXP '^f.*$'; -> 1
  • a*

    ゼロ個以上の a 文字のシーケンスに一致します。

    mysql> SELECT 'Ban' REGEXP '^Ba*n'; -> 1
    mysql> SELECT 'Baaan' REGEXP '^Ba*n'; -> 1
    mysql> SELECT 'Bn' REGEXP '^Ba*n'; -> 1
  • a+

    1 個以上の a 文字のシーケンスに一致します。

    mysql> SELECT 'Ban' REGEXP '^Ba+n'; -> 1
    mysql> SELECT 'Bn' REGEXP '^Ba+n'; -> 0
  • a?

    ゼロまたは 1 個の a 文字に一致します。

    mysql> SELECT 'Bn' REGEXP '^Ba?n'; -> 1
    mysql> SELECT 'Ban' REGEXP '^Ba?n'; -> 1
    mysql> SELECT 'Baan' REGEXP '^Ba?n'; -> 0
  • de|abc

    シーケンス de または abc のいずれかに一致します。

    mysql> SELECT 'pi' REGEXP 'pi|apa'; -> 1
    mysql> SELECT 'axe' REGEXP 'pi|apa'; -> 0
    mysql> SELECT 'apa' REGEXP 'pi|apa'; -> 1
    mysql> SELECT 'apa' REGEXP '^(pi|apa)$'; -> 1
    mysql> SELECT 'pi' REGEXP '^(pi|apa)$'; -> 1
    mysql> SELECT 'pix' REGEXP '^(pi|apa)$'; -> 0
  • (abc)*

    シーケンス abc のゼロ個以上のインスタンスに一致します。

    mysql> SELECT 'pi' REGEXP '^(pi)*$'; -> 1
    mysql> SELECT 'pip' REGEXP '^(pi)*$'; -> 0
    mysql> SELECT 'pipi' REGEXP '^(pi)*$'; -> 1
  • {1}, {2,3}

    {n} または {m,n} 注釈では、パターンの前の原子 (または部分) の数多くの出現に一致する正規表現を記述するより一般的な方法が提供されます。m および n は整数です。

    • a*

      a{0,} と記述できます。

    • a+

      a{1,} と記述できます。

    • a?

      a{0,1} と記述できます。

    より厳密に言えば、a{n} は、a の正確に n 個のインスタンスに一致します。a{n,} は、an 個以上のインスタンスに一致します。a{m,n} は、am 個から n 個までのインスタンスに一致します。

    m および n は、0 から RE_DUP_MAX (デフォルトは 255) までの範囲内である必要があります。m および n の両方が指定されている場合は、mn 以下にする必要があります。

    mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e'; -> 0
    mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e'; -> 1
    mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e'; -> 1
  • [a-dX], [^a-dX]

    abcd、または X である (^ が使用されている場合はそれ以外の) 任意の文字に一致します。2 つの文字の間の - 文字によって、1 番目の文字から 2 番目の文字までのすべての文字に一致する範囲が形成されます。たとえば、[0-9] は任意の 10 進数に一致します。リテラル文字 ] を含めるには、左括弧 [ の直後に記述する必要があります。リテラル文字 - を含めるには、先頭または末尾に記述する必要があります。[] ペアの内側に定義された特殊な意味を持たない文字は、それ自体としか一致しません。

    mysql> SELECT 'aXbc' REGEXP '[a-dXYZ]'; -> 1
    mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]$'; -> 0
    mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]+$'; -> 1
    mysql> SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$'; -> 0
    mysql> SELECT 'gheis' REGEXP '^[^a-dXYZ]+$'; -> 1
    mysql> SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$'; -> 0
  • [.characters.]

    ([] を使用して記述された) 括弧式内で、その照合要素の文字シーケンスに一致します。characters は、単一の文字または newline などの文字名です。次の表には、許可されている文字名を一覧表示します。

    次の表には、許可されている文字名および一致する文字を表示します。数値として指定された文字では、値が 8 進数で表記されます。

    名前文字名前文字
    NUL0SOH001
    STX002ETX003
    EOT004ENQ005
    ACK006BEL007
    alert007BS010
    backspace'\b'HT011
    tab'\t'LF012
    newline'\n'VT013
    vertical-tab'\v'FF014
    form-feed'\f'CR015
    carriage-return'\r'SO016
    SI017DLE020
    DC1021DC2022
    DC3023DC4024
    NAK025SYN026
    ETB027CAN030
    EM031SUB032
    ESC033IS4034
    FS034IS3035
    GS035IS2036
    RS036IS1037
    US037space' '
    exclamation-mark'!'quotation-mark'"'
    number-sign'#'dollar-sign'$'
    percent-sign'%'ampersand'&'
    apostrophe'\''left-parenthesis'('
    right-parenthesis')'asterisk'*'
    plus-sign'+'comma','
    hyphen'-'hyphen-minus'-'
    period'.'full-stop'.'
    slash'/'solidus'/'
    zero'0'one'1'
    two'2'three'3'
    four'4'five'5'
    six'6'seven'7'
    eight'8'nine'9'
    colon':'semicolon';'
    less-than-sign'<'equals-sign'='
    greater-than-sign'>'question-mark'?'
    commercial-at'@'left-square-bracket'['
    backslash'\\'reverse-solidus'\\'
    right-square-bracket']'circumflex'^'
    circumflex-accent'^'underscore'_'
    low-line'_'grave-accent'`'
    left-brace'{'left-curly-bracket'{'
    vertical-line'|'right-brace'}'
    right-curly-bracket'}'tilde'~'
    DEL177  
    mysql> SELECT '~' REGEXP '[[.~.]]'; -> 1
    mysql> SELECT '~' REGEXP '[[.tilde.]]'; -> 1
  • [=character_class=]

    ([] 使用して記述された) 括弧式内の [=character_class=] は、等価クラスを表します。これは、同じ照合順序値を持つすべての文字 (それ自体を含む) に一致します。たとえば、o および (+) が等価クラスのメンバーである場合、[[=o=]][[=(+)=]]、および [o(+)] はすべてシノニムです。等価クラスは、範囲の終点として使用できない場合もあります。

  • [:character_class:]

    ([] を使用して記述された)括弧式内の [:character_class:] は、そのクラスに属するすべての文字と一致する文字クラスを表します。次の表には、標準のクラス名を一覧表示します。これらの名前は、ctype(3) のマニュアルページで定義されている文字クラスを表しています。特定のロケールでは、ほかのクラス名が提供される場合もあります。文字クラスは、範囲の終点として使用できない場合もあります。

    文字クラス名意味
    alnum英数文字
    alphaアルファベット文字
    blank空白文字
    cntrl制御文字
    digit数字文字
    graph図形文字
    lower小文字アルファベット文字
    print図形または空白文字
    punct句読点文字
    space空白、タブ、改行、および復帰改行
    upper大文字アルファベット文字
    xdigit16 進数文字
    mysql> SELECT 'justalnums' REGEXP '[[:alnum:]]+'; -> 1
    mysql> SELECT '!!' REGEXP '[[:alnum:]]+'; -> 0
  • [[:<:]], [[:>:]]

    これらのマーカーは、単語境界を表します。単語の先頭と末尾にそれぞれ一致します。単語とは、前後に単語文字が存在しない単語文字のシーケンスです。単語文字とは、alnum クラス内の英数文字またはアンダースコア (_) です。

    mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1
    mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0

正規表現で特殊文字のリテラルインスタンスを使用するには、前に 2 つのバックスラッシュ (\) 文字を付けます。MySQL パーサーが 2 つのバックスラッシュの一方を解釈し、正規表現ライブラリがもう一方を解釈します。たとえば、特殊文字 + を含む文字列 1+2 に一致する正規表現は、次のうちで最後のものだけです。

mysql> SELECT '1+2' REGEXP '1+2'; -> 0
mysql> SELECT '1+2' REGEXP '1\+2'; -> 0
mysql> SELECT '1+2' REGEXP '1\\+2'; -> 1

12.6 数値関数と演算子

表 12.10 数値関数と演算子

名前説明
ABS() 絶対値を返します
ACOS() アークコサインを返します
ASIN() アークサインを返します
ATAN() アークタンジェントを返します
ATAN2(), ATAN() 2 つの引数のアークタンジェントを返します
CEIL() 引数以上のもっとも小さな整数値を返します
CEILING() 引数以上のもっとも小さな整数値を返します
CONV() 数値を異なる基数間で変換します
COS() コサインを返します
COT() コタンジェントを返します
CRC32() 巡回冗長検査値を計算します
DEGREES() ラジアンを角度に変換します
DIV 整数除算
/ 除算演算子
EXP() 累乗します
FLOOR() 引数以下のもっとも大きな整数値を返します
LN() 引数の自然対数を返します
LOG() 最初の引数の自然対数を返します
LOG10() 引数の底 10 の対数を返します
LOG2() 引数の底 2 の対数を返します
- 減算演算子
MOD() 余りを返します
%, MOD モジュロ演算子
PI() pi の値を返します
+ 加算演算子
POW() 指定した指数で累乗された引数を返します
POWER() 指定した指数で累乗された引数を返します
RADIANS() ラジアンに変換された引数を返します
RAND() ランダムな浮動小数点値を返します
ROUND() 引数を丸めます
SIGN() 引数の符号を返します
SIN() 引数のサインを返します
SQRT() 引数の平方根を返します
TAN() 引数のタンジェントを返します
* 乗算演算子
TRUNCATE() 指定された小数点以下の桁数に切り捨てます
- 引数の符号を変更します

12.6.1 算術演算子

表 12.11 算術演算子

名前説明
DIV 整数除算
/ 除算演算子
- 減算演算子
%, MOD モジュロ演算子
+ 加算演算子
* 乗算演算子
- 引数の符号を変更します

通常の算術演算子を使用できます。結果は次のルールに従って決定されます。

  • -+、および * の場合は、両方のオペランドが整数であれば、結果が BIGINT (64 ビット) 精度で計算されます。

  • 両方のオペランドが整数で、いずれかが符合なしの場合は、結果が符合なし整数になります。減算では、NO_UNSIGNED_SUBTRACTION SQL モードが有効になっている場合は、オペランドのいずれかが符号なしでも、結果が符号付きになります。

  • +-/*% のオペランドのいずれかが実数値または文字列値である場合は、結果の精度が、最大の精度を持つオペランドの精度になります。

  • / を使用して実行される除算では、2 つの正確な値のオペランドを使用したときの結果のスケールが、1 番目のオペランドに div_precision_increment システム変数 (デフォルトでは 4) の値を加えた値になります。たとえば、式 5.05 / 0.014 の結果のスケールは、小数点以下 6 桁になります (360.714286)。

ネストされた計算が各コンポーネントの精度を暗黙的に示すように、これらのルールは演算ごとに適用されます。したがって、(14620 / 9432456) / (24250 / 9432456) では、まず (0.0014) / (0.0026) に解かれて、最終的な結果は小数点以下 8 桁 (0.60288653) になります。

このようなルールおよびそれらが適用される方法があるため、計算のコンポーネントおよびサブコンポーネントで適切な精度レベルが使用されていることを慎重に確認してください。セクション12.10「キャスト関数と演算子」を参照してください。

数値式評価でのオーバーフロー処理については、セクション11.2.6「範囲外およびオーバーフローの処理」を参照してください。

算術演算子は数字に適用されます。その他の型の値では、代替の演算が使用できる場合もあります。たとえば、日付値を追加するには、DATE_ADD() を使用します。セクション12.7「日付および時間関数」を参照してください。

  • +

    加算:

    mysql> SELECT 3+5; -> 8
  • -

    減算:

    mysql> SELECT 3-5; -> -2
  • -

    単項マイナス。この演算子は、オペランドの符号を変更します。

    mysql> SELECT - 2; -> -2
    注記

    この演算子が BIGINT で使用される場合は、戻り値も BIGINT になります。つまり、値 −263 を持つ可能性のある整数では、- の使用を避けるべきです。

  • *

    乗算:

    mysql> SELECT 3*5; -> 15
    mysql> SELECT 18014398509481984*18014398509481984.0; -> 324518553658426726783156020576256.0
    mysql> SELECT 18014398509481984*18014398509481984; -> out-of-range error

    最後の式では、整数乗算の結果が 64 ビット範囲の BIGINT 計算を超過するため、エラーが生成されます。(セクション11.2「数値型」を参照してください。)

  • /

    除算:

    mysql> SELECT 3/5; -> 0.60

    ゼロによる除算では、NULL の結果が生成されます。

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

    結果が整数に変換されるコンテキストで実行される場合にのみ、除算は BIGINT 算術を使用して計算されます。

  • DIV

    整数除算。FLOOR() に類似していますが、BIGINT 値でも安全です。

    MySQL 5.6 では、オペランドのいずれかが整数以外の型である場合は、結果が BIGINT に変換される前に、オペランドが DECIMAL に変換され、DECIMAL 算術を使用して除算されます。結果が BIGINT の範囲を超過する場合は、エラーが発生します。

    mysql> SELECT 5 DIV 2; -> 2
  • N % M, N MOD M

    モジュロ演算。M で除算された N の余りを返します。詳細は、セクション12.6.2「数学関数」MOD() 関数に関する説明を参照してください。

12.6.2 数学関数

表 12.12 数学関数

名前説明
ABS() 絶対値を返します
ACOS() アークコサインを返します
ASIN() アークサインを返します
ATAN() アークタンジェントを返します
ATAN2(), ATAN() 2 つの引数のアークタンジェントを返します
CEIL() 引数以上のもっとも小さな整数値を返します
CEILING() 引数以上のもっとも小さな整数値を返します
CONV() 数値を異なる基数間で変換します
COS() コサインを返します
COT() コタンジェントを返します
CRC32() 巡回冗長検査値を計算します
DEGREES() ラジアンを角度に変換します
EXP() 累乗します
FLOOR() 引数以下のもっとも大きな整数値を返します
LN() 引数の自然対数を返します
LOG() 最初の引数の自然対数を返します
LOG10() 引数の底 10 の対数を返します
LOG2() 引数の底 2 の対数を返します
MOD() 余りを返します
PI() pi の値を返します
POW() 指定した指数で累乗された引数を返します
POWER() 指定した指数で累乗された引数を返します
RADIANS() ラジアンに変換された引数を返します
RAND() ランダムな浮動小数点値を返します
ROUND() 引数を丸めます
SIGN() 引数の符号を返します
SIN() 引数のサインを返します
SQRT() 引数の平方根を返します
TAN() 引数のタンジェントを返します
TRUNCATE() 指定された小数点以下の桁数に切り捨てます

すべての数学関数は、エラーの発生時に NULL を返します。

  • 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
    mysql> SELECT ACOS(1.0001); -> NULL
    mysql> SELECT ACOS(0); -> 1.5707963267949
  • ASIN(X)

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

    mysql> SELECT ASIN(0.2); -> 0.20135792079033
    mysql> SELECT ASIN('foo');+-------------+
    | ASIN('foo') |
    +-------------+
    | 0 |
    +-------------+
    1 row in set, 1 warning (0.00 sec)
    mysql> SHOW WARNINGS;+---------+------+-----------------------------------------+
    | Level | Code | Message |
    +---------+------+-----------------------------------------+
    | Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' |
    +---------+------+-----------------------------------------+
  • ATAN(X)

    X のアークタンジェント (つまり、タンジェントが X である値) を返します。

    mysql> SELECT ATAN(2); -> 1.1071487177941
    mysql> SELECT ATAN(-2); -> -1.1071487177941
  • ATAN(Y,X), ATAN2(Y,X)

    2 つの変数 X および Y のアークタンジェントを返します。これは、両方の引数の符号が結果の象限の判定に使用される点を除いて、Y / X のアークタンジェントの計算と同様です。

    mysql> SELECT ATAN(-2,2); -> -0.78539816339745
    mysql> SELECT ATAN2(PI(),0); -> 1.5707963267949
  • CEIL(X)

    CEIL()CEILING() のシノニムです。

  • CEILING(X)

    X 以上で最小の整数値を返します。

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

    引数が厳密値数値の場合は、戻り値の型も厳密値数値になります。引数が文字列または浮動小数点の場合は、戻り値の型が浮動小数点になります。

  • CONV(N,from_base,to_base)

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

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

    X のコサインを返します。X はラジアンで指定されます。

    mysql> SELECT COS(PI()); -> -1
  • COT(X)

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

    mysql> SELECT COT(12); -> -1.5726734063977
    mysql> SELECT COT(0); -> NULL
  • CRC32(expr)

    巡回冗長検査値を計算し、32 ビット値の符号なし値を返します。引数が NULL である場合は、結果も NULL になります。引数は文字列であると想定され、(可能な場合は) 文字列でない場合でも文字列として処理されます。

    mysql> SELECT CRC32('MySQL'); -> 3259397556
    mysql> SELECT CRC32('mysql'); -> 2501908538
  • DEGREES(X)

    ラジアンからディグリーに変換された引数 X を返します。

    mysql> SELECT DEGREES(PI()); -> 180
    mysql> SELECT DEGREES(PI() / 2); -> 90
  • EXP(X)

    e (自然対数の底) の X 乗の値を返します。この関数の逆は、(単一の引数のみを使用する) LOG() または LN() です。

    mysql> SELECT EXP(2); -> 7.3890560989307
    mysql> SELECT EXP(-2); -> 0.13533528323661
    mysql> SELECT EXP(0); -> 1
  • FLOOR(X)

    X 以下で最大の整数値を返します。

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

    引数が厳密値数値の場合は、戻り値の型も厳密値数値になります。引数が文字列または浮動小数点の場合は、戻り値の型が浮動小数点になります。

  • FORMAT(X,D)

    数値 X'#,###,###.##' のような書式に変換し、小数点第 D 位に丸めて、その結果を文字列として返します。詳細は、セクション12.5「文字列関数」を参照してください。

  • HEX(N_or_S)

    この関数を使用すると、10 進数または文字列の 16 進表現を取得できます。その方法は、引数の型によって異なります。詳細は、セクション12.5「文字列関数」で、この関数の説明を参照してください。

  • LN(X)

    X の自然対数 (つまり、X の底 e の対数) を返します。X が 0 以下である場合は、NULL が返されます。

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

    この関数は LOG(X) のシノニムです。この関数の逆は、EXP() 関数です。

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

    1 つのパラメータで呼び出される場合、この関数は X の自然対数を返します。X が 0 以下である場合は、NULL が返されます。

    この関数 (単一の引数で呼び出された場合) の逆は、EXP() 関数です。

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

    この関数が 2 つのパラメータで呼び出される場合は、B を底とする X の対数が返されます。X が 0 以下である場合、または B が 1 以下である場合は、NULL が返されます。

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

    LOG(B,X)LOG(X) / LOG(B) と同等です。

  • LOG2(X)

    X の底 2 の対数を返します。

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

    LOG2() は、格納に必要なビット数を調べる際に役立ちます。この関数は式 LOG(X) / LOG(2) と同等です。

  • LOG10(X)

    X の底 10 の対数を返します。

    mysql> SELECT LOG10(2); -> 0.30102999566398
    mysql> SELECT LOG10(100); -> 2
    mysql> SELECT LOG10(-100); -> NULL

    LOG10(X)LOG(10,X) と同等です。

  • MOD(N,M)N % MN MOD M

    モジュロ演算。M で除算された N の余りを返します。

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

    この関数は、BIGINT 値でも安全に使用できます。

    MOD() は、小数部を持つ値でも機能し、除算後の正確な余りを返します。

    mysql> SELECT MOD(34.5,3); -> 1.5

    MOD(N,0)NULL を返します。

  • PI()

    π (pi) の値を返します。表示されるデフォルトの小数点以下の桁数は 7 ですが、MySQL では内部的に全倍精度値が使用されます。

    mysql> SELECT PI(); -> 3.141593
    mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116
  • POW(X,Y)

    XY 乗の値を返します。

    mysql> SELECT POW(2,2); -> 4
    mysql> SELECT POW(2,-2); -> 0.25
  • POWER(X,Y)

    これは POW() のシノニムです。

  • RADIANS(X)

    ディグリーからラジアンに変換された引数 X を返します。

    注記

    π ラジアンは、180 ディグリーと同等です。

    mysql> SELECT RADIANS(90); -> 1.5707963267949
  • RAND(), RAND(N)

    0 <= v < 1.0 の範囲内で、ランダムな浮動小数点値 v を返します。定数整数引数 N が指定されている場合は、カラム値の反復可能なシーケンスを生成するシード値として使用されます。次の例では、RAND(3) で生成される値のシーケンスが、発生した両方の場所で同じです。

    mysql> CREATE TABLE t (i INT);Query OK, 0 rows affected (0.42 sec)
    mysql> INSERT INTO t VALUES(1),(2),(3);Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT i, RAND() FROM t;+------+------------------+
    | i | RAND() |
    +------+------------------+
    | 1 | 0.61914388706828 |
    | 2 | 0.93845168309142 |
    | 3 | 0.83482678498591 |
    +------+------------------+
    3 rows in set (0.00 sec)
    mysql> SELECT i, RAND(3) FROM t;+------+------------------+
    | i | RAND(3) |
    +------+------------------+
    | 1 | 0.90576975597606 |
    | 2 | 0.37307905813035 |
    | 3 | 0.14808605345719 |
    +------+------------------+
    3 rows in set (0.00 sec)
    mysql> SELECT i, RAND() FROM t;+------+------------------+
    | i | RAND() |
    +------+------------------+
    | 1 | 0.35877890638893 |
    | 2 | 0.28941420772058 |
    | 3 | 0.37073435016976 |
    +------+------------------+
    3 rows in set (0.00 sec)
    mysql> SELECT i, RAND(3) FROM t;+------+------------------+
    | i | RAND(3) |
    +------+------------------+
    | 1 | 0.90576975597606 |
    | 2 | 0.37307905813035 |
    | 3 | 0.14808605345719 |
    +------+------------------+
    3 rows in set (0.01 sec)

    定数イニシャライザを使用すると、シードは実行される前に、ステートメントのコンパイル時に一度初期化されます。引数として非定数イニシャライザ (カラム名など) が使用される場合は、RAND() が起動されるたびに、その値でシードが初期化されます。(引数値が等しい場合は、RAND() で毎回同じ値が返されることを示しています。)

    i <= R < j の範囲内でランダムな整数 R を取得するには、式 FLOOR(i + RAND() * (ji)) を使用します。たとえば、7 <= R < 12 の範囲内でランダムな整数を取得するには、次のようなステートメントを使用します。

    SELECT FLOOR(7 + (RAND() * 5));

    WHERE 句内の RAND() は、WHERE が実行されるたびに再評価されます。

    ORDER BY ではカラムが複数回評価されるため、ORDER BY 句内では RAND() 値を持つカラムを使用できません。ただし、次のようにランダムな順序で行を取得できます。

    mysql> SELECT * FROM tbl_name ORDER BY RAND();

    LIMIT と組み合わせて ORDER BY RAND() を使用すれば、行のセットからランダムなサンプルを選択する際に役立ちます。

    mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d -> ORDER BY RAND() LIMIT 1000;

    RAND() は、完全なランダムジェネレータとしては設計されていません。要求に応じてランダムな数字をすばやく生成する方法であり、同じ MySQL バージョンのプラットフォーム間で移植可能です。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。(Bug #49222)

  • ROUND(X), ROUND(X,D)

    引数 XD 小数点に丸めます。丸めアルゴリズムは、X のデータ型に依存します。D が指定されていない場合は、デフォルトで 0 に設定されます。D を負の数に指定すると、値 X の小数点左側の 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

    戻り型は、(整数、重複、または 10 進数と仮定すると) 1 番目の引数と同じ型です。つまり、引数が整数の場合は、結果が整数 (小数点なし) になります。

    mysql> SELECT ROUND(150.000,2), ROUND(150,2);+------------------+--------------+
    | ROUND(150.000,2) | ROUND(150,2) |
    +------------------+--------------+
    | 150.00 | 150 |
    +------------------+--------------+

    ROUND() では、第 1 引数の型に応じて次のルールが使用されます。

    • 真値の数字の場合、ROUND() では四捨五入または切り捨て (切り上げ) ルールが使用されます。0.5 以上の小数部を持つ値は、正の場合は次の整数に切り上げられ、負の場合は次の整数に切り下げられます。(つまり、ゼロから遠い方に丸められます。)0.5 未満の小数部を持つ値は、正の場合は次の整数に切り下げられ、負の場合は次の整数に切り上げられます。

    • 近似値の数字の場合、結果は C ライブラリによって異なります。多くのシステムでは、これは、ROUND() で「偶数丸め」ルールが使用されることを意味します。任意の小数部を持つ値は、もっとも近い偶数の整数に丸められます。

    次の例では、正確な値の丸めと近似値の丸めの相違点を示します。

    mysql> SELECT ROUND(2.5), ROUND(25E-1);+------------+--------------+
    | ROUND(2.5) | ROUND(25E-1) |
    +------------+--------------+
    | 3 | 2 |
    +------------+--------------+

    詳細は、セクション12.20「高精度計算」を参照してください。

  • SIGN(X)

    X が負、ゼロ、または正のいずれであるのかに応じて、引数の符号を -10、または 1 として返します。

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

    X のサインを返します。X はラジアンで指定されます。

    mysql> SELECT SIN(PI()); -> 1.2246063538224e-16
    mysql> SELECT ROUND(SIN(PI())); -> 0
  • SQRT(X)

    負ではない数字 X の平方根を返します。

    mysql> SELECT SQRT(4); -> 2
    mysql> SELECT SQRT(20); -> 4.4721359549996
    mysql> SELECT SQRT(-16); -> NULL
  • TAN(X)

    X のタンジェントを返します。X はラジアンで指定されます。

    mysql> SELECT TAN(PI()); -> -1.2246063538224e-16
    mysql> SELECT TAN(PI()+1); -> 1.5574077246549
  • TRUNCATE(X,D)

    D 小数点に切り捨てて、数字 X を返します。D0 の場合は、結果に小数点または小数部が含まれません。D を負の数に指定すると、値 X の小数点左側の D 桁をゼロにすることができます。

    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> SELECT TRUNCATE(122,-2); -> 100
    mysql> SELECT TRUNCATE(10.28*100,0); -> 1028

    すべての数字は、ゼロ方向に丸められます。

12.7 日付および時間関数

このセクションでは、時間値の処理に使用できる関数について説明します。各日付日時型が持つ値の範囲、および値を指定する際の有効な書式については、セクション11.3「日付と時間型」を参照してください。

表 12.13 日付/時間関数

名前説明
ADDDATE() 日付値に時間値 (間隔) を加算します
ADDTIME() 時間を加算します
CONVERT_TZ() あるタイムゾーンから別のタイムゾーンに変換します
CURDATE() 現在の日付を返します
CURRENT_DATE(), CURRENT_DATE CURDATE() のシノニムです
CURRENT_TIME(), CURRENT_TIME CURTIME() のシノニムです
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP NOW() のシノニムです
CURTIME() 現在の時間を返します
DATE() 日付または日付時間式の日付部分を抽出します
DATE_ADD() 日付値に時間値 (間隔) を加算します
DATE_FORMAT() 日付を指定された書式に設定します
DATE_SUB() 日付から時間値 (間隔) を引きます
DATEDIFF() 2 つの日付の差を求めます
DAY() DAYOFMONTH() のシノニムです
DAYNAME() 曜日の名前を返します
DAYOFMONTH() 月の日を返します (0 - 31)
DAYOFWEEK() 引数の曜日インデックスを返します
DAYOFYEAR() 年の日を返します (1 - 366)
EXTRACT() 日付の一部を抽出します
FROM_DAYS() 日数を日付に変換します
FROM_UNIXTIME() UNIX タイムスタンプを日付として書式設定します
GET_FORMAT() 日付書式文字列を返します
HOUR() 時を抽出します
LAST_DAY 引数の月の最終日を返します
LOCALTIME(), LOCALTIME NOW() のシノニムです
LOCALTIMESTAMP, LOCALTIMESTAMP() NOW() のシノニムです
MAKEDATE() 年と年間通算日から日付を作成します
MAKETIME() 時、分、秒から時間を作成します
MICROSECOND() 引数からマイクロ秒を返します
MINUTE() 引数から分を返します
MONTH() 渡された日付から月を返します
MONTHNAME() 月の名前を返します
NOW() 現在の日付と時間を返します
PERIOD_ADD() 年月に期間を加算します
PERIOD_DIFF() 期間内の月数を返します
QUARTER() 日付引数から四半期を返します
SEC_TO_TIME() 秒を「HH:MM:SS」形式に変換します
SECOND() 秒 (0-59) を返します
STR_TO_DATE() 文字列を日付に変換します
SUBDATE() 3 つの引数で呼び出されるときは DATE_SUB() のシノニムです
SUBTIME() 時間の差を求めます
SYSDATE() この関数が実行される時間を返します
TIME() 渡された式の時部分を抽出します
TIME_FORMAT() 時間として書式設定します
TIME_TO_SEC() 秒に変換された引数を返します
TIMEDIFF() 時間の差を求めます
TIMESTAMP() 引数が 1 つの場合、この関数は日付または日付時間式を返します。引数が 2 つの場合、引数の合計を返します
TIMESTAMPADD() 日付時間式に間隔を加算します
TIMESTAMPDIFF() 日付時間式から間隔を減算します
TO_DAYS() 日に変換された日付引数を返します
TO_SECONDS() 0 年以降の秒数に変換された日付または日付時間引数を返します
UNIX_TIMESTAMP() UNIX タイムスタンプを返します
UTC_DATE() 現在の UTC 日付を返します
UTC_TIME() 現在の UTC 時間を返します
UTC_TIMESTAMP() 現在の UTC 日付と時間を返します
WEEK() 週番号を返します
WEEKDAY() 曜日インデックスを返します
WEEKOFYEAR() 日付の暦週を返します (0 - 53)
YEAR() 年を返します
YEARWEEK() 年と週を返します

次に、日付関数の使用例を示します。次のクエリーは、過去 30 日以内の date_col 値を含むすべての行を選択します。

mysql> SELECT something FROM tbl_name -> WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= date_col;

このクエリーは、将来の日付を持つ行も選択します。

通常、日付値が要求される関数では、日付時間値が受け入れられ、時間の部分は無視されます。通常、時間値が要求される関数では、日付時間値が受け入れられ、日付の部分は無視されます。

現在の日付または時間をそれぞれ返す関数は、クエリー実行の開始時にクエリーごとに 1 回だけ評価されます。つまり、NOW() などの関数が単一クエリー内で複数回参照されても、常に同じ結果が生成されます。(設計上、単一クエリーにはストアドプログラム (ストアドルーチン、トリガー、またはイベント) の呼び出し、およびそのプログラムによって呼び出されるすべてのサブプログラムも含まれています。)この原則は、CURDATE()CURTIME()UTC_DATE()UTC_TIME()UTC_TIMESTAMP()、およびそれらのシノニムにも適用されます。

CURRENT_TIMESTAMP()CURRENT_TIME()CURRENT_DATE()、および FROM_UNIXTIME() 関数は、time_zone システム環境変数の値として使用できる接続の現在のタイムゾーンで値を返します。さらに、UNIX_TIMESTAMP() では、その引数が現在のタイムゾーンでの日付時間値であるとみなされます。セクション10.6「MySQL Server でのタイムゾーンのサポート」を参照してください。

zero 日付または '2001-11-00' のような不完全な日付とともに使用できる日付関数もありますが、使用できない日付関数もあります。通常、日付の一部を抽出する関数は不完全な日付でも正しく機能するため、ゼロ以外の値が要求される場合に 0 を返すことができます。例:

mysql> SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00'); -> 0, 0

その他の関数では完全な日付が要求され、日付が不完全な場合は NULL が返されます。これらには、日付演算を実行する関数や日付の一部を名前にマップする関数が含まれます。例:

mysql> SELECT DATE_ADD('2006-05-00',INTERVAL 1 DAY); -> NULL
mysql> SELECT DAYNAME('2006-05-00'); -> NULL

MySQL 5.6.4 の時点では、いくつかの関数は引数として DATE() 関数の値を渡す際により厳密になったため、ゼロの日付部分を持つ不完全な日付は拒否されます。CONVERT_TZ()DATE_ADD()DATE_SUB()DAYOFYEAR()LAST_DAY()TIMESTAMPDIFF()TO_DAYS()TO_SECONDS()WEEK()WEEKDAY()WEEKOFYEAR()YEARWEEK() 関数が影響を受けます。5.6.5 の LAST_DAY() では、この制限は緩やかで、ゼロの日付部分は許可されていました。

MySQL 5.6.4 以上では、マイクロ秒までの精度を持つ小数秒が TIMEDATETIME、および TIMESTAMP 値でサポートされています。時間引数を取る関数は、小数秒を含む値を受け入れます。時間関数からの戻り値には、必要に応じて小数秒が含まれます。

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

    INTERVAL 形式の 2 番目の引数を付けて呼び出されると、ADDDATE()DATE_ADD() のシノニムになります。関連する関数 SUBDATE()DATE_SUB() のシノニムです。INTERVALunit 引数については、DATE_ADD() の説明を参照してください。

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

    days 形式の 2 番目の引数を付けて呼び出されると、MySQL では expr に加算される整数の日数として処理されます。

    mysql> SELECT ADDDATE('2008-01-02', 31); -> '2008-02-02'
  • ADDTIME(expr1,expr2)

    ADDTIME()expr2expr1 を加算し、その結果を返します。expr1 は時間または日付時間式であり、expr2 は時間式です。

    mysql> SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002'); -> '2008-01-02 01:01:01.000001'
    mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998'); -> '03:00:01.999997'
  • CONVERT_TZ(dt,from_tz,to_tz)

    CONVERT_TZ() は、日付時間値 dtfrom_tz で指定されたタイムゾーンから、to_tz で指定されたタイムゾーンに変換し、結果の値を返します。タイムゾーンは、セクション10.6「MySQL Server でのタイムゾーンのサポート」で説明されているように指定されます。引数が無効な場合、この関数は NULL を返します。

    from_tz から UTC に変換される際に、値が TIMESTAMP でサポートされている範囲から外れている場合は、変換が実行されません。TIMESTAMP の範囲については、セクション11.1.2「日付と時間型の概要」で説明されています。

    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET'); -> '2004-01-01 13:00:00'
    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00'); -> '2004-01-01 22:00:00'
    注記

    名前付きタイムゾーン ('MET' または 'Europe/Moscow' など) を使用するには、タイムゾーンテーブルが正しく設定されている必要があります。手順については、セクション10.6「MySQL Server でのタイムゾーンのサポート」を参照してください。

  • CURDATE()

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

    mysql> SELECT CURDATE(); -> '2008-06-13'
    mysql> SELECT CURDATE() + 0; -> 20080613
  • CURRENT_DATECURRENT_DATE()

    CURRENT_DATE および CURRENT_DATE()CURDATE() のシノニムです。

  • CURRENT_TIMECURRENT_TIME([fsp])

    CURRENT_TIME および CURRENT_TIME()CURTIME() のシノニムです。

  • CURRENT_TIMESTAMPCURRENT_TIMESTAMP([fsp])

    CURRENT_TIMESTAMP および CURRENT_TIMESTAMP()NOW() のシノニムです。

  • CURTIME([fsp])

    関数が文字列と数値コンテキストのどちらで使用されているのかに応じて、現在の時間を 'HH:MM:SS' または HHMMSS 書式の値で返します。値は、現在のタイムゾーンで表現されています。

    MySQL 5.6.4 の時点では、0 から 6 までの小数秒の精度を指定するために fsp 引数が指定されている場合は、その桁数の小数秒部分が戻り値に含まれます。5.6.4 よりも前では、すべての引数が無視されます。

    mysql> SELECT CURTIME(); -> '23:50:26'
    mysql> SELECT CURTIME() + 0; -> 235026.000000
  • DATE(expr)

    日付または日付時間式 expr の日付部分を抽出します。

    mysql> SELECT DATE('2003-12-31 01:02:03'); -> '2003-12-31'
  • DATEDIFF(expr1,expr2)

    DATEDIFF() は、ある日付から別の日付までの日数の値として表現された expr1expr2 を返します。expr1 および expr2 は、日付または日付時間式です。値の日付部分のみが計算に使用されます。

    mysql> SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30'); -> 1
    mysql> SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31'); -> -31
  • DATE_ADD(date,INTERVAL exprunit), DATE_SUB(date,INTERVAL exprunit)

    これらの関数は日付演算を実行します。date 引数は、開始日付値または開始日付時間値を指定します。expr は、開始日付から加算または減算される間隔値を指定する式です。expr は文字列であり、負の間隔の場合は - で始めることができます。unit は、式を解釈する際の単位を示すキーワードです。

    INTERVAL キーワードおよび unit 指定子では、大文字と小文字が区別されません。

    次の表には、unit 値ごとに要求される形式の expr 引数を表示します。

    unit要求される expr 書式
    MICROSECONDMICROSECONDS
    SECONDSECONDS
    MINUTEMINUTES
    HOURHOURS
    DAYDAYS
    WEEKWEEKS
    MONTHMONTHS
    QUARTERQUARTERS
    YEARYEARS
    SECOND_MICROSECOND'SECONDS.MICROSECONDS'
    MINUTE_MICROSECOND'MINUTES:SECONDS.MICROSECONDS'
    MINUTE_SECOND'MINUTES:SECONDS'
    HOUR_MICROSECOND'HOURS:MINUTES:SECONDS.MICROSECONDS'
    HOUR_SECOND'HOURS:MINUTES:SECONDS'
    HOUR_MINUTE'HOURS:MINUTES'
    DAY_MICROSECOND'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS'
    DAY_SECOND'DAYS HOURS:MINUTES:SECONDS'
    DAY_MINUTE'DAYS HOURS:MINUTES'
    DAY_HOUR'DAYS HOURS'
    YEAR_MONTH'YEARS-MONTHS'

    戻り値は引数によって異なります。

    • 第 1 引数が DATETIME (または TIMESTAMP) 値である場合と、第 1 引数が DATE で、unit 値に HOURSMINUTES、または SECONDS が使用されている場合は、DATETIME です。

    • それ以外の場合は文字列です。

    必ず結果が DATETIME になるようにするには、CAST() を使用すれば、第 1 引数を DATETIME に変換できます。

    MySQL では、expr 書式の句読点区切り文字が許可されます。表には、提案される区切り文字を表示します。date 引数が DATE 値であり、計算に YEARMONTH、および DAY 部分のみが含まれる (つまり、時間部分は含まれない) 場合は、結果が DATE 値になります。その他の場合は、結果が DATETIME 値になります。

    また、日付演算は、+ または - 演算子とともに INTERVAL を使用して実行することもできます。

    date + INTERVAL exprunitdate - INTERVAL exprunit

    INTERVAL exprunit は、他方の側の式が日付または日付間値である場合に、+ 演算子の一方の側で許可されます。- 演算子では、間隔から日付または日付間値を抽出しても意味がないため、INTERVAL exprunit は右側でのみ許可されます。

    mysql> SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND; -> '2009-01-01 00:00:00'
    mysql> SELECT INTERVAL 1 DAY + '2008-12-31'; -> '2009-01-01'
    mysql> SELECT '2005-01-01' - INTERVAL 1 SECOND; -> '2004-12-31 23:59:59'
    mysql> SELECT DATE_ADD('2000-12-31 23:59:59', ->  INTERVAL 1 SECOND); -> '2001-01-01 00:00:00'
    mysql> SELECT DATE_ADD('2010-12-31 23:59:59', ->  INTERVAL 1 DAY); -> '2011-01-01 23:59:59'
    mysql> SELECT DATE_ADD('2100-12-31 23:59:59', ->  INTERVAL '1:1' MINUTE_SECOND); -> '2101-01-01 00:01:00'
    mysql> SELECT DATE_SUB('2005-01-01 00:00:00', ->  INTERVAL '1 1:1:1' DAY_SECOND); -> '2004-12-30 22:58:59'
    mysql> SELECT DATE_ADD('1900-01-01 00:00:00', ->  INTERVAL '-1 10' DAY_HOUR); -> '1899-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'

    指定した間隔値 (unit キーワードから要求されるすべての間隔部分は含まれません) が短すぎる場合は、MySQL では間隔値の左端部分が省略されているとみなされます。たとえば、DAY_SECONDunit を指定した場合は、expr の値には日、時間、分、秒の部分が含まれるとみなされます。'1:10' のような値を指定すると、MySQL では日と時間の部分が欠落していて、値は分と秒を表しているとみなされます。つまり、'1:10' DAY_SECOND は、'1:10' MINUTE_SECOND と同等の方法で解釈されます。これは、MySQL で TIME 値が時間ではなく経過時間を表していると解釈される方法に類似しています。

    expr は文字列として処理されるため、INTERVAL に文字列以外の値を指定する場合は注意してください。たとえば、間隔指定子が HOUR_MINUTE の場合は、6/41.5000 に評価され、1 時間 5000 分として処理されます。

    mysql> SELECT 6/4; -> 1.5000
    mysql> SELECT DATE_ADD('2009-01-01', INTERVAL 6/4 HOUR_MINUTE); -> '2009-01-04 12:20:00'

    間隔値が予想どおりに解釈されるようにするには、CAST() 演算を使用します。6/4 を 1 時間 5 分として処理するには、小数点以下の桁数が 1 桁の DECIMAL 値にキャストします。

    mysql> SELECT CAST(6/4 AS DECIMAL(3,1)); -> 1.5
    mysql> SELECT DATE_ADD('1970-01-01 12:00:00', ->  INTERVAL CAST(6/4 AS DECIMAL(3,1)) HOUR_MINUTE); -> '1970-01-01 13:05:00'

    時間部分が含まれるものを日付値に加算したり、日付値から減算したりすると、自動的に結果が日付時間値に変換されます。

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

    MONTHYEAR_MONTH、または YEAR を加算した結果の日付に、新しい月の最大日数よりも大きな日が含まれる場合は、その日が新しい月の最大日数に調整されます。

    mysql> SELECT DATE_ADD('2009-01-30', INTERVAL 1 MONTH); -> '2009-02-28'

    日付算術演算では、完全な日付が必須であるため、'2006-07-00' のような不完全な日付や、誤った形式の日付では正常に機能しません。

    mysql> SELECT DATE_ADD('2006-07-00', INTERVAL 1 DAY); -> NULL
    mysql> SELECT '2005-03-32' + INTERVAL 1 MONTH; -> NULL
  • DATE_FORMAT(date,format)

    format 文字列に従って、date 値を書式設定します。

    次の指定子が format 文字列で使用されている場合があります。書式指定子文字の前には、% 文字を付ける必要があります。

    指定子説明
    %a簡略曜日名 (Sun..Sat)
    %b簡略月名 (Jan..Dec)
    %c月、数字 (0..12)
    %D英語のサフィクスを持つ日付 (0th, 1st, 2nd, 3rd, …)
    %d日、数字 (00..31)
    %e日、数字 (0..31)
    %fマイクロ秒 (000000..999999)
    %H時間 (00..23)
    %h時間 (01..12)
    %I時間 (01..12)
    %i分、数字 (00..59)
    %j年間通算日 (001..366)
    %k時 (0..23)
    %l時 (1..12)
    %M月名 (January..December)
    %m月、数字 (00..12)
    %pAM または PM
    %r時間、12 時間単位 (hh:mm:ssAM または PM が続く)
    %S秒 (00..59)
    %s秒 (00..59)
    %T時間、24 時間単位 (hh:mm:ss)
    %U週 (00..53)、日曜日が週の初日、WEEK() モード 0
    %u週 (00..53)、月曜日が週の初日、WEEK() モード 1
    %V週 (01..53)、日曜日が週の初日、WEEK() モード 2、%X とともに使用
    %v週 (01..53)、月曜日が週の初日、WEEK() モード 3、%x とともに使用
    %W曜日名 (Sunday..Saturday)
    %w曜日 (0=Sunday..6=Saturday)
    %X年間の週、日曜日が週の初日、数字、4 桁、%V とともに使用
    %x年間の週、月曜日が週の初日、数字、4 桁、%v とともに使用
    %Y年、数字、4 桁
    %y年、数字 (2 桁)
    %%リテラル % 文字
    %xx (上記にないすべての x)

    MySQL では '2014-00-00' などの不完全な日付の格納が許可されるため、月および日の指定子の範囲はゼロから始まります。

    日および月の名前と略語に使用される言語は、lc_time_names システム変数 (セクション10.7「MySQL Server のロケールサポート」) の値で制御されます。

    %U%u%V、および %v 指定子のモード値については、WEEK() 関数の説明を参照してください。モードによって、週番号が付与される方法が影響を受けます。

    DATE_FORMAT() は、ASCII 以外の文字を含む月および週の名前を返すことができるように、character_set_connection および collation_connection で指定された文字セットおよび照合順序を含む文字列を返します。

    mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009'
    mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00'
    mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', ->  '%D %y %a %d %m %b %j'); -> '4th 00 Thu 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'
    mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00'
  • DATE_SUB(date,INTERVAL exprunit)

    DATE_ADD() の説明を参照してください。

  • DAY(date)

    DAY()DAYOFMONTH() のシノニムです。

  • DAYNAME(date)

    date に対応する曜日の名前を返します。名前に使用される言語は、lc_time_names システム変数 (セクション10.7「MySQL Server のロケールサポート」) の値で制御されます。

    mysql> SELECT DAYNAME('2007-02-03'); -> 'Saturday'
  • DAYOFMONTH(date)

    1 から 31 までの範囲内で date に対応する日を返します。'0000-00-00''2008-00-00' のように日の部分がゼロの場合は、0 を返します。

    mysql> SELECT DAYOFMONTH('2007-02-03'); -> 3
  • DAYOFWEEK(date)

    date の曜日インデックス (1 = Sunday、2 = Monday、…、7 = Saturday) を返します。これらのインデックス値は、ODBC 標準に対応しています。

    mysql> SELECT DAYOFWEEK('2007-02-03'); -> 7
  • DAYOFYEAR(date)

    1 から 366 までの範囲内で date に対応する通日を返します。

    mysql> SELECT DAYOFYEAR('2007-02-03'); -> 34
  • EXTRACT(unit FROM date)

    EXTRACT() 関数では、DATE_ADD() または DATE_SUB() と同じ単位指定子が使用されますが、データ演算が実行されるのではなく、データから一部が抽出されます。

    mysql> SELECT EXTRACT(YEAR FROM '2009-07-02'); -> 2009
    mysql> SELECT EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03'); -> 200907
    mysql> SELECT EXTRACT(DAY_MINUTE FROM '2009-07-02 01:02:03'); -> 20102
    mysql> SELECT EXTRACT(MICROSECOND -> FROM '2003-01-02 10:30:00.000123'); -> 123
  • FROM_DAYS(N)

    日数 N が指定され、DATE 値を返します。

    mysql> SELECT FROM_DAYS(730669); -> '2007-07-03'

    古い日付では、FROM_DAYS() を慎重に使用してください。グレゴリオ暦 (1582) の出現よりも前の値とともに使用することを目的に設計されていません。セクション12.8「MySQL で使用されるカレンダー」を参照してください。

  • FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)

    関数が文字列と数値のどちらのコンテキストで使用されたのかに応じて、unix_timestamp 引数の表現を 'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 書式の値として返します。値は、現在のタイムゾーンで表現されています。unix_timestamp は、UNIX_TIMESTAMP() 関数で生成されるような内部タイムスタンプ値です。

    format が指定されている場合は、DATE_FORMAT() 関数のエントリで一覧表示される場合と同じ方法で使用される format 文字列に従って、結果が書式設定されます。

    mysql> SELECT FROM_UNIXTIME(1196440219); -> '2007-11-30 10:30:19'
    mysql> SELECT FROM_UNIXTIME(1196440219) + 0; -> 20071130103019.000000
    mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), -> '%Y %D %M %h:%i:%s %x'); -> '2007 30th November 10:30:59 2007'

    注: UNIX_TIMESTAMP() および FROM_UNIXTIME() を使用して TIMESTAMP 値と Unix タイムスタンプ値とを変換する場合は、どちらの方向でもマッピングが 1 対 1 ではないため、変換は不可逆です。詳細は UNIX_TIMESTAMP() 関数の説明を参照してください。

  • GET_FORMAT({DATE|TIME|DATETIME}, {'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL'})

    書式文字列を返します。この関数は、DATE_FORMAT() およびSTR_TO_DATE() 関数と組み合わせて使用すると便利です。

    1 番目と 2 番目の引数に値を指定できるため、複数の書式文字列を生成できます (使用される指定子については、DATE_FORMAT() 関数の説明で示す表を参照してください)。ISO 書式は ISO 8601 ではなく、ISO 9075 を参照しています。

    関数呼び出し結果
    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(DATETIME,'USA')'%Y-%m-%d %H.%i.%s'
    GET_FORMAT(DATETIME,'JIS')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(DATETIME,'ISO')'%Y-%m-%d %H:%i:%s'
    GET_FORMAT(DATETIME,'EUR')'%Y-%m-%d %H.%i.%s'
    GET_FORMAT(DATETIME,'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'

    TIMESTAMP は、GET_FORMAT() への 1 番目の引数としても使用できます。その場合、関数は DATETIME の場合と同じ値を返します。

    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'
  • HOUR(time)

    time に対応する時を返します。戻り値の範囲は、日付時間値の 0 から 23 までです。ただし、TIME 値の範囲は実際にはもっと大きいため、HOUR23 よりも大きい値を返すことができます。

    mysql> SELECT HOUR('10:05:03'); -> 10
    mysql> SELECT HOUR('272:59:59'); -> 272
  • LAST_DAY(date)

    日付または日付時間の値が指定され、月の最終日に対応する値を返します。引数が無効である場合は、NULL を返します。

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

    LOCALTIME および LOCALTIME()NOW() のシノニムです。

  • LOCALTIMESTAMP, LOCALTIMESTAMP([fsp])

    LOCALTIMESTAMP および LOCALTIMESTAMP()NOW() のシノニムです。

  • MAKEDATE(year,dayofyear)

    指定された年と年間通算値から、日付を返します。dayofyear は 0 よりも大きくする必要があり、それ以外の場合は結果が NULL になります。

    mysql> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32); -> '2011-01-31', '2011-02-01'
    mysql> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365); -> '2011-12-31', '2014-12-31'
    mysql> SELECT MAKEDATE(2011,0); -> NULL
  • MAKETIME(hour,minute,second)

    hourminute、および second 引数から計算された時間値を返します。

    MySQL 5.6.4 の時点では、second 引数に小数部を含めることができます。

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

    0 から 999999 までの範囲内の数値として、時間または日付時間式 expr からのマイクロ秒を返します。

    mysql> SELECT MICROSECOND('12:00:00.123456'); -> 123456
    mysql> SELECT MICROSECOND('2009-12-31 23:59:59.000010'); -> 10
  • MINUTE(time)

    0 から 59 までの範囲内で、time に対応する分を返します。

    mysql> SELECT MINUTE('2008-02-03 10:05:03'); -> 5
  • MONTH(date)

    1 (1 月) から 12 (12 月) の範囲内で、date に対応する月を返します。'0000-00-00''2008-00-00' のように月の部分がゼロの場合は、0 を返します。

    mysql> SELECT MONTH('2008-02-03'); -> 2
  • MONTHNAME(date)

    date に対応する月の完全名を返します。名前に使用される言語は、lc_time_names システム変数 (セクション10.7「MySQL Server のロケールサポート」) の値で制御されます。

    mysql> SELECT MONTHNAME('2008-02-03'); -> 'February'
  • NOW([fsp])

    関数が文字列と数値のどちらのコンテキストで使用されているのかに応じて、現在の日付と時間を 'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 書式の値として返します。値は、現在のタイムゾーンで表現されています。

    MySQL 5.6.4 の時点では、0 から 6 までの小数秒の精度を指定するために fsp 引数が指定されている場合は、その桁数の小数秒部分が戻り値に含まれます。5.6.4 よりも前では、すべての引数が無視されます。

    mysql> SELECT NOW(); -> '2007-12-15 23:50:26'
    mysql> SELECT NOW() + 0; -> 20071215235026.000000

    NOW() は、ステートメントが実行を開始する時刻を示す定数時間を返します。(ストアドファンクションまたはトリガーでは、NOW() は関数またはトリガーステートメントが実行を開始する時間を返します。)これは、正確な実行時間を返す SYSDATE() の動作とは異なります。

    mysql> SELECT NOW(), SLEEP(2), NOW();+---------------------+----------+---------------------+
    | NOW() | SLEEP(2) | NOW() |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |
    +---------------------+----------+---------------------+
    mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();+---------------------+----------+---------------------+
    | SYSDATE() | SLEEP(2) | SYSDATE() |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |
    +---------------------+----------+---------------------+

    さらに、SET TIMESTAMP ステートメントによって、NOW() で返された値は影響を受けますが、SYSDATE() で返された値は影響を受けません。つまり、バイナリログのタイムスタンプ設定は、SYSDATE() の呼び出しに影響しないことを意味します。タイムスタンプをゼロ以外の値に設定すると、後続の NOW() が起動されるたびに、その値が返されます。タイムスタンプをゼロに設定すると、この効果が取り消され、再度 NOW() が現在の日付と時間を返すようになります。

    2 つの関数の相違点についての詳細は、SYSDATE() の説明を参照してください。

  • PERIOD_ADD(P,N)

    N 月を期間 P に (YYMM または YYYYMM の書式で) 加算します。YYYYMM の書式で値を返します。

    注記

    期間引数 P は、日付値ではありません

    mysql> SELECT PERIOD_ADD(200801,2); -> 200803
  • PERIOD_DIFF(P1,P2)

    期間 P1P2 間の月数を返します。P1 および P2 は、YYMM または YYYYMM の書式にする必要があります。期間引数 P1 および P2 は日付値ではないことに注意してください。

    mysql> SELECT PERIOD_DIFF(200802,200703); -> 11
  • QUARTER(date)

    1 から 4 までの範囲内で date に対応する四半期を返します。

    mysql> SELECT QUARTER('2008-04-01'); -> 2
  • SECOND(time)

    0 から 59 までの範囲内で、time に対応する秒数を返します。

    mysql> SELECT SECOND('10:05:03'); -> 3
  • SEC_TO_TIME(seconds)

    TIME 値として、時、分、秒に変換された seconds 引数を返します。結果の範囲は、TIME データ型の範囲に制約されます。引数がその範囲外の値に対応している場合は、警告が発行されます。

    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 が指定されます。STR_TO_DATE() は、書式文字列に日付と時間の両方の部分が含まれる場合は DATETIME 値を返し、文字列に日付と時間の部分の一方のみが含まれる場合は DATE または TIME 値を返します。str から抽出された日付値、時間値、または日付時間値が不正な場合は、STR_TO_DATE() によって NULL が返され、警告が発行されます。

    サーバーは str をスキャンすることで、format の一致を試みます。書式文字列には、リテラル文字と % で始まる書式指定子を含めることができます。format 内のリテラル文字は、str 内と完全に一致する必要があります。format 内の書式指定子は、str 内の日付または時間の部分に一致する必要があります。format で使用できる指定子については、DATE_FORMAT() 関数の説明を参照してください。

    mysql> SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y'); -> '2013-05-01'
    mysql> SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y'); -> '2013-05-01'

    str の先頭からスキャンが開始され、一致しない format が見つかった場合は失敗します。str の末尾にある余分な文字は、無視されます。

    mysql> SELECT STR_TO_DATE('a09:30:17','a%h:%i:%s'); -> '09:30:17'
    mysql> SELECT STR_TO_DATE('a09:30:17','%h:%i:%s'); -> NULL
    mysql> SELECT STR_TO_DATE('09:30:17a','%h:%i:%s'); -> '09:30:17'

    指定されていない日付または時間の部分の値は 0 になるため、str に指定された値が不完全な場合は、結果の一部または全部が 0 に設定されます。

    mysql> SELECT STR_TO_DATE('abc','abc'); -> '0000-00-00'
    mysql> SELECT STR_TO_DATE('9','%m'); -> '0000-09-00'
    mysql> SELECT STR_TO_DATE('9','%s'); -> '00:00:09'

    日付値の部分をチェックする範囲は、セクション11.3.1「DATE、DATETIME、および TIMESTAMP 型」の説明どおりです。たとえば、ゼロの日付または部分値が 0 の日付は、このような値が許可されないように SQL モードが設定されていなければ、許可されます。

    mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); -> '0000-00-00'
    mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y'); -> '2004-04-31'
    注記

    週が月の境界を越えた場合は、年と週の組み合わせでは年と月を一意に識別できないため、"%X%V" の書式を使用しても、年と週の文字列を日付に変換できません。年と週を日付に変換するには、曜日も指定する必要があります。

    mysql> SELECT STR_TO_DATE('200442 Monday', '%X%V %W'); -> '2004-10-18'
  • SUBDATE(date,INTERVAL exprunit), SUBDATE(expr,days)

    INTERVAL 形式で 2 番目の引数を付けて呼び出されると、SUBDATE()DATE_SUB() のシノニムになります。INTERVALunit 引数については、DATE_ADD() の説明を参照してください。

    mysql> SELECT DATE_SUB('2008-01-02', INTERVAL 31 DAY); -> '2007-12-02'
    mysql> SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY); -> '2007-12-02'

    2 番目の形式では、days の整数値を使用できます。このような場合は、日付または日付時間式 expr から日数が減算されると解釈されます。

    mysql> SELECT SUBDATE('2008-01-02 12:00:00', 31); -> '2007-12-02 12:00:00'
  • SUBTIME(expr1,expr2)

    SUBTIME() は、expr1 と同じ書式で表現される expr1expr2 を返します。expr1 は時間または日付時間式であり、expr2 は時間式です。

    mysql> SELECT SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002'); -> '2007-12-30 22:58:58.999997'
    mysql> SELECT SUBTIME('01:00:00.999999', '02:00:00.999998'); -> '-00:59:59.999999'
  • SYSDATE([fsp])

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

    MySQL 5.6.4 の時点では、0 から 6 までの小数秒の精度を指定するために fsp 引数が指定されている場合は、その桁数の小数秒部分が戻り値に含まれます。5.6.4 よりも前では、すべての引数が無視されます。

    SYSDATE() は、実行された時間を返します。これは、ステートメントが実行を開始する時間を示す定数時間を返す NOW() の動作とは異なります。(ストアドファンクションまたはトリガーでは、NOW() は関数またはトリガーステートメントが実行を開始する時間を返します。)

    mysql> SELECT NOW(), SLEEP(2), NOW();+---------------------+----------+---------------------+
    | NOW() | SLEEP(2) | NOW() |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |
    +---------------------+----------+---------------------+
    mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();+---------------------+----------+---------------------+
    | SYSDATE() | SLEEP(2) | SYSDATE() |
    +---------------------+----------+---------------------+
    | 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |
    +---------------------+----------+---------------------+

    さらに、SET TIMESTAMP ステートメントによって、NOW() で返された値は影響を受けますが、SYSDATE() で返された値は影響を受けません。つまり、バイナリログのタイムスタンプ設定は、SYSDATE() の呼び出しに影響しないことを意味します。

    SYSDATE() は、同じステートメント内でもさまざまな値を返すことができ、SET TIMESTAMP による影響も受けないため、非決定的です。そのため、ステートメントベースのバイナリロギングが使用されている場合は、レプリケーションで安全に使用できません。これが問題となる場合は、行ベースのロギングを使用できます。

    また、--sysdate-is-now オプションを使用すると、SYSDATE()NOW() のエイリアスにすることができます。これは、オプションがマスターとスレーブの両方で使用される場合に機能します。

    SYSDATE() に非決定的な特性があるということは、それを参照する式を評価する際にインデックスを使用できないことも意味します。

  • TIME(expr)

    時間または日付時間式 expr の時部分を抽出し、文字列として返します。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

    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'
  • TIMEDIFF(expr1,expr2)

    TIMEDIFF() は、時間値として表現された expr1expr2 を返します。expr1 および expr2 は時間または日付時間式ですが、両方とも同じ型にする必要があります。

    TIMEDIFF() で返される結果は、TIME 値で許可される範囲に制限されています。また、TIMESTAMPDIFF() および UNIX_TIMESTAMP() 関数のいずれかを使用することもできます。両方とも整数を返します。

    mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', -> '2000:01:01 00:00:00.000001'); -> '-00:00:00.000001'
    mysql> SELECT TIMEDIFF('2008-12-31 23:59:59.000001', ->  '2008-12-30 01:01:01.000002'); -> '46:58:57.999999'
  • TIMESTAMP(expr), TIMESTAMP(expr1,expr2)

    引数を 1 つ付けると、この関数は日付または日付時間式 expr を日付時間値として返します。引数を 2 つ付けると、時間式 expr2 を日付または日付時間式 expr1 に加算し、その結果を日付時間値として返します。

    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'
  • TIMESTAMPADD(unit,interval,datetime_expr)

    整数式 interval を日付または日付時間式 datetime_expr に加算します。interval の単位は、unit 引数で指定されます。この引数は、MICROSECOND (マイクロ秒)、SECONDMINUTEHOURDAYWEEKMONTHQUARTERYEAR 値のいずれかにする必要があります。

    unit 値を指定するには、ここで示したキーワードのいずれかを使用するか、SQL_TSI_ をプリフィクスとして付けます。たとえば、DAYSQL_TSI_DAY は両方とも有効です。

    mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02'); -> '2003-01-02 00:01:00'
    mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02'); -> '2003-01-09'
  • TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)

    datetime_expr2datetime_expr1 を返します。datetime_expr1datetime_expr2 は、日付または日付時間式です。式の一方が日付で、他方が日付時間にすることもできます。日付値は、必要に応じて時間部分が '00:00:00' の日付時間として処理されます。結果 (整数) の単位は、unit 引数で指定されます。unit の有効な値は、TIMESTAMPADD() 関数の説明で一覧表示された値と同じです。

    mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01'); -> 3
    mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01'); -> -1
    mysql> SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55'); -> 128885
    注記

    この関数の日付または日付時間引数の順序は、TIMESTAMP() 関数を 2 つの引数を指定して呼び出す場合の順序と逆になります。

  • 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('2007-10-07'); -> 733321

    TO_DAYS() は、カレンダーが変更された際に失われた日が考慮されないため、グレゴリオ暦 (1582) の出現よりも前の値とともに使用するために設計されていません。日付が 1582 よりも前の場合は (ほかのロケールでは、さらにあとの年になる可能性があります)、この関数の結果は信頼できません。詳細は セクション12.8「MySQL で使用されるカレンダー」を参照してください。

    MySQL では セクション11.3「日付と時間型」 のルールを使用して、日付の 2 桁の年の値が 4 桁の形式に変換されることを忘れないでください。たとえば、'2008-10-07''08-10-07' は同じ日付と認識されます。

    mysql> SELECT TO_DAYS('2008-10-07'), TO_DAYS('08-10-07'); -> 733687, 733687

    MySQL では、ゼロの日付は '0000-00-00' として定義されます。ただし、このデータ自体は無効とみなされます。つまり、'0000-00-00' および '0000-01-01' の場合、TO_DAYS() は次に示す値を返します。

    mysql> SELECT TO_DAYS('0000-00-00');+-----------------------+
    | to_days('0000-00-00') |
    +-----------------------+
    | NULL |
    +-----------------------+
    1 row in set, 1 warning (0.00 sec)
    mysql> SHOW WARNINGS;+---------+------+----------------------------------------+
    | Level | Code | Message |
    +---------+------+----------------------------------------+
    | Warning | 1292 | Incorrect datetime value: '0000-00-00' |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT TO_DAYS('0000-01-01');+-----------------------+
    | to_days('0000-01-01') |
    +-----------------------+
    | 1 |
    +-----------------------+
    1 row in set (0.00 sec)

    このことは、ALLOW_INVALID_DATES SQL サーバーモードが有効であるかどうかに関係なく当てはまります。

  • TO_SECONDS(expr)

    日付または日付時間の expr が指定され、0 年以降の日数を返します。expr が有効な日付または日付時間の値ではない場合は、NULL を返します。

    mysql> SELECT TO_SECONDS(950501); -> 62966505600
    mysql> SELECT TO_SECONDS('2009-11-29'); -> 63426672000
    mysql> SELECT TO_SECONDS('2009-11-29 13:43:32'); -> 63426721412
    mysql> SELECT TO_SECONDS( NOW() ); -> 63426721458

    TO_DAYS() と同様に、TO_SECONDS() は、カレンダーが変更された際に失われた日が考慮されないため、グレゴリオ暦 (1582) の出現よりも前の値とともに使用する目的で設計されていません。日付が 1582 よりも前の場合は (ほかのロケールでは、さらにあとの年になる可能性があります)、この関数の結果は信頼できません。詳細は セクション12.8「MySQL で使用されるカレンダー」を参照してください。

    TO_DAYS() と同様に、TO_SECONDS()セクション11.3「日付と時間型」 のルールを使用して日付の 2 桁の年の値を 4 桁の形式に変換します。

    MySQL では、ゼロの日付は '0000-00-00' として定義されます。ただし、このデータ自体は無効とみなされます。つまり、'0000-00-00' および '0000-01-01' の場合、TO_SECONDS() は次に示す値を返します。

    mysql> SELECT TO_SECONDS('0000-00-00');+--------------------------+
    | TO_SECONDS('0000-00-00') |
    +--------------------------+
    | NULL |
    +--------------------------+
    1 row in set, 1 warning (0.00 sec)
    mysql> SHOW WARNINGS;+---------+------+----------------------------------------+
    | Level | Code | Message |
    +---------+------+----------------------------------------+
    | Warning | 1292 | Incorrect datetime value: '0000-00-00' |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT TO_SECONDS('0000-01-01');+--------------------------+
    | TO_SECONDS('0000-01-01') |
    +--------------------------+
    | 86400 |
    +--------------------------+
    1 row in set (0.00 sec)

    このことは、ALLOW_INVALID_DATES SQL サーバーモードが有効であるかどうかに関係なく当てはまります。

  • UNIX_TIMESTAMP()UNIX_TIMESTAMP(date)

    引数なしで呼び出された場合は、Unix タイムスタンプ ('1970-01-01 00:00:00' UTC 以降の秒数) を符号なし整数として返します。date 引数を付けて UNIX_TIMESTAMP() が呼び出された場合は、その引数の値が '1970-01-01 00:00:00' UTC 以降の秒数として返されます。date には、DATE 文字列、DATETIME 文字列、TIMESTAMPYYMMDD または YYYYMMDD 書式の数値を指定できます。サーバーは date を現在のタイムゾーンの値として解釈し、UTC の内部値に変換します。クライアントは、セクション10.6「MySQL Server でのタイムゾーンのサポート」で説明するとおりに、独自のタイムゾーンを設定できます。

    mysql> SELECT UNIX_TIMESTAMP(); -> 1196440210
    mysql> SELECT UNIX_TIMESTAMP('2007-11-30 10:30:19'); -> 1196440219

    UNIX_TIMESTAMP()TIMESTAMP カラムで使用されると、暗黙的に string-to-Unix-timestamp に変換されずに、内部タイムスタンプ値が直接返されます。UNIX_TIMESTAMP() に範囲外の日付を渡すと、0 が返されます。

    注: UNIX_TIMESTAMP() および FROM_UNIXTIME() を使用して TIMESTAMP 値と Unix タイムスタンプ値とを変換する場合は、どちらの方向でもマッピングが 1 対 1 ではないため、変換は不可逆です。たとえば、ローカルタイムゾーンを変更するための変換が原因で、2 つの UNIX_TIMESTAMP() で 2 つの TIMESTAMP 値が同じ Unix タイムスタンプ値にマップされる可能性があります。FROM_UNIXTIME() は、その値を元の TIMESTAMP 値のいずれかにのみマップし直します。次に、CET タイムゾーンでの TIMESTAMP 値の使用例を示します。

    mysql> SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00');+---------------------------------------+
    | UNIX_TIMESTAMP('2005-03-27 03:00:00') |
    +---------------------------------------+
    | 1111885200 |
    +---------------------------------------+
    mysql> SELECT UNIX_TIMESTAMP('2005-03-27 02:00:00');+---------------------------------------+
    | UNIX_TIMESTAMP('2005-03-27 02:00:00') |
    +---------------------------------------+
    | 1111885200 |
    +---------------------------------------+
    mysql> SELECT FROM_UNIXTIME(1111885200);+---------------------------+
    | FROM_UNIXTIME(1111885200) |
    +---------------------------+
    | 2005-03-27 03:00:00 |
    +---------------------------+

    UNIX_TIMESTAMP() カラムを減算する場合は、結果を符号付きの整数にキャストします。セクション12.10「キャスト関数と演算子」を参照してください。

  • UTC_DATEUTC_DATE()

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

    mysql> SELECT UTC_DATE(), UTC_DATE() + 0; -> '2003-08-14', 20030814
  • UTC_TIME, UTC_TIME([fsp])

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

    MySQL 5.6.4 の時点では、0 から 6 までの小数秒の精度を指定するために fsp 引数が指定されている場合は、その桁数の小数秒部分が戻り値に含まれます。5.6.4 よりも前では、すべての引数が無視されます。

    mysql> SELECT UTC_TIME(), UTC_TIME() + 0; -> '18:07:53', 180753.000000
  • UTC_TIMESTAMPUTC_TIMESTAMP([fsp])

    関数が文字列と数値のどちらのコンテキストで使用されているのかに応じて、現在の UTC 日付と時間を 'YYYY-MM-DD HH:MM:SS' または YYYYMMDDHHMMSS 書式の値として返します。

    MySQL 5.6.4 の時点では、0 から 6 までの小数秒の精度を指定するために fsp 引数が指定されている場合は、その桁数の小数秒部分が戻り値に含まれます。5.6.4 よりも前では、すべての引数が無視されます。

    mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0; -> '2003-08-14 18:08:04', 20030814180804.000000
  • WEEK(date[,mode])

    この関数は、date に対応する週番号を返します。2 つの引数を取る形式の WEEK() を使用すると、週が日曜日と月曜日のどちらから始まるのか、および戻り値が 0 から 53までと 1 から 53 までのどちらの範囲内であるのかを指定できます。mode 引数が省略された場合は、default_week_format システム変数の値が使用されます。セクション5.1.4「サーバーシステム変数」を参照してください。

    次の表では、mode 引数がどのように機能するのかについて説明します。

    モード週の 1 日目範囲第 1 週は次の条件を満たす最初の週
    0日曜日0-53本年の日曜日を含む
    1月曜日0-53本年の 4 日以上を含む
    2日曜日1-53本年の日曜日を含む
    3月曜日1-53本年の 4 日以上を含む
    4日曜日0-53本年の 4 日以上を含む
    5月曜日0-53本年の月曜日を含む
    6日曜日1-53本年の 4 日以上を含む
    7月曜日1-53本年の月曜日を含む

    本年の 4 日以上を含むという意味を持つ mode 値では、ISO 8601:1988 に従って週番が付けられます。

    • 1 月 1 日を含む週に新年の 4 日以上が含まれる場合は、その週が第 1 週です。

    • それ以外の場合は、前年の最終週となり、次の週が第 1 週です。

    mysql> SELECT WEEK('2008-02-20'); -> 7
    mysql> SELECT WEEK('2008-02-20',0); -> 7
    mysql> SELECT WEEK('2008-02-20',1); -> 8
    mysql> SELECT WEEK('2008-12-31',1); -> 53

    日付が前年の最終週に入っている場合は、オプションの mode 引数として236、または 7 を使用しなければ、MySQL によって 0 が返されます。

    mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0); -> 2000, 0

    指定された日付は実際には 1999 年の第 52 週に発生するため、WEEK()52 を返す必要があると議論されることもあります。代わりに WEEK() は、戻り値が指定された年の週番号となるように 0 を返します。これにより、日付から日付部分を抽出するその他の関数と組み合わせると、WEEK() 関数を信頼して使用できるようになります。

    指定された日付に対応する週の 1 日目を含む年について評価された結果を優先する場合は、オプションの mode 引数として 025、または 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 = Monday、1 = Tuesday、…6 = Sunday) を返します。

    mysql> SELECT WEEKDAY('2008-02-03 22:23:00'); -> 6
    mysql> SELECT WEEKDAY('2007-11-06'); -> 1
  • WEEKOFYEAR(date)

    1 から 53 までの範囲内で、日付の暦週を返します。WEEKOFYEAR()WEEK(date,3) に同等の互換性のある関数です。

    mysql> SELECT WEEKOFYEAR('2008-02-20'); -> 8
  • YEAR(date)

    1000 から 9999 までの範囲内で、date に対応する年を返します。日付がゼロの場合は、0 を返します。

    mysql> SELECT YEAR('1987-01-01'); -> 1987
  • YEARWEEK(date)YEARWEEK(date,mode)

    日付に対応する年と週を返します。mode 引数は、WEEK() への mode 引数とまったく同様に機能します。結果の年と日付引数の年では、その年の最初と最後の週が異なる可能性があります。

    mysql> SELECT YEARWEEK('1987-01-01'); -> 198653

    WEEK() はその後、指定された年のコンテキストで週を返すため、週番号はオプションの引数 0 または 1 を付けた場合に WEEK() 関数で返される数字 (0) とは異なります。

12.8 MySQL で使用されるカレンダー

MySQL では、先発グレゴリオ暦と呼ばれるものが使用されています。

ユリウス暦からグレゴリオ暦に切り替えた国はすべて、切り替え時に少なくとも 10 日間を破棄する必要がありました。この動作を確認するために、最初にユリウス暦からグレゴリオ暦への切り替えが発生した 1582 年 10 月を考えてください。

月曜日火曜日水曜日木曜日金曜日土曜日日曜日
1234151617
18192021222324
25262728293031

10 月 4 日から 10 月 15 日の間には日付がありません。この不連続性はカットオーバーと呼ばれます。カットオーバー前の日付はユリウス暦で、カットオーバー後の日付はグレゴリオ暦です。カットオーバー中の日付は存在しません。

実際に使用されていなかった日付に適用されるカレンダーは、先発と呼ばれます。したがって、カットオーバーが発生せず、常にグレゴリオ暦のルールで制御されていると考えられる場合は、先発グレゴリオ暦が使用されています。これが MySQL で使用されるものであり、標準 SQL でも必須です。そのため、MySQL DATE または DATETIME 値として格納されたカットオーバー前の日付は、その違いが補正されるように調整する必要があります。すべての国で同時にカットオーバーが発生しなかったこと、および発生が遅くなるほど失われる日数も多かったことに気付くことが重要です。たとえば、イギリスでは 1752 年に発生し、9 月 2 日水曜日の翌日が 9 月 14 日木曜日になりました。ロシアでは 1918 年までユリウス暦のままでしたが、その過程で 13 日間が失われました。10 月革命として知られる有名な事件は、グレゴリオ暦に従うと 11 月に発生しました。

12.9 全文検索関数

MATCH (col1,col2,...) AGAINST (expr [search_modifier])

search_modifier: { IN NATURAL LANGUAGE MODE | IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION | IN BOOLEAN MODE | WITH QUERY EXPANSION }

MySQL では、次のような全文インデックス設定および検索がサポートされています。

  • MySQL の全文インデックスは、型 FULLTEXT のインデックスです。

  • 全文インデックスは、InnoDB または MyISAM テーブルでのみ使用でき、CHARVARCHAR、または TEXT カラムにのみ作成できます。

  • FULLTEXT インデックスの定義は、テーブルの作成時に CREATE TABLE ステートメントで指定することも、あとで ALTER TABLE または CREATE INDEX を使用して追加することもできます。

  • データセットが大きい場合は、FULLTEXT インデックスが付いていないテーブルにロードしてから、そのあとでインデックスを作成した方が、既存のFULLTEXT インデックスが付いているテーブルにロードするよりも断然速いです。

全文検索は、MATCH() ... AGAINST 構文を使用して実行されます。MATCH() には、検索対象のカラム名をカンマで区切ったリストを指定します。AGAINST には、検索する文字列と、実行する検索のタイプを示すオプションの修飾子を指定します。検索文字列は、クエリー評価時に定数である文字列値にする必要があります。たとえば、テーブルカラムは、行ごとに異なる可能性があるため除外されます。

全文検索には、次の 3 つの種類があります。

  • 自然言語の検索では、検索文字列が人間の自然な言語でのフレーズ (フリーテキストのフレーズ) として解釈されます。特別な演算子はありません。ストップワードリストが適用されます。これらは、InnoDB 検索インデックスの場合は innodb_ft_enable_stopwordinnodb_ft_server_stopword_table、および innodb_ft_user_stopword_tableMyISAM 検索インデックスの場合は ft_stopword_file によって制御されます。詳細は、セクション12.9.4「全文ストップワード」を参照してください。

    IN NATURAL LANGUAGE MODE 修飾子が指定されている場合または修飾子がまったく指定されていない場合は、全文検索が自然言語検索になります。詳細は、セクション12.9.1「自然言語全文検索」を参照してください。

  • ブール検索では、特別なクエリー言語のルールを使用して検索文字列が解釈されます。文字列には、検索対象の単語が含まれます。また、一致する行に単語が存在しなければならない、または存在してはならないように、あるいは通常よりも単語の重みが高くまたは低くなるように、要件を指定する演算子を含めることもできます。特定の共通単語 (ストップワード) は、検索インデックスから省略され、検索文字列に存在しない場合は一致が行われません。IN BOOLEAN MODE 修飾子は、ブール検索を指定します。詳細は、セクション12.9.2「ブール全文検索」を参照してください。

  • クエリー拡張検索は、自然言語検索を改善したものです。自然言語検索を実行する際は、検索文字列が使用されます。その後、検索で返されたもっとも関連性の高い行からの単語が検索文字列に追加され、再度検索が実行されます。クエリーでは、2 回目の検索からの行が返されます。IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION または WITH QUERY EXPANSION 修飾子は、クエリー拡張検索を指定します。詳細は、セクション12.9.3「クエリー拡張を使用した全文検索」を参照してください。

FULLTEXT クエリーのパフォーマンスについては、セクション8.3.4「カラムインデックス」を参照してください。

InnoDBFULLTEXT インデックスの処理に関するより技術的な詳細は、セクション14.2.13.3「FULLTEXT インデックス」を参照してください。

全文検索上の制約については、セクション12.9.5「全文制限」に一覧表示されています。

myisam_ftdump ユーティリティーは、MyISAM 全文インデックスの内容をダンプします。これは、全文クエリーのデバッグ時に役立つことがあります。セクション4.6.2「myisam_ftdump — 全文インデックス情報の表示」を参照してください。

12.9.1 自然言語全文検索

デフォルトの場合や IN NATURAL LANGUAGE MODE 修飾子が指定された場合は、MATCH() 関数は、テキストコレクションに対して文字列の自然言語検索を実行します。コレクションは、FULLTEXT インデックスに含まれる 1 つ以上のカラムのセットです。検索文字列は、AGAINST() への引数として指定されます。MATCH() は、テーブルの行ごとに関連性の値を返します。つまり、検索文字列と、MATCH() リストで名前が指定されたカラムの該当行のテキスト間で類似性が評価されます。

mysql> CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body)) ENGINE=InnoDB;Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO articles (title,body) VALUES('MySQL Tutorial','DBMS stands for DataBase ...'),('How To Use MySQL Well','After you went through a ...'),('Optimizing MySQL','In this tutorial we will show ...'),('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),('MySQL vs. YourSQL','In the following database comparison ...'),('MySQL Security','When configured properly, MySQL ...');Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM articlesWHERE MATCH (title,body)AGAINST ('database' IN NATURAL LANGUAGE MODE);+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

デフォルトでは、大文字と小文字が区別される方法で検索が実行されます。大文字と大文字が区別された全文検索を実行するには、インデックス付きカラムのバイナリ照合順序を使用します。たとえば、全文検索で大文字と小文字が区別されるように、latin1 文字セットが使用されているカラムに latin1_bin の照合順序を割り当てることができます。

以前に例で示したように、MATCH()WHERE 句で使用されると、もっとも関連性の高い行が 1 番目に返されるように、自動的にソートされます。関連性の値は、負ではない浮動小数点数です。ゼロの関連性は、類似性がないという意味です。関連性は、行内の単語の数、該当行内の一意な単語の数、コレクション内の単語の合計数、および特定の単語を含むドキュメント (行) の数に基づいて計算されます。

単に一致をカウントするには、次のようなクエリーを使用してください。

mysql> SELECT COUNT(*) FROM articlesWHERE MATCH (title,body)AGAINST ('database' IN NATURAL LANGUAGE MODE);+----------+
| COUNT(*) |
+----------+
| 2 |
+----------+
1 row in set (0.00 sec)

次のように、クエリーを再作成した方が早い場合もあります。

mysql> SELECTCOUNT(IF(MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))AS countFROM articles;+-------+
| count |
+-------+
| 2 |
+-------+
1 row in set (0.03 sec)

1 つ目のクエリーでは、いくつかの追加作業 (関連性別の結果のソート) が実行されますが、WHERE 句に基づくインデックス検索を使用することもできます。インデックス検索では、検索でほとんど行が一致しない場合に、最初のクエリーが速くなる可能性があります。2 つ目のクエリーではテーブルの完全スキャンが実行され、ほとんどの行に検索語句が存在した場合に、インデックス検索よりも高速になる可能性があります。

自然言語による全文検索では、MATCH() 関数で名前が指定されたカラムは、テーブル内の一部の FULLTEXT インデックスに含まれるカラムと同じである必要があります。上記のクエリーでは、MATCH() 関数で名前が指定されたカラム (titlebody) は、article テーブルの FULLTEXT インデックスの定義で名前が指定されたカラムと同じです。title または body を個別に検索するには、カラムごとに個別の FULLTEXT インデックスを作成します。

ブール検索やクエリー拡張を使用した検索を実行することもできます。これらの検索タイプについては、セクション12.9.2「ブール全文検索」およびセクション12.9.3「クエリー拡張を使用した全文検索」で説明されています。

インデックスを使用した全文検索では、インデックスが複数のテーブルに及ぶ可能性はないため、MATCH() 句の単一テーブルにあるカラムにしか名前を付けることができません。MyISAM テーブルでは、インデックスが存在しない場合でも、ブール検索を実行できます (ただし、低速になります)。この場合、複数のテーブルのカラムに名前を指定できます。

上記の例では、関連性の降順で行が返される MATCH() 関数の使用方法について簡単に説明しました。次の例では、関連性の値を明示的に取得する方法を示します。SELECT ステートメントには WHERE 句も ORDER BY 句も含まれていないため、返される行は順序付けられません。

mysql> SELECT id, MATCH (title,body)AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS scoreFROM articles;+----+---------------------+
| id | score |
+----+---------------------+
| 1 | 0.22764469683170319 |
| 2 | 0 |
| 3 | 0.22764469683170319 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+---------------------+
6 rows in set (0.00 sec)

次の例はさらに複雑です。このクエリーでは関連性の値が返され、関連性の降順での行のソートも行われます。この結果を実現するには、MATCH() を 2 回 (1 回は SELECT リストに、もう 1 回は WHERE 句に) 指定します。MySQL オプティマイザによって、2 回の MATCH() 呼び出しが同じであり、全文検索コードが 1 回のみ起動されることが検出されるため、追加のオーバーヘッドは発生しません。

mysql> SELECT id, body, MATCH (title,body) AGAINST('Security implications of running MySQL as root'IN NATURAL LANGUAGE MODE) AS scoreFROM articles WHERE MATCH (title,body) AGAINST('Security implications of running MySQL as root'IN NATURAL LANGUAGE MODE);+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |
| 6 | When configured properly, MySQL ... | 1.3114095926285 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

MySQL FULLTEXT の実装では、トゥルーワード文字 (文字、数字、およびアンダースコア) のシーケンスが単語とみなされます。そのシーケンスには、アポストロフィー (') も含めることはできますが、1 行に 1 つまでです。つまり、aaa'bbb は 1 語とみなされますが、aaa''bbb は 2 語とみなされます。単語の先頭または末尾のアポストロフィーは、FULLTEXT パーサーによって削除されます。'aaa'bbb' は、aaa'bbb として解析されます。

FULLTEXT パーサーは、特定の区切り文字 ( (空白)、, (カンマ)、. (ピリオド) など) を検索することで、単語の先頭と末尾を特定します。単語が区切り文字で区切られていない場合 (たとえば中国語の場合)、FULLTEXT パーサーでは単語の先頭と末尾を特定できません。このような言語で単語やその他のインデックス付きの語句を FULLTEXT インデックスに追加するには、" などの任意の区切り文字で区切られるように前処理を行う必要があります。

MySQL 5.6 では、組み込みの全文パーサーから置き換えられるプラグインを作成できます (MyISAM でのみサポートされています)。詳細は、セクション24.2「MySQL プラグイン API」を参照してください。パーサープラグインのサンプルソースコードについては、MySQL のソース配布の plugin/fulltext ディレクトリを参照してください。

全文検索では、一部の単語が無視されます。

  • 短すぎる単語は無視されます。全文検索で見つかった単語のデフォルトの最小長は、InnoDB 検索インデックスの場合は 3 文字、MyISAM の場合は 4 文字です。インデックスを作成する前に、構成オプション (InnoDB 検索インデックスの場合は innodb_ft_min_token_size 構成オプション、MyISAM の場合は ft_min_word_len) を設定すると、カットオフを制御できます。

  • ストップワードリスト内の単語は無視されます。ストップワードは、セマンティクス値がゼロであると考えられるほど一般的な単語 (thesome など) です。組み込みのストップワードリストもありますが、ユーザー定義のリストでオーバーライドできます。ストップワードリストおよび関連する構成オプションは、InnoDB 検索インデックスと MyISAM 検索インデックスとで異なります。ストップワードの処理は、InnoDB 検索インデックスの場合は構成オプション innodb_ft_enable_stopwordinnodb_ft_server_stopword_table、および innodb_ft_user_stopword_tableMyISAM 検索インデックスの場合は ft_stopword_file によって制御されます。

デフォルトのストップワードリストおよびそれを変更する方法を表示する方法については、セクション12.9.4「全文ストップワード」を参照してください。単語のデフォルト最小長は、セクション12.9.6「MySQL の全文検索の微調整」で説明したように変更できます。

コレクションおよびクエリー内のすべての正確な単語は、コレクションまたはクエリーでの重要性に従って重み付けられます。したがって、多くのドキュメント内に存在する単語では、この特定のコレクション内のセマンティクス値が低くなるため、重みも低くなります。反対に、まれな単語には、高い重みが付けられます。単語の重みを組み合わせることで、行の関連性が計算されます。この技術は、大きなコレクションで最適に機能します。

MyISAM の制限

非常に小さなテーブルでは、単語の配布が適切にセマンティクス値に反映されないため、このモデルでは、MyISAM テーブル上の検索インデックスに対して異常な結果が生成される可能性があります。たとえば、以前に示した articles テーブルのすべての行には、MySQL という単語が存在しますが、MyISAM 検索インデックス内の単語を検索しても結果が生成されません。

mysql> SELECT * FROM articlesWHERE MATCH (title,body)AGAINST ('MySQL' IN NATURAL LANGUAGE MODE);Empty set (0.00 sec)

MySQL という単語は 50% 以上の行に存在するため、検索の結果が空になります。そのため、事実上ストップワードとして処理されます。このフィルタ処理技術は、よくある語句に対して不適切な結果が生成される可能性のある小さなデータセットよりも、1G バイトのテーブルから 1 行おきに結果セットが返される可能性のない大きなデータセットに適しています。

全文検索がどのように動作するかを確認するために最初に試すと、しきい値が 50% であることに驚くかもしれませんが、これによって InnoDB テーブルが全文検索での実験によりふさわしいことがわかります。MyISAM テーブルを作成し、それに 1、2 行のテキストのみを挿入する場合は、テキスト内のすべての単語が 50% 以上の行に出現します。その結果、テーブルにより多くの行が含まれるまで、検索の結果が返されません。50% の制限を回避する必要のあるユーザーは、InnoDB テーブル上に検索インデックスを構築したり、セクション12.9.2「ブール全文検索」で説明したブール検索モードを使用したりできます。

12.9.2 ブール全文検索

MySQL では、IN BOOLEAN MODE 修飾子を使用することでブール全文検索を実行できます。この修飾子を使用すると、検索文字列の先頭または末尾にある特定の文字が特別な意味を持ちます。次のクエリーでは、+ および - 演算子は、一致が発生するために単語が存在しなければならないことと、単語が存在してはならないことをそれぞれ示します。したがって、このクエリーでは、MySQL という単語は含まれるが、YourSQL という単語は含まれないすべての行が取得されます。

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 Well | 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 では暗黙的ブール論理とも呼ばれる次のようなものが使用されます。

  • +AND を表します

  • -NOT を表します

  • [演算子なし] は暗黙的に OR を表します

ブール全文検索には、次のような特徴があります。

  • 行は自動的に関連性の降順にソートされません。

  • InnoDB テーブルでブールクエリーを実行するには、MATCH() 式のすべてのカラム上に FULLTEXT インデックスが必要です。MyISAM 検索インデックスに対するブールクエリーは、FULLTEXT インデックスなしでも機能します。ただし、この方法で実行される検索の速度は、非常に遅くなります。

  • 単語の最小長および最大長の全文パラメータは、InnoDB 検索インデックスの場合は innodb_ft_min_token_size および innodb_ft_max_token_sizeMyISAM 検索インデックスの場合は ft_min_word_len および ft_max_word_len に適用されます。

  • ストップワードリストが適用されます。これらは、InnoDB 検索インデックスの場合は innodb_ft_enable_stopwordinnodb_ft_server_stopword_table、および innodb_ft_user_stopword_tableMyISAM 検索インデックスの場合は ft_stopword_file によって制御されます。

  • InnoDB の全文検索では、'++apple' の例と同様に、単一の検索単語で複数の演算子を使用するようサポートされていません。MyISAM の全文検索では、同じ検索が正常に処理され、検索単語に隣接する演算子を除くすべての演算子が無視されます。

  • InnoDB の全文検索では、先頭のプラス記号またはマイナス記号のみがサポートされています。たとえば、InnoDB では '+apple' がサポートされますが、'apple+' はサポートされていません。末尾にプラス記号またはマイナス記号を指定すると、InnoDB で構文エラーがレポートされます。

  • InnoDB の全文検索では、ワイルドカード ('+*') を使用した先頭のプラス記号、プラス記号とマイナス記号の組み合わせ ('+-')、または先頭のプラス記号とマイナス記号の組み合わせ ('+-apple') はサポートされていません。このような無効なクエリーでは、構文エラーが返されます。

  • MyISAM 検索インデックスに適用される 50% のしきい値は使用されません。

ブール全文検索機能では、次の演算子がサポートされています。

  • +

    先頭または末尾のプラス記号は、この単語が返される各行に存在しなければならないことを示します。InnoDB では、先頭のプラス記号のみがサポートされています。

  • -

    先頭または末尾のマイナス記号は、この単語が返される行のいずれにも存在してはならないことを示します。InnoDB では、先頭のマイナス記号のみがサポートされています。

    注: - 演算子は、本来ならほかの検索語句で一致が行われる行を除外することのみに使用します。したがって、- の前にある検索語句のみを含むブールモードの検索では、空の結果が返されます。除外された検索語句のいずれかを含む行を除いたすべての行が返されるわけではありません。

  • (演算子なし)

    デフォルトでは (+- のどちらも指定されてない場合)、この単語はオプションですが、それを含む行の評価は高くなります。これは、IN BOOLEAN MODE 修飾子なしの MATCH() ... AGAINST() の動作と似ています。

  • @distance

    この演算子は、InnoDB テーブルでのみ機能します。2 つ以上の単語がすべて、相互に指定された距離内で始まっているかどうかが単語単位でテストされます。@distance 演算子の直前に、二重引用符で囲まれた文字列内の検索単語を指定します (たとえば、MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE))。

  • > <

    これらの 2 つの演算子は、行に割り当てられた関連性の値への単語の貢献度を変更する際に使用されます。> 演算子は貢献度を上げ、< 演算子は貢献度を下げます。次のリストのあとに示す例を参照してください。

  • ( )

    丸括弧は、単語を部分式にグループ化します。丸括弧で囲まれたグループはネストできます。

  • ~

    先頭のチルダは否定演算子として機能するため、行の関連性への単語の貢献度がマイナスになります。これは、ノイズ単語にマークを付ける際に便利です。このような単語を含む行は、その他よりも低く評価されますが、- 演算子を使用した場合のように、完全に除外されることはありません。

  • *

    アスタリスクは、切り捨て (またはワイルドカード) 演算子として機能します。その他の演算子とは異なり、影響を受ける単語に追加されます。* 演算子の前の単語で始まれば、単語が一致します。

    切り捨て演算子を付けて単語が指定されている場合は、その単語が短すぎたり、ストップワードであったりしても、ブールクエリーから削除されません。単語が短すぎるかどうかは、InnoDB テーブルの場合は innodb_ft_min_token_size 設定、MyISAM テーブルの場合は ft_min_word_len によって判断されます。ワイルドカード単語は、1 つ以上の単語の先頭に存在しなければならないプリフィクスとみなされます。単語の最小長が 4 である場合は、'+word +the*' の検索では、2 番目のクエリーで短すぎる検索語句 the が無視されるため、'+word +the' の検索よりも少ない行が返される可能性があります。

  • "

    二重引用符 (") 文字内で囲まれたフレーズは、入力されたそのままのフレーズを含む行にのみ一致します。全文エンジンでは、フレーズが複数の単語に分割され、それらの単語の FULLTEXT インデックス内で検索が実行されます。単語以外の文字は、正確に一致する必要がありません。フレーズ検索では、そのフレーズとまったく同じ単語が同じ順序で一致に含まれることのみが必要です。たとえば、"test phrase""test, phrase" と一致します。

    フレーズにインデックス内にある単語が含まれない場合は、結果が空になります。単語がテキスト内に存在しない場合、ストップワードである場合、またはインデックス付きの単語の最小長よりも短い場合の組み合わせが原因で、単語がインデックス内に存在しない可能性があります。

次の例では、ブール全文演算子を使用する一部の検索文字列を実演します。

  • 'apple banana'

    2 つの単語の 1 つ以上を含む行を検索します。

  • '+apple +juice'

    両方の単語を含む行を検索します。

  • '+apple macintosh'

    単語 apple を含む行を検索しますが、行に macintosh も含まれる場合は行を高く評価されます。

  • '+apple -macintosh'

    単語 apple を含むが、macintosh は含まない行を検索します。

  • '+apple ~macintosh'

    単語 apple を含む行を検索しますが、行に単語 macintosh も含まれる場合は、行に含まれない場合よりも低く評価されます。これは、macintosh が存在すると、行がまったく返されない '+apple -macintosh' の検索よりもソフトです。

  • '+apple +(>turnover <strudel)'

    単語 appleturnover、または applestrudel (順序は不問) を含む行を検索しますが、apple turnoverapple strudel よりも高く評価します。

  • 'apple*'

    appleapplesapplesauceapplet などの単語を含む行を検索します。

  • '"some words"'

    some words とまったく同じフレーズを含む行を検索します (たとえば、some words of wisdom を含む行は検索しますが、some noise words は検索しません)。

    注記

    フレーズを囲む " 文字は、フレーズを区切る演算子文字です。検索文字列自体を囲む引用符ではありません。

InnoDB ブールモード検索の関連性ランキング

InnoDB の全文検索は、Sphinx の全文検索エンジンをモデルにし、使用されるアルゴリズムは、BM25 および TF-IDF のランキングアルゴリズムに基づいています。このような理由のため、InnoDB のブール全文検索の関連性ランキングは、MyISAM の関連性ランキングと異なる場合があります。

InnoDB では、term frequency-inverse document frequency (TF-IDF) 重み付けシステムの偏差を使用して、指定された全文検索クエリーのドキュメントの関連性にランクが付けられます。TF-IDF の重み付けは、ドキュメントで単語が出現する頻度に基づき、コレクション内のすべてのドキュメントで単語が出現する頻度によってオフセットされます。言い換えると、ある単語がドキュメントで出現する頻度が高くなるほど、その単語がドキュメントコレクションで出現する頻度が低くなり、ドキュメントのランクが高くなります。

関連性ランキングの計算方法

単語の出現頻度 (TF) 値は、単語がドキュメントで出現する回数です。単語の逆文書頻度 (IDF) 値は、次の公式を使用して計算されます。ここで、total_records はコレクション内のレコード数、matching_records は検索語句が表示されるレコード数です。

${IDF} = log10( ${total_records} / ${matching_records} ) 

ドキュメントに単語が複数回含まれる場合は、IDF 値が TF 値で乗算されます。

${TF} * ${IDF}

TF および IDF 値を使用する場合は、ドキュメントの関連性ランキングが次の公式を使用して計算されます。

${rank} = ${TF} * ${IDF} * ${IDF}

公式については、次の例で実演されています。

単一単語検索の関連性ランキング

この例では、単一単語検索の関連性ランキングの計算を実演します。

mysql> CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)
mysql> INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','This database tutorial ...'),
("How To Use MySQL",'After you went through a ...'),
('Optimizing Your Database','In this database tutorial ...'),
('MySQL vs. YourSQL','When comparing databases ...'),
('MySQL Security','When configured properly, MySQL ...'),
('Database, Database, Database','database database database'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> SELECT id, title, body, MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE)
AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title | body | score |
+----+------------------------------+-------------------------------------+---------------------+
| 6 | Database, Database, Database | database database database | 1.0886961221694946 |
| 3 | Optimizing Your Database | In this database tutorial ... | 0.36289870738983154 |
| 1 | MySQL Tutorial | This database tutorial ... | 0.18144935369491577 |
| 2 | How To Use MySQL | After you went through a ... | 0 |
| 4 | MySQL vs. YourSQL | When comparing databases ... | 0 |
| 5 | MySQL Security | When configured properly, MySQL ... | 0 |
| 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0 |
| 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec)

合計で 8 つのレコードがあり、そのうち 3 つが database という検索語句に一致します。1 つ目のレコード (id 6) には、検索語句が 6 回含まれ、関連性ランキングは 1.0886961221694946 です。このランキング値は、6 の TF 値 (レコード id 6 には database という検索語句が 6 回出現します)、および次のように計算される 0.42596873216370745 の IDF 値 (ここで、8 はレコードの合計数、3 は検索語句が出現するレコードの数) を使用して計算されます。

${IDF} = log10( 8 / 3 ) = 0.42596873216370745

その後、TF および IDF 値はランキング公式に入力されます。

${rank} = ${TF} * ${IDF} * ${IDF}

MySQL コマンド行クライアントで計算を実行すると、1.088696164686938 のランキング値が返されます。

mysql> SELECT 6*log10(8/3)*log10(8/3);
+-------------------------+
| 6*log10(8/3)*log10(8/3) |
+-------------------------+
| 1.088696164686938 |
+-------------------------+
1 row in set (0.00 sec)
注記

SELECT ... MATCH ... AGAINST ステートメントと MySQL コマンド行クライアントで返されるランキング値 (1.08869612216949461.088696164686938) に、わずかな相違がある場合があります。この相違は、整数と浮動小数点/倍精度間のキャストが (関連する精度および丸めの決定とともに) InnoDB によって内部で実行される方法、およびその他の場所 (MySQL コマンド行クライアントやその他のタイプの計算機など) で実行される方法が原因で発生します。

複数単語検索の関連性ランキング

この例では、以前の例で使用された articles テーブルおよびデータに基づいて、複数単語の全文検索の関連性ランキングの計算を実演します。

複数の単語で検索する場合は、次の公式に示すように、関連性ランキングの値が各単語の関連性ランキングの合計になります。

${rank} = ${TF} * ${IDF} * ${IDF} + ${TF} * ${IDF} * ${IDF}

2 つの語句 ('mysql tutorial') で検索を実行すると、次の結果が返されます。

mysql> SELECT id, title, body, MATCH (title,body) AGAINST ('mysql tutorial' IN BOOLEAN MODE) AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+----------------------+
| id | title | body | score |
+----+------------------------------+-------------------------------------+----------------------+
| 1 | MySQL Tutorial | This database tutorial ... | 0.7405621409416199 |
| 3 | Optimizing Your Database | In this database tutorial ... | 0.3624762296676636 |
| 5 | MySQL Security | When configured properly, MySQL ... | 0.031219376251101494 |
| 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0.031219376251101494 |
| 2 | How To Use MySQL | After you went through a ... | 0.015609688125550747 |
| 4 | MySQL vs. YourSQL | When comparing databases ... | 0.015609688125550747 |
| 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 |
| 6 | Database, Database, Database | database database database | 0 |
+----+------------------------------+-------------------------------------+----------------------+
8 rows in set (0.00 sec)

1 つ目のレコード (id 8) では、'mysql' が 1 回出現し、'tutorial' が 2 回出現します。'mysql' に一致するレコードは 6 つ、'tutorial' に一致するレコードは 2 つあります。MySQL コマンド行クライアントでは、これらの値を複数単語検索のランキング公式に挿入するときに、予期されるランキング値が返されます。

mysql> SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2));
+-------------------------------------------------------+
| (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) |
+-------------------------------------------------------+
| 0.7405621541938003 |
+-------------------------------------------------------+
1 row in set (0.00 sec)
注記

上記の例では、SELECT ... MATCH ... AGAINST ステートメントと MySQL コマンド行クライアントで返されるランキング値に、わずかな相違があることについて説明しました。

12.9.3 クエリー拡張を使用した全文検索

全文検索では、クエリー拡張 (特に、そのバリアントの ブラインドクエリー拡張) がサポートされています。一般に、これは検索フレーズが短すぎるときに役立ちます。つまり、ユーザーは多くの場合暗黙的な知識に依存しますが、全文検索エンジンにはこれが不足していることを意味します。たとえば、ユーザーが database を検索することは、実際は MySQLOracleDB2、および RDBMS がすべて、databases に一致して返されるはずのフレーズであることを意味する場合があります。これが暗黙的な知識です。

ブラインドクエリー拡張 (自動関連性フィードバックとも呼ばれる) は、検索フレーズのあとに WITH QUERY EXPANSION または IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION を追加することで有効になります。これは、検索を 2 回実行することで機能します。2 回目の検索での検索フレーズは、1 回目の検索でのもっとも関連性の高い数個のドキュメントと連結されたオリジナルの検索フレーズです。したがって、これらのドキュメントのいずれかに単語 databases および単語 MySQL が含まれている場合は、単語 database が含まれていなくても、2 回目の検索で単語 MySQL を含むドキュメントが検索されます。次の例では、この相違点を示します。

mysql> SELECT * FROM articlesWHERE MATCH (title,body)AGAINST ('database' IN NATURAL LANGUAGE MODE);+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM articlesWHERE MATCH (title,body)AGAINST ('database' WITH QUERY EXPANSION);+----+-----------------------+------------------------------------------+
| id | title | body |
+----+-----------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 3 | Optimizing MySQL | In this tutorial we will show ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
| 2 | How To Use MySQL Well | After you went through a ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
+----+-----------------------+------------------------------------------+
6 rows in set (0.00 sec)

もう 1 つの例では、ユーザーが Maigret のスペルに自信がないときに、Georges Simenon 著の Maigret に関する書籍を検索しています。クエリー拡張を使用しなければ、Megre and the reluctant witnesses を検索しても Maigret and the Reluctant Witnesses のみが検索されます。クエリー拡張を使用すれば、2 回目の検索で単語 Maigret を含むすべての書籍が検索されます。

注記

ブラインドクエリー拡張には、関連性のないドキュメントが返されるとノイズが大幅に増加する傾向があるため、検索フレーズが短すぎる場合にのみ使用してください。

12.9.4 全文ストップワード

サーバー文字セットおよび照合順序 (character_set_server および collation_server システム変数の値) を使用すると、全文クエリー用のストップワードリストがロードおよび検索されます。全文インデックス作成または検索で使用されるストップワードファイルまたはカラムに、character_set_server または collation_server とは異なる文字セットまたは照合順序が含まれている場合は、ストップワード検索で誤ったヒットまたはミスが発生する可能性があります。

ストップワード検索で大文字と小文字が区別されるかどうかは、サーバー照合順序によって異なります。たとえば、照合順序が latin1_swedish_ci の場合は検索で大文字と小文字が区別されませんが、照合順序が latin1_general_cs または latin1_bin の場合は検索で大文字と小文字が区別されます。

InnoDB 検索インデックスのストップワード

技術的、文学的、およびその他のソースからのドキュメントでは、キーワードとしてまたは重要なフレーズで短い単語が使用されることが多いため、InnoDB ではデフォルトのストップワードリストが比較的短くなります。たとえば、to be or not to be を検索し、これらの単語がすべて無視されるのではなく、適切な結果が取得されることを期待するとします。

デフォルトの InnoDB ストップワードリストを確認するには、INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD テーブルを問い合わせます。

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD;
+-------+
| value |
+-------+
| a |
| about |
| an |
| are |
| as |
| at |
| be |
| by |
| com |
| de |
| en |
| for |
| from |
| how |
| i |
| in |
| is |
| it |
| la |
| of |
| on |
| or |
| that |
| the |
| this |
| to |
| was |
| what |
| when |
| where |
| who |
| will |
| with |
| und |
| the |
| www |
+-------+
36 rows in set (0.00 sec)

すべての InnoDB テーブルで独自のストップワードリストを定義するには、INNODB_FT_DEFAULT_STOPWORD テーブルと同じ構造を持つテーブルを定義し、それにストップワードを移入し、innodb_ft_server_stopword_table オプションの値を db_name/table_name 形式の値に設定してから、全文インデックスを作成します。ストップワードテーブルには、value という名前の単一の VARCHAR カラムが含まれている必要があります。次の例では、InnoDB 用に新しいグローバルストップワードテーブルを作成および構成するよう実演します。

-- Create a new stopword table
mysql> CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;
Query OK, 0 rows affected (0.01 sec)
-- Insert stopwords (for simplicity, a single stopword is used in this example)
mysql> INSERT INTO my_stopwords(value) VALUES ('Ishmael');
Query OK, 1 row affected (0.00 sec)
-- Create the table
mysql> CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200)
) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)
-- Insert data into the table
mysql> INSERT INTO opening_lines(opening_line,author,title) VALUES
('Call me Ishmael.','Herman Melville','Moby-Dick'),
('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
('I am an invisible man.','Ralph Ellison','Invisible Man'),
('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
('It was love at first sight.','Joseph Heller','Catch-22'),
('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
Query OK, 8 rows affected (0.00 sec)
Records: 8 Duplicates: 0 Warnings: 0
-- Set the innodb_ft_server_stopword_table option to the new stopword table
mysql> SET GLOBAL innodb_ft_server_stopword_table = 'test/my_stopwords';
Query OK, 0 rows affected (0.00 sec)
-- Create the full-text index (which rebuilds the table if no FTS_DOC_ID column is defined)
mysql> CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
Query OK, 0 rows affected, 1 warning (1.17 sec)
Records: 0 Duplicates: 0 Warnings: 1

INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE で単語を問い合わせて、指定したストップワード ('Ishmael') が表示されないことを確認します。

注記

デフォルトでは、長さが 3 文字よりも少ない単語または 84 文字よりも多い単語は、InnoDB の全文検索インデックスに表示されません。単語の最大長および最小長の値は、innodb_ft_max_token_size および innodb_ft_min_token_size 変数を使用して構成できます。

mysql> SET GLOBAL innodb_ft_aux_table='test/opening_lines';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT word FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 15;
+-----------+
| word |
+-----------+
| across |
| all |
| burn |
| buy |
| call |
| comes |
| dalloway |
| first |
| flowers |
| happened |
| herself |
| invisible |
| less |
| love |
| man |
+-----------+
15 rows in set (0.00 sec)

ストップワードリストをテーブルごとに作成するには、その他のストップワードテーブルを作成し、innodb_ft_user_stopword_table オプションを使用して使用されるストップワードテーブルを指定してから、全文インデックスを作成します。

MyISAM 検索インデックスのストップワード

MySQL 5.6 では、character_set_serverucs2utf16utf16le、または utf32 の場合、ストップワードファイルが latin1 を使用してロードおよび検索されます。

MyISAM テーブル用のデフォルトのストップワードリストをオーバーライドするには、ft_stopword_file システム変数を設定します。(セクション5.1.4「サーバーシステム変数」を参照してください。)変数の値は、ストップワードリストを含むファイルのパス名、またはストップワードのフィルタ処理が無効になる空の文字列になるようにしてください。サーバーは、別のディレクトリを指定する絶対パス名が指定されないかぎり、データディレクトリ内のファイルを検索します。この変数の値またはストップワードファイルの内容を変更したら、サーバーを再起動し、FULLTEXT インデックスを再構築してください。

ストップワードリストは自由形式で、改行、空白、カンマなどの英数字以外の文字でストップワードが区切られます。例外として、下線文字 (_) と単一アポストロフィー (') は単語の一部として処理されます。ストップワードリストの文字セットは、サーバーのデフォルト文字セットです。セクション10.1.3.1「サーバー文字セットおよび照合順序」を参照してください。

次の表には、MyISAM 検索インデックスのデフォルトのストップワードリストを示します。このリストは、MySQL ソース配布の storage/myisam/ft_static.c ファイルで検索できます。

a'sableaboutaboveaccording
accordinglyacrossactuallyafterafterwards
againagainstain'tallallow
allowsalmostalonealongalready
alsoalthoughalwaysamamong
amongstanandanotherany
anybodyanyhowanyoneanythinganyway
anywaysanywhereapartappearappreciate
appropriatearearen'taroundas
asideaskaskingassociatedat
availableawayawfullybebecame
becausebecomebecomesbecomingbeen
beforebeforehandbehindbeingbelieve
belowbesidebesidesbestbetter
betweenbeyondbothbriefbut
byc'monc'scamecan
can'tcannotcantcausecauses
certaincertainlychangesclearlyco
comcomecomesconcerningconsequently
considerconsideringcontaincontainingcontains
correspondingcouldcouldn'tcoursecurrently
definitelydescribeddespitediddidn't
differentdodoesdoesn'tdoing
don'tdonedowndownwardsduring
eacheduegeighteither
elseelsewhereenoughentirelyespecially
etetceveneverevery
everybodyeveryoneeverythingeverywhereex
exactlyexampleexceptfarfew
fifthfirstfivefollowedfollowing
followsforformerformerlyforth
fourfromfurtherfurthermoreget
getsgettinggivengivesgo
goesgoinggonegotgotten
greetingshadhadn'thappenshardly
hashasn'thavehaven'thaving
hehe'shellohelphence
herherehere'shereafterhereby
hereinhereuponhersherselfhi
himhimselfhishitherhopefully
howhowbeithoweveri'di'll
i'mi'veieifignored
immediateininasmuchincindeed
indicateindicatedindicatesinnerinsofar
insteadintoinwardisisn't
itit'dit'llit'sits
itselfjustkeepkeepskept
knowknownknowslastlately
laterlatterlatterlyleastless
lestletlet'slikeliked
likelylittlelooklookinglooks
ltdmainlymanymaymaybe
memeanmeanwhilemerelymight
moremoreovermostmostlymuch
mustmymyselfnamenamely
ndnearnearlynecessaryneed
needsneitherneverneverthelessnew
nextninenonobodynon
nonenoonenornormallynot
nothingnovelnownowhereobviously
ofoffoftenohok
okayoldononceone
onesonlyontoorother
othersotherwiseoughtourours
ourselvesoutoutsideoveroverall
ownparticularparticularlyperperhaps
placedpleasepluspossiblepresumably
probablyprovidesquequiteqv
ratherrdrereallyreasonably
regardingregardlessregardsrelativelyrespectively
rightsaidsamesawsay
sayingsayssecondsecondlysee
seeingseemseemedseemingseems
seenselfselvessensiblesent
seriousseriouslysevenseveralshall
sheshouldshouldn'tsincesix
sosomesomebodysomehowsomeone
somethingsometimesometimessomewhatsomewhere
soonsorryspecifiedspecifyspecifying
stillsubsuchsupsure
t'staketakentelltends
ththanthankthanksthanx
thatthat'sthatsthetheir
theirsthemthemselvesthenthence
therethere'sthereaftertherebytherefore
thereintheresthereuponthesethey
they'dthey'llthey'rethey'vethink
thirdthisthoroughthoroughlythose
thoughthreethroughthroughoutthru
thustotogethertootook
towardtowardstriedtriestruly
trytryingtwicetwoun
underunfortunatelyunlessunlikelyuntil
untoupuponususe
usedusefulusesusingusually
valuevariousveryviaviz
vswantwantswaswasn't
waywewe'dwe'llwe're
we'vewelcomewellwentwere
weren'twhatwhat'swhateverwhen
whencewheneverwherewhere'swhereafter
whereaswherebywhereinwhereuponwherever
whetherwhichwhilewhitherwho
who'swhoeverwholewhomwhose
whywillwillingwishwith
withinwithoutwon'twonderwould
wouldn'tyesyetyouyou'd
you'llyou'reyou'veyouryours
yourselfyourselveszero  

12.9.5 全文制限

  • 全文検索は、InnoDB および MyISAM テーブルでのみサポートされています。InnoDB テーブルで FULLTEXT インデックスがサポートされるようにするには、MySQL 5.6.4 以上が必要です。

  • パーティション化されたテーブルでは、全文検索がサポートされていません。セクション19.6「パーティショニングの制約と制限」を参照してください。

  • 全文検索は、ほとんどのマルチバイト文字セットで使用できます。例外として、Unicode では、utf8 文字セットは使用できますが、ucs2 文字セットは使用できません。ucs2 カラム上では FULLTEXT インデックスを使用できませんが、このようなインデックスが含まれない ucs2 上で IN BOOLEAN MODE 検索を実行することはできます。

    utf8 に関する備考は utf8mb4 にも適用され、ucs2 に関する備考は utf16utf16le、および utf32 にも適用されます。

  • 中国語や日本語のような表意文字を使用する言語には、単語の区切り文字がありません。したがって、FULLTEXT パーサーでは、このような言語で単語の初めと終わりを特定できません。この意味および問題の一部の回避策については、セクション12.9「全文検索関数」で説明されています。

  • 単一テーブル内で複数の文字セットを使用することはサポートされていますが、FULLTEXT インデックス内のすべてのカラムで同じ文字セットおよび照合順序が使用される必要があります。

  • MATCH() カラムリストは、この MATCH()MyISAM テーブル上の IN BOOLEAN MODE である場合を除いて、テーブルの一部の FULLTEXT インデックス定義に含まれるカラムリストに完全に一致する必要があります。MyISAM テーブルでは、インデックスが付いていないカラムでもブールモード検索を実行できます。ただし、検索が遅くなる可能性があります。

  • AGAINST() への引数は、クエリー評価時に定数である文字列値にする必要があります。たとえば、テーブルカラムは、行ごとに異なる可能性があるため除外されます。

  • FULLTEXT 以外の検索の場合よりも FULLTEXT 検索の場合の方が、インデックスヒントに対する制限が多くなります。セクション13.2.9.3「インデックスヒントの構文」を参照してください。

  • InnoDB では、全文インデックスを含むカラムを必要とするすべての DML 演算子 (INSERTUPDATEDELETE) は、トランザクションのコミット時に処理されます。たとえば、INSERT 演算では、挿入された文字列がトークン化され、個々の単語に分解されます。その後、個々の単語は、トランザクションのコミット時に全文インデックステーブルに追加されます。その結果、全文検索ではコミットされたデータのみが返されます。

12.9.6 MySQL の全文検索の微調整

MySQL の全文検索機能には、ユーザーが調整できるパラメータがほとんどありません。一部の変更でソースコードを変更する必要があるために、MySQL ソース配布を持っている場合は、全文検索の動作をさらに制御できます。セクション2.9「ソースから MySQL をインストールする」を参照してください。

全文検索の有効性は、慎重に調整されます。ほとんど場合、デフォルトの動作を変更すると、実際には有効性が低くなる可能性があります。使用方法を理解していない場合は、MySQL ソースは変更しないでください

このセクションで説明するほとんどの全文変数は、サーバーの起動時に設定する必要があります。変更するには、サーバーの再起動が必要です。サーバーが動作しているときは、変更できません。

一部の変数を変更するには、テーブル内の FULLTEXT インデックスを再構築する必要があります。これを行う手順については、このセクションの後半で説明します。

単語の最小長と最大長の構成

インデックスが付けられる単語の最小長および最大長は、InnoDB 検索インデックスの場合は innodb_ft_min_token_size および innodb_ft_max_token_sizeMyISAM 検索インデックスの場合は ft_min_word_len および ft_max_word_len で定義されます。これらのオプションのいずれかを変更したら、変更を有効にするために FULLTEXT インデックスを再構築してください。たとえば、2 文字の単語を検索可能にするには、オプションファイルに次の行を配置します。

[mysqld]
innodb_ft_min_token_size=2
ft_min_word_len=2

次に、サーバーを再起動し、FULLTEXT インデックスを再構築します。MyISAM テーブルについては、MyISAM の全文インデックスを再構築する際に従う手順で、myisamchk に関する備考に注意してください。

自然言語検索のしきい値の構成

MyISAM 検索インデックスでは、選択された特定の重み付けスキームによって、自然言語検索で 50% のしきい値が決定されます。これを無効にするには、storage/myisam/ftdefs.h で次の行を検索してください。

#define GWS_IN_USE GWS_PROB

この行を次のように変更します。

#define GWS_IN_USE GWS_FREQ

次に、MySQL を再コンパイルします。この場合、インデックスを再構築する必要はありません。

注記

このように変更すると、MATCH() 関数に適切な関連性値を提供する MySQL の能力が大幅に低下します。このような一般的な単語を検索する必要がある場合は、代わりに、50% のしきい値に従わない IN BOOLEAN MODE を使用して検索する方が適切です。

ブール全文検索演算子の変更

MyISAM テーブル上でブール全文検索に使用される演算子を変更するには、ft_boolean_syntax システム変数を設定します。(InnoDB には同等の設定がありません。)この変数はサーバーの実行中に変更できますが、そのためには SUPER 権限を持っている必要があります。この場合は、インデックスを再構築する必要はありません。この変数を設定する方法を制御するルールについては、セクション5.1.4「サーバーシステム変数」を参照してください。

文字セットの変更

次のリストで説明するように、単語文字とみなされる文字セットは複数の方法で変更できます。変更が完了したら、任意の FULLTEXT インデックスを含むテーブルごとにインデックスを再構築します。ハイフン文字 (' - ') を単語文字として処理すると仮定します。次の方法のいずれかを使用します。

  • MySQL ソースを変更します。storage/innobase/handler/ha_innodb.cc (InnoDB の場合) または storage/myisam/ftdefs.h (MyISAM の場合) で、true_word_char() および misc_word_char() マクロを参照してください。それらのマクロのいずれかに '-' を追加し、MySQL を再コンパイルします。

  • 文字セットファイルを変更します。再コンパイルする必要はありません。true_word_char() マクロでは、英数字とその他の文字を区別するために character type テーブルが使用されます。文字セット XML ファイルのいずれかで <ctype><map> 配列の内容を編集すると、'-'英字になるように指定できます。次に、FULLTEXT インデックスに指定された文字セットを使用します。<ctype><map> 配列の書式については、セクション10.3.1「文字定義配列」を参照してください。

  • インデックス付きのカラムで使用される文字セットに新しい照合順序を追加し、その照合順序が使用されるようにカラムを変更します。照合順序の追加に関する一般的な情報については、セクション10.4「文字セットへの照合順序の追加」を参照してください。全文インデックス作成に固有の例については、セクション12.9.7「全文インデックス作成用の照合順序の追加」を参照してください。

InnoDB 全文インデックスの再構築

インデックス作成に影響を与える全文変数 (innodb_ft_min_token_sizeinnodb_ft_max_token_sizeinnodb_ft_server_stopword_tableinnodb_ft_user_stopword_tableinnodb_ft_enable_stopword) を変更する場合は、変更したあとに FULLTEXT インデックスを再構築する必要があります。innodb_ft_min_token_size および innodb_ft_max_token_size 変数は動的に設定できないため、変更するにはサーバーを再起動し、インデックスを再構築する必要があります。

InnoDB テーブルの FULLTEXT インデックスを再構築するには、DROP INDEX および ADD INDEX オプションを付けて ALTER TABLE を使用して、各インデックスを削除してから再作成します。

InnoDB 全文インデックスの最適化

全文インデックス付きのテーブル上で OPTIMIZE TABLE を実行すると、全文インデックスが再構築され、削除済みのドキュメント ID が削除され、同じ単語に対応する複数のエントリが連結されます (可能な場合)。

全文インデックスを最適化するには、innodb_optimize_fulltext_only を有効にして、OPTIMIZE TABLE を実行します。

mysql> set GLOBAL innodb_optimize_fulltext_only=ON;
Query OK, 0 rows affected (0.01 sec)
mysql> OPTIMIZE TABLE opening_lines;
+--------------------+----------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------------+----------+----------+----------+
| test.opening_lines | optimize | status | OK |
+--------------------+----------+----------+----------+
1 row in set (0.01 sec) 

大きなテーブルで全文インデックスの再構築時間が長くなることを回避するには、innodb_ft_num_word_optimize オプションを使用すれば、最適化を段階的に実行できます。innodb_ft_num_word_optimize オプションでは、OPTIMIZE TABLE が実行されるたびに最適化される単語の数が定義されます。デフォルト設定は 2000 です。これは、OPTIMIZE TABLE が実行されるたびに 2000 個の単語が最適化されることを表します。後続の OPTIMIZE TABLE 演算は、先行する OPTIMIZE TABLE 演算が終了した場所から続行されます。

MyISAM 全文インデックスの再構築

インデックス作成に影響を与える全文変数 (ft_min_word_lenft_max_word_len、または ft_stopword_file) を変更する場合や、ストップワードファイル自体を変更する場合は、変更して、サーバーを再起動したあとに、FULLTEXT インデックスを再構築する必要があります。

MyISAM テーブルの FULLTEXT インデックスを再構築するには、QUICK 修復演算を実行すれば十分です。

mysql> REPAIR TABLE tbl_name QUICK;

または、先ほど説明した ALTER TABLE を使用します。これは、修復演算よりも高速になる可能性もあります。

任意の FULLTEXT インデックスを含む各テーブルは、上記のように修復する必要があります。それ以外の場合は、テーブルのクエリーで不正な結果が生成される可能性があり、テーブルを変更すると、サーバーでは、テーブルが破損していて修復が必要であるとみなされます。

myisamchk を使用して、MyISAM テーブルインデックスを変更する演算 (修復や分析など) を実行する場合は、ほかに指定がなければ、単語の最小長、単語の最大長、およびストップワードファイルのデフォルトの全文パラメータ値を使用して、FULLTEXT インデックスが再構築されます。これにより、クエリーに失敗する可能性があります。

この問題は、これらのパラメータがサーバーでのみ認識されていることが原因で発生します。MyISAM インデックスファイルには格納されていません。サーバーで使用される単語の最小長や最大長、またはストップワードファイルの値を変更した場合の問題を回避するには、mysqld で使用される myisamchk と同じ ft_min_word_lenft_max_word_len、および ft_stopword_file 値を指定します。たとえば、単語の最小長を 3 に設定した場合は、次のように myisamchk を使用してテーブルを修復できます。

shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI

myisamchk およびサーバーで全文パラメータに必ず同じ値が使用されるようにするには、オプションファイルの [mysqld][myisamchk] の両方のセクションにそれぞれを配置してください。

[mysqld]
ft_min_word_len=3
[myisamchk]
ft_min_word_len=3

MyISAM テーブルインデックスの変更に myisamchk を使用する方法の代替として、REPAIR TABLEANALYZE TABLEOPTIMIZE TABLE、または ALTER TABLE ステートメントを使用します。これらのステートメントは、適切に使用される全文パラメータ値が認識されているサーバーで実行されます。

12.9.7 全文インデックス作成用の照合順序の追加

このセクションでは、全文検索用に新しい照合順序を追加する方法について説明します。サンプルの照合順序は latin1_swedish_ci と似ていますが、'-' 文字は、単語文字としてインデックスを付けることができるように、句読文字としてではなく英字として処理されます。照合順序の追加に関する一般的な情報については、セクション10.4「文字セットへの照合順序の追加」で説明されています。この情報を参照し、関与するファイルをよく理解することが前提となっています。

全文インデックス作成用に照合順序を追加するには、次の手順を使用します。

  1. 照合順序を Index.xml ファイルに追加します。照合順序 ID は未使用にする必要があるため、その ID がすでにシステムで取得されている場合は、1000 以外の値を選択してください。

    <charset name="latin1">
    ...
    <collation name="latin1_fulltext_ci" id="1000"/>
    </charset>
  2. latin1.xml ファイルで照合順序のソート順序を宣言します。この場合、latin1_swedish_ci から順序をコピーできます。

    <collation name="latin1_fulltext_ci">
    <map>
    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
    20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
    30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
    50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
    60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
    50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
    80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
    90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
    A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
    B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
    41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
    44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
    41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
    44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
    </map>
    </collation>
  3. latin1.xmlctype 配列を変更します。0x2D ('-' 文字のコード) に対応する値を 10 (句読点) から 01 (小文字) に変更します。次の配列では、これは 4 行目の要素で、最後から 3 番目の値です。

    <ctype>
    <map>
    00
    20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
    20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
    48 10 10 10 10 10 10 10 10 10 10 10 10 01 10 10
    84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
    10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
    01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
    10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
    02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
    10 00 10 02 10 10 10 10 10 10 01 10 01 00 01 00
    00 10 10 10 10 10 10 10 10 10 02 10 02 00 02 01
    48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
    10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
    01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
    01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
    02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
    02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
    </map>
    </ctype>
  4. サーバーを再起動します。

  5. 新しい照合順序を使用するには、使用されるカラムの定義に追加します。

    mysql> DROP TABLE IF EXISTS t1;Query OK, 0 rows affected (0.13 sec)
    mysql> CREATE TABLE t1 (a TEXT CHARACTER SET latin1 COLLATE latin1_fulltext_ci,FULLTEXT INDEX(a)) ENGINE=InnoDB;Query OK, 0 rows affected (0.47 sec)
  6. 照合順序をテストして、ハイフンが単語文字としてみなされることを確認します。

    mysql> INSERT INTO t1 VALUEs ('----'),('....'),('abcd');Query OK, 3 rows affected (0.22 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT * FROM t1 WHERE MATCH a AGAINST ('----' IN BOOLEAN MODE);+------+
    | a |
    +------+
    | ---- |
    +------+
    1 row in set (0.00 sec)

12.10 キャスト関数と演算子

表 12.14 キャスト関数

名前説明
BINARY 文字列をバイナリ文字列にキャストします
CAST() 値を特定の型としてキャストします
CONVERT() 値を特定の型としてキャストします

  • BINARY

    BINARY 演算子は、それに続く文字列をバイナリ文字列にキャストします。これは、カラムの比較を文字ごとでなく、バイトごとに強制的に実行させる簡単な方法です。これにより、カラムが BINARY または BLOB として定義されていない場合でも、比較で大文字と小文字が区別されます。また、BINARY では末尾の空白文字が重要になります。

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

    比較時に、BINARY によって演算全体が影響を受けます。これは、同じ結果を持ついずれかのオペランドの前に指定できます。

    BINARY str は、CAST(str AS BINARY) の略です。

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

  • CAST(expr AS type)

    CONVERT() と同様に、CAST() 関数には任意の型の式が指定され、指定された型の結果値が生成されます。詳細は、CONVERT() の説明を参照してください。

  • CONVERT(expr,type), CONVERT(expr USING transcoding_name)

    CONVERT() および CAST() 関数には、任意の型の式が指定され、指定された型の結果値が生成されます。

    結果の type には、次の値のいずれかを指定できます。

    • BINARY[(N)]

    • CHAR[(N)]

    • DATE

    • DATETIME

    • DECIMAL[(M[,D])]

    • SIGNED [INTEGER]

    • TIME

    • UNSIGNED [INTEGER]

    BINARY は、BINARY データ型の文字列を生成します。これによる比較への影響度については、セクション11.4.2「BINARY および VARBINARY 型」を参照してください。オプションの長さ N が指定されている場合に、BINARY(N) を使用すると、キャストで N バイトの引数しか使用されなくなります。値が N バイトよりも短い場合は、N の長さになるまで 0x00 バイトでパディングされます。

    CHAR(N) 句を使用すると、キャストで N 文字の引数しか使用されなくなります。

    CAST() および CONVERT(... USING ...) は標準 SQL の構文です。USING 形式以外の CONVERT() は ODBC の構文です。

    USING とともに CONVERT() を使用すると、さまざまな文字セット間でデータが変換されます。MySQL では、トランスコーディング名は対応する文字セット名と同じです。たとえば、このステートメントは、デフォルトの文字セットの文字列 'abc'utf8 文字セットの対応する文字列に変換します。

    SELECT CONVERT('abc' USING utf8);

バイナリ文字列には文字セットがなく、大文字と小文字の区別の概念もないため、通常は、大文字と小文字が区別されない方法で、BLOB 値またはその他のバイナリ文字列を比較できません。大文字と小文字が区別されない比較を実行するには、CONVERT() 関数を使用して、値を非バイナリ文字列に変換します。結果の比較には、文字列照合順序が使用されます。たとえば、結果の文字セットに大文字と小文字が区別されない照合順序が含まれる場合は、LIKE 演算子でも大文字と小文字が区別されません。

SELECT 'A' LIKE CONVERT(blob_col USING latin1) FROM tbl_name;

別の文字セットを使用するには、上記のステートメントの latin1 にその名前を代入します。変換された文字列用に特定の照合順序を指定するには、セクション10.1.9.2「CONVERT() と CAST()」で説明するように、CONVERT() の呼び出しのあとに COLLATE 句を使用します。たとえば、latin1_german1_ci を使用する場合は次のとおりです。

SELECT 'A' LIKE CONVERT(blob_col USING latin1) COLLATE latin1_german1_ci FROM tbl_name;

CONVERT() は、さまざま文字セットで表される文字列を比較する際に、より一般的に使用できます。

LOWER() (および UPPER()) をバイナリ文字列 (BINARYVARBINARYBLOB) に適用しても、何の効果もありません。大文字/小文字の変換を実行するには、バイナリ文字列を非バイナリ文字列に変換します。

mysql> SET @str = BINARY 'New York';mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));+-------------+-----------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |
+-------------+-----------------------------------+
| New York | new york |
+-------------+-----------------------------------+

キャスト関数は、CREATE TABLE ... 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(str AS BINARY)BINARY str と同じです。CAST(expr AS CHAR) では、式はデフォルトの文字セットを持つ文字列として処理されます。

CONCAT('Date: ',CAST(NOW() AS DATE)) のように、より複雑な式の一部として使用する場合でも、CAST() の結果が変わります。

データを別の書式で抽出するには、CAST() ではなく、代わりに LEFT() または EXTRACT() のような文字列関数を使用してください。セクション12.7「日付および時間関数」を参照してください。

数値のコンテキストで文字列を数値にキャストするには、通常は、文字列値を数字と同様に使用する以外には何もする必要はありません。

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

算術演算で文字列を使用する場合は、式の評価時に浮動小数点数に変換されます。

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

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

MySQL 5.6.4 よりも前では、どのテーブルからも選択されないステートメントの TIMESTAMP 値で明示的に CAST() を使用すると、変換が実行される前に、その値が MySQL 5.6 で文字列として処理されます。これにより、値を数値型にキャストすると、次に示すように値が切り捨てられます。

mysql> SELECT CAST(TIMESTAMP '2014-09-08 18:07:54' AS SIGNED);+-------------------------------------------------+
| CAST(TIMESTAMP '2014-09-08 18:07:54' AS SIGNED) |
+-------------------------------------------------+
| 2014 |
+-------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;+---------+------+----------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: '2014-09-08 18:07:54' |
+---------+------+----------------------------------------------------------+
1 row in set (0.00 sec)

次に示すように、これはテーブルから行を選択するときには適用されません。

mysql> USE test;Database changed
mysql> CREATE TABLE c_test (col TIMESTAMP);Query OK, 0 rows affected (0.07 sec)
mysql> INSERT INTO c_test VALUES ('2014-09-08 18:07:54');Query OK, 1 row affected (0.05 sec)
mysql> SELECT col, CAST(col AS UNSIGNED) AS c_col FROM c_test;+---------------------+----------------+
| col | c_col |
+---------------------+----------------+
| 2014-09-08 18:07:54 | 20140908180754 |
+---------------------+----------------+
1 row in set (0.00 sec)

MySQL 5.6.4 以降では、次に示すように、どの行も選択されていないクエリーでも、選択されている場合と同様に CAST() で TIMESTAMP 値が処理されます。

mysql> SELECT CAST(TIMESTAMP '2014-09-08 18:07:54' AS SIGNED);+-------------------------------------------------+
| CAST(TIMESTAMP '2014-09-08 18:05:07' AS SIGNED) |
+-------------------------------------------------+
| 20140908180754 |
+-------------------------------------------------+
1 row in set (0.00 sec)

数字から文字列への暗黙的な変換については、セクション12.2「式評価での型変換」を参照してください。

MySQL では、符号付きと符号なしの両方の 64 ビット値を使用した演算がサポートされています。数値演算子 (+- など) を使用していて、オペランドのいずれかが符号なし整数である場合は、デフォルトの結果が符号なしになります (セクション12.6.1「算術演算子」を参照してください)。これは、SIGNED または UNSIGNED キャスト演算子を使用して、値をそれぞれ符号付きまたは符号なしの 64 ビット整数にキャストすることでオーバーライドできます。

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

オペランドのいずれかが浮動小数点値である場合は、結果が浮動小数点値になり、上記のルールによる影響を受けません。(このコンテキストでは、DECIMAL カラム値は浮動小数点値とみなされます。)

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

SQL モードは、変換演算の結果に影響を与えます。例:

  • zero 日付文字列を日付に変換する場合、CONVERT()CAST()NULL を返し、NO_ZERO_DATE SQL モードが有効になると警告を発行します。

  • 整数の減算では、NO_UNSIGNED_SUBTRACTION SQL モードが有効になっている場合は、オペランドのいずれかが符号なしでも、結果が符号付きになります。

詳細は、セクション5.1.7「サーバー SQL モード」を参照してください。

12.11 XML 関数

表 12.15 XML 関数

名前説明
ExtractValue() XPath 表記法を使用して、XML 文字列から値を抽出します
UpdateXML() 置換後 XML フラグメントを返します

このセクションでは、MySQL での XML および関連する機能について説明します。

注記

--xml オプションを付けて呼び出すと、mysql および mysqldump クライアントで XML 書式の出力を MySQL から取得できます。セクション4.5.1「mysql — MySQL コマンド行ツール」およびセクション4.5.4「mysqldump — データベースバックアッププログラム」を参照してください。

基本的な XPath 1.0 (XML Path Language、バージョン 1.0) の機能を提供する 2 つの関数が使用可能です。XPath の構文および使用法に関する一部の基本情報については、このセクションの後半で提供しますが、このようなトピックの詳しい説明は、このマニュアルのスコープ外です。最終的な情報については、「XML Path Language (XPath) 1.0 標準」を参照してください。XPath がはじめてのユーザーや基本の復習を希望するユーザーに役立つリソースは、複数の言語で入手できる「Zvon.org XPath Tutorial」です。

注記

これらの関数はまだ開発中です。XML および XPath 機能のこれらの側面やその他の側面については、MySQL 5.6 以降で引き続き改善します。これらについて議論したり、質問したり、MySQL XML ユーザーフォーラムでほかのユーザーからの支援を得たりすることもできます。

これらの関数で使用される XPath の式では、ユーザー変数およびローカルストアドプログラム変数がサポートされています。ユーザー変数は簡単にチェックされます。ストアドプログラムへのローカル変数は厳密にチェックされます (Bug#26518 も参照してください)。

  • ユーザー変数 (簡単なチェック)  構文 $@variable_name を使用する変数 (つまり、ユーザー変数) はチェックされません。変数の型が間違っている場合や、変数に値が事前に割り当てられていない場合でも、サーバーから警告やエラーが発行されません。これは、(たとえば) $@myvariable が使用されても警告が発行されないため ($@myvariable は故意に間違えたものです)、入力ミスについてはユーザーが全責任を負うことも意味します。

    例:

    mysql> SET @xml = '<a><b>X</b><b>Y</b></a>';Query OK, 0 rows affected (0.00 sec)
    mysql> SET @i =1, @j = 2;Query OK, 0 rows affected (0.00 sec)
    mysql> SELECT @i, ExtractValue(@xml, '//b[$@i]');+------+--------------------------------+
    | @i | ExtractValue(@xml, '//b[$@i]') |
    +------+--------------------------------+
    | 1 | X |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT @j, ExtractValue(@xml, '//b[$@j]');+------+--------------------------------+
    | @j | ExtractValue(@xml, '//b[$@j]') |
    +------+--------------------------------+
    | 2 | Y |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT @k, ExtractValue(@xml, '//b[$@k]');+------+--------------------------------+
    | @k | ExtractValue(@xml, '//b[$@k]') |
    +------+--------------------------------+
    | NULL | |
    +------+--------------------------------+
    1 row in set (0.00 sec)
  • ストアドプログラム内の変数 (厳密なチェック)  これらの関数をストアドプログラム内部で呼び出すときに、構文 $variable_name を使用する変数を宣言し、これらの関数で使用できます。このような変数は、定義されているストアドプログラムへのローカル変数であり、型および値について厳密にチェックされます。

    例:

    mysql> DELIMITER |mysql> CREATE PROCEDURE myproc () -> BEGIN -> DECLARE i INT DEFAULT 1; -> DECLARE xml VARCHAR(25) DEFAULT '<a>X</a><a>Y</a><a>Z</a>'; -> -> WHILE i < 4 DO -> SELECT xml, i, ExtractValue(xml, '//a[$i]'); -> SET i = i+1; -> END WHILE; -> END |Query OK, 0 rows affected (0.01 sec)
    mysql> DELIMITER ;mysql> CALL myproc();+--------------------------+---+------------------------------+
    | xml | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 1 | X |
    +--------------------------+---+------------------------------+
    1 row in set (0.00 sec)
    +--------------------------+---+------------------------------+
    | xml | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 2 | Y |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)
    +--------------------------+---+------------------------------+
    | xml | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 3 | Z |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)

    パラメータ  ストアドルーチン内部の XPath 式で使用され、パラメータとして渡される変数も、厳密なチェックの対象です。

ユーザー変数やストアドプログラムへのローカル変数を含む式は、その他の点 (表記法は除く) では、XPath 1.0 仕様で規定されている変数を含む XPath 式のルールに準拠する必要があります。

注記

現時点では、XPath 式の格納に使用されたユーザー変数は、空の文字列として処理されます。このため、ユーザー変数として XPath 式を格納することはできません。(Bug #32911)

  • ExtractValue(xml_frag, xpath_expr)

    ExtractValue() には、XML マークアップ xml_frag のフラグメントと XPath 式 xpath_expr (locator とも呼ばれます) の 2 つの文字列引数が指定され、要素の子または XPath 式で一致された要素である 1 番目のテキストノードのテキスト (CDATA) が返されます。MySQL 5.6.6 以前では、XPath 式に最大でも 127 文字しか含めることができませんでした。この制限は、MySQL 5.6.7 で解除されました。(Bug #13007062、Bug #62429)

    この関数を使用することは、/text() を追加したあとに xpath_expr を使用して一致を実行することと同等です。言い換えると、ExtractValue('<a><b>Sakila</b></a>', '/a/b')ExtractValue('<a><b>Sakila</b></a>', '/a/b/text()') では同じ結果が生成されます。

    複数の一致が見つかった場合は、一致する各要素の 1 番目の子テキストノードの内容が空白文字で区切られた単一文字列として (一致した順序で) 返されます。

    式に一致するテキストノード (暗黙的な /text() を含む) が見つからない場合は、どのような理由でも、xpath_expr が有効で、xml_frag が適切にネストされ、閉じられた要素で構成されていれば、空の文字列が返されます。空の要素で一致することと、まったく一致しないこととは区別されません。これは意図的なものです。

    xml_frag で一致する要素が見つからなかったのか、またはこのような要素は見つかったが、子テキストノードが含まれていなかったのかを判断する必要がある場合は、XPath count() 関数を使用する式の結果をテストしてください。たとえば、次に示すように、これらのステートメントの両方で空の文字列が返されます。

    mysql> SELECT ExtractValue('<a><b/></a>', '/a/b');+-------------------------------------+
    | ExtractValue('<a><b/></a>', '/a/b') |
    +-------------------------------------+
    | |
    +-------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue('<a><c/></a>', '/a/b');+-------------------------------------+
    | ExtractValue('<a><c/></a>', '/a/b') |
    +-------------------------------------+
    | |
    +-------------------------------------+
    1 row in set (0.00 sec)

    ただし、次のコマンドを使用すれば、実際に一致する要素があったかどうかを判断できます。

    mysql> SELECT ExtractValue('<a><b/></a>', 'count(/a/b)');+-------------------------------------+
    | ExtractValue('<a><b/></a>', 'count(/a/b)') |
    +-------------------------------------+
    | 1 |
    +-------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue('<a><c/></a>', 'count(/a/b)');+-------------------------------------+
    | ExtractValue('<a><c/></a>', 'count(/a/b)') |
    +-------------------------------------+
    | 0 |
    +-------------------------------------+
    1 row in set (0.01 sec)
    重要

    ExtractValue() では CDATA のみが返され、一致するタグ内に含まれるタグや、それらの内容は返されません (次の例で、val1 として返された結果を参照してください)。

    mysql> SELECT ->  ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1, ->  ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2, ->  ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3, ->  ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4, ->  ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;+------+------+------+------+---------+
    | val1 | val2 | val3 | val4 | val5 |
    +------+------+------+------+---------+
    | ccc | ddd | ddd | | ddd eee |
    +------+------+------+------+---------+

    この関数では、contains() との比較を実行し、その他の文字列関数 (CONCAT() など) と同じ照合順序アグリゲーションを実行し、それらの引数の照合順序強制性を考慮に入れる際に、現在の SQL 照合順序が使用されます。この動作を制御するルールの説明については、セクション10.1.7.5「式の照合順序」を参照してください。

    (以前は、大文字と小文字が区別されるバイナリが常に使用されていました。)

    次の例に示すように、xml_frag に、適切にネストされていない要素や閉じられていない要素が含まれ、警告が生成された場合は、NULL が返されます。

    mysql> SELECT ExtractValue('<a>c</a><b', '//a');+-----------------------------------+
    | ExtractValue('<a>c</a><b', '//a') |
    +-----------------------------------+
    | NULL |
    +-----------------------------------+
    1 row in set, 1 warning (0.00 sec)
    mysql> SHOW WARNINGS\G*************************** 1. row *************************** Level: Warning Code: 1525
    Message: Incorrect XML value: 'parse error at line 1 pos 11: END-OF-INPUT unexpected ('>' wanted)'
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue('<a>c</a><b/>', '//a');+-------------------------------------+
    | ExtractValue('<a>c</a><b/>', '//a') |
    +-------------------------------------+
    | c |
    +-------------------------------------+
    1 row in set (0.00 sec)
  • UpdateXML(xml_target, xpath_expr, new_xml)

    この関数は、XML マークアップ xml_target の特定のフラグメントの一部を新しい XML フラグメント new_xml に置き換えてから、変更された XML を返します。置換された xml_target の一部は、ユーザーが指定した XPath 式 xpath_expr に一致します。MySQL 5.6.6 以前では、XPath 式に最大でも 127 文字しか含めることができませんでした。この制限は、MySQL 5.6.7 で解除されました。(Bug #13007062、Bug #62429)

    xpath_expr に一致する式が見つからない場合、または複数の一致が見つかった場合、この関数は元の xml_target XML フラグメントを返します。3 つの引数はすべて文字列にする必要があります。

    mysql> SELECT ->  UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1, ->  UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2, ->  UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3, ->  UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4, ->  UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5 -> \G*************************** 1. row ***************************
    val1: <e>fff</e>
    val2: <a><b>ccc</b><d></d></a>
    val3: <a><e>fff</e><d></d></a>
    val4: <a><b>ccc</b><e>fff</e></a>
    val5: <a><d></d><b>ccc</b><d></d></a>
注記

XPath 構文のさらに詳しい説明や使用法については、このマニュアルのスコープ外です。最終的な情報については、「XML Path Language (XPath) 1.0 仕様」を参照してください。XPath がはじめてのユーザーや基本の復習を希望するユーザーに役立つリソースは、複数の言語で入手できる「Zvon.org XPath Tutorial」です。

一部の基本的な XPath 式の説明および例は、次のとおりです。

  • /tag

    <tag/> がルート要素の場合にかぎり、<tag/> に一致します。

    例: /a はいちばん外側の (ルート) タグに一致するため、<a><b/></a> には一致があります。この例では、別の要素の子であるため、<b><a/></b> の内側の a 要素には一致しません。

  • /tag1/tag2

    <tag1/> の子であり、<tag1/> がルート要素である場合にかぎり、<tag2/> に一致します。

    例: /a/b はルート要素 a の子であるため、XML フラグメント <a><b/></a>b 要素に一致します。この場合、b はルート要素 (その他の要素の子) であるため、<b><a/></b> には一致がありません。XPath 式でも <a><c><b/></c></a> に一致がありません。ここで、ba の子孫ですが、実際には a の子ではありません。

    この構成は、3 つ以上の要素に拡張できます。たとえば、XPath 式 /a/b/c は、フラグメント <a><b><c/></b></a> 内の c 要素に一致します。

  • //tag

    <tag> の任意のインスタンスに一致します。

    例: //a は、<a><b><c/></b></a><c><a><b/></a></b><c><b><a/></b></c> のいずれかの a 要素に一致します。

    /// と組み合わせることができます。たとえば、//a/b は、フラグメント <a><b/></a> または <a><b><c/></b></a> 内の b 要素に一致します。

    注記

    //tag/descendant-or-self::*/tag と同等です。よく見られる誤りは、これと /descendant-or-self::tag とを混同することです。次に示すように、実際には後者の式ではまったく異なる結果が生成される可能性があります。

    mysql> SET @xml = '<a><b><c>w</c><b>x</b><d>y</d>z</b></a>';Query OK, 0 rows affected (0.00 sec)
    mysql> SELECT @xml;+-----------------------------------------+
    | @xml |
    +-----------------------------------------+
    | <a><b><c>w</c><b>x</b><d>y</d>z</b></a> |
    +-----------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue(@xml, '//b[1]');+------------------------------+
    | ExtractValue(@xml, '//b[1]') |
    +------------------------------+
    | x z |
    +------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue(@xml, '//b[2]');+------------------------------+
    | ExtractValue(@xml, '//b[2]') |
    +------------------------------+
    | |
    +------------------------------+
    1 row in set (0.01 sec)
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');+---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[1]') |
    +---------------------------------------------------+
    | x z |
    +---------------------------------------------------+
    1 row in set (0.06 sec)
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');+---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[2]') |
    +---------------------------------------------------+
    | |
    +---------------------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');+-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[1]') |
    +-------------------------------------------------+
    | z |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');+-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[2]') |
    +-------------------------------------------------+
    | x |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
  • * 演算子は、任意の要素に一致するワイルドカードとして機能します。たとえば、式 b/* は、それ自体がルート要素でない b 要素の任意の子に一致します。

  • | (UNION) 演算子を使用すれば、複数のロケータのいずれかに一致できます。たとえば、式 //b|//c は、XML ターゲット内のすべての b および c 要素に一致します。

  • その属性の 1 つ以上の値に基づいて、要素に一致することもできます。これは、構文 tag[@attribute="value"] を使用して実行されます。たとえば、式 //b[@id="idB"] は、フラグメント <a><b id="idA"/><c/><b id="idB"/></a> 内の 2 番目の b 要素に一致します。attribute="value" を含む任意の要素に対して一致を行うには、XPath 式 //*[attribute="value"] を使用します。

    複数の属性値をフィルタ処理するには、単に複数の属性比較句を連続して使用するだけです。たとえば、式 //b[@c="x"][@d="y"] は、指定した XML フラグメントの任意の場所で発生した要素 <b c="x" d="y"/> に一致します。

    同じ属性が複数の値のいずれかに一致する要素を見つけるには、| 演算子で結合された複数のロケータを使用します。たとえば、c 属性の値が 23 または 17 であるすべての b 要素に一致するには、式 //b[@c="23"]|//b[@c="17"] を使用します。この目的のために、//b[@c="23" or @c="17"] のように論理 or 演算子を使用することもできます。

    注記

    or| の相違点として、or は条件を結合するのに対し、| は結果セットを結合します。

XPath の制限  現在、これらの関数でサポートされている XPath 構文は、次の制限の対象となっています。

  • ノードセット間の比較 ('/a/b[@c=@d]' など) はサポートされていません。

  • 標準の XPath 比較演算子はすべてサポートされています。(Bug #22823)

  • 相対ロケータ式は、ルートノードのコンテキストで解決されます。たとえば、次のようなクエリーと結果を考えてみます。

    mysql> SELECT ExtractValue( -> '<a><b c="1">X</b><b c="2">Y</b></a>', -> 'a/b' -> ) AS result;+--------+
    | result |
    +--------+
    | X Y |
    +--------+
    1 row in set (0.03 sec)

    この場合は、ロケータ a/b/a/b に解決されています。

    相対ロケータは、述語内でもサポートされています。次の例では、d[../@c="1"]/a/b[@c="1"]/d として解決されています。

    mysql> SELECT ExtractValue( -> '<a> -> <b c="1"><d>X</d></b> -> <b c="2"><d>X</d></b> -> </a>', -> 'a/b/d[../@c="1"]') -> AS result;+--------+
    | result |
    +--------+
    | X |
    +--------+
    1 row in set (0.00 sec)
  • スカラー値 (変数参照、リテラル、数字、およびスカラー関数の呼び出しを含む) として評価する式が前に付けられたロケータは許可されず、使用するとエラーが発生します。

  • :: 演算子を次のようなノード型と組み合わせることは、サポートされていません。

    • axis::comment()

    • axis::text()

    • axis::processing-instructions()

    • axis::node()

    ただし、次の例に示すように、名前のテスト (axis::nameaxis::* など) はサポートされています。

    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b');+-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b') |
    +-------------------------------------------------------+
    | x |
    +-------------------------------------------------------+
    1 row in set (0.02 sec)
    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*');+-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*') |
    +-------------------------------------------------------+
    | x y |
    +-------------------------------------------------------+
    1 row in set (0.01 sec)
  • パスがルート要素を上方向に導いている場合は、上下の移動がサポートされていません。つまり、現在の要素の 1 つ以上の祖先がルート要素の祖先でもある場合は、指定された要素の祖先の子孫で一致する式を使用できません (Bug #16321 を参照してください)。

  • 次の XPath 関数はサポートされていないか、または説明したような既知の問題があります。

    • id()

    • lang()

    • local-name()

    • name()

    • namespace-uri()

    • normalize-space()

    • starts-with()

    • string()

    • substring-after()

    • substring-before()

    • translate()

  • 次の軸はサポートされていません。

    • following-sibling

    • following

    • preceding-sibling

    • preceding

ExtractValue() および UpdateXML() への引数として渡される XPath 式の要素セレクタ内には、コロン文字 (:) が含まれている可能性があります。これにより、XML 名前空間の表記法を使用しているマークアップとの使用が有効になります。例:

mysql> SET @xml = '<a>111<b:c>222<d>333</d><e:f>444</e:f></b:c></a>';Query OK, 0 rows affected (0.00 sec)
mysql> SELECT ExtractValue(@xml, '//e:f');+-----------------------------+
| ExtractValue(@xml, '//e:f') |
+-----------------------------+
| 444 |
+-----------------------------+
1 row in set (0.00 sec)
mysql> SELECT UpdateXML(@xml, '//b:c', '<g:h>555</g:h>');+--------------------------------------------+
| UpdateXML(@xml, '//b:c', '<g:h>555</g:h>') |
+--------------------------------------------+
| <a>111<g:h>555</g:h></a> |
+--------------------------------------------+
1 row in set (0.00 sec)

これは、いくつかの点で Apache Xalan およびその他の一部のパーサーで許可されているものと似ていますが、名前空間の制限や namespace-uri() および local-name() 関数の使用を必要とするよりも大幅に単純です。

エラー処理 ExtractValue()UpdateXML() のどちらの場合でも、使用される XPath ロケータが有効であり、検索対象の XML が適切にネストされ、閉じられた要素で構成されている必要があります。ロケータが無効な場合は、次のようなエラーが生成されます。

mysql> SELECT ExtractValue('<a>c</a><b/>', '/&a');ERROR 1105 (HY000): XPATH syntax error: '&a'

xml_frag が適切にネストされ、閉じられている要素で構成されていない場合は、次の例に示すように、NULL が返され、警告が生成されます。

mysql> SELECT ExtractValue('<a>c</a><b', '//a');+-----------------------------------+
| ExtractValue('<a>c</a><b', '//a') |
+-----------------------------------+
| NULL |
+-----------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS\G*************************** 1. row *************************** Level: Warning Code: 1525
Message: Incorrect XML value: 'parse error at line 1 pos 11: END-OF-INPUT unexpected ('>' wanted)'
1 row in set (0.00 sec)
mysql> SELECT ExtractValue('<a>c</a><b/>', '//a');+-------------------------------------+
| ExtractValue('<a>c</a><b/>', '//a') |
+-------------------------------------+
| c |
+-------------------------------------+
1 row in set (0.00 sec)
重要

UpdateXML() への第 3 引数として使用される置換用の XML は、適切にネストされ、閉じられている要素のみで構成されているかどうかを判断するためにチェックされません

XPath インジェクション コードインジェクションは、権限やデータへの不正アクセス権を取得するために、悪意のあるコードがシステムに導入された場合に発生します。これは、ユーザーが入力したデータの型や内容について開発者が行なった想定の悪用に基づいています。これに関しては、XPath も例外ではありません。

この問題が発生する可能性のある一般的なシナリオは、次のような XPath 式を使用して、ログイン名とパスワードの組み合わせを XML ファイル内で見つかったものと一致させることで承認を処理するアプリケーションのケースです。

//user[login/text()='neapolitan' and password/text()='1c3cr34m']/attribute::id

この XPath 式は、次のような SQL ステートメントと同等です。

SELECT id FROM users WHERE login='neapolitan' AND password='1c3cr34m';

XPath を使用している PHP アプリケーションでは、次のようにログインプロセスが処理される可能性があります。

<?php $file = "users.xml"; $login = $POST["login"]; $password = $POST["password"]; $xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id"; if( file_exists($file) ) { $xml = simplexml_load_file($file); if($result = $xml->xpath($xpath)) echo "You are now logged in as user $result[0]."; else echo "Invalid login name or password."; } else exit("Failed to open $file.");
?>

入力時にはチェックが実行されません。これは、悪意のあるユーザーがログイン名とパスワードの両方に ' or 1=1 と入力することで、テストを回避できることを意味します。その結果、$xpath が次のように評価されます。

//user[login/text()='' or 1=1 and password/text()='' or 1=1]/attribute::id

角括弧内の式は常に true と評価されるため、事実上、XML ドキュメント内のすべての user 要素の id 属性に一致する次の式と同じです。

//user/attribute::id

この攻撃を回避する方法の 1 つは、$xpath の定義内に挿入される変数名を単に引用符で囲むだけです。これにより、Web フォームから渡された値が強制的に文字列に変換されます。

$xpath = "//user[login/text()='$login' and password/text()='$password']/attribute::id";

これは、SQL インジェクション攻撃を回避する際に推奨されることの多い方法と同じです。一般に、XPath インジェクション攻撃を回避するために従うべき方法は、SQL インジェクションを回避するための方法と同じです。

  • アプリケーションでは、テストされていないユーザーデータは許可されません。

  • ユーザーが送信したすべてのデータの型をチェックします。不正な型のデータは拒否または変換します。

  • 数値データに範囲外の値が含まれていないかをテストします。範囲外の値は切り捨てるか、丸めるか、拒否します。文字列に不正な文字が含まれていないかをテストし、不正な文字が含まれる入力は削除するか拒否します。

  • 明示的なエラーメッセージは、システムを危険にさらすために使用できる手がかりを未承認ユーザーに与える可能性があるため、出力しないでください。その代わりに、ファイルやデータベーステーブルにログを記録してください。

SQL インジェクション攻撃を使用すればデータベーススキーマに関する情報を取得できるように、XPath インジェクションを使用すれば、Amit Klein 氏の論文『Blind XPath Injection』(PDF ファイル、46K バイト) で説明されているように、XML ファイルをスキャンして構造を明らかにできます。

クライアントに返送される出力をチェックすることも重要です。MySQL の ExtractValue() 関数を使用すると何が発生する可能性があるのかを検討します。

mysql> SELECT ExtractValue( -> LOAD_FILE('users.xml'), -> '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id' -> ) AS id;+-------------------------------+
| id |
+-------------------------------+
| 00327 13579 02403 42354 28570 |
+-------------------------------+
1 row in set (0.01 sec)

ExtractValue() は複数の一致を空白で区切られた単一の文字列として返すため、このインジェクション攻撃によって、users.xml 内に含まれるすべての有効な ID が単一の出力行としてユーザーに提供されます。追加の保護手段として、ユーザーに返される前に出力のテストも行うべきです。次に、単純な例を示します。

mysql> SELECT @id = ExtractValue( -> LOAD_FILE('users.xml'), -> '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id' -> );Query OK, 0 rows affected (0.00 sec)
mysql> SELECT IF( -> INSTR(@id, ' ') = 0, -> @id, -> 'Unable to retrieve user ID') -> AS singleID;+----------------------------+
| singleID |
+----------------------------+
| Unable to retrieve user ID |
+----------------------------+
1 row in set (0.00 sec)

一般に、ユーザーにデータをセキュアに返すためのガイドラインは、ユーザー入力を受け入れるためのガイドラインと同じです。それらは、次のように要約できます。

  • 常に、出力データの型および許可される値をテストします。

  • 未承認ユーザーがエラーメッセージを表示することを許可しないでください。アプリケーションに関する情報が提供される可能性があり、それを悪用されるおそれがあります。

12.12 ビット関数

表 12.16 ビット単位の関数

名前説明
BIT_COUNT() 設定されているビット数を返します
& ビット単位の AND
~ ビットを反転します
| ビット単位の OR
^ ビット単位の XOR
<< 左シフト
>> 右シフト

MySQL では、演算子の最大範囲が 64 ビットになるように、ビット演算に BIGINT (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 ビット整数です。

  • <<

    longlong (BIGINT) 数値を左にシフトします。

    mysql> SELECT 1 << 2; -> 4

    結果は符合なしの 64 ビット整数です。値は 64 ビットに切り捨てられます。特に、シフト数が符号なし 64 ビット数値の幅以上の大きさの場合は、結果がゼロになります。

  • >>

    longlong (BIGINT) 数値を右にシフトします。

    mysql> SELECT 4 >> 2; -> 1

    結果は符合なしの 64 ビット整数です。値は 64 ビットに切り捨てられます。特に、シフト数が符号なし 64 ビット数値の幅以上の大きさの場合は、結果がゼロになります。

  • ~

    すべてのビットを反転します。

    mysql> SELECT 5 & ~1; -> 4

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

  • BIT_COUNT(N)

    引数 N で設定されているビットの数を返します。

    mysql> SELECT BIT_COUNT(29), BIT_COUNT(b'101010'); -> 4, 3

12.13 暗号化関数と圧縮関数

表 12.17 暗号化関数

名前説明
AES_DECRYPT() AES を使用して復号化します
AES_ENCRYPT() AES を使用して暗号化します
COMPRESS() バイナリ文字列として結果を返します
DECODE() ENCODE() を使用して暗号化された文字列をデコードします
DES_DECRYPT() 文字列を復号化します
DES_ENCRYPT() 文字列を暗号化します
ENCODE() 文字列をエンコードします
ENCRYPT() 文字列を暗号化します
MD5() MD5 チェックサムを計算します
OLD_PASSWORD() (deprecated 5.6.5) 4.1 より前の PASSWORD 実装の値を返します
PASSWORD() パスワード文字列を計算して返します
RANDOM_BYTES() ランダムなバイトベクトルを返します
SHA1(), SHA() SHA-1 160 ビットチェックサムを計算します
SHA2() SHA-2 チェックサムを計算します
UNCOMPRESS() 圧縮された文字列を圧縮解除します
UNCOMPRESSED_LENGTH() 圧縮前の文字列長を返します
VALIDATE_PASSWORD_STRENGTH() パスワードの強度を判断します

多くの暗号化関数および圧縮関数では、結果に任意のバイト値が含まれている可能性のある文字列が返されます。これらの結果を格納する場合は、VARBINARY または BLOB バイナリ文字列データ型のカラムを使用します。これにより、末尾の空白を削除したり、文字セットを変換したりするとデータ値が変更される可能性があるという問題を回避できます。たとえば、非バイナリ文字列のデータ型 (CHARVARCHARTEXT) を使用した場合に、これが発生する可能性があります。

一部の暗号化関数では、ASCII 文字 (MD5()OLD_PASSWORD()PASSWORD()SHA()SHA1()SHA2()) の文字列が返されます。MySQL 5.6 では、戻り値は、character_set_connection および collation_connection システム変数で決定された文字セットおよび照合順序を含む非バイナリ文字列です。

MD5()SHA1() などの関数がバイナリ文字列として 16 進数の文字列を返すバージョンでは、戻り値を大文字に変換したり、大文字と小文字が区別されない方法でそのまま比較したりできません。値を非バイナリ文字列に変換する必要があります。セクション12.10「キャスト関数と演算子」で、バイナリ文字列の変換の説明を参照してください。

アプリケーションで 16 進数の文字列を返す関数 (MD5()SHA1() など) からの値を格納する場合は、UNHEX() を使用して 16 進表現をバイナリに変換し、その結果を BINARY(N) カラムに格納すれば、より効率的な格納および比較を実現できます。16 進数の各ペアには、バイナリ形式での 1 バイトが必要であるため、N の値は、16 進文字列の長さによって異なります。N は、MD5() 値の場合は 16、SHA1() の場合は 20 です。SHA2() の場合、N の範囲は、結果の目的のビット長を指定する引数に応じて 28 から 32 までです。

utf8 文字セット (文字ごとに 4 バイト使用されます) が使用されるカラムに値が格納される場合に、16 進文字列を CHAR カラムに格納する際のサイズのペナルティーは最小で 2 回、最大で 8 回です。また、文字列を格納すると、値が大きくなり、文字セットの照合順序ルールを考慮に入れる必要があるため、比較が遅くなります。

アプリケーションで MD5() 文字列値が CHAR(32) カラムに格納されると仮定します。

CREATE TABLE md5_tbl (md5_val CHAR(32), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(MD5('abcdef'), ...);

16 進文字列をよりコンパクトな形式に変換するには、次のように、代わりに UNHEX() および BINARY(16) が使用されるようにアプリケーションを変更します。

CREATE TABLE md5_tbl (md5_val BINARY(16), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(UNHEX(MD5('abcdef')), ...);

ハッシュ関数が 2 つの異なる入力値に同じ値を生成するという非常にまれなケースに対応できるように、アプリケーションが準備されるはずです。競合を検出可能にする方法の 1 つは、ハッシュカラムを主キーにすることです。

注記

MD5 および SHA-1 アルゴリズムの悪用が知られています。代わりに、このセクションで説明するその他の暗号化関数 (SHA2() など) のいずれか使用することを検討してください。

注意

SSL 接続が使用されていなければ、暗号化関数への引数として指定されたパスワードやその他の機密の値は、プレーンテキストで MySQL サーバーに送信されます。また、このような値は、書き込み先の MySQL ログにも表示されます。このようなタイプの露出を回避するために、アプリケーションはクライアント側で機密の値を暗号化してから、サーバーに送信できます。同じ考慮事項が暗号化鍵にも適用されます。これらの露出を回避するために、アプリケーションはストアドプロシージャーを使用して、サーバー側で値を暗号化および復号化できます。

  • AES_DECRYPT(crypt_str,key_str[,init_vector])

    この関数は、公式の AES (Advanced Encryption Standard) アルゴリズムを使用してデータを復号化します。詳細は、AES_ENCRYPT() の説明を参照してください。

    MySQL 5.6.17 の時点では、オプションの初期化ベクトル引数 init_vector を使用できます。そのバージョンでは、AES_DECRYPT() が使用されるステートメントはステートメントベースのレプリケーションに対して安全ではなく、クエリーキャッシュ内に格納できません。

  • AES_ENCRYPT(str,key_str[,init_vector])

    AES_ENCRYPT() および AES_DECRYPT() では、AES (Advanced Encryption Standard) アルゴリズム (以前は Rijndael と呼ばれていました) を使用したデータの暗号化および復号化が実装されます。AES の標準では、さまざまな鍵の長さが許可されます。デフォルトでは、これらの関数で鍵の長さが 128 ビットの AES が実装されます。MySQL 5.6.17 の時点では、あとで説明するように、使用できる鍵の長さは 196 または 256 ビットです。鍵の長さは、パフォーマンスとセキュリティーの間でのトレードオフです。

    AES_ENCRYPT() は、鍵文字列 key_str を使用して文字列 str を暗号化し、暗号化された出力を含むバイナリ文字列を返します。AES_DECRYPT() は、鍵文字列 key_str を使用して暗号化された文字列 crypt_str を復号化し、元のプレーンテキスト文字列を返します。関数引数のいずれかが NULL の場合は、関数で NULL が返されます。

    str および crypt_str 引数は任意の長さにすることができ、AES などのブロックベースのアルゴリズムによって、必要に応じてブロックの倍数になるように、自動的にパディングが str に追加されます。このパディングは、AES_DECRYPT() 関数によって自動的に削除されます。crypt_str の長さは、次の公式を使用して計算できます。

    16 * (trunc(string_length / 16) + 1)

    鍵の長さが 128 ビットの場合、key_str 引数に鍵を渡すもっともセキュアな方法は、完全にランダムな 128 ビット値を作成し、それをバイナリ値として渡すことです。例:

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

    パスフレーズを使用すると、パスフレーズをハッシュ化することで AES 鍵を生成できます。例:

    INSERT INTO t VALUES (1,AES_ENCRYPT('text', SHA2('My secret passphrase',512)));

    パスワードまたはパスフレーズは直接 crypt_str に渡さず、最初にハッシュ化してください。このドキュメントの以前のバージョンでは、従来のアプローチが提案されていましたが、ここで示す例の方がセキュアであるため、推奨されなくなりました。

    AES_DECRYPT() で無効な日付または不正なパディングが検出された場合は、NULL が返されます。ただし、入力データまたは鍵が無効になっている場合は、AES_DECRYPT()NULL 以外の値 (ごみの可能性もあります) が返される可能性があります。

    MySQL 5.6.17 の時点では、AES_ENCRYPT() および AES_DECRYPT() でブロック暗号化モードの制御が許可され、オプションの init_vector 初期化ベクトル引数が指定されます。

    • block_encryption_mode システム変数は、ブロックベースの暗号化アルゴリズムのモードを制御します。そのデフォルト値は、128 ビットの鍵の長さと ECB モードを使用した暗号化を表す aes-128-ecb です。この変数で許可されている値については、セクション5.1.4「サーバーシステム変数」を参照してください。

    • オプションの init_vector 引数では、必要とするブロック暗号化モードに対応する初期化ベクトルが提供されます。

    オプションの init_vector 引数が必要なモードでは、16 バイト以上の長さにする必要があります (16 を超えるバイトは無視されます)。init_vector が欠落している場合は、エラーが発生します。

    init_vector が必要ないモードでは、これが無視され、指定されている場合は警告が生成されます。

    RANDOM_BYTES(16) を呼び出すと、初期化ベクトルに使用されるバイトのランダム文字列を生成できます。初期化ベクトルが必要な暗号化モードでは、暗号化および復号化でも同じベクトルを使用する必要があります。

    mysql> SET block_encryption_mode = 'aes-256-cbc';mysql> SET @key_str = SHA2('My secret passphrase',512);mysql> SET @init_vector = RANDOM_BYTES(16);mysql> SET @crypt_str = AES_ENCRYPT('text',@key_str,@init_vector);mysql> SELECT AES_DECRYPT(@crypt_str,@key_str,@init_vector);+-----------------------------------------------+
    | AES_DECRYPT(@crypt_str,@key_str,@init_vector) |
    +-----------------------------------------------+
    | text |
    +-----------------------------------------------+

    次の表には、許可されている各ブロック暗号化モード、サポートされている SSL ライブラリ、および初期化ベクトル引数が必須であるかどうかを一覧表示します。

    ブロック暗号化モードモードがサポートされている SSL ライブラリ初期化ベクトルが必要
    ECBOpenSSL、yaSSLいいえ
    CBCOpenSSL、yaSSLはい
    CFB1OpenSSLはい
    CFB8OpenSSLはい
    CFB128OpenSSLはい
    OFBOpenSSLはい

    MySQL 5.6.17 では、AES_ENCRYPT() または AES_DECRYPT() が使用されるステートメントはステートメントベースのレプリケーションに対して安全ではなく、クエリーキャッシュ内に格納できません。

  • COMPRESS(string_to_compress)

    文字列を圧縮し、その結果をバイナリ文字列として返します。この関数を使用するには、MySQL が zlib などの圧縮ライブラリを使用してコンパイルされている必要があります。そうでない場合、戻り値は常に NULL になります。圧縮された文字列は、UNCOMPRESS() を使用して圧縮解除できます。

    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

    圧縮された文字列の内容は、次の方法で格納されます。

    • 空の文字列は、空の文字列として格納されます。

    • 空以外の文字列は、4 バイトの長さの圧縮されていない文字列として格納され (低いバイトが 1 番目)、そのあとに圧縮された文字列が続きます。文字列が空白文字で終わる場合は、結果が CHAR または VARCHAR カラムに格納されていても、末尾の空白文字が削除されるという問題が回避されるように、. 文字が追加されます。(ただし、CHARVARCHAR などの非バイナリ文字列のデータ型を使用して圧縮された文字列を格納すると、文字セットの変換が発生する可能性があるため、いずれにしても推奨されません。代わりに、VARBINARY または BLOB バイナリ文字列のカラムを使用してください。)

  • DECODE(crypt_str,pass_str)

    暗号化された文字列 crypt_str は、パスワードとして pass_str を使用して復号化します。crypt_str は、ENCODE() から返された文字列にするようにしてください。

  • DES_DECRYPT(crypt_str[,key_str])

    DES_ENCRYPT() を使用して暗号化された文字列を復号化します。エラーが発生した場合、この関数は NULL を返します。

    この関数は、MySQL が SSL サポートで構成されている場合のみ機能します。セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。

    key_str 引数が指定されていない場合、DES_DECRYPT() は暗号化された文字列の最初のバイトを調査して、元の文字列を暗号化したときに使用した DES 鍵番号を特定してから、DES 鍵ファイルからメッセージを復号化するための鍵を読み取ります。これが機能するには、ユーザーが SUPER 権限を持っている必要があります。鍵ファイルは、--des-key-file サーバーオプションを使用して指定できます。

    この関数を key_str 引数に渡すと、その文字列がメッセージを復号化するための鍵として使用されます。

    crypt_str 引数が暗号化された文字列として表示されない場合は、MySQL では指定された crypt_str が返されます。

  • DES_ENCRYPT(str[,{key_num|key_str}])

    Triple-DES アルゴリズムを使用して、指定された鍵で文字列を暗号化します。

    この関数は、MySQL が SSL サポートで構成されている場合のみ機能します。セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。

    使用する暗号化鍵は、指定されていれば、DES_ENCRYPT() への 2 番目の引数に基づいて選択されます。引数を付けない場合は、DES 鍵ファイルの最初の鍵が使用されます。key_num 引数を付けると、DES 鍵ファイルの指定された鍵番号 (0 - 9) が使用されます。key_str 引数を付けた場合は、指定された鍵文字列を使用して str が暗号化されます。

    鍵ファイルは、--des-key-file サーバーオプションを使用して指定できます。

    返される文字列は、最初の文字が CHAR(128 | key_num) であるバイナリ文字列です。エラーが発生した場合、DES_ENCRYPT()NULL を返します。

    暗号化された鍵を認識しやすくするために、128 が追加されます。文字列鍵を使用する場合、key_num は 127 です。

    結果の文字列の長さは、次の公式で指定されます。

    new_len = orig_len + (8 - (orig_len % 8)) + 1

    DES 鍵ファイルの各行の書式は、次のとおりです。

    key_numdes_key_str

    key_num 値は、0 から 9 までの範囲内の数字にする必要があります。ファイル内の行は、任意の順序で指定できます。des_key_str は、メッセージを暗号化する際に使用される文字列です。数字と鍵の間には、少なくとも 1 つの空白文字を入れるようにしてください。最初の鍵は、DES_ENCRYPT() への鍵引数を指定しなかった場合に使用されるデフォルトのキーです。

    FLUSH DES_KEY_FILE ステートメントで鍵ファイルから新しいキー値を読み取るように、MySQL に指示できます。これには、RELOAD 権限が必須です。

    デフォルト鍵のセットを持つ利点は、これらの値を復号化する権利をエンドユーザーに付与せずに、暗号化されたカラム値の有無をチェックする方法がアプリケーションに提供されることです。

    mysql> SELECT customer_address FROM customer_table  > WHERE crypted_credit_card = DES_ENCRYPT('credit_card_number');
  • ENCODE(str,pass_str)

    パスワードとして pass_str を使用して、str を暗号化します。結果は、str と同じ長さのバイナリ文字列です。結果を復号化するには、DECODE() を使用します。

    ENCODE() 関数は使用されるべきではなくなっています。まだ ENCODE() を使用する必要がある場合は、リスクを軽減するために、一緒に salt 値を使用する必要があります。例:

    ENCODE('plaintext', CONCAT('my_random_salt','my_secret_password'))

    パスワードを更新するたびに、新しいランダムな salt 値を使用する必要があります。

  • ENCRYPT(str[,salt])

    Unix crypt() システム呼び出しを使用して str を暗号化し、バイナリ文字列を返します。salt 引数は、2 つ以上の文字を含む文字列にする必要があります。それ以外の場合は、結果が NULL になります。salt 引数が指定されていない場合は、ランダムな値が使用されます。

    mysql> SELECT ENCRYPT('hello'); -> 'VxuFAJXVARROc'

    少なくとも一部のシステムでは、ENCRYPT()str の最初の 8 文字以外のすべてを無視します。この動作は、ベースとなる crypt() システム呼び出しの実装によって決まります。

    システム呼び出しではゼロバイトで終了する文字列が要求されるため、ucs2utf16utf16le、または utf32 マルチバイト文字セットを含む ENCRYPT() の使用は推奨されません。

    システムで crypt() を使用できない場合 (Windows の場合など)、ENCRYPT() は常に NULL を返します。

  • MD5(str)

    文字列の MD5 128 ビットチェックサムを計算します。この値は、32 桁の 16 進数の文字列として返されます。引数が NULL だった場合は、NULL になります。たとえば、戻り値をハッシュ鍵として使用できます。効率的なハッシュ値の格納については、このセクションの冒頭で示した注記を参照してください。

    戻り値は、接続文字セット内の非バイナリ文字列です。

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

    これは、RSA Data Security, Inc. MD5 Message-Digest Algorithm です。

    このセクションの冒頭で示した MD5 アルゴリズムに関する注記を参照してください。

  • OLD_PASSWORD(str)

    OLD_PASSWORD() は、セキュリティーを改善するために、MySQL 4.1 で PASSWORD() の実装が変更されたときに追加されました。OLD_PASSWORD() は、PASSWORD() の 4.1 よりも前の実装の値を文字列として返します。これは、バージョン 5.6 の MySQL サーバーに接続する必要のある 4.1 よりも前のクライアントをロックアウトせずに、それらのクライアントのパスワードをリセットするよう許可するためです。セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。

    戻り値は、接続文字セット内の非バイナリ文字列です。

    注記

    4.1 より前のハッシュ方式を使用するパスワードはネイティブのパスワードハッシュ方式を使用するパスワードよりもセキュアでないため、使用しないようにしてください。4.1 よりも前のパスワードは非推奨であり、これらのサポートは今後の MySQL リリースで削除される予定です。最終的に、OLD_PASSWORD() も非推奨になりました。

  • PASSWORD(str)

    平文のパスワード str から計算してハッシュ化されたパスワード文字列を返します。戻り値は、接続文字セット内の非バイナリ文字列です。引数が NULL の場合は、NULL になります。この関数は、mysql.user 付与テーブルに格納する MySQL パスワードを暗号化する際に、サーバーで使用されるアルゴリズムへの SQL インタフェースです。

    old_passwords システム変数は、PASSWORD() 関数で使用されるパスワードのハッシュ化方法を制御します。これは、IDENTIFIED BY 句を使用してパスワードを指定する CREATE USER および GRANT ステートメントによって実行されるパスワードハッシュにも影響します。

    次の表は、old_passwords の許可される値、それぞれの値に対するパスワードハッシュ方式、およびそれぞれの方式でハッシュされたパスワードを使用する認証プラグインを示します。これらの値は MySQL 5.6.6 以降で許可されます。5.6.6 より前では、許可される値は 0 (または OFF) および 1 (または ON) です。

    パスワードハッシュ方式関連付けられた認証プラグイン
    0MySQL 4.1 ネイティブハッシュmysql_native_password
    14.1 以前の (古い) ハッシュmysql_old_password
    2SHA-256 ハッシュsha256_password

    old_passwords=1 の場合、PASSWORD(str)OLD_PASSWORD(str) と同じ値を返します。後者の関数は old_passwords の値によって影響を受けません。

    mysql> SET old_passwords = 0;mysql> SELECT PASSWORD('mypass'), OLD_PASSWORD('mypass');+-------------------------------------------+------------------------+
    | PASSWORD('mypass') | OLD_PASSWORD('mypass') |
    +-------------------------------------------+------------------------+
    | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 | 6f8c114b58f2ce9e |
    +-------------------------------------------+------------------------+
    mysql> SET old_passwords = 1;mysql> SELECT PASSWORD('mypass'), OLD_PASSWORD('mypass');+--------------------+------------------------+
    | PASSWORD('mypass') | OLD_PASSWORD('mypass') |
    +--------------------+------------------------+
    | 6f8c114b58f2ce9e | 6f8c114b58f2ce9e |
    +--------------------+------------------------+

    SHA-256 パスワードのハッシュ化 (old_passwords=2) では、PASSWORD() からの結果を非決定的にするランダムな salt 値が使用されます。その結果、この関数が使用されるステートメントはステートメントベースのレプリケーションで安全ではなく、クエリーキャッシュ内に格納できません。

    PASSWORD() で実行される暗号化は一方向です (可逆ではありません)。暗号化のタイプは、Unix パスワードに使用されるものと同じではありません。そのタイプを使用するには、ENCRYPT() を使用します。

    注記

    PASSWORD() 関数は、MySQL サーバーの認証システムで使用されます。独自のアプリケーションでは、使用しないようにしてください。そのためには、代わりに MD5() または SHA2() を使用してください。アプリケーションでのセキュアなパスワードの処理および認証セキュリティーについての詳細は、RFC 2195 のセクション 2 (「Challenge-Response Authentication Mechanism (CRAM)」)も参照してください。

    注記

    4.1 より前のハッシュ方式を使用するパスワードはネイティブのパスワードハッシュ方式を使用するパスワードよりもセキュアでないため、使用しないようにしてください。4.1 よりも前のパスワードは非推奨であり、これらのサポートは今後の MySQL リリースで削除される予定です。その結果、PASSWORD() で 4.1 以前のパスワードハッシュを生成する old_passwords=1 も非推奨となります。アカウントのアップグレード手順については、セクション6.3.8.3「4.1 よりも前のパスワードハッシュ方式と mysql_old_password プラグインからの移行」を参照してください。

    注意

    状況によっては、サーバーログまたはクライアント側の ~/.mysql_history などの履歴ファイルに、PASSWORD() を呼び出すステートメントが記録される可能性があります。これは、その情報への読み取りアクセス権を持っているユーザーならだれでも、平文のパスワードを読み取る可能性があることを意味します。これがサーバーログで発生する条件およびこれを制御する方法については、セクション6.1.2.3「パスワードおよびロギング」を参照してください。クライアント側のロギングに関する同様の情報については、セクション4.5.1.3「mysql のロギング」を参照してください。

  • RANDOM_BYTES(len)

    この関数は、SSL ライブラリ (OpenSSL または yaSSL) の乱数ジェネレータを使用して生成されたランダムな len バイトのバイナリ文字列を返します。len で許可されている値は、1 から 1024 までの範囲内です。値がこの範囲外の場合、RANDOM_BYTES() は警告を生成し、NULL を返します。

    RANDOM_BYTES() を使用すると、AES_DECRYPT() および AES_ENCRYPT() 関数に初期化ベクトルを提供できます。このコンテキストで使用するには、len を 16 以上にする必要があります。さらに大きい値も許可されますが、16 を超えるバイトは無視されます。

    RANDOM_BYTES() は、その結果を非決定的にするランダムな値を生成します。その結果、この関数が使用されるステートメントはステートメントベースのレプリケーションに対して安全ではなく、クエリーキャッシュ内に格納できません。

    この関数は、MySQL 5.6.17 の時点で使用可能です。

  • SHA1(str)SHA(str)

    RFC 3174 (Secure Hash Algorithm) で説明されているように、文字列の SHA-1 160 ビットチェックサムを計算します。この値は、40 桁の 16 進数の文字列として返されます。引数が NULL だった場合は、NULL になります。この関数を使用する一例として、ハッシュ鍵が考えられます。効率的なハッシュ値の格納については、このセクションの冒頭で示した注記を参照してください。SHA1() は、パスワードを格納する暗号化関数としても使用できます。SHA()SHA1() のシノニムです。

    戻り値は、接続文字セット内の非バイナリ文字列です。

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

    SHA1()MD5() と同等ですが、暗号化に関してはよりセキュアであると考えられます。ただし、このセクションの冒頭で示した MD5 と SHA-1 アルゴリズムに関する注記を参照してください。

  • SHA2(str, hash_length)

    SHA-2 ファミリのハッシュ関数 (SHA-224、SHA-256、SHA-384、および SHA-512) を計算します。1 番目の引数は、ハッシュ化される平文の文字列です。2 番目の引数には、結果の目的のビット長が指定されます。値は、224、256、384、512、または 0 (256 と同等です) にする必要があります。引数のいずれかが NULL の場合や、ハッシュの長さが許可される値のいずれでもない場合は、戻り値が NULL になります。それ以外の場合は、関数の結果が目的のビット数が含まれるハッシュ値になります。効率的なハッシュ値の格納については、このセクションの冒頭で示した注記を参照してください。

    戻り値は、接続文字セット内の非バイナリ文字列です。

    mysql> SELECT SHA2('abc', 224); -> '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'

    この関数は、MySQL が SSL サポートで構成されている場合のみ機能します。セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。

    SHA2()MD5()SHA1() よりも、暗号化に関してはよりセキュアであると考えられます。

  • UNCOMPRESS(string_to_uncompress)

    COMPRESS() 関数で圧縮された文字列を圧縮解除します。引数が圧縮された値でない場合は、結果が NULL になります。この関数を使用するには、MySQL が zlib などの圧縮ライブラリを使用してコンパイルされている必要があります。そうでない場合、戻り値は常に NULL になります。

    mysql> SELECT UNCOMPRESS(COMPRESS('any string')); -> 'any string'
    mysql> SELECT UNCOMPRESS('any string'); -> NULL
  • UNCOMPRESSED_LENGTH(compressed_string)

    圧縮された文字列が圧縮される前の長さを返します。

    mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30))); -> 30
  • VALIDATE_PASSWORD_STRENGTH(str)

    平文のパスワードを表す引数が指定された場合、この関数はパスワードの強度を示す整数を返します。戻り値は、0 (弱) から 100 (強) までの範囲内です。

    パスワードは、一段と厳密になったテストの対象であり、戻り値は、次の表に示すように、どのテストに合格したのかを示します。

    パスワードテスト戻り値
    長さ < 40
    長さ ≥ 4 および < validate_password_length25
    ポリシー 1 を満たす (LOW)50
    ポリシー 2 を満たす (MEDIUM)75
    ポリシー 3 を満たす (STRONG)100

    VALIDATE_PASSWORD_STRENGTH() によるパスワードの評価は、validate_password プラグインで実行されます。このプラグインがインストールされていない場合、関数は常に 0 を返します。validate_password プラグインのインストールについては、セクション6.1.2.6「パスワード検証プラグイン」を参照してください。パスワードのテストに影響を与えるパラメータを確認または構成するには、validate_password プラグインで実装されているシステム変数をチェックまたは設定します。セクション6.1.2.6.2「パスワード検証プラグインのオプションおよび変数」を参照してください。

    この関数は、MySQL 5.6.6 で追加されました。

12.14 情報関数

表 12.18 情報関数

名前説明
BENCHMARK() 式を繰り返し実行します
CHARSET() 引数の文字セットを返します
COERCIBILITY() 文字列引数の照合順序強制性値を返します
COLLATION() 文字列引数の照合順序を返します
CONNECTION_ID() 接続のための接続 ID (スレッド ID) を返します
CURRENT_USER(), CURRENT_USER 認証済みユーザー名とホスト名
DATABASE() デフォルト (現在) のデータベース名を返します
FOUND_ROWS() LIMIT 句付き SELECT で、LIMIT 句がない場合に戻される可能性がある行の数です
LAST_INSERT_ID() 前回の INSERT での AUTOINCREMENT カラムの値です
ROW_COUNT() 更新された行数
SCHEMA() DATABASE() のシノニムです
SESSION_USER() USER() のシノニムです
SYSTEM_USER() USER() のシノニムです
USER() ユーザー名と、クライアントによって提供されるホスト名です
VERSION() MySQL サーバーのバージョンを示す文字列を返します

  • BENCHMARK(count,expr)

    BENCHMARK() 関数は、式 exprcount の回数だけ繰り返し実行します。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() を複数回実行し、サーバーマシン上の負荷量について結果を解釈することをお勧めします。

    BENCHMARK() の目的は、スカラー式の実行時パフォーマンスを測定することです。これにより、その使用方法や結果の解釈方法について、重要ないくつかの推測が提供されます。

    • スカラー式しか使用できません。式をサブクエリーにすることはできますが、単一のカラムおよび最大でも単一の行が返される必要があります。たとえば、テーブル t に複数のカラムや複数の行が含まれていると、BENCHMARK(10, (SELECT * FROM t)) は失敗します。

    • SELECT expr ステートメントを N 回実行する場合と、SELECT BENCHMARK(N, expr) を実行する場合とでは、発生するオーバーヘッドの量が異なります。この 2 つは非常に異なる実行プロファイルを持つため、両者の所要時間は同一になりません。前者では、パーサー、オプティマイザ、テーブルロック、および実行時評価がそれぞれ N 回ずつ発生します。後者では、実行時評価のみが N 回発生し、その他のすべてのコンポーネントは 1 回だけ発生します。割り当て済みのメモリー構造体は再使用され、集約関数で評価済みの結果をローカルキャッシュに入れるなどの実行時最適化によって、結果が変わる可能性もあります。したがって、BENCHMARK() を使用して、実行時コンポーネントに高い重みを付加し、ネットワーク、パーサー、オプティマイザなどで導入されたノイズを削除することで、そのコンポーネントのパフォーマンスが測定されます。

  • CHARSET(str)

    文字列引数の文字セットを返します。

    mysql> SELECT CHARSET('abc'); -> 'latin1'
    mysql> SELECT CHARSET(CONVERT('abc' USING utf8)); -> 'utf8'
    mysql> SELECT CHARSET(USER()); -> 'utf8'
  • COERCIBILITY(str)

    文字列引数の照合順序強制性値を返します。

    mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci); -> 0
    mysql> SELECT COERCIBILITY(USER()); -> 3
    mysql> SELECT COERCIBILITY('abc'); -> 4

    戻り値の意味は、次の表に示すとおりです。値が低いほど、優先順位は高くなります。

    型変換属性意味
    0明示的な照合順序COLLATE 句の値
    1照合順序なしさまざまな照合順序との文字列の連結
    2暗黙的な照合順序カラム値、ストアドルーチンパラメータ、またはローカル変数
    3系統定数USER() の戻り値
    4型変換可能リテラル文字列
    5無視可能NULL または NULL から派生した式
  • COLLATION(str)

    文字列引数の照合順序を返します。

    mysql> SELECT COLLATION('abc'); -> 'latin1_swedish_ci'
    mysql> SELECT COLLATION(_utf8'abc'); -> 'utf8_general_ci'
  • CONNECTION_ID()

    接続用の接続 ID (スレッド ID) を返します。すべての接続は、現在接続されているクライアントのセット間で一意の ID を持っています。

    CONNECTION_ID() で返される値の型は、INFORMATION_SCHEMA.PROCESSLIST テーブルの ID カラム、SHOW PROCESSLIST 出力の Id カラム、およびパフォーマンススキーマ threads テーブルの PROCESSLIST_ID カラムに表示される値と同じです。

    mysql> SELECT CONNECTION_ID(); -> 23786
  • CURRENT_USER, CURRENT_USER()

    現在のクライアントを認証する際にサーバーで使用された MySQL アカウントを表すユーザー名とホスト名の組み合わせを返します。このアカウントで、アクセス権限が決まります。戻り値は、utf8 文字セット内の文字列です。

    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() 値の空のユーザー名部分に表示されます) を使用してクライアントを認証したことを示しています。これが発生する原因として、davida の付与テーブルにアカウントが一覧表示されていないことが考えられます。

    ストアドプログラムまたはビューでは、SQL SECURITY INVOKER 特性で定義されていなければ、CURRENT_USER() はオブジェクトを定義したユーザー (その DEFINER 値で指定されます) のアカウントを返します。後者の場合、CURRENT_USER() はオブジェクトを呼び出したユーザーを返します。

    トリガーおよびイベントには、SQL SECURITY 特性を定義するためのオプションがありません。したがって、このようなオブジェクトの場合、CURRENT_USER() はオブジェクトを定義したユーザーのアカウントを返します。呼び出したユーザーを返すには、USER() または SESSION_USER() を使用します。

    次のステートメントでは、影響を受けるユーザーや定義したユーザーの名前 (ホストの可能性もあります) の代わりに、CURRENT_USER() 関数を使用することがサポートされています。このような場合、必要に応じて CURRENT_USER() が拡張されます。

    • DROP USER

    • RENAME USER

    • GRANT

    • REVOKE

    • CREATE FUNCTION

    • CREATE PROCEDURE

    • CREATE TRIGGER

    • CREATE EVENT

    • CREATE VIEW

    • ALTER EVENT

    • ALTER VIEW

    • SET PASSWORD

    このような CURRENT_USER() の拡張がさまざまな MySQL 5.6 リリースのレプリケーションで持つ意味については、セクション17.4.1.7「CURRENT_USER() のレプリケーション」を参照してください。

  • DATABASE()

    デフォルト (現在) のデータベース名を utf8 文字セット内の文字列として返します。デフォルトのデータベースがない場合は、DATABASE()NULL を返します。ストアドルーチン内では、デフォルトのデータベースはルーチンが関連付けられたデータベースですが、これは呼び出し元のコンテキストでのデフォルトのデータベースと同じであるとはかぎりません。

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

    デフォルトのデータベースがない場合は、DATABASE()NULL を返します。

  • 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 は、1 番目の SELECTLIMIT 句なしで記述した場合に返される行数を示す数字を返します。

    最近成功した SELECT ステートメントに SQL_CALC_FOUND_ROWS オプションを付けなければ、FOUND_ROWS() は、そのステートメントで返された結果セットの行数を返します。ステートメントに LIMIT 句が含まれている場合、FOUND_ROWS() はその制限値以下の行数を返します。たとえば、ステートメントに LIMIT 10 または LIMIT 50, 10 が含まれている場合、FOUND_ROWS() はそれぞれ 10 と 60 を返します。

    FOUND_ROWS() から取得できる行数は一時的なもので、SELECT SQL_CALC_FOUND_ROWS ステートメントのあとに、このステートメントを発行しても取得できるようには設計されていません。あとで値を参照する必要がある場合は、保存してください。

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM ... ;mysql> SET @rows = FOUND_ROWS();

    SELECT SQL_CALC_FOUND_ROWS を使用している場合は、MySQL では完全な結果セット内の行数を計算する必要があります。ただし、結果セットはクライアントに送信される必要がないため、LIMIT なしでクエリーを再度実行するよりも速くなります。

    SQL_CALC_FOUND_ROWS および FOUND_ROWS() は、クエリーで返される行数を制限するが、クエリーを再度実行しないで完全な結果セット内の行数を確認する必要がある状況でも役立ちます。例として、検索結果のほかのセクションを表示するページへのリンクを含むページが表示される Web スクリプトがあります。FOUND_ROWS() を使用すると、残りの結果を表示するために必要なその他のページ数を確認できます。

    SQL_CALC_FOUND_ROWS および FOUND_ROWS() を使用すると、UNION の複数箇所で LIMIT が発生する可能性があるため、単純な SELECT ステートメントよりも、UNION ステートメントで使用した方が複雑になります。これは、UNION 内の個々の SELECT ステートメントに適用される場合と、UNION の結果全体にグローバルに適用される場合があります。

    UNIONSQL_CALC_FOUND_ROWS を使用する目的は、グローバルな LIMIT なしで返される行数を返すことです。UNIONSQL_CALC_FOUND_ROWS を使用する条件は、次のとおりです。

    • UNION の 1 番目の SELECT に、SQL_CALC_FOUND_ROWS キーワードが表示される必要があります。

    • FOUND_ROWS() の値は、UNION ALL が使用されている場合にのみ正確です。ALL なしで UNION が使用される場合は、重複の削除が発生し、FOUND_ROWS() の値が単なる近似値になります。

    • UNIONLIMIT が表示されない場合は、SQL_CALC_FOUND_ROWS が無視され、UNION を処理するために作成された一時テーブル内の行数が返されます。

    ここで説明した以外のケースでは、FOUND_ROWS() の動作 (エラーが発生して SELECT ステートメントに失敗したあとの値など) が定義されません。

    重要

    ステートメントベースのレプリケーションでは、確実に FOUND_ROWS() をレプリケートすることはできません。行ベースのレプリケーションを使用すると、この関数は自動的にレプリケートされます。

  • LAST_INSERT_ID()LAST_INSERT_ID(expr)

    LAST_INSERT_ID() に引数を付けない場合は、最近実行された INSERT ステートメントの結果として、最初に自動的に生成され、正常に AUTO_INCREMENT カラムに挿入された値を表す 64 ビット値が返されます。この値の型は、MySQL 5.6.9 の時点では BIGINT UNSIGNED、それよりも前では BIGINT (符号付き) です。正常に挿入された行がない場合は、LAST_INSERT_ID() の値は未変更のままです。

    LAST_INSERT_ID() に引数を付けない場合は、MySQL 5.6.9 の時点では符号なし整数、それよりも前では符号付き整数が返されます。

    たとえば、AUTO_INCREMENT 値を生成する行を挿入したあとは、次のようにして値を取得できます。

    mysql> SELECT LAST_INSERT_ID(); -> 195

    現在実行中のステートメントによって、LAST_INSERT_ID() の値は影響を受けません。1 つのステートメントで AUTO_INCREMENT 値を生成してから、独自の AUTO_INCREMENT カラムを含むテーブルに行を挿入する複数行の INSERT ステートメントで LAST_INSERT_ID() を参照すると仮定します。LAST_INSERT_ID() の値は、2 番目のステートメントでも未変更のままです。2 番目以降の行でも、その値は以前に行われた行の挿入による影響を受けません。(ただし、LAST_INSERT_ID()LAST_INSERT_ID(expr) への参照を混在させると、効果は定義されません。)

    以前のステートメントでエラーが返された場合は、LAST_INSERT_ID() の値が定義されません。トランザクションテーブルでは、エラーによってステートメントがロールバックされる場合、LAST_INSERT_ID() の値は未定義のままです。手動の ROLLBACK では、LAST_INSERT_ID() の値はトランザクション前の値にリストアされず、ROLLBACK 時点と同じままです。

    MySQL 5.6.15 よりも前では、レプリケーションのフィルタ処理ルールが使用されている場合に、この関数が正常にレプリケートされませんでした。(Bug #17234370、Bug #69861)

    ストアドルーチン (プロシージャーや関数) またはトリガーの本文内では、LAST_INSERT_ID() の値は、このような種類のオブジェクトの本文外で実行されたステートメントと同様に変更されます。あとに続くステートメントで参照される LAST_INSERT_ID() の値でのストアドルーチンまたはトリガーの効果は、ルーチンの種類によって異なります。

    • ストアドプロシージャーで LAST_INSERT_ID() の値を変更するステートメントが実行される場合は、プロシージャー呼び出しが続くステートメントで変更された値が参照されます。

    • 値を変更するストアドファンクションおよびトリガーでは、値は関数やトリガーが終了したときにリストアされ、あとに続くステートメントでは変更された値が参照されません。

    生成された ID は、接続ごとにサーバー内に保持されます。つまり、関数によって指定されたクライアントに返された値は、そのクライアントによってAUTO_INCREMENT カラムに影響を与える最近のステートメント用に最初に生成された AUTO_INCREMENT 値です。この値は、ほかのクライアントが独自の AUTO_INCREMENT 値を生成した場合でも影響を受ける可能性はありません。この動作によって、各クライアントはほかのクライアントのアクティビティーを気にすることなく、ロックやトランザクションを実行しないで独自の ID を取得できます。

    行の AUTO_INCREMENT カラムを非マジック値 (つまり、NULL でも 0 でもない値) に設定する場合は、LAST_INSERT_ID() の値が変更されません。

    重要

    単一の INSERT ステートメントを使用して複数の行を挿入する場合、LAST_INSERT_ID() は、最初に挿入された行のみに対して生成された値を返します。この理由は、ほかの一部のサーバーに対して同じ INSERT ステートメントを簡単に再現できるようにするためです。

    例:

    mysql> USE test;Database changed
    mysql> CREATE TABLE t ( -> id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -> name VARCHAR(10) NOT NULL -> );Query OK, 0 rows affected (0.09 sec)
    mysql> INSERT INTO t VALUES (NULL, 'Bob');Query OK, 1 row affected (0.01 sec)
    mysql> SELECT * FROM t;+----+------+
    | id | name |
    +----+------+
    | 1 | Bob |
    +----+------+
    1 row in set (0.01 sec)
    mysql> SELECT LAST_INSERT_ID();+------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1 |
    +------------------+
    1 row in set (0.00 sec)
    mysql> INSERT INTO t VALUES -> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT * FROM t;
    +----+------+
    | id | name |
    +----+------+
    | 1 | Bob |
    | 2 | Mary |
    | 3 | Jane |
    | 4 | Lisa |
    +----+------+
    4 rows in set (0.01 sec)
    mysql> SELECT LAST_INSERT_ID();+------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 2 |
    +------------------+
    1 row in set (0.00 sec)

    2 番目の INSERT ステートメントで 3 つの新しい行が t に挿入されましたが、これらの行の 1 番目に生成された ID は 2 であり、あとに続く SELECT ステートメントでも、この値が LAST_INSERT_ID() によって返されます。

    INSERT IGNORE を使用し、その行が無視された場合、LAST_INSERT_ID() は現在の値から未変更のままです (接続で正常な INSERT が実行されていない場合は、0 が返されます)。トランザクショナル以外のテーブルでは、AUTO_INCREMENT カウンタが増分されません。InnoDB テーブルでは、innodb_autoinc_lock_mode1 または 2 に設定されている場合は、次の例で示すように AUTO_INCREMENT が増分されます。

    mysql> USE test;
    Database changed
    mysql> SELECT @@innodb_autoinc_lock_mode;
    +----------------------------+
    | @@innodb_autoinc_lock_mode |
    +----------------------------+
    | 1 |
    +----------------------------+
    1 row in set (0.00 sec)
    mysql> CREATE TABLE `t` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `val` INT(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `i1` (`val`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    Query OK, 0 rows affected (0.02 sec)
    -- Insert two rows
    mysql> INSERT INTO t (val) VALUES (1),(2);
    Query OK, 2 rows affected (0.00 sec)
    Records: 2 Duplicates: 0 Warnings: 0
    -- With auto_increment_offset=1, the inserted rows
    -- result in an AUTO_INCREMENT value of 3
    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row *************************** Table: t
    Create Table: CREATE TABLE `t` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `i1` (`val`)
    ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    -- LAST_INSERT_ID() returns the first automatically generated
    -- value that is successfully inserted for the AUTO_INCREMENT column
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1 |
    +------------------+
    1 row in set (0.00 sec)
    -- The attempted insertion of duplicate rows fail but errors are ignored
    mysql> INSERT IGNORE INTO t (val) VALUES (1),(2);
    Query OK, 0 rows affected (0.00 sec)
    Records: 2 Duplicates: 2 Warnings: 0
    -- With innodb_autoinc_lock_mode=1, the AUTO_INCREMENT counter
    -- is incremented for the ignored rows
    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row *************************** Table: t
    Create Table: CREATE TABLE `t` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `i1` (`val`)
    ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    -- The LAST_INSERT_ID is unchanged becuase the previous insert was unsuccessful
    mysql> SELECT LAST_INSERT_ID();
    +------------------+
    | LAST_INSERT_ID() |
    +------------------+
    | 1 |
    +------------------+
    1 row in set (0.00 sec) 

    詳細は、セクション14.6.5「InnoDB での AUTO_INCREMENT 処理」を参照してください。

    exprLAST_INSERT_ID() への引数として指定されている場合は、その引数の値が関数によって返され、LAST_INSERT_ID() によって次に返される値として記憶されます。これを使用すると、シーケンスのシミュレーションを行うことができます。

    1. シーケンスカウンタを保持するテーブルを作成し、それを初期化します。

      mysql> CREATE TABLE sequence (id INT NOT NULL);mysql> INSERT INTO sequence VALUES (0);
    2. そのテーブルを使用して、次のようにシーケンス番号を生成します。

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

      UPDATE ステートメントは、シーケンスカウンタを増分し、LAST_INSERT_ID() への次の呼び出しで更新された値が返されるようにします。SELECT ステートメントは、その値を取得します。mysql_insert_id() C API 関数を使用して、値を取得することもできます。セクション23.8.7.37「mysql_insert_id()」を参照してください。

    LAST_INSERT_ID() を呼び出さずに、シーケンスを生成できます。このように関数を使用する有用性は、ID 値が最後に自動的に生成された値として保持されることです。独自のシーケンス値を生成するほかのクライアントと互いに影響しあうことなく、複数のクライアントが UPDATE ステートメントを発行し、SELECT ステートメント (または mysql_insert_id()) で独自のシーケンス値を取得できるため、マルチユーザーでも安全です。

    mysql_insert_id() 関数は、INSERT および UPDATE ステートメントのあとにしか更新されないため、SELECTSET などのその他の SQL ステートメントを実行したあとに、この C API 関数を使用しても、LAST_INSERT_ID(expr) の値を取得できません。

  • ROW_COUNT()

    MySQL 5.6 では、ROW_COUNT() は次のように値を返します。

    • DDL ステートメント: 0。これは、CREATE TABLEDROP TABLE などのステートメントに適用されます。

    • SELECT 以外の DML ステートメント: 影響を受ける行数です。これは、(以前と同様に) UPDATEINSERTDELETE などのステートメントに適用されますが、ALTER TABLELOAD DATA INFILE などのステートメントにも適用されるようになりました。

    • SELECT: ステートメントで結果セットが返される場合は -1、そうでない場合は影響を受ける行数。たとえば、SELECT * FROM t1 の場合、ROW_COUNT() は -1 を返します。SELECT * FROM t1 INTO OUTFILE 'file_name' の場合、ROW_COUNT() はファイルに書き込まれた行の数を返します。

    • SIGNAL ステートメント: 0。

    UPDATE ステートメントの場合、デフォルトで影響を受けた行の値は実際に変更された行の数です。mysqld への接続時に CLIENT_FOUND_ROWS フラグを mysql_real_connect() に指定した場合、影響を受けた行の値は見つかった、つまり WHERE 句に一致した行数です。

    REPLACE ステートメントの場合、影響を受けた行の値は、新しい行が古い行に置き換わった場合 2 です。この場合、重複が削除されたあとに行が挿入されたためです。

    INSERT ... ON DUPLICATE KEY UPDATE ステートメントの場合、行ごとの影響を受けた行の値は、その行が新しい行として挿入された場合は 1、既存の行が更新された場合は 2、既存の行がその現在の値に設定された場合は 0 です。CLIENT_FOUND_ROWS フラグを指定した場合、影響を受けた行の値は、既存の行がその現在の値に設定された場合は (0 ではなく) 1 になります。

    ROW_COUNT() は、mysql_affected_rows() C API 関数から取得される値と同様で、ステートメントの実行後に mysql クライアントに表示される行数です。

    mysql> INSERT INTO t VALUES(1),(2),(3);Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT ROW_COUNT();+-------------+
    | ROW_COUNT() |
    +-------------+
    | 3 |
    +-------------+
    1 row in set (0.00 sec)
    mysql> DELETE FROM t WHERE i IN(1,2);Query OK, 2 rows affected (0.00 sec)
    mysql> SELECT ROW_COUNT();+-------------+
    | ROW_COUNT() |
    +-------------+
    | 2 |
    +-------------+
    1 row in set (0.00 sec)
    重要

    ステートメントベースのレプリケーションでは、確実に ROW_COUNT() をレプリケートすることはできません。行ベースのレプリケーションを使用すると、この関数は自動的にレプリケートされます。

  • SCHEMA()

    この関数は DATABASE() のシノニムです。

  • SESSION_USER()

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

  • SYSTEM_USER()

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

  • USER()

    現在の MySQL ユーザー名とホスト名を utf8 文字セット内の文字列として返します。

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

    この値は、サーバーへの接続時に指定したユーザー名および接続元のクライアントホストを示します。CURRENT_USER() の値とは異なる可能性があります。

    次のように、ユーザー名の部分のみを抽出できます。

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

    MySQL サーバーのバージョンを示す文字列を返します。この文字列では、utf8 文字セットが使用されます。値にはバージョン番号に加えて、サフィクスが付いている場合もあります。セクション5.1.4「サーバーシステム変数」内の version システム変数の説明を参照してください。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

    mysql> SELECT VERSION(); -> '5.6.23-standard'

12.15 空間分析関数

MySQL には、空間データに対してさまざまな操作を実行する関数が用意されています。これらの関数は、実行する操作の種類に従って、次のいくつかの主なカテゴリにグループ化できます。

  • さまざまな形式 (WKT、WKB、内部) の幾何図形を作成する関数

  • 幾何図形の形式を変換する関数

  • 幾何図形の定性的または定量的なプロパティーにアクセスする関数

  • 2 つの幾何図形間の関係を記述する関数

  • 既存の幾何図形から新しい幾何図形を作成する関数

空間データを使用するための MySQL のサポートに関する一般的なバックグラウンドについては、セクション11.5「空間データの拡張」を参照してください。

12.15.1 空間関数のリファレンス

表 12.19 空間関数

名前説明
Area() Polygon または MultiPolygon 領域を返します
AsBinary(), AsWKB() 内部幾何形式から WKB に変換します
AsText(), AsWKT() 内部幾何形式から WKT に変換します
Buffer() 幾何図形から指定された距離内にある点の幾何図形を返します
Centroid() 重心を Point として返します
Contains() ある幾何図形に別の幾何図形が含まれているかどうか
Crosses() ある幾何図形が別の幾何図形と交差しているかどうか
Dimension() 幾何図形の次元
Disjoint() ある幾何図形が別の幾何図形から切り離されているかどうか
EndPoint() LineString の終点
Envelope() 幾何図形の MBR を返します
Equals() ある幾何図形が別の幾何図形に等しいかどうか
ExteriorRing() Polygon の外側のリングを返します
GeomCollFromText(), GeometryCollectionFromText() WKT からジオメトリコレクションを返します
GeomCollFromWKB(), GeometryCollectionFromWKB() WKB からジオメトリコレクションを返します
GeometryCollection() 幾何図形からジオメトリコレクションを構築します
GeometryN() ジオメトリコレクションから N 番目の幾何図形を返します
GeometryType() 幾何型の名前を返します
GeomFromText(), GeometryFromText() WKT から幾何図形を返します
GeomFromWKB() WKB から幾何図形を返します
GLength() LineString の長さを返します
InteriorRingN() Polygon の N 番目の内側のリングを返します
Intersects() ある幾何図形が別の幾何図形と交差しているかどうか
IsClosed() 幾何図形が閉じていて単純かどうか
IsEmpty() プレースホルダ関数
IsSimple() 幾何図形が単純かどうか
LineFromText() WKT から LineString を構築します
LineFromWKB(), LineStringFromWKB() WKB から LineString を構築します
LineString() Point 値から LineString を構築します
MBRContains() ある幾何図形の MBR に、別の幾何図形の MBR が含まれているかどうか
MBRDisjoint() 2 つの幾何図形の MBR が切り離されているかどうか
MBREqual() 2 つの幾何図形の MBR が等しいかどうか
MBRIntersects() 2 つの幾何図形の MBR が交差しているかどうか
MBROverlaps() 2 つの幾何図形の MBR がオーバーラップしているかどうか
MBRTouches() 2 つの幾何図形の MBR が接しているかどうか
MBRWithin() ある幾何図形の MBR が、別の幾何図形の MBR の内部にあるかどうか
MLineFromText(), MultiLineStringFromText() WKT から MultiLineString を構築します
MLineFromWKB(), MultiLineStringFromWKB() WKB から MultiLineString を構築します
MPointFromText(), MultiPointFromText() WKT から MultiPoint を構築します
MPointFromWKB(), MultiPointFromWKB() WKB から MultiPoint を構築します
MPolyFromText(), MultiPolygonFromText() WKT から MultiPolygon を構築します
MPolyFromWKB(), MultiPolygonFromWKB() WKB から MultiPolygon を構築します
MultiLineString() LineString 値から MultiLineString を構築します
MultiPoint() Point 値から MultiPoint を構築します
MultiPolygon() Polygon 値から MultiPolygon を構築します
NumGeometries() ジオメトリコレクション内の幾何図形数を返します
NumInteriorRings() Polygon 内の内側のリング数を返します
NumPoints() LineString 内の Point の数を返します
Overlaps() ある幾何図形が別の幾何図形とオーバーラップしているかどうか
Point() 座標から Point を構築します
PointFromText() WKT から Point を構築します
PointFromWKB() WKB から Point を構築します
PointN() LineString から N 番目の Point を返します
PolyFromText(), PolygonFromText() WKT から Polygon を構築します
PolyFromWKB(), PolygonFromWKB() WKB から Polygon を構築します
Polygon() LineString 引数から Polygon を構築します
SRID() 幾何図形の空間参照システム ID を返します
ST_Area() Polygon または MultiPolygon 領域を返します
ST_Centroid() 重心を Point として返します
ST_Contains() ある幾何図形に別の幾何図形が含まれているかどうか
ST_Crosses() ある幾何図形が別の幾何図形と交差しているかどうか
ST_Difference() 2 つの幾何図形の点集合の差集合を返します
ST_Disjoint() ある幾何図形が別の幾何図形から切り離されているかどうか
ST_Distance() ある幾何図形の別の幾何図形からの距離
ST_Envelope() 幾何図形の MBR を返します
ST_Equals() ある幾何図形が別の幾何図形に等しいかどうか
ST_Intersection() 2 つの幾何図形の点集合の積集合を返します
ST_Intersects() ある幾何図形が別の幾何図形と交差しているかどうか
ST_Overlaps() ある幾何図形が別の幾何図形とオーバーラップしているかどうか
ST_SymDifference() 2 つの幾何図形の点集合の対称差を返します
ST_Touches() ある幾何図形が別の幾何図形に接しているかどうか
ST_Union() 2 つの幾何図形の点集合の和集合を返します
ST_Within() ある幾何図形が別の幾何図形の内部にあるかどうか
StartPoint() LineString の始点
Touches() ある幾何図形が別の幾何図形に接しているかどうか
Within() ある幾何図形が別の幾何図形の内部にあるかどうか
X() Point の X 座標を返します
Y() Point の Y 座標を返します

12.15.2 空間関数による引数処理

空間値 (または幾何図形) は、セクション11.5.2.2「Geometry クラス」で説明されているプロパティーを持っています。次の説明では、空間関数の一般的な引数処理特性を一覧表示します。特定の関数または関数のグループには、追加の引数処理特性がある場合があります。これらについては、これらの関数の説明が行われるセクションで説明されています。

空間関数は、有効な幾何値に対してのみ定義されています。無効な幾何図形が空間関数に渡された場合の結果は定義されていません。

幾何図形の空間参照識別子 (SRID) は、その幾何図形が定義されている座標空間を識別します。MySQL の SRID 値は、幾何値に関連付けられた整数です。ただし、すべての計算が実際の SRID 値には関係なく、デカルト (平面) 座標を表す SRID 0 を想定して実行されます。将来は、指定された SRID 値が計算で使用される可能性があります。SRID 0 の動作を保証するには、SRID 0 を使用して幾何図形を作成します。SRID 0 は、SRID が指定されていない場合の新しい幾何図形のためのデフォルトです。

使用可能な SRID の最大値は 232−1 です。より大きな値が指定されると、低位の 32 ビットだけが使用されます。

どの空間関数によって生成された幾何値も、その幾何図形の引数の SRID を継承します。

12.15.3 WKT 値から幾何値を作成する関数

これらの関数は、引数として Well-Known Text (WKT) 表現と、オプションで空間参照システム識別子 (SRID) を受け取ります。これらは、対応する幾何図形を返します。

GeomFromText() は、その最初の引数として任意の幾何型の WKT 値を受け入れます。その他の関数は、各幾何型の幾何値の構築のための型固有の構築関数を提供します。

WKT 形式については、セクション11.5.3.1.1「WKT (Well-Known Text) 形式」を参照してください。

  • GeomCollFromText(wkt[,srid])GeometryCollectionFromText(wkt[,srid])

    WKT 表現と SRID を使用して GeometryCollection 値を構築します。

  • GeomFromText(wkt[,srid])GeometryFromText(wkt[,srid])

    WKT 表現と SRID を使用して任意の型の幾何値を構築します。

  • LineFromText(wkt[,srid])LineStringFromText(wkt[,srid])

    WKT 表現と SRID を使用して LineString 値を構築します。

  • MLineFromText(wkt[,srid])MultiLineStringFromText(wkt[,srid])

    WKT 表現と SRID を使用して MultiLineString 値を構築します。

  • MPointFromText(wkt[,srid])MultiPointFromText(wkt[,srid])

    WKT 表現と SRID を使用して MultiPoint 値を構築します。

  • MPolyFromText(wkt[,srid])MultiPolygonFromText(wkt[,srid])

    WKT 表現と SRID を使用して MultiPolygon 値を構築します。

  • PointFromText(wkt[,srid])

    WKT 表現と SRID を使用して Point 値を構築します。

  • PolyFromText(wkt[,srid])PolygonFromText(wkt[,srid])

    WKT 表現と SRID を使用して Polygon 値を構築します。

12.15.4 WKB 値から幾何値を作成する関数

これらの関数は、引数として Well-Known Binary (WKB) 表現を含む BLOB と、オプションで空間参照システム識別子 (SRID) を受け取ります。これらは、対応する幾何図形を返します。

これらの関数はまた、セクション12.15.5「幾何値を作成する MySQL 固有の関数」にある関数の戻り値との互換性のために幾何オブジェクトも受け入れます。そのため、これらの関数を使用すると、このセクションにある関数への最初の引数を提供できます。

GeomFromWKB() は、その最初の引数として任意の幾何型の WKB 値を受け入れます。その他の関数は、各幾何型の幾何値の構築のための型固有の構築関数を提供します。

WKB 形式については、セクション11.5.3.1.2「WKB (Well-Known Binary) 形式」を参照してください。

  • GeomCollFromWKB(wkb[,srid])GeometryCollectionFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して GeometryCollection 値を構築します。

  • GeomFromWKB(wkb[,srid])GeometryFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して任意の型の幾何値を構築します。

  • LineFromWKB(wkb[,srid])LineStringFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して LineString 値を構築します。

  • MLineFromWKB(wkb[,srid])MultiLineStringFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して MultiLineString 値を構築します。

  • MPointFromWKB(wkb[,srid])MultiPointFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して MultiPoint 値を構築します。

  • MPolyFromWKB(wkb[,srid])MultiPolygonFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して MultiPolygon 値を構築します。

  • PointFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して Point 値を構築します。

  • PolyFromWKB(wkb[,srid])PolygonFromWKB(wkb[,srid])

    WKB 表現と SRID を使用して Polygon 値を構築します。

12.15.5 幾何値を作成する MySQL 固有の関数

MySQL には、幾何値を作成するために役立つ一連の非標準関数が用意されています。このセクションで説明されている関数は、OpenGIS 仕様への MySQL 拡張です。

これらの関数は、引数としての WKB 値または幾何オブジェクトから幾何オブジェクトを生成します。いずれかの引数が適切な WKB でも、適切なオブジェクト型の幾何表現でもない場合、戻り値は NULL になります。

たとえば、Point() からの幾何図形の戻り値を POINT カラムに直接挿入できます。

INSERT INTO t1 (pt_col) VALUES(Point(1,2));
  • GeometryCollection(g1,g2,...)

    GeometryCollection を構築します。

    引数にサポートされていない幾何図形が含まれている場合、戻り値は NULL になります。

  • LineString(pt1,pt2,...)

    複数の Point または WKB Point 引数から LineString 値を構築します。引数の数が 2 未満の場合、戻り値は NULL になります。

  • MultiLineString(ls1,ls2,...)

    LineString または WKB LineString 引数を使用して MultiLineString 値を構築します。

  • MultiPoint(pt1,pt2,...)

    Point または WKB Point 引数を使用して MultiPoint 値を構築します。

  • MultiPolygon(poly1,poly2,...)

    一連の Polygon または WKB Polygon 引数から MultiPolygon 値を構築します。

  • Point(x,y)

    座標を使用して Point を構築します。

  • Polygon(ls1,ls2,...)

    複数の LineString または WKB LineString 引数から Polygon 値を構築します。いずれかの引数が LinearRing を表していない (つまり、閉じた単純な LineString でない) 場合、戻り値は NULL になります。

12.15.6 幾何形式変換関数

MySQL は、内部形式と WKT または WKB 形式の間で幾何値を変換するための次の関数をサポートします。

  • AsBinary(g)AsWKB(g)

    内部幾何形式の値を WKB 表現に変換し、そのバイナリの結果を返します。

    SELECT AsBinary(g) FROM geom;
  • AsText(g)AsWKT(g)

    内部幾何形式の値を WKT 表現に変換し、その文字列の結果を返します。

    mysql> SET @g = 'LineString(1 1,2 2,3 3)';mysql> SELECT AsText(GeomFromText(@g));+--------------------------+
    | AsText(GeomFromText(@g)) |
    +--------------------------+
    | LINESTRING(1 1,2 2,3 3) |
    +--------------------------+
  • GeomFromText(wkt[,srid])

    文字列値を WKT 表現から内部幾何形式に変換し、その結果を返します。また、PointFromText()LineFromText() などの型固有の関数もいくつかサポートされます。セクション12.15.3「WKT 値から幾何値を作成する関数」を参照してください。

  • GeomFromWKB(wkb[,srid])

    バイナリ値を WKB 表現から内部幾何形式に変換し、その結果を返します。また、PointFromWKB()LineFromWKB() などの型固有の関数もいくつかサポートされます。セクション12.15.4「WKB 値から幾何値を作成する関数」を参照してください。

12.15.7 幾何プロパティー関数

このグループに属する各関数は、引数として幾何値を受け取り、その幾何図形の何らかの定量的または定性的なプロパティーを返します。一部の関数では、その引数の型が制限されます。このような関数は、その引数の幾何型が正しくない場合は NULL を返します。たとえば、Area() 多角形関数は、オブジェクト型が Polygon でも MultiPolygon でもない場合は NULL を返します。

12.15.7.1 一般的な幾何プロパティー関数

このセクションに示されている関数では引数が制限されず、任意の型の幾何値が受け入れられます。

  • Dimension(g)

    幾何値 g の固有の次元を返します。結果は、-1、0、1、2 のいずれかです。これらの値の意味は、セクション11.5.2.2「Geometry クラス」で指定されています。

    mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));+------------------------------------------------+
    | Dimension(GeomFromText('LineString(1 1,2 2)')) |
    +------------------------------------------------+
    | 1 |
    +------------------------------------------------+
  • Envelope(g)

    ST_Envelope()Envelope() はシノニムです。詳細は、ST_Envelope() の説明を参照してください。

  • GeometryType(g)

    幾何インスタンス g がメンバーになっている幾何型の名前を示すバイナリ文字列を返します。この名前は、インスタンス化可能な Geometry サブクラスのいずれかに対応します。

    mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));+------------------------------------------+
    | GeometryType(GeomFromText('POINT(1 1)')) |
    +------------------------------------------+
    | POINT |
    +------------------------------------------+
  • IsEmpty(g)

    この関数は、すべての有効な幾何値に対しては 0、すべての無効な幾何値または NULL に対しては 1 を返すプレースホルダです。

    MySQL は、POINT EMPTY などの GIS の EMPTY 値をサポートしていません。

  • IsSimple(g)

    幾何値 g に自己交差や自己接触などの異常な幾何点が含まれていない場合は 1 を返します。IsSimple() は、その引数が単純でない場合は 0 を、NULL である場合は NULL を返します。

    この章の最初の方で指定されているインスタンス化可能な各幾何クラスの説明には、そのクラスのインスタンスが単純でないとして分類される具体的な条件が含まれています。(セクション11.5.2.1「幾何クラスの階層」を参照してください。)

    MySQL 5.6.1 より前は、この関数は常に 0 を返します。

  • SRID(g)

    幾何値 g の空間参照システム ID を示す整数を返します。

    MySQL では、SRID 値は幾何値に関連付けられた整数にすぎません。すべての計算はユークリッド (平面) 幾何学を前提にして実行されます。

    mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));+-----------------------------------------------+
    | SRID(GeomFromText('LineString(1 1,2 2)',101)) |
    +-----------------------------------------------+
    | 101 |
    +-----------------------------------------------+
  • ST_Envelope(g)

    幾何値 g の最小外接矩形 (MBR) を返します。結果は、その外接矩形の角の点によって定義された Polygon 値として返されます。

    POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
    mysql> SELECT AsText(ST_Envelope(GeomFromText('LineString(1 1,2 2)')));+----------------------------------------------------------+
    | AsText(ST_Envelope(GeomFromText('LineString(1 1,2 2)'))) |
    +----------------------------------------------------------+
    | POLYGON((1 1,2 1,2 2,1 2,1 1)) |
    +----------------------------------------------------------+

    ST_Envelope()Envelope() はシノニムです。

    ST_Envelope() は、MySQL 5.6.1 で追加されました。

12.15.7.2 点プロパティー関数

Point は、次の関数を使用して取得できる X 座標と Y 座標で構成されます。

  • X(p)

    Point オブジェクト p の X 座標値を倍精度数値として返します。

    mysql> SELECT X(POINT(56.7, 53.34));+-----------------------+
    | X(POINT(56.7, 53.34)) |
    +-----------------------+
    | 56.7 |
    +-----------------------+
  • Y(p)

    Point オブジェクト p の Y 座標値を倍精度数値として返します。

    mysql> SELECT Y(POINT(56.7, 53.34));+-----------------------+
    | Y(POINT(56.7, 53.34)) |
    +-----------------------+
    | 53.34 |
    +-----------------------+

12.15.7.3 LineString プロパティー関数

LineString は、Point 値で構成されます。LineString の特定の点を抽出したり、そこに含まれている点の数をカウントしたり、その長さを取得したりできます。

  • EndPoint(ls)

    LineStringls の終点である Point を返します。

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';mysql> SELECT AsText(EndPoint(GeomFromText(@ls)));+-------------------------------------+
    | AsText(EndPoint(GeomFromText(@ls))) |
    +-------------------------------------+
    | POINT(3 3) |
    +-------------------------------------+
  • GLength(ls)

    LineStringls の関連付けられた空間参照内の長さを示す倍精度数値を返します。

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';mysql> SELECT GLength(GeomFromText(@ls));+----------------------------+
    | GLength(GeomFromText(@ls)) |
    +----------------------------+
    | 2.8284271247462 |
    +----------------------------+

    GLength() は非標準名です。これは、OpenGIS の Length() 関数に対応します。(文字列値の長さを計算する既存の SQL 関数 Length() が存在します。)

  • IsClosed(ls)

    LineStringls が閉じており (つまり、その StartPoint() 値と EndPoint() 値が同じであり)、かつ単純である (同じ点を複数回通っていない) 場合は 1 を返します。ls が閉じていない場合は 0 を、NULL である場合は -1 を返します。

    mysql> SET @ls1 = 'LineString(1 1,2 2,3 3,2 2)';Query OK, 0 rows affected (0.00 sec)
    mysql> SET @ls2 = 'LineString(1 1,2 2,3 3,1 1)';Query OK, 0 rows affected (0.00 sec)
    mysql> SELECT IsClosed(GeomFromText(@ls1));+------------------------------+
    | IsClosed(GeomFromText(@ls1)) |
    +------------------------------+
    | 0 |
    +------------------------------+
    1 row in set (0.00 sec)
    mysql> SELECT IsClosed(GeomFromText(@ls2));+------------------------------+
    | IsClosed(GeomFromText(@ls2)) |
    +------------------------------+
    | 1 |
    +------------------------------+
    1 row in set (0.00 sec)
  • NumPoints(ls)

    LineStringls 内の Point オブジェクトの数を返します。

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';mysql> SELECT NumPoints(GeomFromText(@ls));+------------------------------+
    | NumPoints(GeomFromText(@ls)) |
    +------------------------------+
    | 3 |
    +------------------------------+
  • PointN(ls,N)

    Linestringls 内の N 番目の Point を返します。点の番号は 1 から始まります。

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';mysql> SELECT AsText(PointN(GeomFromText(@ls),2));+-------------------------------------+
    | AsText(PointN(GeomFromText(@ls),2)) |
    +-------------------------------------+
    | POINT(2 2) |
    +-------------------------------------+
  • StartPoint(ls)

    LineStringls の始点である Point を返します。

    mysql> SET @ls = 'LineString(1 1,2 2,3 3)';mysql> SELECT AsText(StartPoint(GeomFromText(@ls)));+---------------------------------------+
    | AsText(StartPoint(GeomFromText(@ls))) |
    +---------------------------------------+
    | POINT(1 1) |
    +---------------------------------------+

12.15.7.4 MultiLineString プロパティー関数

これらの関数は、MultiLineString 値のプロパティーを返します。

  • GLength(mls)

    MultiLineStringmls の長さを示す倍精度数値を返します。mls の長さは、その要素の長さの合計に等しくなります。

    mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';mysql> SELECT GLength(GeomFromText(@mls));+-----------------------------+
    | GLength(GeomFromText(@mls)) |
    +-----------------------------+
    | 4.2426406871193 |
    +-----------------------------+

    GLength() は非標準名です。これは、OpenGIS の Length() 関数に対応します。

  • IsClosed(mls)

    MultiLineStringmls が閉じている (つまり、mls 内の各 LineStringStartPoint() 値と EndPoint() 値が同じである) 場合は 1 を返します。mls が閉じていない場合は 0 を、NULL である場合は -1 を返します。

    mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';mysql> SELECT IsClosed(GeomFromText(@mls));+------------------------------+
    | IsClosed(GeomFromText(@mls)) |
    +------------------------------+
    | 0 |
    +------------------------------+

12.15.7.5 Polygon プロパティー関数

これらの関数は、Polygon 値のプロパティーを返します。

  • Area(poly)

    ST_Area()Area() はシノニムです。詳細は、ST_Area() の説明を参照してください。

  • ExteriorRing(poly)

    Polygonpoly の外側のリングを LineString として返します。

    mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly)));+-------------------------------------------+
    | AsText(ExteriorRing(GeomFromText(@poly))) |
    +-------------------------------------------+
    | LINESTRING(0 0,0 3,3 3,3 0,0 0) |
    +-------------------------------------------+
  • InteriorRingN(poly,N)

    PolygonpolyN 番目の内側のリングを LineString として返します。リングの番号は 1 から始まります。

    mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));+----------------------------------------------+
    | AsText(InteriorRingN(GeomFromText(@poly),1)) |
    +----------------------------------------------+
    | LINESTRING(1 1,1 2,2 2,2 1,1 1) |
    +----------------------------------------------+
  • NumInteriorRings(poly)

    Polygonpoly 内の内側のリングの数を返します。

    mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';mysql> SELECT NumInteriorRings(GeomFromText(@poly));+---------------------------------------+
    | NumInteriorRings(GeomFromText(@poly)) |
    +---------------------------------------+
    | 1 |
    +---------------------------------------+
  • ST_Area(poly)

    空間参照システムで測定された引数の面積を示す倍精度数値を返します。次元 0 または 1 の引数の場合、結果は 0 です。

    mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';mysql> SELECT ST_Area(GeomFromText(@poly));+------------------------------+
    | ST_Area(GeomFromText(@poly)) |
    +------------------------------+
    | 4 |
    +------------------------------+
    mysql> SET @mpoly = -> 'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))';mysql> SELECT ST_Area(GeomFromText(@mpoly));+-------------------------------+
    | ST_Area(GeomFromText(@mpoly)) |
    +-------------------------------+
    | 8 |
    +-------------------------------+

    ST_Area()Area() はシノニムです。

    ST_Area() は、MySQL 5.6.1 で追加されました。

12.15.7.6 MultiPolygon プロパティー関数

これらの関数は、MultiPolygon 値のプロパティーを返します。

  • Area(mpoly)

    セクション12.15.7.5「Polygon プロパティー関数」にある Area() の説明を参照してください。

  • Centroid(mpoly)

    ST_Centroid()Centroid() はシノニムです。詳細は、ST_Centroid() の説明を参照してください。

  • ST_Area(mpoly)

    セクション12.15.7.5「Polygon プロパティー関数」にある Area() の説明を参照してください。

  • ST_Centroid(mpoly)

    MultiPolygonmpoly の数学的な重心を Point として返します。結果が MultiPolygon 上にある保証はありません。

    mysql> SET @poly = -> GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))');mysql> SELECT GeometryType(@poly),AsText(ST_Centroid(@poly));+---------------------+--------------------------------------------+
    | GeometryType(@poly) | AsText(ST_Centroid(@poly)) |
    +---------------------+--------------------------------------------+
    | POLYGON | POINT(4.958333333333333 4.958333333333333) |
    +---------------------+--------------------------------------------+

    ST_Centroid()Centroid() はシノニムです。

    ST_Centroid() は、MySQL 5.6.1 で追加されました。

12.15.7.7 GeometryCollection プロパティー関数

これらの関数は、GeometryCollection 値のプロパティーを返します。

  • GeometryN(gc,N)

    GeometryCollectiongc 内の N 番目の幾何図形を返します。幾何図形の番号は 1 から始まります。

    mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';mysql> SELECT AsText(GeometryN(GeomFromText(@gc),1));+----------------------------------------+
    | AsText(GeometryN(GeomFromText(@gc),1)) |
    +----------------------------------------+
    | POINT(1 1) |
    +----------------------------------------+
  • NumGeometries(gc)

    GeometryCollectiongc 内の幾何図形の数を返します。

    mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';mysql> SELECT NumGeometries(GeomFromText(@gc));+----------------------------------+
    | NumGeometries(GeomFromText(@gc)) |
    +----------------------------------+
    | 2 |
    +----------------------------------+

12.15.8 空間演算子関数

OpenGIS では、幾何図形を生成できる関数がいくつか提案されています。これらは、空間演算子を実装するように設計されています。

  • Buffer(g,d)

    幾何値 g からの距離が d の距離以下であるすべての点を表す幾何図形を返します。

    Buffer() は、多角形、複数多角形、および多角形または複数多角形を含む幾何図形コレクションに対して負の距離をサポートしています。点、複数点、ライン文字列、複数ライン文字列、および多角形または複数多角形を含まない幾何図形コレクションに対して、負の距離を含む Buffer()NULL を返します。

    Buffer() は、MySQL 5.6.1 で追加されました。

  • ST_Difference(g1, g2)

    幾何値 g1g2 の点集合の差集合を表す幾何図形を返します。

    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);mysql> SELECT AsText(ST_Difference(@g1, @g2));+---------------------------------+
    | AsText(ST_Difference(@g1, @g2)) |
    +---------------------------------+
    | POINT(1 1) |
    +---------------------------------+

    ST_Difference() は、MySQL 5.6.1 で追加されました。

  • ST_Intersection(g1, g2)

    幾何値 g1g2 の点集合の共通集合を表す幾何図形を返します。

    mysql> SET @g1 = GeomFromText('LineString(1 1, 3 3)');mysql> SET @g2 = GeomFromText('LineString(1 3, 3 1)');mysql> SELECT AsText(ST_Intersection(@g1, @g2));+-----------------------------------+
    | AsText(ST_Intersection(@g1, @g2)) |
    +-----------------------------------+
    | POINT(2 2) |
    +-----------------------------------+

    ST_Intersection() は、MySQL 5.6.1 で追加されました。

  • ST_SymDifference(g1, g2)

    幾何値 g1g2 の点集合の対称差を表す幾何図形を返します。これは、次のように定義されます。

    g1 symdifference g2 := (g1 union g2) difference (g1 intersection g2)

    または、関数呼び出しの表記では次のようになります。

    ST_SymDifference(g1, g2) = ST_Difference(ST_Union(g1, g2), ST_Intersection(g1, g2))
    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);mysql> SELECT AsText(ST_SymDifference(@g1, @g2));+-------------------------------------------+
    | AsText(ST_SymDifference(@g1, @g2)) |
    +-------------------------------------------+
    | GEOMETRYCOLLECTION(POINT(1 1),POINT(2 2)) |
    +-------------------------------------------+

    ST_SymDifference() は、MySQL 5.6.1 で追加されました。

  • ST_Union(g1, g2)

    幾何値 g1g2 の点集合の和集合を表す幾何図形を返します。

    mysql> SET @g1 = GeomFromText('LineString(1 1, 3 3)');mysql> SET @g2 = GeomFromText('LineString(1 3, 3 1)');mysql> SELECT AsText(ST_Union(@g1, @g2));+--------------------------------------+
    | AsText(ST_Union(@g1, @g2)) |
    +--------------------------------------+
    | MULTILINESTRING((1 1,3 3),(3 1,1 3)) |
    +--------------------------------------+

    ST_Union() は、MySQL 5.6.1 で追加されました。

さらに、セクション12.15.7「幾何プロパティー関数」では、既存の幾何図形から新しい幾何図形を構築するいくつかの関数について説明しています。これらの関数の説明については、そのセクションを参照してください。

  • Envelope(g)

  • StartPoint(ls)

  • EndPoint(ls)

  • PointN(ls,N)

  • ExteriorRing(poly)

  • InteriorRingN(poly,N)

  • GeometryN(gc,N)

12.15.9 幾何オブジェクト間の空間関係をテストする関数

このセクションで説明されている関数は、引数として 2 つの幾何図形を受け取り、それらの間の定性的または定量的な関係を返します。

  • OpenGIS 仕様では、2 つの幾何値間の関係をテストする一連の関数が定義されています。MySQL は最初、これらの関数を実装することにより、オブジェクトの最小外接矩形 (MBR) を使用し、対応する MBR ベースの関数と同じ結果を返していました。たとえば、Contains()MBRContains() は同じ結果を返します。(例外: Crosses() は存在しますが、MBRCrosses() は存在しません。)

    MySQL 5.6.1 の時点では、正確なオブジェクト形状を使用する対応するバージョンを使用できます。これらのバージョンの名前には ST_ プリフィクスが付けられています。たとえば、Contains() が最小外接矩形を使用するのに対して、ST_Contains() はオブジェクト形状を使用します。

    MySQL 5.6.1 の時点では、すでに正確であった既存の空間関数のための ST_ エイリアスも存在します。たとえば、ST_IsEmpty()IsEmpty() のエイリアスです。さらに、ST_Distance() も使用できます。

  • 2 つの幾何値間の関係をテストするには、MySQL 固有の一連の MBR ベースの関数を使用できます。

12.15.9.1 オブジェクト形状を使用する空間関係関数

OpenGIS 仕様では、次の関数が定義されています。これらは、正確なオブジェクト形状を使用して、2 つの幾何値 g1g2 の間の関係をテストします。戻り値 1 と 0 は、それぞれ true と false を示します。

  • ST_Contains(g1,g2)

    g1g2 を完全に含んでいるかどうかを示す 1 または 0 を返します。これは、ST_Within() とは逆の関係をテストします。

  • ST_Crosses(g1,g2)

    g1g2 と空間的に交差している場合は 1 を返します。g1Polygon または MultiPolygon である場合、あるいは g2Point または MultiPoint である場合は NULL を返します。それ以外の場合は、0 を返します。

    空間的に交差しているという用語は、2 つの指定された幾何図形間の空間関係が次の性質を持っていることを示します。

    • 2 つの幾何図形が交差している

    • それらの交差によって、2 つの指定された幾何図形の最大の次元より 1 つ小さい次元を持つ幾何図形が生成される

    • それらの交差が 2 つの指定された幾何図形のどちらとも等しくない

  • ST_Disjoint(g1,g2)

    g1g2 と空間的に切り離されている (交差していない) かどうかを示す 1 または 0 を返します。

  • ST_Distance(g1,g2)

    g1g2 の間の距離を返します。

    mysql> SET @g1 = POINT(1,1), @g2 = POINT(2,2);mysql> SELECT ST_Distance(@g1, @g2);+-----------------------+
    | ST_Distance(@g1, @g2) |
    +-----------------------+
    | 1.4142135623730951 |
    +-----------------------+

    ST_Distance() は、MySQL 5.6.1 で追加されました。

  • ST_Equals(g1,g2)

    g1g2 と空間的に等しいかどうかを示す 1 または 0 を返します。

  • ST_Intersects(g1,g2)

    g1g2 と空間的に交差しているかどうかを示す 1 または 0 を返します。

  • ST_Overlaps(g1,g2)

    g1g2 と空間的にオーバーラップしているかどうかを示す 1 または 0 を返します。空間的にオーバーラップしているという用語が使用されるのは、2 つの幾何図形が交差しており、かつそれらの交差によって同じ次元の幾何図形が生成されるが、指定された幾何図形のどちらとも等しくない場合です。

  • ST_Touches(g1,g2)

    g1g2 に空間的に接しているかどうかを示す 1 または 0 を返します。2 つの幾何図形が空間的に接しているのは、これらの幾何図形の内部は交差していないが、一方の幾何図形の境界が他方の幾何図形の境界または内部と交差している場合です。

  • ST_Within(g1,g2)

    g1 が空間的に g2 の内部にあるかどうかを示す 1 または 0 を返します。これは、ST_Contains() とは逆の関係をテストします。

12.15.9.2 最小外接矩形 (MBR) を使用する空間関係関数

OpenGIS 仕様では、次の関数が定義されています。これらは、2 つの幾何値 g1g2 の間の関係をテストします。MySQL 実装では最小外接矩形を使用するため、これらの関数は、対応する MBR ベースの関数と同じ結果を返します。戻り値 1 と 0 は、それぞれ true と false を示します。

  • Contains(g1,g2)

    g1g2 を完全に含んでいるかどうかを示す 1 または 0 を返します。これは、Within() とは逆の関係をテストします。

  • Crosses(g1,g2)

    g1g2 と空間的に交差している場合は 1 を返します。g1Polygon または MultiPolygon である場合、あるいは g2Point または MultiPoint である場合は NULL を返します。それ以外の場合は、0 を返します。

    空間的に交差しているという用語は、2 つの指定された幾何図形間の空間関係が次の性質を持っていることを示します。

    • 2 つの幾何図形が交差している

    • それらの交差によって、2 つの指定された幾何図形の最大の次元より 1 つ小さい次元を持つ幾何図形が生成される

    • それらの交差が 2 つの指定された幾何図形のどちらとも等しくない

  • Disjoint(g1,g2)

    g1g2 と空間的に切り離されている (交差していない) かどうかを示す 1 または 0 を返します。

  • Equals(g1,g2)

    g1g2 と空間的に等しいかどうかを示す 1 または 0 を返します。

  • Intersects(g1,g2)

    g1g2 と空間的に交差しているかどうかを示す 1 または 0 を返します。

  • Overlaps(g1,g2)

    g1g2 と空間的にオーバーラップしているかどうかを示す 1 または 0 を返します。空間的にオーバーラップしているという用語が使用されるのは、2 つの幾何図形が交差しており、かつそれらの交差によって同じ次元の幾何図形が生成されるが、指定された幾何図形のどちらとも等しくない場合です。

  • Touches(g1,g2)

    g1g2 に空間的に接しているかどうかを示す 1 または 0 を返します。2 つの幾何図形が空間的に接しているのは、これらの幾何図形の内部は交差していないが、一方の幾何図形の境界が他方の幾何図形の境界または内部と交差している場合です。

  • Within(g1,g2)

    g1 が空間的に g2 の内部にあるかどうかを示す 1 または 0 を返します。これは、Contains() とは逆の関係をテストします。

12.15.9.3 最小外接矩形 (MBR) を使用する MySQL 固有の空間関係関数

MySQL には、2 つの幾何図形 g1g2 の最小外接矩形間の関係をテストする関数がいくつか用意されています。戻り値 1 と 0 は、それぞれ true と false を示します。

  • MBRContains(g1,g2)

    g1 の最小外接矩形が g2 の最小外接矩形を含んでいるかどうかを示す 1 または 0 を返します。これは、MBRWithin() とは逆の関係をテストします。

    mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');mysql> SET @g2 = GeomFromText('Point(1 1)');mysql> SELECT MBRContains(@g1,@g2), MBRWithin(@g2,@g1);+----------------------+--------------------+
    | MBRContains(@g1,@g2) | MBRWithin(@g2,@g1) |
    +----------------------+--------------------+
    | 1 | 1 |
    +----------------------+--------------------+
  • MBRDisjoint(g1,g2)

    2 つの幾何図形 g1g2 の最小外接矩形が切り離されている (交差していない) かどうかを示す 1 または 0 を返します。

  • MBREqual(g1,g2)

    2 つの幾何図形 g1g2 の最小外接矩形が同じであるかどうかを示す 1 または 0 を返します。

  • MBRIntersects(g1,g2)

    2 つの幾何図形 g1g2 の最小外接矩形が交差しているかどうかを示す 1 または 0 を返します。

  • MBROverlaps(g1,g2)

    2 つの幾何図形 g1g2 の最小外接矩形がオーバーラップしているかどうかを示す 1 または 0 を返します。空間的にオーバーラップしているという用語が使用されるのは、2 つの幾何図形が交差しており、かつそれらの交差によって同じ次元の幾何図形が生成されるが、指定された幾何図形のどちらとも等しくない場合です。

  • MBRTouches(g1,g2)

    2 つの幾何図形 g1g2 の最小外接矩形が接しているかどうかを示す 1 または 0 を返します。2 つの幾何図形が空間的に接しているのは、これらの幾何図形の内部は交差していないが、一方の幾何図形の境界が他方の幾何図形の境界または内部と交差している場合です。

  • MBRWithin(g1,g2)

    g1 の最小外接矩形が g2 の最小外接矩形の内部にあるかどうかを示す 1 または 0 を返します。これは、MBRContains() とは逆の関係をテストします。

    mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);+--------------------+--------------------+
    | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |
    +--------------------+--------------------+
    | 1 | 0 |
    +--------------------+--------------------+

12.16 グローバルトランザクション ID とともに使用される関数

このセクションで説明する関数は、GTID ベースのレプリケーション (MySQL 5.6.5 以降で使用可能) で使用されます。これらのすべての関数には、引数として GTID セットの文字列表現が指定されるため、これらの関数とともに GTID セットを使用する際は、常に引用符で囲む必要があることを忘れないことが重要です。

2 つの GTID セットの結合は、単にカンマを挿入して結合された文字列として表現されたものです。言い換えると、ここで作成した関数と同様に、非常に単純な関数を定義すれば、GTID セットの結合を取得できます。

CREATE FUNCTION GTID_UNION(g1 TEXT, g2 TEXT) RETURNS TEXT DETERMINISTIC RETURN CONCAT(g1,',',g2); 

GTID の詳細およびこれらの GTID 関数を実際に使用する方法については、セクション17.1.3「グローバルトランザクション識別子を使用したレプリケーション」を参照してください。

表 12.20 GTID 関数

名前説明
GTID_SUBSET() サブセット内のすべての GTID がセット内にもある場合は、true を返します。そうでない場合は、false を返します。
GTID_SUBTRACT() セット内の GTID のうち、サブセット内にないものをすべてを返します。
SQL_THREAD_WAIT_AFTER_GTIDS() (deprecated 5.6.9) 廃止: WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() に置き換わりました
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() 指定された GTID がスレーブで実行されるまで待ちます。

  • GTID_SUBSET(subset,set)

    2 セットのグローバルトランザクション ID subsetset が指定された場合、subset 内のすべての GTID が set にも存在すれば true (1) を返します。それ以外の場合は、false (0) を返します。

    この関数で使用される GTID セットは、次の例で示すように文字列で表現されます。

    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G*************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
    1 row in set (0.00 sec)
    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G*************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23-25', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 1
    1 row in set (0.00 sec)
    mysql> SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')\G*************************** 1. row ***************************
    GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'): 0
    1 row in set (0.00 sec)

    この関数は、MySQL 5.6.5 で追加されました。

  • GTID_SUBTRACT(set,subset)

    2 セットのグローバルトランザクション ID subsetset が指定された場合、set 内の GTID で、subset に存在しないものだけを返します。

    この関数で使用される GTID セットはすべて文字列で表現されるため、次の例で示すように引用符で囲む必要があります。

    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:21')\G*************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:22-57
    1 row in set (0.00 sec)
    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25')\G*************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:26-57
    1 row in set (0.00 sec)
    mysql> SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', -> '3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24')\G*************************** 1. row ***************************
    GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57', '3E11FA47-71CA-11E1-9E33-C80AA9429562:23-24'): 3e11fa47-71ca-11e1-9e33-c80aa9429562:21-22:25-57
    1 row in set (0.01 sec)

    この関数は、MySQL 5.6.5 で追加されました。

  • SQL_THREAD_WAIT_AFTER_GTIDS(gtid_set[, timeout])

    SQL_THREAD_WAIT_AFTER_GTIDS() は MySQL 5.6.5 で追加され、MySQL 5.6.9 で WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() に置き換えられました。(Bug #14775984)

    詳細は、セクション17.1.3「グローバルトランザクション識別子を使用したレプリケーション」を参照してください。

  • WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(gtid_set[, timeout])

    スレーブ SQL スレッドで gtid_set 内にグローバルトランザクション ID が含まれるすべてのトランザクションが実行されるか (GTID セットの定義については、セクション17.1.3.1「GTID の概念」を参照してください)、timeout 秒が経過するかのどちらかが先に発生するまで待機します。timeout はオプションで、デフォルトのタイムアウトは 0 です。この場合、マスターは単に、GTID セット内のすべてのトランザクションが実行されるまで待機するだけです。

    MySQL 5.6.9 よりも前では、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()SQL_THREAD_WAIT_AFTER_GTIDS() という名前でした。(Bug #14775984)

    詳細は、セクション17.1.3「グローバルトランザクション識別子を使用したレプリケーション」を参照してください。

    この関数で使用される GTID セットは、次の例で示すように文字列で表現されるため、引用符で囲む必要があります。

    mysql> SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5'); -> 5

    戻り値は、実行されたトランザクションイベントの数です。MySQL 5.6.8 よりも前では、この関数は、タイムアウトが設定されていない場合は予想不可能な動作となり、GTID ベースのレプリケーションがアクティブでない場合でも呼び出されていました。MySQL 5.6.8 以降では、gtid_modeOFF である場合は、常に NULL を返します。(Bug #14640065)

12.17 MySQL Enterprise Encryption の関数

MySQL 5.6.21 の時点で MySQL Enterprise Edition には、SQL レベルで OpenSSL 機能を表示する OpenSSL ライブラリに基づいた一連の暗号化機能が含まれています。これらの関数を使用することによって、エンタープライズアプリケーションが次の操作を実行できるようになります。

  • 公開鍵非対称暗号方式を使用した、追加のデータ保護の実装

  • 公開鍵、秘密鍵、およびデジタル署名の作成

  • 非対称暗号化および非対称復号化の実行

  • デジタル署名およびデータの検証や妥当性検査に対する暗号化ハッシュの使用

Enterprise Encryption では、RSA、DSA、および DH の暗号アルゴリズムがサポートされています。

Enterprise Encryption は、個々の関数を個別にインストールできるユーザー定義関数 (UDF) ライブラリとして提供されます。

12.17.1 Enterprise Encryption のインストール

Enterprise Encryption の関数は、プラグインディレクトリ (plugin_dir システム変数で名前が指定されたディレクトリ) にインストールされたユーザー定義関数 (UDF) ライブラリファイルに配置されています。UDF ライブラリのベース名は openssl_udf であり、サフィクスはプラットフォームに依存します。たとえば、ファイル名は Linux では openssl_udf.so、Windows では openssl_udf.dll です。

ライブラリファイルから関数をインストールするには、CREATE FUNCTION ステートメントを使用します。ライブラリからすべての関数をロードするには、次のステートメントセットを使用します (必要に応じて、ファイル名サフィクスを調整します)。

CREATE FUNCTION asymmetric_decrypt RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_derive RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_encrypt RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_sign RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION asymmetric_verify RETURNS INTEGER SONAME 'openssl_udf.so';
CREATE FUNCTION create_asymmetric_priv_key RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION create_asymmetric_pub_key RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION create_dh_parameters RETURNS STRING SONAME 'openssl_udf.so';
CREATE FUNCTION create_digest RETURNS STRING SONAME 'openssl_udf.so';

一度インストールすれば、何回サーバーを再起動しても UDF はインストールされたままです。UDF をアンロードするには、DROP FUNCTION ステートメントを使用します。たとえば、鍵生成の関数をアンロードするには、次のように実行します。

DROP FUNCTION create_asymmetric_priv_key;
DROP FUNCTION create_asymmetric_pub_key;

CREATE FUNCTION および DROP FUNCTION ステートメントでは、関数名を小文字で指定する必要があります。これは、大文字と小文字のどちらでも使用できる関数の呼び出し時での使用とは異なります。

mysql データベースの場合、CREATE FUNCTION および DROP FUNCTION ステートメントでは、それぞれ INSERT および DROP 権限が必要です。

12.17.2 Enterprise Encryption の使用法と例

アプリケーションで Enterprise Encryption を使用するには、実行する演算に適した関数を呼び出します。このセクションでは、一部の典型的なタスクを実行する方法を示します。

タスク: RSA 暗号化を使用して秘密鍵と公開鍵のペアを作成します。

-- Encryption algorithm; can be 'DSA' or 'DH' instead
SET @algo = 'RSA';
-- Minimum key length in bits; make larger for stronger keys
SET @key_len = 1024;
-- Create private key
SET @priv = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @key_len);
-- Derive corresponding public key from private key, using same algorithm
SET @pub = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv);

鍵のペアを使用すると、データを暗号化および復号化したり、データを署名および検証したり、対称鍵を生成したりできるようになりました。

タスク: 秘密鍵を使用してデータを暗号化し、公開鍵を使用して復号化します。これには、鍵ペアのメンバーが RSA 鍵である必要があります。

SET @ciphertext = ASYMMETRIC_ENCRYPT(@algo, 'My secret text', @priv);
SET @plaintext = ASYMMETRIC_DECRYPT(@algo, @ciphertext, @pub);

反対に、公開鍵を使用して暗号化し、秘密鍵を使用して復号化できます。

SET @ciphertext = ASYMMETRIC_ENCRYPT(@algo, 'My secret text', @pub);
SET @plaintext = ASYMMETRIC_DECRYPT(@algo, @ciphertext, @priv);

いずれの場合でも、暗号化関数および復号化関数用に指定されたアルゴリズムは、鍵を生成したときに使用されたアルゴリズムと一致する必要があります。

タスク: 文字列からダイジェストを生成します。

-- Digest type; can be 'SHA256', 'SHA384', or 'SHA512' instead
SET @dig_type = 'SHA224';
-- Generate digest string
SET @dig = CREATE_DIGEST(@dig_type, 'My text to digest');

タスク: 鍵ペアを含むダイジェストを使用してデータを署名してから、その署名がダイジェストと一致することを確認します。

-- Encryption algorithm; could be 'DSA' instead; keys must
-- have been created using same algorithm
SET @algo = 'RSA';
-- Generate signature for digest and verify signature against digest
SET @sig = ASYMMETRIC_SIGN(@algo, @dig, @priv, @dig_type);
-- Verify signature against digest
SET @verf = ASYMMETRIC_VERIFY(@algo, @dig, @sig, @pub, @dig_type);

タスク: 対称鍵を作成します。これには、共有対称シークレットを使用して作成される DH 秘密鍵/公開鍵が入力として必要です。鍵の長さを CREATE_DH_PARAMETERS() に渡してシークレットを作成してから、そのシークレットを鍵の長さとして CREATE_ASYMMETRIC_PRIV_KEY() に渡します。

-- Generate DH shared symmetric secret
SET @dhp = CREATE_DH_PARAMETERS(1024);
-- Generate DH key pairs
SET @algo = 'DH';
SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @dhp);
SET @pub1 = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv1);
SET @priv2 = CREATE_ASYMMETRIC_PRIV_KEY(@algo, @dhp);
SET @pub2 = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv2);
-- Generate symmetric key using public key of first party,
-- private key of second party
SET @sym1 = ASYMMETRIC_DERIVE(@pub1, @priv2);
-- Or use public key of second party, private key of first party
SET @sym2 = ASYMMETRIC_DERIVE(@pub2, @priv1);

鍵文字列の値は、SETSELECT、または INSERT を使用することで実行時に作成し、変数やテーブルに格納できます。

SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024);
SELECT CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024) INTO @priv2;
INSERT INTO t (key_col) VALUES(CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024));

ファイルに格納されている鍵文字列の値は、FILE 権限を持つユーザーが LOAD_FILE() 関数を使用することで読み取ることができます。

ダイジェストと署名の文字列は、同様に処理できます。

12.17.3 Enterprise Encryption 関数のリファレンス

表 12.21 MySQL Enterprise Encryption の関数

名前説明
ASYMMETRIC_DECRYPT() 秘密鍵または公開鍵を使用して暗号文を復号化します
ASYMMETRIC_DERIVE() 非対称鍵から対称鍵を導出します
ASYMMETRIC_ENCRYPT() 秘密鍵または公開鍵を使用してプレーンテキストを暗号化します
ASYMMETRIC_SIGN() ダイジェストから署名を生成します
ASYMMETRIC_VERIFY() 署名がダイジェストと一致することを確認します
CREATE_ASYMMETRIC_PRIV_KEY() 秘密鍵を作成します
CREATE_ASYMMETRIC_PUB_KEY() 公開鍵を作成します
CREATE_DH_PARAMETERS() 共有 DH シークレットを生成します
CREATE_DIGEST() 文字列からダイジェストを生成します

12.17.4 Enterprise Encryption 関数の説明

Enterprise Encryption の関数には、次のような一般的な特性があります。

  • 引数の型が不正な場合や引数の数が間違っている場合は、各関数でエラーが返されます。

  • 要求された演算を実行することを関数に許可するのに引数が適していない場合は、必要に応じて NULL または 0 が返されます。これは、指定されたアルゴリズムが関数でサポートされていない場合、鍵の長さが短すぎたり長すぎたりする場合、PEM 書式の鍵文字列として要求される文字列が有効な鍵でない場合などに発生します。

  • ベースとなる SSL ライブラリでは、ランダム度の初期化が処理されます。

関数の一部には、暗号化アルゴリズムの引数が指定されます。次の表には、サポートされているアルゴリズムのサマリーを関数別に示します。

表 12.22 関数でサポートされているアルゴリズム

関数サポートされているアルゴリズム
ASYMMETRIC_DECRYPT()RSA
ASYMMETRIC_DERIVE()DH
ASYMMETRIC_ENCRYPT()RSA
ASYMMETRIC_SIGN()RSA、DSA
ASYMMETRIC_VERIFY()RSA、DSA
CREATE_ASYMMETRIC_PRIV_KEY()RSA、DSA、DH
CREATE_ASYMMETRIC_PUB_KEY()RSA、DSA、DH

注記

RSA、DSA、または DH のいずれかの暗号化アルゴリズムを使用すれば鍵を作成できますが、鍵引数が指定されるその他の関数では、特定のタイプの鍵のみが許可される可能性があります。たとえば、ASYMMETRIC_ENCRYPT() および ASYMMETRIC_DECRYPT() では RSA 鍵のみが許可されます。

次の説明では、Enterprise Encryption 関数を呼び出す手順を示します。追加の例と説明については、セクション12.17.2「Enterprise Encryption の使用法と例」を参照してください。

  • ASYMMETRIC_DECRYPT(algorithm, crypt_str, key_str)

    指定されたアルゴリズムおよび鍵文字列を使用して、暗号化された文字列を復号化し、結果として生成されるプレーンテキストをバイナリ文字列として返します。復号化に失敗した場合は、結果が NULL になります。

    key_str は、PEM 書式の有効な鍵文字列である必要があります。復号化に成功した場合は、公開鍵または秘密鍵の文字列が、暗号化された文字列を生成する際に ASYMMETRIC_ENCRYPT() で使用された公開鍵または秘密鍵の文字列に対応している必要があります。algorithm は、鍵を作成する際に使用された暗号化アルゴリズムを示します。

    サポートされている algorithm 値: 'RSA'

    使用例については、ASYMMETRIC_ENCRYPT() の説明を参照してください。

  • ASYMMETRIC_DERIVE(pub_key_str, priv_key_str)

    あるパーティーの秘密鍵と別のパーティーの公開鍵を使用して対称鍵を導出し、結果として生成される鍵をバイナリ文字列として返します。鍵の抽出に失敗した場合は、結果が NULL になります。

    pub_key_str および priv_key_str は、PEM 書式の有効な鍵文字列である必要があります。これらは、DH アルゴリズムを使用して作成する必要があります。

    公開鍵と秘密鍵の 2 つのペアを持っていると仮定します。

    SET @dhp = CREATE_DH_PARAMETERS(1024);
    SET @priv1 = CREATE_ASYMMETRIC_PRIV_KEY('DH', @dhp);
    SET @pub1 = CREATE_ASYMMETRIC_PUB_KEY('DH', @priv1);
    SET @priv2 = CREATE_ASYMMETRIC_PRIV_KEY('DH', @dhp);
    SET @pub2 = CREATE_ASYMMETRIC_PUB_KEY('DH', @priv2);

    さらに、1 つのペアから秘密鍵を使用し、もう 1 つのペアから公開鍵を使用して、対称鍵文字列を作成すると仮定します。その後、この対称鍵の ID 関係が次のように保持されます。

    ASYMMETRIC_DERIVE(@pub1, @priv2) = ASYMMETRIC_DERIVE(@pub2, @priv1)
  • ASYMMETRIC_ENCRYPT(algorithm, str, key_str)

    指定されたアルゴリズムおよび鍵文字列を使用して文字列を暗号化し、結果として生成される暗号化テキストをバイナリ文字列として返します。暗号化に失敗した場合は、結果が NULL になります。

    str の長さは、バイト単位で key_str の長さ − 11 よりも大きくすることができません。

    key_str は、PEM 書式の有効な鍵文字列にする必要があります。algorithm は、鍵を作成する際に使用された暗号化アルゴリズムを示します。

    サポートされている algorithm 値: 'RSA'

    文字列を暗号化するには、秘密鍵または公開鍵の文字列を ASYMMETRIC_ENCRYPT() に渡します。元の非暗号化文字列をリカバリするには、暗号化に使用された秘密鍵または公開鍵の文字列に対応する公開鍵または秘密鍵の文字列とともに、暗号化された文字列を ASYMMETRIC_DECRYPT() に渡します。

    -- Generate private/public key pair
    SET @priv = CREATE_ASYMMETRIC_PRIV_KEY('RSA', 1024);
    SET @pub = CREATE_ASYMMETRIC_PUB_KEY('RSA', @priv);
    -- Encrypt using private key, decrypt using public key
    SET @ciphertext = ASYMMETRIC_ENCRYPT('RSA', 'The quick brown fox', @priv);
    SET @plaintext = ASYMMETRIC_DECRYPT('RSA', @ciphertext, @pub);
    -- Encrypt using public key, decrypt using private key
    SET @ciphertext = ASYMMETRIC_ENCRYPT('RSA', 'The quick brown fox', @pub);
    SET @plaintext = ASYMMETRIC_DECRYPT('RSA', @ciphertext, @priv);

    次のように仮定します。

    SET @s = a string to be encrypted
    SET @priv = a valid private RSA key string in PEM format
    SET @pub = the corresponding public RSA key string in PEM format

    その後、これらの ID 関係が次のように保持されます。

    ASYMMETRIC_DECRYPT('RSA', ASYMMETRIC_ENCRYPT('RSA', @s, @priv), @pub) = @s
    ASYMMETRIC_DECRYPT('RSA', ASYMMETRIC_ENCRYPT('RSA', @s, @pub), @priv) = @s
  • ASYMMETRIC_SIGN(algorithm, digest_str, priv_key_str, digest_type)

    秘密鍵文字列を使用してダイジェスト文字列に署名し、その署名をバイナリ文字列として返します。署名に失敗した場合は、結果が NULL になります。

    digest_str はダイジェスト文字列です。これは、CREATE_DIGEST() を呼び出すことで生成できます。digest_type は、ダイジェスト文字列を生成する際に使用されたダイジェストアルゴリズムを示します。

    priv_key_str は、ダイジェスト文字列に著名する際に使用される秘密鍵文字列です。これは、PEM 書式の有効な鍵文字列にする必要があります。algorithm は、鍵を作成する際に使用された暗号化アルゴリズムを示します。

    サポートされている algorithm 値: 'RSA''DSA'

    サポートされている digest_type 値: 'SHA224''SHA256''SHA384''SHA512'

    使用例については、ASYMMETRIC_VERIFY() の説明を参照してください。

  • ASYMMETRIC_VERIFY(algorithm, digest_str, sig_str, pub_key_str, digest_type)

    署名文字列がダイジェスト文字列と一致するかどうかを確認し、確認に成功したのか失敗したのかを示す 1 または 0 を返します。

    digest_str はダイジェスト文字列です。これは、CREATE_DIGEST() を呼び出すことで生成できます。digest_type は、ダイジェスト文字列を生成する際に使用されたダイジェストアルゴリズムを示します。

    sig_str は署名文字列です。これは、ASYMMETRIC_SIGN() を呼び出すことで生成できます。

    pub_key_str は、署名者の公開鍵文字列です。これは、署名文字列を生成する ASYMMETRIC_SIGN() に渡される秘密鍵に対応し、PEM 書式の有効な鍵文字列にする必要があります。algorithm は、鍵を作成する際に使用された暗号化アルゴリズムを示します。

    サポートされている algorithm 値: 'RSA''DSA'

    サポートされている digest_type 値: 'SHA224''SHA256''SHA384''SHA512'

    -- Set the encryption algorithm and digest type
    SET @algo = 'RSA';
    SET @dig_type = 'SHA224';
    -- Create private/public key pair
    SET @priv = CREATE_ASYMMETRIC_PRIV_KEY(@algo, 1024);
    SET @pub = CREATE_ASYMMETRIC_PUB_KEY(@algo, @priv);
    -- Generate digest from string
    SET @dig = CREATE_DIGEST(@dig_type, 'The quick brown fox');
    -- Generate signature for digest and verify signature against digest
    SET @sig = ASYMMETRIC_SIGN(@algo, @dig, @priv, @dig_type);
    SET @verf = ASYMMETRIC_VERIFY(@algo, @dig, @sig, @pub, @dig_type);
  • CREATE_ASYMMETRIC_PRIV_KEY(algorithm, {key_len|dh_secret})

    指定されたアルゴリズムおよび鍵の長さまたは DH シークレットを使用して秘密鍵を作成し、その鍵を PEM 書式のバイナリ文字列として返します。鍵の生成に失敗した場合は、結果が NULL になります。

    サポートされている algorithm 値: 'RSA''DSA''DH'

    サポートされている key_len 値: 最小の鍵の長さは 1024 ビットです。最大の鍵の長さはアルゴリズムによって異なり、RSA の場合は 16,384、DSA の場合は 10,000 です。これらの長さは、OpenSSL によって課された制約です。

    DH 鍵の場合は、キーの長さの代わりに、共有 DH シークレットを渡します。シークレットを作成するには、鍵の長さを CREATE_DH_PARAMETERS() に渡します。

    この例では、2,048 ビットの DSA 秘密鍵を作成してから、その秘密鍵から公開鍵を導出します。

    SET @priv = CREATE_ASYMMETRIC_PRIV_KEY('DSA', 2048);
    SET @pub = CREATE_ASYMMETRIC_PUB_KEY('DSA', @priv);

    DH 鍵の生成を示す例については、ASYMMETRIC_DERIVE() の説明を参照してください。

    鍵の長さと暗号化アルゴリズムを選択する際の一般的ないくつかの考慮事項は、次のとおりです。

    • 鍵のサイズとともに、公開鍵と秘密鍵の暗号化強度が増加しますが、鍵の生成時間も同様に増加します。

    • DH 鍵の生成時間は、RSA 鍵または RSA 鍵よりも大幅に長くなります。

    • 非対称暗号化関数は、対称関数よりも遅くなります。パフォーマンスが重要な要素であり、その関数が非常に頻繁に使用される場合は、対称暗号化を使用した方が適切です。たとえば、AES_ENCRYPT() および AES_DECRYPT() を使用することを検討してください。

  • CREATE_ASYMMETRIC_PUB_KEY(algorithm, priv_key_str)

    指定されたアルゴリズムを使用して、指定された秘密鍵から公開鍵を導出し、その鍵を PEM 書式のバイナリ文字列として返します。鍵の抽出に失敗した場合は、結果が NULL になります。

    priv_key_str は、PEM 書式の有効な鍵文字列にする必要があります。algorithm は、鍵を作成する際に使用された暗号化アルゴリズムを示します。

    サポートされている algorithm 値: 'RSA''DSA''DH'

    使用例については、CREATE_ASYMMETRIC_PRIV_KEY() の説明を参照してください。

  • CREATE_DH_PARAMETERS(key_len)

    DH 秘密鍵と公開鍵のペアを生成するための共有シークレットを作成し、CREATE_ASYMMETRIC_PRIV_KEY() に渡すことができるバイナリ文字列を返します。シークレットの生成に失敗した場合は、結果が NULL になります。

    サポートされている key_len 値: 最小および最大の鍵の長さは、1024 ビットおよび 10,000 ビットです。これらの長さは、OpenSSL によって課された制約です。

    対称鍵を生成するための戻り値を使用する方法を示す例については、ASYMMETRIC_DERIVE() の説明を参照してください。

    SET @dhp = CREATE_DH_PARAMETERS(1024);
  • CREATE_DIGEST(digest_type, str)

    指定されたダイジェストタイプを使用して、指定された文字列からダイジェストを作成し、そのダイジェストをバイナリ文字列として返します。ダイジェストの生成に失敗した場合は、結果が NULL になります。

    サポートされている digest_type 値: 'SHA224''SHA256''SHA384''SHA512'

    SET @dig = CREATE_DIGEST('SHA512', The quick brown fox');

    結果として生成されるダイジェスト文字列は、ASYMMETRIC_SIGN() および ASYMMETRIC_VERIFY() との使用に適しています。

12.18 その他の関数

表 12.23 その他の関数

名前説明
DEFAULT() テーブルカラムのデフォルト値を返します
GET_LOCK() 名前付きロックを取得します
INET_ATON() IP アドレスの数値を返します
INET_NTOA() 数値から IP アドレスを返します
INET6_ATON() IPv6 アドレスの数値を返します
INET6_NTOA() 数値から IPv6 アドレスを返します
IS_FREE_LOCK() 名前付きロックが解放されているかどうかを確認します
IS_IPV4() 引数が IPv4 アドレスの場合、true を返します
IS_IPV4_COMPAT() 引数が IPv4 互換アドレスの場合、true を返します
IS_IPV4_MAPPED() 引数が IPv4 マップアドレスの場合、true を返します
IS_IPV6() 引数が IPv6 アドレスの場合、true を返します
IS_USED_LOCK() 名前付きロックが使用中かどうかを確認します。true の場合は接続識別子を返します。
MASTER_POS_WAIT() スレーブが指定された位置まですべての更新を読み取って適用するまで、ブロックします
NAME_CONST() 指定された名前がカラムに付けられます
RAND() ランダムな浮動小数点値を返します
RELEASE_LOCK() 名前付きロックを解放します
SLEEP() ある秒数間スリープ状態にします
UUID() ユニバーサル固有識別子 (UUID) を返します
UUID_SHORT() 整数値のユニバーサル識別子を返します
VALUES() INSERT で使用される値を定義します

  • DEFAULT(col_name)

    テーブルカラムのデフォルト値を返します。カラムにデフォルト値がない場合は、エラーが発生します。

    mysql> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;
  • FORMAT(X,D)

    数値 X'#,###,###.##' のような書式に変換し、小数点第 D 位に丸めて、その結果を文字列として返します。詳細は、セクション12.5「文字列関数」を参照してください。

  • GET_LOCK(str,timeout)

    timeout 秒のタイムアウトを使用して、文字列 str で指定された名前でロックの取得を試みます。負の timeout 値は、無限のタイムアウトを表します。

    ロックの取得に成功した場合は 1 を返し、試行がタイムアウトになった場合 (たとえば、ほかのクライアントがすでにその名前をロックしている場合) は 0 を返し、エラー (メモリー不足や mysqladmin kill によるスレッドの停止など) が発生した場合は NULL を返します。GET_LOCK() を使用してロックを取得した場合は、RELEASE_LOCK() を実行したとき、新しい GET_LOCK() を実行したとき、または接続が切断されたとき (正常または異常を問わず) に解除されます。GET_LOCK() を使用して取得されたロックは、トランザクションとやりとりを行いません。つまり、トランザクションをコミットしても、トランザクション中に取得されたロックは解除されません。

    GET_LOCK() を使用すると、アプリケーションロックを実装したり、レコードロックのシミュレーションを行なったりできます。名前はサーバー全体にわたってロックされます。1 つのセッション内で名前がロックされた場合は、GET_LOCK() によって、別のセッションによる同じ名前を持つロックのリクエストがブロックされます。これにより、指定されたロック名について合意したクライアントは、その名前を使用すると共同のアドバイザリロックを実行できます。ただし、共同するクライアントのセットに属さないクライアントも、不注意と故意のどちらででも、名前をロックできることに注意してください。したがって、共同するクライアントがその名前をロックできないようにしてください。この可能性を減らす方法の 1 つは、データベース固有またはアプリケーション固有のロック名を使用することです。たとえば、db_name.str または app_name.str 形式のロック名を使用します。

    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

    ロック 'lock1' は 2 番目の GET_LOCK() 呼び出しによって自動的に解除されるため、2 番目の RELEASE_LOCK() 呼び出しは NULL を返します。

    複数のクライアントがロックを待機している場合は、ロックを取得する順序が定義されません。アプリケーションは、ロックリクエストを発行したときと同じ順序でクライアントがロックを取得すると仮定しません。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • INET_ATON(expr)

    IPv4 ネットワークアドレスのドット区切り表現が文字列として指定された場合、アドレスの数値を表す整数をネットワークバイト順序 (ビッグエンディアン) で返します。引数が認識されない場合、INET_ATON()NULL を返します。

    mysql> SELECT INET_ATON('10.0.5.9'); -> 167773449

    この例では、戻り値は 10×2563 + 0×2562 + 5×256 + 9 として計算されます。

    INET_ATON() は、短い形式の IP アドレス ('127.0.0.1' の表現として '127.1' など) の場合に、非 NULL を返す場合と返さない場合があります。このため、このようなアドレスには INET_ATON() を使用しないでください。

    注記

    INET_ATON() で生成された値を格納するには、署名される INT ではなく、INT UNSIGNED カラムを使用します。署名付きのカラムを使用する場合は、第 1 オクテットが 127 よりも大きい IP アドレスに対応する値を正常に格納できません。セクション11.2.6「範囲外およびオーバーフローの処理」を参照してください。

  • INET_NTOA(expr)

    数値の IPv4 ネットワークアドレスがネットワークバイト順序で指定された場合、アドレスのドット区切り文字列表現を接続文字セット内の非バイナリ文字列として返します。引数が認識されない場合、INET_NTOA()NULL を返します。

    mysql> SELECT INET_NTOA(167773449); -> '10.0.5.9'
  • INET6_ATON(expr)

    IPv6 または IPv4 ネットワークアドレスが文字列として指定された場合、アドレスの数値を表すバイナリ文字列をネットワークバイト順序 (ビッグエンディアン) で返します。数値書式の IPv6 アドレスでは最大の整数型よりも大きいバイトが必要であるため、この関数で返される表現のデータ型は、VARBINARY (IPv6 アドレスの場合は VARBINARY(16)、IPv4 アドレスの場合は VARBINARY(4)) です。引数が有効なアドレスでない場合、INET6_ATON()NULL を返します。

    次の例では、HEX() を使用して INET6_ATON() の結果を出力可能な形式で表示します。

    mysql> SELECT HEX(INET6_ATON('fdfe::5a55:caff:fefa:9089')); -> 'FDFE0000000000005A55CAFFFEFA9089'
    mysql> SELECT HEX(INET6_ATON('10.0.5.9')); -> '0A000509'

    INET6_ATON() は、有効な引数上の複数の制約を監視します。これらについては、次のリストに例とともに示します。

    • fe80::3%1fe80::3%eth0 のような末尾のゾーン ID は許可されません。

    • 2001:45f:3:ba::/64192.168.1.0/24 のような末尾のネットワークマスクは許可されません。

    • IPv4 アドレスを表す値では、クラスレスアドレスのみがサポートされます。192.168.1 などのクラスフルアドレスは拒否されます。192.168.1.2:8080 のような末尾のポート番号は許可されません。192.0xa0.1.2 のようなアドレスコンポーネント内の 16 進数は許可されません。8 進数はサポートされていません。192.168.010.1192.168.8.1 ではなく、192.168.10.1 として処理されます。このような IPv4 の制約は、IPv4 アドレス部分を持つ IPv6 アドレス (IPv4 互換アドレスや IPv4 マップアドレスなど) にも適用されます。

    INT 値として数値形式で表現された IPv4 アドレス expr を、VARBINARY 値として数値形式で表現された IPv6 アドレスに変換するには、次の式を使用します。

    INET6_ATON(INET_NTOA(expr))

    例:

    mysql> SELECT HEX(INET6_ATON(INET_NTOA(167773449))); -> '0A000509'

    この関数は、MySQL 5.6.3 で追加されました。

  • INET6_NTOA(expr)

    バイナリ文字列として数値形式で表現された IPv6 または IPv4 ネットワークアドレスが指定された場合、アドレスの文字列表現を接続文字セット内の非バイナリ文字列として返します。引数が有効なアドレスでない場合、INET6_NTOA()NULL を返します。

    INET6_NTOA() には、次のようなプロパティーがあります。

    • 変換はオペレーティングシステムの機能を使用して実行されないため、出力文字列はプラットフォームに依存しません。

    • 戻り文字列の最大長は 39 (4 x 8 + 7) です。次のステートメントが指定された場合、

      CREATE TABLE t AS SELECT INET6_NTOA(expr) AS c1;

      結果として生成されるテーブルに次の定義が含まれます。

      CREATE TABLE t (c1 VARCHAR(39) CHARACTER SET utf8 DEFAULT NULL);
    • 戻り文字列では、IPv6 アドレスを表す小文字が使用されます。

    mysql> SELECT INET6_NTOA(INET6_ATON('fdfe::5a55:caff:fefa:9089')); -> 'fdfe::5a55:caff:fefa:9089'
    mysql> SELECT INET6_NTOA(INET6_ATON('10.0.5.9')); -> '10.0.5.9'
    mysql> SELECT INET6_NTOA(UNHEX('FDFE0000000000005A55CAFFFEFA9089')); -> 'fdfe::5a55:caff:fefa:9089'
    mysql> SELECT INET6_NTOA(UNHEX('0A000509')); -> '10.0.5.9'

    この関数は、MySQL 5.6.3 で追加されました。

  • IS_FREE_LOCK(str)

    str という名前が付けられたロックが使用可能であるか (つまり、ロックされていないか) どうかをチェックします。ロックが使用可能である (だれもロックを使用していない) 場合は 1 を返し、使用中である場合は 0 を返し、エラー (不正な引数など) が発生した場合は NULL を返します。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • IS_IPV4(expr)

    引数が文字列として指定された有効な IPv4 アドレスの場合は 1 を返し、それ以外の場合は 0 を返します。

    mysql> SELECT IS_IPV4('10.0.5.9'), IS_IPV4('10.0.5.256'); -> 1, 0

    特定の引数では、IS_IPV4() が 1 を返すと、INET_ATON() (および INET6_ATON()) は NULL 以外を返します。逆のステートメントは該当しません。一部のケースでは、IS_IPV4() が 0 を返すと、INET_ATON()NULL 以外を返します。

    上記の備考で示したように、IS_IPV4() は、有効な IPv4 アドレスを構成するものに関して、INET_ATON() よりも厳密であるため、無効な値に対して強固なチェックを実行する必要のあるアプリケーションで役立つことがあります。または、INET6_ATON() を使用して、IPv4 アドレスを内部形式に変換し、(無効なアドレスを示す) NULL の結果をチェックします。INET6_ATON() は、IPv4 アドレスのチェックという点では、IS_IPV4() と同等の強固さです。

    この関数は、MySQL 5.6.3 で追加されました。

  • IS_IPV4_COMPAT(expr)

    この関数には、INET6_ATON() で返されるように、バイナリ文字列として数値形式で表現された IPv6 アドレスが指定されます。引数が有効な IPv4 互換 IPv6 アドレスの場合は 1 を返し、それ以外の場合は 0 を返します。IPv4 互換アドレスの形式は、::ipv4_address です。

    mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.5.9')); -> 1
    mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::ffff:10.0.5.9')); -> 0

    IPv4 互換アドレスの IPv4 部分は、16 進表記法を使用して表現することもできます。たとえば、192.168.0.1 には、次のような生の 16 進値が含まれます。

    mysql> SELECT HEX(INET6_ATON('192.168.0.1')); -> 'C0A80001'

    IPv4 互換形式で表現された ::192.168.0.1 は、::c0a8:0001 または (先頭のゼロなしの) ::c0a8:1 と同等です。

    mysql> SELECT ->  IS_IPV4_COMPAT(INET6_ATON('::192.168.0.1')), ->  IS_IPV4_COMPAT(INET6_ATON('::c0a8:0001')), ->  IS_IPV4_COMPAT(INET6_ATON('::c0a8:1')); -> 1, 1, 1

    この関数は、MySQL 5.6.3 で追加されました。

  • IS_IPV4_MAPPED(expr)

    この関数には、INET6_ATON() で返されるように、バイナリ文字列として数値形式で表現された IPv6 アドレスが指定されます。引数が有効な IPv4 マップ IPv6 アドレスの場合は 1 を返し、それ以外の場合は 0 を返します。IPv4 マップアドレスの形式は、::ffff:ipv4_address です。

    mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::10.0.5.9')); -> 0
    mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.5.9')); -> 1

    IS_IPV4_COMPAT() と同様に、IPv4 マップアドレスの IPv4 部分は、16 進表記法を使用して表現することもできます。

    mysql> SELECT ->  IS_IPV4_MAPPED(INET6_ATON('::ffff:192.168.0.1')), ->  IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:0001')), ->  IS_IPV4_MAPPED(INET6_ATON('::ffff:c0a8:1')); -> 1, 1, 1

    この関数は、MySQL 5.6.3 で追加されました。

  • IS_IPV6(expr)

    引数が文字列として指定された有効な IPv6 アドレスの場合は 1 を返し、それ以外の場合は 0 を返します。この関数では、IPv4 アドレスが有効な IPv6 アドレスとみなされません。

    mysql> SELECT IS_IPV6('10.0.5.9'), IS_IPV6('::1'); -> 0, 1

    特定の引数では、IS_IPV6() が 1 を返すと、INET6_ATON()NULL 以外を返します。

    この関数は、MySQL 5.6.3 で追加されました。

  • IS_USED_LOCK(str)

    str という名前が付けられたロックが使用中であるか (つまり、ロックされているか) どうかをチェックします。その場合は、ロックを保持しているクライアントの接続識別子を返します。そうでない場合は、NULL を返します。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • MASTER_POS_WAIT(log_name,log_pos[,timeout])

    この関数は、マスター/スレーブの同期化を制御する際に役立ちます。スレーブがマスターログで指定された位置までのすべての更新を読み取り、適用するまでブロックします。戻り値は、指定された位置まで進むまでスレーブが待機する必要のあるログイベントの数です。この関数は、スレーブ SQL スレッドが開始されていない場合、スレーブのマスター情報が初期化されていない場合、引数が正しくない場合、またはエラーが発生した場合に NULL を返します。タイムアウトを超えた場合は、-1 を返します。MASTER_POS_WAIT() の待機中にスレーブ SQL スレッドが停止すると、関数は NULL を返します。スレーブが指定された位置を過ぎると、関数は即座に返します。

    timeout 値が指定されている場合、MASTER_POS_WAIT() は、timeout 秒が経過した時点で待機を停止します。timeout は 0 よりも大きい値にする必要があります。timeout がゼロまたは負の値である場合は、タイムアウトがないことを意味します。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • NAME_CONST(name,value)

    指定された値を返します。結果セットのカラムを生成する際に NAME_CONST() を使用すると、指定された名前がカラムに付けられます。引数には定数を指定してください。

    mysql> SELECT NAME_CONST('myname', 14);+--------+
    | myname |
    +--------+
    | 14 |
    +--------+

    この関数は、内部でのみ使用されます。セクション20.7「ストアドプログラムのバイナリロギング」で説明したように、ローカルプログラム変数への参照を含むストアドプログラムからステートメントを記述する際に、サーバーで使用されます。この関数は、mysqlbinlog からの出力に表示されることがあります。

    アプリケーションで次のような単純なエイリアスを使用しても、上記で示した例とまったく同じ結果を取得できます。

    mysql> SELECT 14 AS myname;+--------+
    | myname |
    +--------+
    | 14 |
    +--------+
    1 row in set (0.00 sec)

    カラムのエイリアスについての詳細は、セクション13.2.9「SELECT 構文」を参照してください。

  • RELEASE_LOCK(str)

    GET_LOCK() を使用して取得された文字列 str によって名前が付けられたロックを解除します。ロックが解除された場合は 1 を返し、このスレッドによってロックが確立されなかった場合 (その場合、ロックは解除されません) は 0 を返し、名前付きのロックが存在しない場合は NULL を返します。GET_LOCK() を呼び出しても取得されなかった場合や、事前に解除された場合は、ロックが存在しません。

    DO ステートメントは、RELEASE_LOCK() とともに使用すると便利です。セクション13.2.3「DO 構文」を参照してください。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • SLEEP(duration)

    duration 引数で指定された秒数間スリープ状態に (一時停止) してから、0 を返します。SLEEP() が中断された場合は、1 を返します。この期間には、小数部分が含まれている場合もあります。

    この関数は、ステートメントベースのレプリケーションでは安全に使用できません。binlog_formatSTATEMENT に設定されているときに、この関数を使用すると、警告のログが記録されます。

  • UUID()

    1997 年 10 月に The Open Group によって公開された DCE 1.1: Remote Procedure Call (付録 A) 「CAE (Common Applications Environment) Specifications」(ドキュメント番号 C706、http://www.opengroup.org/public/pubs/catalog/c706.htm)に従って生成されたユニバーサル固有識別子 (UUID) を返します。

    UUID は、空間と時間においてグローバルに一意の数字として設計されています。UUID() の 2 回の呼び出しが、相互に接続されていない 2 台の異なるコンピュータ上で実行された場合でも、これらの呼び出しでは 2 つの異なる値が生成されると想定されます。

    UUID は、aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee という書式で、5 つの 16 進数で構成される utf8 文字列で表現された 128 ビットの数値です。

    • 最初の 3 つの数字は、タイムスタンプから生成されます。

    • 4 番目の数字には、(たとえば、サマータイムが原因で) タイムスタンプ値の単調性が失われる場合に備えて、時間の一意性が保持されます。

    • 5 番目の数字は、空間の一意性を提供する IEEE 802 ノード番号です。(たとえば、ホストコンピュータに Ethernet カードが搭載されていないことや、オペレーティングシステム上のインタフェースのハードウェアアドレスを見つける方法がわからないことが原因で) 後者を使用できない場合は、ランダムな数字で置き換えられます。この場合、空間の一意性は保証できません。しかしそれでも、競合が発生する可能性は非常に低くなります。

      現在、インタフェースの MAC アドレスは、FreeBSD と Linux でのみ考慮されています。その他のオペレーティングシステムでは、ランダムに生成された 48 ビットの数字が MySQL で使用されます。

    mysql> SELECT UUID(); -> '6ccd780c-baba-1026-9564-0040f4311e29'
    警告

    UUID() 値の目的は一意性を保つことですが、必ずしも推測不可能または予測不可能であるとはかぎりません。予測不可能性が必要である場合は、UUID 値を何か別の方法で生成してください。

    注記

    UUID() は、ステートメントベースのレプリケーションでは正しく動作しません。

  • UUID_SHORT()

    (UUID() 関数で返されるような文字列形式の 128 ビット識別子ではなく)、短いユニバーサル識別子を 64 ビットの符号なし整数として返します。

    次の条件を満たす場合は、UUID_SHORT() の値が一意であることが保証されます。

    • 一連のマスター/スレーブサーバーの中で現在のホストの server_id が一意である

    • server_id の範囲が 0 から 255 である

    • mysqld の再起動間にサーバーのシステム時間を戻さない

    • mysqld の再起動間に、UUID_SHORT() を 1 秒あたり平均 1600 万を上回る回数で呼び出さない

    UUID_SHORT() の戻り値は、次のように構成されます。

     (server_id & 255) << 56
    + (server_startup_time_in_seconds << 24)
    + incremented_variable++;
    mysql> SELECT UUID_SHORT(); -> 92395783831158784
    注記

    UUID_SHORT() は、ステートメントベースのレプリケーションでは正しく動作しません。

  • VALUES(col_name)

    INSERT ... ON DUPLICATE KEY UPDATE ステートメントでは、UPDATE 句の VALUES(col_name) 関数を使用すると、ステートメントの INSERT 部分からカラム値を参照できます。つまり、UPDATE 句の VALUES(col_name) は、挿入される col_name 値を参照するため、重複キーの競合が発生しなくなります。この関数は、複数の行を挿入する際に特に役立ちます。VALUES() 関数は、INSERT ステートメントの ON DUPLICATE KEY UPDATE 句でのみ有効であり、それ以外の場合は NULL を返します。セクション13.2.5.3「INSERT ... ON DUPLICATE KEY UPDATE 構文」を参照してください。

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

12.19 GROUP BY 句で使用される関数と修飾子

12.19.1 GROUP BY (集約) 関数

表 12.24 集約 (GROUP BY) 関数

名前説明
AVG() 引数の平均値を返します
BIT_AND() ビット単位の And を返します
BIT_OR() ビット単位の OR を返します
BIT_XOR() ビット単位の XOR を返します
COUNT() 返された行数のカウントを返します
COUNT(DISTINCT) 異なる値のカウントを返します
GROUP_CONCAT() 連結された文字列を返します
MAX() 最大値を返します
MIN() 最小値を返します
STD() 母標準偏差を返します
STDDEV() 母標準偏差を返します
STDDEV_POP() 母標準偏差を返します
STDDEV_SAMP() 標本標準偏差を返します
SUM() 集計を返します
VAR_POP() 母標準分散を返します
VAR_SAMP() 標本分散を返します
VARIANCE() 母標準分散を返します

このセクションでは、値のセットを演算するグループ (集約) 関数について説明します。特に指定されていなければ、グループ関数では NULL 値が無視されます。

GROUP BY 句を含まないステートメントでグループ関数を使用する場合は、すべての行をグループ化することと同等になります。詳細は、セクション12.19.3「MySQL での GROUP BY の処理」を参照してください。

数値の引数の場合、分散および標準偏差関数が DOUBLE 値を返します。SUM() および AVG() 関数は、正確な値の引数 (整数または DECIMAL) の場合は DECIMAL 値を返し、近似値の引数 (FLOAT または DOUBLE) の場合は DOUBLE 値を返します。

SUM() および AVG() 集計関数は時間値を扱いません。(これらは値を数字に変換するので、最初の数字以外の文字のあとのすべての情報が失われます。)この問題を回避するには、数値単位に変換し、集計操作を実行してから、時間値に戻します。例:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

数値引数を取る SUM()AVG() などの関数は、必要に応じて引数を数値にキャストします。SETENUM 値の場合、キャスト演算でベースとなる数値が使用されます。

  • AVG([DISTINCT] expr)

    expr の平均値を返します。DISTINCT オプションを使用すると、個別の expr 値の平均を返すことができます。

    一致する行がなかった場合、AVG()NULL を返します。

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

    expr 内のすべてのビットのビット単位の AND を返します。計算は 64 ビット (BIGINT) の精度で実行されます。

    一致する行がなかった場合、この関数は 18446744073709551615 を返します。(これは、すべてのビットが 1 に設定された符号なし BIGINT 値の値です。)

  • BIT_OR(expr)

    expr 内のすべてのビットのビット単位の OR を返します。計算は 64 ビット (BIGINT) の精度で実行されます。

    一致する行がなかった場合、この関数は 0 を返します。

  • BIT_XOR(expr)

    expr 内のすべてのビットのビット単位の XOR を返します。計算は 64 ビット (BIGINT) の精度で実行されます。

    一致する行がなかった場合、この関数は 0 を返します。

  • COUNT(expr)

    SELECT ステートメントで取得された行に含まれる expr の非 NULL 値の数を返します。結果は BIGINT 値になります。

    一致する行がなかった場合、COUNT()0 を返します。

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

    COUNT(*) は、NULL 値が含まれるかどうかに関係なく、取得された行の数を返すという点で少し異なります。

    COUNT(*) は、SELECT が 1 つのテーブルから取得し、その他のカラムは取得されず、WHERE 句がない場合に、非常に迅速に返すように最適化されています。例:

    mysql> SELECT COUNT(*) FROM student;

    この最適化は、MyISAM テーブルにのみ適用されます。その理由は、正確な行数は、このストレージエンジンで格納されることで、非常にすばやくアクセスできるためです。InnoDB などのトランザクショナルストレージエンジンで正確な行数を格納すると、複数のトランザクションが発生し、それぞれが数に影響を与える可能性があるため、問題が発生する可能性が高くなります。

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

    さまざまな非 NULLexpr 値を含む行の数を返します。

    一致する行がなかった場合、COUNT(DISTINCT)0 を返します。

    mysql> SELECT COUNT(DISTINCT results) FROM student;

    MySQL では、式のリストを指定することで、NULL が含まれない個別の式の組み合わせ数を取得できます。標準 SQL では、COUNT(DISTINCT ...) 内部で、すべての式の連結を行う必要があります。

  • GROUP_CONCAT(expr)

    この関数は、グループから連結された非 NULL 値を含む文字列の結果を返します。非 NULL 値がない場合は、NULL を返します。完全な構文は次のとおりです。

    GROUP_CONCAT([DISTINCT] expr [,expr ...] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name ...]] [SEPARATOR str_val])
    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 システム変数で指定された最大長まで切り捨てられます。その変数のデフォルト値は 1024 です。さらに高い値にも設定できますが、戻り値の有効な最大長は、max_allowed_packet の値によって制約されます。実行時に group_concat_max_len の値を変更するための構文は、次のとおりです。ここで、val は符号なし整数です。

    SET [GLOBAL | SESSION] group_concat_max_len = val;

    戻り値は、引数が非バイナリとバイナリのどちらの文字列であるのかに応じて、非バイナリ文字列またはバイナリ文字列になります。結果の型は、group_concat_max_len が 512 以下の場合 (この場合、結果の型は VARCHAR または VARBINARY です) を除いて、TEXT または BLOB です。

    CONCAT() および CONCAT_WS(): セクション12.5「文字列関数」も参照してください。

  • MAX([DISTINCT] expr)

    expr の最大値を返します。MAX() には、文字列の引数を指定できます。このような場合は、最大の文字列値が返されます。セクション8.3.1「MySQL のインデックスの使用の仕組み」を参照してください。DISTINCT キーワードを使用すると、個別の expr 値の最大を検索できます。ただし、DISTINCT を省略した場合と同じ結果が生成されます。

    一致する行がなかった場合、MAX()NULL を返します。

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

    現在、MySQL の MAX() では、ENUMSET カラムが、セット内の文字列の相対位置ではなく、文字列値について比較されます。これは、ORDER BY による比較方法とは異なります。これは、今後の MySQL リリースで反映される予定です。

  • MIN([DISTINCT] expr)

    expr の最小値を返します。MIN() には、文字列の引数を指定できます。このような場合は、最小の文字列値が返されます。セクション8.3.1「MySQL のインデックスの使用の仕組み」を参照してください。DISTINCT キーワードを使用すると、個別の expr 値の最小を検索できます。ただし、DISTINCT を省略した場合と同じ結果が生成されます。

    一致する行がなかった場合、MIN()NULL を返します。

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

    現在、MySQL の MIN() では、ENUMSET カラムが、セット内の文字列の相対位置ではなく、文字列値について比較されます。これは、ORDER BY による比較方法とは異なります。これは、今後の MySQL リリースで反映される予定です。

  • STD(expr)

    expr の母標準偏差を返します。これは、標準 SQL の拡張です。代わりに、標準 SQL 関数 STDDEV_POP() を使用できます。

    一致する行がなかった場合、この関数は NULL を返します。

  • STDDEV(expr)

    expr の母標準偏差を返します。この関数は、Oracle との互換性を確保するために提供されています。代わりに、標準 SQL 関数 STDDEV_POP() を使用できます。

    一致する行がなかった場合、この関数は NULL を返します。

  • STDDEV_POP(expr)

    expr の母標準偏差 (VAR_POP() の平方根) を返します。STD() または STDDEV() を使用することもできます。これらは同等ですが、標準 SQL ではありません。

    一致する行がなかった場合、STDDEV_POP()NULL を返します。

  • STDDEV_SAMP(expr)

    expr の標本標準偏差 (VAR_SAMP() の平方根) を返します。

    一致する行がなかった場合、STDDEV_SAMP()NULL を返します。

  • SUM([DISTINCT] expr)

    expr の集計を返します。戻り値のセットに行が含まれていない場合、SUM()NULL を返します。DISTINCT キーワードを使用すると、個別の expr 値のみを集計できます。

    一致する行がなかった場合、SUM()NULL を返します。

  • VAR_POP(expr)

    expr の母標準分散を返します。行は標本ではなく、母集団全体とみなされるため、行の数が分母とみなされます。また、VARIANCE() を使用することもできます。これは同等ですが、標準 SQL ではありません。

    一致する行がなかった場合、VAR_POP()NULL を返します。

  • VAR_SAMP(expr)

    expr の標本分散を返します。つまり、分母は行の数から 1 を引いたものです。

    一致する行がなかった場合、VAR_SAMP()NULL を返します。

  • VARIANCE(expr)

    expr の母標準分散を返します。これは、標準 SQL の拡張です。代わりに、標準 SQL 関数 VAR_POP() を使用できます。

    一致する行がなかった場合、VARIANCE()NULL を返します。

12.19.2 GROUP BY 修飾子

GROUP BY 句では、追加の行がサマリー出力に追加される WITH ROLLUP 修飾子が許可されます。これらの行は、高レベル (または超集約) のサマリー演算を表します。したがって、ROLLUP で単一のクエリーを使用すれば、複数レベルの分析で質問に回答できます。たとえば、これを使用すれば、OLAP (Online Analytical Processing) 演算をサポートできます。

sales という名前が付けられたテーブルに、売り上げの収益性を記録するための yearcountryproduct、および profit カラムが含まれていると仮定します。

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

次のような単純な GROUP BY を使用すれば、テーブルの内容を年ごとにまとめることができます。

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

この出力には、年ごとの合計収益が表示されますが、すべての年にわたって集計された合計収益を確認する場合は、各値を自分で合計するか、追加のクエリーを実行する必要があります。

または、単一のクエリーで両方のレベルの分析を提供する ROLLUP も使用できます。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 値で識別されます。

複数の GROUP BY カラムがある場合は、ROLLUP の効果がより複雑になります。この場合、最後のグループ化カラム以外でブレイク (値の変更) が発生するたびに、クエリーによって追加の超集約サマリー行が生成されます。

たとえば、ROLLUP を使用しない場合は、yearcountry、および product に基づいた sales テーブルのサマリーが次のように表示されます。

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 |
+------+---------+------------+-------------+

この出力には、year/country/product の分析レベルでのみサマリー値が示されます。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 出力の解釈方法を示します。

  • 指定された year と country に対応する product 行の各セットに続いて、すべての product の合計を示す追加のサマリー行が生成されます。これらの行には、NULL に設定された product カラムが含まれています。

  • 指定された year に対応する行の各セットに続いて、すべての country と product の合計を示す追加のサマリー行が生成されます。これらの行には、NULL に設定された country および products カラムが含まれています。

  • 最後に、その他のすべての行に続いて、すべての year、country、および product の総合計を示す追加のサマリー行が生成されます。この行には、NULL に設定された yearcountry、および products カラムが含まれています。

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 値はクライアント側で NULL として表示され、MySQL クライアントプログラミングインタフェースのいずれかを使用してテストできます。

MySQL では、GROUP BY リストに表示されないカラムを、選択リストで名前を指定することが許可されます。この場合、サーバーはサマリー行内のこのような非集約カラムから任意の値を自由に選択できます。これには、WITH ROLLUP で追加された追加の行も含まれます。たとえば、次のクエリーでは、countryGROUP BY リストに表示されない非集約カラムであり、このカラムで選択された値は不確定です。

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

この動作は、ONLY_FULL_GROUP_BY SQL モードが無効になっている場合に発生します。このモードが有効になっている場合は、countryGROUP BY 句に一覧表示されないため、サーバーはそのクエリーを不正として拒否します。非集約カラムおよび GROUP BY についての詳細は、セクション12.19.3「MySQL での GROUP BY の処理」を参照してください。

12.19.3 MySQL での GROUP BY の処理

標準 SQL では、GROUP BY 句を含むクエリーは、GROUP BY 句で名前が指定されていない選択リスト内の非集約カラムを参照できません。たとえば、このクエリーは、選択リスト内の name カラムが GROUP BY に表示されていないため、標準 SQL では不正です。

SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid;

このクエリーを正当にするには、name カラムを選択リストから削除するか、GROUP BY 句で名前を指定する必要があります。

MySQL では、選択リストが GROUP BY 句で名前が指定されていない非集約カラムを参照できないように、GROUP BY の使用が拡張されています。つまり、上記のクエリーは MySQL では正当です。この機能を使用すると、不要なカラムのソートおよびグループ化が回避されるため、パフォーマンスを改善できます。ただし、これは主に、GROUP BY で名前が指定されていない各非集約カラム内のすべての値がグループごとに同じである場合に役立ちます。サーバーは各グループから任意の値を自由に選択できるため、同じ値でなければ、選択した値は不確定です。さらに、ORDER BY 句を追加しても、各グループからの値の選択が影響を受ける可能性はありません。値が選択されたあとに結果セットのソートが発生しますが、ORDER BY によって、サーバーで選択された各グループ内の値は影響を受けません。

同様の MySQL 拡張が HAVING 句に適用されます。標準 SQL では、GROUP BY 句を含むクエリーは、GROUP BY 句で名前が指定されていない HAVING 句の非集約カラムを参照できません。MySQL 拡張では、計算を簡単にするために、このようなカラムへの参照が許可されます。この拡張では、グループ化されていないカラムに同じグループに関する値が含まれると仮定されます。それ以外の場合は、結果が不確定です。

MySQL GROUP BY の拡張を無効にするには、ONLY_FULL_GROUP_BY SQL モードを有効にします。これにより、標準 SQL の動作が有効になります。GROUP BY 句で名前が指定されていないカラムは、集約関数で囲まなければ、選択リストまたは HAVING 句で使用できません。

また、ONLY_FULL_GROUP_BY によって、HAVING 句のエイリアスの使用も影響を受けません。たとえば、次のクエリーは、orders テーブルで 1 回だけ発生する name 値を返します。

SELECT name, COUNT(name) FROM orders GROUP BY name HAVING COUNT(name) = 1;

MySQL では、集約カラム用に HAVING 句でエイリアスを使用することが許可されるように、この動作が拡張されています。

SELECT name, COUNT(name) AS c FROM orders GROUP BY name HAVING c = 1;

ONLY_FULL_GROUP_BY を有効にすると、この MySQL 拡張が無効になり、HAVING 句の c カラムが集約関数で囲まれていないため (これは、集約関数です)、「non-grouping field 'c' is used in HAVING clause」というエラーが発生します。

選択リストの拡張は、ORDER BY にも適用されます。つまり、GROUP BY 句に表示されていない ORDER BY 句の非集約カラムは参照できません。(ただし、すでに説明したように、ORDER BY によって、非集約カラムからどの値が選択されるのかは影響を受けません。選択されたあとにはじめてソートされます。)ONLY_FULL_GROUP_BY SQL モードが有効になっている場合は、この拡張が適用されません。

一部のケースでは、MIN() および MAX() を使用すると、一意でない場合でも特定のカラム値を取得できます。sort カラムに 6 桁以内の整数が含まれている場合、次のクエリーは、最小の sort 値を含む行から column の値を取得します。

SUBSTR(MIN(CONCAT(LPAD(sort,6,'0'),column)),7)

セクション3.6.4「特定のカラムのグループごとの最大値が格納されている行」を参照してください。

標準 SQL に従おうとすると、GROUP BY 句で式を使用できません。回避策として、式のエイリアスを使用します。

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

MySQL では、GROUP BY 句で式を使用することが許可されているため、エイリアスは必要ありません。

SELECT id, FLOOR(value/100) FROM tbl_name GROUP BY id, FLOOR(value/100);

12.20 高精度計算

MySQL 5.6 は、高精度計算、つまり、きわめて正確な結果が得られ、さらに無効な値を高いレベルで制御できる数値処理をサポートしています。高精度計算は、次の 2 つの機能に基づいています。

  • サーバーが無効なデータの受け入れまたは拒否に関してどの程度厳密かを制御する SQL モード。

  • 固定小数点数演算のための MySQL ライブラリ。

これらの機能は数値操作にいくつかの影響を与えるとともに、標準 SQL への高度の準拠を実現します。

  • 正確な計算: 厳密値数値の場合、計算に浮動小数点エラーは導入されません。代わりに、正確な精度が使用されます。たとえば、MySQL は .0001 などの数値を近似値ではなく厳密値として処理し、それを 10,000 回合計すると 1 に近いだけの値ではなく、正確に 1 の結果が生成されます。

  • 適切に定義された丸め動作: 厳密値数値の場合、ROUND() の結果は、ベースとなる C ライブラリの動作方法などの環境要因ではなく、その引数に依存します。

  • プラットフォームからの独立: 厳密値数値に対する操作は、Windows や Unix などの各プラットフォームにわたって同じです。

  • 無効な値の処理に対する制御: オーバーフローおよび 0 による除算が検出可能であり、これらはエラーとして処理できます。たとえば、あるカラムに対して大きすぎる値は、そのカラムのデータ型の範囲内に収まるように値が切り捨てられるようにするのではなく、エラーとして処理できます。同様に、0 による除算は、NULL の結果を生成する操作としてではなく、エラーとして処理できます。どちらのアプローチをとるかの選択は、サーバー SQL モードの設定によって決定されます。

次の説明では、古いアプリケーションとの非互換性の可能性を含め、高精度計算の動作方法のいくつかの側面について触れています。最後に、MySQL 5.6 が数値操作をどのように処理するかを正確に示すいくつかの例を示します。SQL モードの制御については、セクション5.1.7「サーバー SQL モード」を参照してください。

12.20.1 数値の型

厳密値の操作に関する高精度計算のスコープには、厳密値データ型 (整数および DECIMAL 型) と厳密値数値リテラルが含まれます。近似値データ型および数値リテラルは、浮動小数点数として処理されます。

正確値の数値リテラルには、整数部または小数部、あるいはその両方が含まれています。これらには符号を付けることができます。例: 1.23.4-5-6.78+9.10

近似値の数値リテラルは仮数と指数による指数表現で表されます。一方または両方の部分に符号を付けることができます。例: 1.2E31.2E-3-1.2E3-1.2E-3

2 つの数値が同じように見えても、別々に扱われることがあります。たとえば、2.34 は (固定小数点の) 正確値ですが、2.34E0 は (浮動小数点の) 近似値です。

DECIMAL データ型は固定小数点型で、計算は正確です。MySQL では、DECIMAL 型には、NUMERICDECFIXED という複数のシノニムがあります。整数型も正確値型です。

FLOAT データ型および DOUBLE データ型は浮動小数点型で、計算によって近似値が得られます。MySQL では、FLOAT または DOUBLE のシノニムである型は DOUBLE PRECISION および REAL です。

12.20.2 DECIMAL データ型の特性

このセクションでは、MySQL 5.6 での DECIMAL データ型 (およびそのシノニム) の特性について、特に次のトピックに注意を払いながら説明します。

  • 最大桁数

  • ストレージフォーマット

  • ストレージ要件

  • DECIMAL カラムの上限への非標準の MySQL 拡張。

このセクション全体を通して、古いバージョン (5.0.3 より前) の MySQL のために記述されたアプリケーションとの非互換性の可能性が記載されています。

DECIMAL カラムの宣言構文は、DECIMAL(M,D) です。MySQL 5.6 での引数の値の範囲は次のとおりです。

  • M は、最大桁数 (精度) です。その範囲は 1 から 65 までです。(古いバージョンの MySQL では 1 から 254 までの範囲が許可されました。)

  • D は、小数点の右側の桁数 (スケール) です。その範囲は 0 から 30 までであり、M より大きくすることはできません。

M が 65 の最大値である場合は、DECIMAL 値に対する計算が 65 桁まで正確であることを示します。この 65 桁の精度の制限は厳密値数値リテラルにも適用されるため、このようなリテラルの最大範囲は以前とは異なります。(古いバージョンの MySQL では、10 進数値の最大桁数は 254 でした。ただし、計算は浮動小数点を使用して実行されたために厳密値ではなく、近似値でした。)

MySQL 5.6 での DECIMAL カラムの値は、9 桁の 10 進数が 4 バイトにパックされたバイナリ形式を使用して格納されます。各値の整数部と小数部に対するストレージ要件は個別に決定されます。9 桁の繰り返しごとに 4 バイトが必要であり、残りの桁がある場合は、4 バイトのうちの一部が必要になります。残りの桁に必要なストレージは、次の表で指定されます。

余りの桁バイト数
00
1–21
3–42
5–63
7–94

たとえば、DECIMAL(18,9) カラムは小数点の両側に 9 桁あるため、整数部と小数部のそれぞれに 4 バイトが必要です。DECIMAL(20,6) カラムは整数部に 14 桁、小数部に 6 桁あります。整数部の桁は、そのうちの 9 桁に 4 バイト、残りの 5 桁に 3 バイトが必要です。小数部の 6 桁には 3 バイトが必要です。

一部の古いバージョンの MySQL とは異なり、MySQL 5.6 での DECIMAL カラムには、先頭の + 文字や - 文字、または先頭の 0 の桁が格納されません。DECIMAL(5,1) カラムに +0003.1 を挿入すると、それは 3.1 として格納されます。負の数の場合、リテラルの - 文字は格納されません。古い動作に依存するアプリケーションは、この変更が反映されるように変更する必要があります。

MySQL 5.6 での DECIMAL カラムでは、カラム定義によって暗黙的に指定された範囲を超える値が許可されません。たとえば、DECIMAL(3,0) カラムは -999 から 999 までの範囲をサポートします。DECIMAL(M,D) カラムでは、小数点の左側に許可されるのは多くても M - D 桁です。これは、+ 記号の代わりに追加の桁の格納が許可されていた古いバージョンの MySQL に依存するアプリケーションとは互換性がありません。

SQL 標準では、NUMERIC(M,D) の精度は正確にM 桁である必要があります。DECIMAL(M,D) の場合、この標準では少なくとも M 桁の精度が必要ですが、それを超える精度が許可されます。MySQL では、DECIMAL(M,D)NUMERIC(M,D) は同じであり、どちらも正確に M 桁の精度を持っています。

DECIMAL 値の内部形式の完全な説明については、MySQL ソース配布内のファイル strings/decimal.c を参照してください。この形式は、decimal2bin() 関数で (例を使用して) 説明されています。

DECIMAL データ型の古い処理に依存するアプリケーションの移植の詳細は、『MySQL 5.0 リファレンスマニュアル』を参照してください。

12.20.3 式の処理

高精度計算では、可能な場合は常に、厳密値数値は与えられたとおりに使用されます。たとえば、比較での数値は、値を変更することなく正確に指定されたとおりに使用されます。厳密な SQL モードでは、厳密値データ型 (DECIMAL または整数) を持つカラムへの INSERT の場合、数値の厳密値がそのカラムの範囲内にあれば、その数値が厳密値で挿入されます。取得されると、その値は、挿入された値と同じになるはずです。(厳密な SQL モードが有効になっていない場合は、INSERT での切り捨てが許可されます。)

数値式の処理は、その式にどのような種類の値が含まれているかによって異なります。

  • 近似値が存在する場合、その式は近似値であるため、浮動小数点演算を使用して評価されます。

  • 近似値が存在しない場合、その式には厳密値のみが含まれています。いずれかの厳密値に小数部 (小数点に続く値) が含まれている場合、その式は DECIMAL の正確な演算を使用して評価され、精度は 65 桁になります。正確なという用語は、バイナリで表すことができる精度の制限に従います。たとえば、1.0/3.0 は 10 進数表記で .333... と近似できますが、厳密値数値として記述されないため、(1.0/3.0)*3.0 は正確には 1.0 に評価されません。

  • それ以外の場合、式には整数値のみが含まれています。その式は厳密値であり、整数演算を使用して評価され、精度は BIGINT (64 ビット) と同じになります。

数値式に文字列が含まれている場合、その文字列は倍精度浮動小数点値に変換され、その式は近似値になります。

数値カラムへの挿入は、sql_mode システム変数によって制御される SQL モードによって影響を受けます。(セクション5.1.7「サーバー SQL モード」を参照してください。)次の説明では、厳密モード (STRICT_ALL_TABLES または STRICT_TRANS_TABLES モード値によって選択されます) および ERROR_FOR_DIVISION_BY_ZERO について触れています。すべての制限を有効にするには、単純に、厳密モード値と ERROR_FOR_DIVISION_BY_ZERO の両方を含む TRADITIONAL モードを使用できます。

mysql> SET sql_mode='TRADITIONAL';

数値が厳密値型のカラム (DECIMAL または整数) に挿入された場合は、数値の厳密値がそのカラムの範囲内にあれば、その数値が厳密値で挿入されます。

その値の小数部に含まれている桁が多すぎる場合は、丸めが発生し、警告が生成されます。丸めは、セクション12.20.4「丸め動作」で説明されているとおりに実行されます。

その値の整数部に含まれている桁が多すぎる場合は、その値が大きすぎるため、次のように処理されます。

  • 厳密モードが有効になっていない場合は、その値がもっとも近い正当な値に切り捨てられ、警告が生成されます。

  • 厳密モードが有効になっている場合は、オーバーフローエラーが発生します。

アンダーフローは検出されないため、アンダーフローの処理は定義されていません。

数値カラムへの文字列の挿入では、その文字列に非数値の内容が含まれている場合、文字列から数値への変換は次のように処理されます。

  • 数値で始まらない文字列を数値として使用することはできないため、この文字列により厳密モードではエラーが生成され、それ以外の場合は警告が生成されます。これには、空の文字列が含まれます。

  • 数値で始まる文字列は変換できますが、後続の非数値の部分は切り捨てられます。その切り捨てられた部分にスペース以外の文字が含まれている場合、厳密モードではエラーが生成され、それ以外の場合は警告が生成されます。

デフォルトでは、0 による除算によって NULL の結果が生成され、警告は生成されません。SQL モードを適切に設定することにより、0 による除算を制限できます。

ERROR_FOR_DIVISION_BY_ZERO SQL モードが有効になっている場合、MySQL は、0 による除算を次の異なった方法で処理します。

  • 厳密モードが有効になっていない場合は、警告が発生します。

  • 厳密モードが有効になっている場合は、0 による除算を含む挿入と更新が禁止され、エラーが発生します。

つまり、0 による除算を実行する式を含む挿入や更新をエラーとして処理できますが、それには、厳密モードに加えて ERROR_FOR_DIVISION_BY_ZERO が必要です。

次のステートメントがあるとします。

INSERT INTO t SET i = 1/0;

次に、厳密モードと ERROR_FOR_DIVISION_BY_ZERO モードの各組み合わせに対する動作を示します。

sql_mode結果
'' (デフォルト)警告なし、エラーなし。iNULL に設定されます。
厳密警告なし、エラーなし。iNULL に設定されます。
ERROR_FOR_DIVISION_BY_ZERO警告あり、エラーなし。iNULL に設定されます。
厳密、ERROR_FOR_DIVISION_BY_ZEROエラー状態。行は挿入されません。

12.20.4 丸め動作

このセクションでは、ROUND() 関数、および厳密値型 (DECIMAL と整数) を持つカラムへの挿入での高精度計算の丸めについて説明します。

ROUND() 関数は、その引数が厳密値または近似値のどちらであるかに応じて、異なった方法で丸めます。

  • 真値の数値の場合、ROUND()四捨五入ルールを使用します。0.5 以上の小数部を持つ値は、正の場合は次の整数に切り上げられ、負の場合は次の整数に切り下げられます。(つまり、ゼロから遠い方に丸められます。)0.5 未満の小数部を持つ値は、正の場合は次の整数に切り下げられ、負の場合は次の整数に切り上げられます。

  • 近似値の数字の場合、結果は C ライブラリによって異なります。つまり、多くのシステムでは、ROUND()偶数丸めルールを使用します。どのような小数部を持つ値も、もっとも近い偶数に丸められます。

次の例では、正確な値の丸めと近似値の丸めの相違点を示します。

mysql> SELECT ROUND(2.5), ROUND(25E-1);+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3 | 2 |
+------------+--------------+

DECIMAL または整数カラムへの挿入では、ターゲットが厳密値データ型であるため、挿入される値が厳密値または近似値のどちらであるかには関係なく、丸めでは四捨五入が使用されます。

mysql> CREATE TABLE t (d DECIMAL(10,0));Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t VALUES(2.5),(2.5E0);Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 2
mysql> SELECT d FROM t;+------+
| d |
+------+
| 3 |
| 3 |
+------+

12.20.5 高精度計算の例

このセクションでは、MySQL 5.6 での高精度計算のクエリー結果を示すいくつかの例について説明します。これらの例は、セクション12.20.3「式の処理」およびセクション12.20.4「丸め動作」で説明されている原則を示しています。

例 1。数値は、可能であれば、指定されたとおりにその厳密値で使用されます。

mysql> SELECT (.1 + .2) = .3;+----------------+
| (.1 + .2) = .3 |
+----------------+
| 1 |
+----------------+

浮動小数点値の場合、結果は不正確です。

mysql> SELECT (.1E0 + .2E0) = .3E0;+----------------------+
| (.1E0 + .2E0) = .3E0 |
+----------------------+
| 0 |
+----------------------+

厳密値と近似値の処理の違いを確認するための別の方法として、合計値に小さい数値を何回も加える方法があります。ある変数に .0001 を 1,000 回加える次のストアドプロシージャーを考えてみます。

CREATE PROCEDURE p ()
BEGIN DECLARE i INT DEFAULT 0; DECLARE d DECIMAL(10,4) DEFAULT 0; DECLARE f FLOAT DEFAULT 0; WHILE i < 10000 DO SET d = d + .0001; SET f = f + .0001E0; SET i = i + 1; END WHILE; SELECT d, f;
END;

論理的には、df の両方の合計値が 1 になるはずですが、それは 10 進数の計算にしか当てはまりません。浮動小数点の計算では、小さなエラーが発生します。

+--------+------------------+
| d | f |
+--------+------------------+
| 1.0000 | 0.99999999999991 |
+--------+------------------+

例 2。乗算は、標準 SQL に必要なスケールで実行されます。つまり、スケール S1S2 を持つ 2 つの数値 X1X2 の場合、結果のスケールは S1 + S2 になります。

mysql> SELECT .01 * .01;+-----------+
| .01 * .01 |
+-----------+
| 0.0001 |
+-----------+

例 3。厳密値数値に対する丸め動作は、適切に定義されています。

丸め動作 (たとえば、ROUND() 関数を使用した動作) は、ベースとなる C ライブラリの実装には依存しません。つまり、その結果は各プラットフォームにわたって一貫性があります。

  • 厳密値カラム (DECIMAL と整数) および厳密値数値に対する丸めでは、四捨五入ルールが使用されます。0.5 以上の小数部を持つ値は、次に示すように、0 から遠いもっとも近い整数に丸められます。

    mysql> SELECT ROUND(2.5), ROUND(-2.5);+------------+-------------+
    | ROUND(2.5) | ROUND(-2.5) |
    +------------+-------------+
    | 3 | -3 |
    +------------+-------------+
  • 浮動小数点値に対する丸めでは、C ライブラリが使用されます。これは、多くのシステムでは偶数丸めルールを使用します。このようなシステムでは、どのような小数部を持つ値も、もっとも近い偶数に丸められます。

    mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0);+--------------+---------------+
    | ROUND(2.5E0) | ROUND(-2.5E0) |
    +--------------+---------------+
    | 2 | -2 |
    +--------------+---------------+

例 4。厳密モードでは、カラムの範囲を外れている値を挿入すると、正当な値への切り捨てではなく、エラーが発生します。

MySQL が厳密モードで実行されていない場合は、正当な値への切り捨てが発生します。

mysql> SET sql_mode='';Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t (i TINYINT);Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t SET i = 128;Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> SELECT i FROM t;+------+
| i |
+------+
| 127 |
+------+
1 row in set (0.00 sec)

ただし、厳密モードが有効になっている場合は、エラーが発生します。

mysql> SET sql_mode='STRICT_ALL_TABLES';Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t (i TINYINT);Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t SET i = 128;ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1
mysql> SELECT i FROM t;Empty set (0.00 sec)

例 5: 厳密モードで ERROR_FOR_DIVISION_BY_ZERO が設定されている場合は、0 による除算によって NULL の結果ではなく、エラーが発生します。

非厳密モードでは、0 による除算によって NULL の結果が生成されます。

mysql> SET sql_mode='';Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE t (i TINYINT);Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t SET i = 1 / 0;Query OK, 1 row affected (0.00 sec)
mysql> SELECT i FROM t;+------+
| i |
+------+
| NULL |
+------+
1 row in set (0.03 sec)

ただし、適切な SQL モードが有効になっている場合、0 による除算はエラーになります。

mysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t (i TINYINT);Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t SET i = 1 / 0;ERROR 1365 (22012): Division by 0
mysql> SELECT i FROM t;Empty set (0.01 sec)

例 6。厳密値リテラルは、厳密値として評価されます。

MySQL 5.0.3 より前は、厳密値リテラルと近似値リテラルはどちらも、倍精度浮動小数点値として評価されます。

mysql> SELECT VERSION();+------------+
| VERSION() |
+------------+
| 4.1.18-log |
+------------+
1 row in set (0.01 sec)
mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;Query OK, 1 row affected (0.07 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> DESCRIBE t;+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| a | double(3,1) | | | 0.0 | |
| b | double | | | 0 | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.04 sec)

MySQL 5.0.3 の時点では、近似値リテラルは浮動小数点を使用して評価されますが、厳密値リテラルは DECIMAL として処理されます。

mysql> SELECT VERSION();+-----------------+
| VERSION() |
+-----------------+
| 5.1.6-alpha-log |
+-----------------+
1 row in set (0.11 sec)
mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> DESCRIBE t;+-------+-----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| a | decimal(2,1) unsigned | NO | | 0.0 | |
| b | double | NO | | 0 | |
+-------+-----------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

例 7。集約関数への引数が厳密値数値型である場合は、その結果も、少なくとも引数と同じスケールを持つ厳密値数値型になります。

これらのステートメントを考慮してください。

mysql> CREATE TABLE t (i INT, d DECIMAL, f FLOAT);mysql> INSERT INTO t VALUES(1,1,1);mysql> CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;

MySQL 5.0.3 より前は、引数の型にかかわらず、結果が倍精度値になります。

mysql> DESCRIBE y;+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| AVG(i) | double(17,4) | YES | | NULL | |
| AVG(d) | double(17,4) | YES | | NULL | |
| AVG(f) | double | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+

MySQL 5.0.3 の時点では、結果が倍精度値になるのは浮動小数点引数の場合だけです。厳密値型引数の場合は、結果も厳密値型になります。

mysql> DESCRIBE y;+--------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(14,4) | YES | | NULL | |
| AVG(d) | decimal(14,4) | YES | | NULL | |
| AVG(f) | double | YES | | NULL | |
+--------+---------------+------+-----+---------+-------+

結果が倍精度値になるのは浮動小数点引数の場合だけです。厳密値型引数の場合は、結果も厳密値型になります。

関連キーワード:  関数,expr,セクション,カラム,ステートメント,インデックス,セット,FROM,CREATE,バイナリ