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