MySQL:@variable与变量.有什么不同?

aar*_*ona 488 mysql sql variables

在我发布的另一个问题中有人告诉我,之间有区别:

@variable
Run Code Online (Sandbox Code Playgroud)

和:

variable
Run Code Online (Sandbox Code Playgroud)

在MySQL中.他还提到了MSSQL如何具有批量作用域以及MySQL具有会话作用域.有人可以为我详细说明这个吗?

Qua*_*noi 612

MySQL具有用户定义变量的概念.

它们是松散类型的变量,可以在会话中的某个位置初始化,并保持其值直到会话结束.

它们前面带有一个@符号,如下所示:@var

您可以使用SET语句或查询内部初始化此变量:

SET @var = 1

SELECT @var2 := 2
Run Code Online (Sandbox Code Playgroud)

在开发存储过程时MySQL,可以传递输入参数并声明局部变量:

DELIMITER //

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

DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

这些变量不会添加任何前缀.

过程变量和特定于会话的用户定义变量之间的区别在于,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
Run Code Online (Sandbox Code Playgroud)

如您所见,var2每次调用过程时都会重新初始化(过程变量),而@var2(特定于会话的变量)则不会.

(除了用户定义的变量之外,MySQL 还有一些预定义的"系统变量",它可能是"全局变量",例如@@global.port"会话变量"等@@session.sql_mode;这些"会话变量"与特定于会话的用户定义无关变量.)

  • @ confiq,@ Quassnoi:`:=`和`=`之间有一个显着的区别,那就是`:=`作为一个变量赋值运算符到处运行,而`=`只能在`SET`中那样工作语句,并且是其他地方的比较运算符.所以`SELECT @var = 1 + 1;`将保持@var不变并返回一个布尔值(1或0取决于@var的当前值),而`SELECT @var:= 1 + 1;`将改变@var到2,并返回2. (70认同)
  • 另请注意,有可用的全局变量:例如,请参阅`SELECT @@ version;`.这也是一个原因,为什么使用`DELIMITER @@`并不是一个好主意. (42认同)
  • 它为新人提出了新的问题......在你的例子中,"var = var"和"var:= var"之间有什么区别吗? (13认同)
  • @confiq:没有. (13认同)
  • 另一个问题是新人.什么时候建议使用`@` vs不? (9认同)
  • @Quassnoi如果将用户变量定义为会话变量并设置一个值,是否会污染下一个使用相同变量名称的存储过程调用? (3认同)
  • @Quassnoi然后不会更好****根本不使用会话变量?为什么每个人都在使用它? (3认同)
  • @Quassnoi对...有时候.我猜我到底在哪里,不使用"@"有什么害处吗? (3认同)
  • 所以@variables是`static`变量。得到它了。 (2认同)
  • @Mchl`DELIMITER //`更酷(适用于C++程序员).`DELIMITER $$`适合世俗. (2认同)

mol*_*olf 69

在MySQL中,@variable表示用户定义的变量.你可以定义自己的.

SET @a = 'test';
SELECT @a;
Run Code Online (Sandbox Code Playgroud)

在存储的程序之外,a variable,without @,是一个系统变量,您无法自己定义.

此变量的范围是整个会话.这意味着当您与数据库的连接存在时,仍然可以使用该变量.

这与MSSQL形成对比,其中变量仅在当前批次的查询(存储过程,脚本或其他)中可用.它不会在同一会话中的其他批次中可用.

  • @RobM,你读错了.仔细阅读整段内容,而不仅仅是项目内的段落.简而言之,有两种会话变量:1)用户定义的会话变量,以及2)**系统**定义的会话变量.您不能使用`@@`设置用户定义的会话变量.例如,`set @@ my_var = 1`,`set @@ session.my_var = 1`,`set session my_var = 1`将不起作用,因为`my_var`不是**系统**变量,而我们可以做`set @@ big_tables = 1`,`set @@ session.big_tables = 1`和`set session big_tables = 1`,因为`big_tables`是一个系统变量. (5认同)
  • 不要与会话变量混淆,会话变量有简写`SET @@ a ='test';`,cf.http://dev.mysql.com/doc/refman/5.1/en/set-statement.html (2认同)

Xyb*_*ybo 10

MSSQL要求程序中的变量为DECLAREd,并且人们使用@Variable语法(DECLARE @TEXT VARCHAR(25)='text').此外,MS允许在过程中的任何块内声明,不像mySQL需要顶部的所有DECLARE.

虽然命令行很好,但我觉得在mySQL的存储过程中使用"set = @variable"是有风险的.跨范围边界没有范围和变量.这与声明没有"var"前缀的JavaScript中的变量类似,后者是全局命名空间并创建意外的冲突和覆盖.

我希望mySQL的优秀人员能够在存储过程中的各个块级别允许DECLARE @Variable.注意@(在标志处).@符号前缀有助于将变量名称与表列名分开 - 因为它们通常是相同的.当然,总是可以添加"v"或"l_"前缀,但@符号是一种方便而简洁的方法,可以使变量名称与您可能从中提取数据的列匹配而不会破坏它.

MySQL是存储过程的新手,他们在第一个版本上做得很好.很高兴看到他们在这里采用它的形式,并观察语言的服务器端方面是否成熟.