MySQL:@変数と変数。違いは何ですか?


501

別の質問で私が投稿した誰かが私には次のような違いがあると言った:

@variable

そして:

variable

MySQLで。また、MSSQLにバッチスコープがあり、MySQLにセッションスコープがあることについても言及しました。誰かが私のためにこれについて詳しく説明できますか?


1
私はMsSQLに精通しているので、そのような質問をすることは決して思いつきませんでした。ここで提供された答えは、私が考えていなかったものに私を導きました!Thx ..
ケン

回答:


624

MySQLユーザー定義変数の概念があります

それらは緩やかに型付けされた変数であり、セッションのどこかで初期化され、セッションが終了するまでその値を保持します。

次の@ように、先頭に記号を付けます。@var

この変数は、SETステートメントまたはクエリ内で初期化できます。

SET @var = 1

SELECT @var2 := 2

でストアドプロシージャを開発する場合MySQL、入力パラメータを渡してローカル変数を宣言できます。

DELIMITER //

CREATE PROCEDURE prc_test (var INT)
BEGIN
    DECLARE  var2 INT;
    SET var2 = 1;
    SELECT  var2;
END;
//

DELIMITER ;

これらの変数の前にはプレフィックスがありません。

プロシージャ変数とセッション固有のユーザー定義変数の違いはNULL、セッション固有の変数ではなく、プロシージャが呼び出されるたびにプロシージャ変数が再初期化されることです。

CREATE PROCEDURE prc_test ()
BEGIN
    DECLARE var2 INT DEFAULT 1;
    SET var2 = var2 + 1;
    SET @var2 = @var2 + 1;
    SELECT  var2, @var2;
END;

SET @var2 = 1;

CALL prc_test();

var2  @var2
---   ---
2     2


CALL prc_test();

var2  @var2
---   ---
2     3


CALL prc_test();

var2  @var2
---   ---
2     4

ご覧のとおり、var2(プロシージャ変数)は呼び出されるたびに再初期化されますが、@var2(セッション固有の変数)は呼び出されません。

(MySQL は、ユーザー定義変数に加えて、「グローバル変数」などの「グローバル変数」や、@@global.port「セッション変数」などの事前定義された「システム変数」もあります@@session.sql_mode。これらの「セッション変数」は、セッション固有のユーザー定義とは無関係です。変数。)


43
また、利用可能なグローバル変数があることに注意してくださいSELECT @@version;。例を参照してください。これは理由でもありますが、使用するのDELIMITER @@は本当に良い考えではありません。
Mchl、2011

13
新規参入者に新しい質問をします...あなたの例のように "var = var"と "var:= var"の間に違いはありますか?
confiq

13
@confiq:ありません。
Quassnoi、2012年

10
初心者のための別の質問。いつ使用することが推奨されます@か?
pixelfreak 2012年

73
@confiq、@Quassnoi:そこの間に1つの有意な差がある:==、それはそれで:=いる間、どこでも可変代入演算子として働く=だけでそのように動作するSET文、および他のどこでも比較演算子です。そうSELECT @var = 1 + 1;不変@varままとしながら、(@varの電流値に応じて1または0)ブール値を返しますSELECT @var := 1 + 1;2に@var変わり、2返す
デイウィー・モーガン

71

MySQLでは@variableユーザー定義変数を示します。独自に定義できます。

SET @a = 'test';
SELECT @a;

ストアドプログラムの外では、はvariable、なし@で、システム変数であり、自分で定義することはできません。

この変数のスコープは、セッション全体です。つまり、データベースとの接続が存在している間も、変数を使用できます。

これは、変数が現在のクエリのバッチ(ストアドプロシージャ、スクリプトなど)でのみ使用できるMSSQLとは対照的です。同じセッションの別のバッチでは使用できません。


2
速記を持つセッション変数、と混同しないようにしてSET @@a = 'test';、参照 dev.mysql.com/doc/refman/5.1/en/set-statement.html
RobM

@RobM、それらはセッション変数ではなくシステム変数と呼ばれます。
Pacerier、2015

1
@Pacerier:ドキュメントを間違って読んでいますか?"" "変数がセッション変数であることを明示するには、その名前の前にSESSION、@@ session。、または@@を付けます。" ""
RobM

5
@RobM、あなたはそれを間違って読んでいます。箇条書き内の段落だけでなく、段落全体を読み通してください。簡単に言うと、2種類のセッション変数があります。1)ユーザー定義のセッション変数と、2)システム  定義のセッション変数です。を使用してユーザー定義のセッション変数を設定することはできません@@。たとえば、set@@my_var=1set@@session.my_var=1、およびset session my_var=1ので、動作しませんmy_varではありません、システム変数私たちにできるのに対し、set@@big_tables=1set@@session.big_tables=1、およびset session big_tables=1ので、big_tablesシステム変数です。
ペーチェリエ

1
@GovindRai:Quassnoiの答えでvar2は、@プレフィックスのない変数ですが、システム変数ではなく、プロシージャ変数です。ストアドプロシージャ(別名ストアドプログラム)内にあるため、これは許可されます。ストアドプロシージャの外で@は、なしの変数はシステム変数です。
LarsH 2016

10

MSSQLでは、プロシージャ内の変数を宣言する必要があり、@ Variable構文を使用します(DECLARE @TEXT VARCHAR(25)= 'text')。また、MSは、最上位のすべてのDECLAREを必要とするmySQLとは異なり、プロシージャの任意のブロック内での宣言を許可します。

コマンドラインは適切ですが、mySQLのストアドプロシージャ内で "set = @variable"を使用するのは危険だと思います。スコープはなく、スコープの境界を越えて変数が存在します。これは、 "var"プレフィックスなしで宣言されているJavaScriptの変数に似ています。これはグローバルネームスペースになり、予期しない衝突と上書きを引き起こします。

mySQLの優れたスタッフが、ストアドプロシージャ内のさまざまなブロックレベルでDECLARE @Variableを許可することを期待しています。@(アットマーク)に注意してください。@記号の接頭辞は、変数名とテーブルの列名を区別するのに役立ちます-変数名は同じであることが多いためです。もちろん、いつでも「v」または「l_」接頭辞を追加できますが、@記号は、変数名を、データを抽出せずに抽出する列と一致させるための便利で簡潔な方法です。

MySQLはストアドプロシージャの新機能であり、最初のバージョンでは優れた機能を果たしています。彼らがここでそれをどこから取っているかを見て、言語のサーバー側の側面が成熟するのを見るのは喜びです。


3

原則として、私はストアドプロシージャ内でUserDefinedVariables(@を先頭に追加)を使用します。これにより、特に2つ以上のストアドプロシージャでこれらの変数が必要な場合に、作業が楽になります。1つのストアドプロシージャ内でのみ変数が必要なときは、システム変数を使用します(@を前に付けません)。

@Xybo:StoredProceduresで@variablesを使用することが危険である理由がわかりません。「スコープ」と「境界」について少し簡単に説明していただけますか(私にとっては初心者)。


3
これは、ソフトウェアエンジニアリングの基本原則に違反しています。スコープが正確にわかり、グローバル変数の使用が一般にひどい考えになる理由がわかるまでは、別のコード行を記述しないでください。私が101のプログラミングクラスを受講したとき、ほとんどすべてにグローバルを使用すると、自動 "F"になります。特別な例外はありますが、原則として-しないでください!
BuvinJ 2017

どうして?-@変数はすべてのMySQL-Bookで絶対的に一般的です。
Peter

確かに、関数呼び出し、プロシージャ、トリガーなどのない「フラット」スクリプトで、その単純なスクリプトまたは限られたコマンドセットを実行してからセッションを終了する場合(それによってグローバルを破棄します)。その場合は、先に進んで、必要に応じて使用してください。ただし、関数内では使用しないでください。単にGoogleのグローバル変数やスコープを使用すれば、普遍的に不満を抱いているというアイデアがすぐにわかります。これが出発点です:wiki.c2.com/?GlobalVariablesAreBadまたはより一般的な説明:en.wikipedia.org/wiki/Global_variable
BuvinJ

2
MySQLでは、@ variablesはグローバルです。これは簡単に確認できます。関数の外で1つ設定してから、1つの内部で評価します。逆に、関数の内部で1つ設定し、それを外部で評価します。関数がその範囲を保護しないことがわかります。彼らはお互いのつま先を踏みます。
BuvinJ 2017

1
MySQLの用語を使用すると、@@GLOBAL変数はさらに「グローバル」で油断ならないものになります。彼らはセッションを横断します! @variables「セッションスコープ」があるため、少なくともそれらはそのように制限されたままです。ただし、「グローバル」スコープと呼ばれる通常の言語では(関数が交差する場合など)。MySQLの「グローバル」の概念は、それを実行するプロセスの境界を超えて拡張されるという点で、おそらく「ユニバーサル」と呼ばれるべきです。プロセスはメモリ空間を共有しないため、「グローバル」は通常、標準言語ではそれを行うことができません。これは、SQLの永続的な(揮発性に対する)傾向に起因します。
BuvinJ 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.