ユーザー定義変数に値を保存し、あとで参照することができます。これで 1 つのステートメントから次のステートメントに変数を移行させることができます。ユーザー定義変数は接続に固有のものです。. つまり、あるクライアントによって定義されたユーザー変数をほかのクライアントが表示したり、使用したりすることはできません。特定のクライアント接続で使用されているすべての変数は、クライアントが接続を切ったときに自動的に開放されます。
ユーザー変数は
@
として記述され、変数名
var_name
var_name
は現在のキャラクタセットの英数字、「.
」、「_
」、および
「$
」
で構成できます。デフォルトキャラクタセットは
latin1
(cp1252
西ヨーロッパ言語)
です。これは--character-set-server
オプションで
mysqld
に変換されることがあります。詳しくはCharacter Set Configurationを参照してください。ユーザー変数名を文字列や識別子として引用符で囲む場合、ほかの文字を含むことができます
(例:
@'my-var'
、@"my-var"
または@`my-var`
)。
MySQL 5.0 以降のバージョンでは、ユーザー変数名は大文字と小文字が区別されません。
ユーザー定義変数を設定する方法の 1
つに、SET
ステートメントを発行する方法が挙げられます。
SET @var_name
=expr
[, @var_name
=expr
] ...
SET
では、=
または:=
のどちらかが代入演算子として使用できます。
SET
以外のステートメントで、ユーザー変数に値を割り当てることもできます。この場合、代入演算子は:=
でなくてはならず、=
ではありません。これは=
が非
SET
ステートメンとに置いて比較オペレータとして扱われるからです。
mysql>SET @t1=0, @t2=0, @t3=0;
mysql>SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+ | @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 | +----------------------+------+------+------+ | 5 | 5 | 1 | 4 | +----------------------+------+------+------+
ユーザー変数には、限定された一連のデータ型の値
(整数、小数、浮動小数点、バイナリ列、非バイナリ列、または
NULL
値)
を割り当てることができます。10
進値と実数値の割り当てでは、値の精度やスケールは維持されません。許可されている型以外の型の値は、許可されている型に変換されます。たとえば、時間を表すデータ型や空間データ型の値は、バイナリ列に変換されます。
ユーザー変数に非バイナリ (文字) 文字列値を割り当てた場合、その変数には文字列と同じキャラクタセットと照合順序が含まれます。ユーザー変数の強制力は絶対です。(これはテーブルカラム値と同等の強制力です)。
ユーザー変数に割り当てられたビット値は、バイナリ列として扱われます。ビット値を数値としてユーザー変数に割り当てるには、CAST()
または +0
を使用します。
mysql>SET @v1 = b'1000001';
mysql>SET @v2 = CAST(b'1000001' AS UNSIGNED), @v3 = b'1000001'+0;
mysql>SELECT @v1, @v2, @v3;
+------+------+------+ | @v1 | @v2 | @v3 | +------+------+------+ | A | 65 | 65 | +------+------+------+
結果セットでユーザー変数の値が選択された場合、それは文字列としてクライアントに返されます。
ユーザー変数は表現が許可されているコンテキストで使用される可能性があります。これには現在、リテラル値を明確に要求するコンテキストは含まれません。たとえば
SELECT
ステートメントの
LIMIT
節や、LOAD DATA
ステートメントの
IGNORE
節になります。
N
LINES
初期化されていない変数を参照する場合、それは
NULL
値および文字列の型が存在します。
SELECT
ステートメントでは、それぞれの式はクライアントに送信されたときにだけ評価されます。これはつまり、HAVING
、GROUP
BY
または ORDER
BY
節において、SELECT
リストに設定された変数を含む表現を参照できないことを意味します。たとえば、次のステートメントは期待通りには機能しません。
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name
HAVING b=5;
HAVING
節での
b
に対する参照は、@aa
を使用した SELECT
リスト内の表現に対応するエイリアスを参照します。これは期待通りには機能しません。@aa
は以前選択された行の
id
値を含み、現在の行から選択された値は含みません。
ユーザー変数の評価順序は定義されておらず、与えられたクエリー内の要素に基づいて変更されることがあります。SELECT
@a, @a := @a+1 ...
では、MySQL
は@a
を先に評価し次に割り当てが実行されるように見えますが、クエリーの変更(たとえば
GROUP
BY
、HAVING
または
ORDER BY
節による変更)は評価順序を変更する可能性があります。
基本的な規則は、ステートメントの一部でユーザー変数値を割り当てないことおよび同一ステートメント内の他部分で同じ変数を使用しないことです。期待通りの結果を得られるかもしれませんが、これは確約されていません。
変数の設定および同ステートメント内での使用におけるほかの問題点は、変数のデフォルト結果型がステートメントが開始時の変数型に基づく点です。次の例で説明します。
mysql>SET @a='test';
mysql>SELECT @a,(@a:=20) FROM
tbl_name
;
この SELECT
ステートメントに対して、MySQL では、カラム 1
は文字列であり、@a
から文字列へのすべてのアクセスを変換することがクライアントに通知されます。これは、@a
が 2
行目では数値に設定されていても行われます。SELECT
ステートメント実行後、@a
は次のステートメントの数値として認識されます。
この問題を避けるためには、単一ステートメント内で、同変数を設定・使用してはいけません。また、変数の使用前に型を定義するために、0
、0.0
または''
に変数を設定してもいけません。
ユーザー変数は、データ値を提供するためのものです。ユーザー変数は、テーブル名やデータベース名が想定されるコンテキストなどの識別子または識別子の一部として、または
SELECT
などの予約語として、SQL
ステートメントの中で直接使用することはできません。これは、次の例に示すように、変数が引用符で囲まれている場合でも同じです。
mysql>SELECT c1 FROM t;
+----+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2 rows in set (0.00 sec) mysql>SET @col = "c1";
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @col FROM t;
+------+ | @col | +------+ | c1 | +------+ 1 row in set (0.00 sec) mysql>SELECT `@col` FROM t;
ERROR 1054 (42S22): Unknown column '@col' in 'field list' mysql> SET @col = "`c1`"; Query OK, 0 rows affected (0.00 sec) mysql>SELECT @col FROM t;
+------+ | @col | +------+ | `c1` | +------+ 1 row in set (0.00 sec)
ユーザー変数は識別子を提供するためには使用できないというこの原則の例外は、あとで実行される準備済みステートメントとして使用するための文字列を作成している場合です。この場合、ユーザー変数はステートメントの一部を提供するために使用できます。次の例は、その方法を示しています。
mysql>SET @c = "c1";
Query OK, 0 rows affected (0.00 sec) mysql>SET @s = CONCAT("SELECT ", @c, " FROM t");
Query OK, 0 rows affected (0.00 sec) mysql>PREPARE stmt FROM @s;
Query OK, 0 rows affected (0.04 sec) Statement prepared mysql>EXECUTE stmt;
+----+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2 rows in set (0.00 sec) mysql>DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
詳細については、項8.7. 「準備済みステートメントのための SQL 構文」 を参照してください。
PHP 5 を使用して次に示すように、同じような手法をアプリケーションプログラムの中で使用することによって、プログラム変数を使用する SQL ステートメントを作成できます。
<?php $mysqli = new mysqli("localhost", "user", "pass", "test"); if( mysqli_connect_errno() ) die("Connection failed: %s\n", mysqli_connect_error()); $col = "c1"; $query = "SELECT $col FROM t"; $result = $mysqli->query($query); while($row = $result->fetch_assoc()) { echo "<p>" . $row["$col"] . "</p>\n"; } $result->close(); $mysqli->close(); ?>
この方法で SQL ステートメントを作成することを「ダイナミック SQL」と呼ぶことがあります。