在另一个问题中,我发帖人告诉我,两者之间有区别:

@variable


和:

variable


在MySQL中。他还提到了MSSQL如何具有批处理范围,而MySQL如何具有会话范围。有人可以为我详细说明吗?

评论

我对MsSQL很熟悉,因此我从未想到问这样的问题。这里提供的答案使我陷入了我没有想法的事情!谢谢..

#1 楼

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);这些“会话变量”与特定于会话的用户定义变量无关。)

评论


还要注意,有可用的全局变量:请参见SELECT @@ version;例如。这也是一个原因,为什么使用DELIMITER @@并不是一个好主意。

– Mchl
2011年2月2日,14:10

这就给新产品带来了新问题……在您的示例中,“ var = var”和“ var:= var”之间有什么区别吗?

–confiq
2012年5月13日13:45

@confiq:没有。

– Quassnoi
2012年5月13日20:12



新人的另一个问题。建议什么时候使用@ vs?

– pixelfreak
2012年11月27日0:46

@ confiq,@ Quassnoi :: =和=之间有一个显着的区别,即:=在任何地方都可以用作变量赋值运算符,而=只能在SET语句中用作变量赋值运算符,而在其他地方则是比较运算符。所以SELECT @var = 1 +1;将保持@var不变,并返回一个布尔值(1或0,具体取决于@var的当前值),而SELECT @var:= 1 + 1;将@var更改为2,并返回2。

– Dewi Morgan
2014年4月16日23:36



#2 楼

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

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


在存储程序之外,没有variable@是系统变量,您无法定义自己。

此变量的范围是整个会话。也就是说,尽管您与数据库之间存在连接,但仍可以使用该变量。

这与MSSQL相反,在MSSQL中,该变量仅在当前的查询批次中可用(存储过程,脚本)。在同一会话中将不能以其他批次使用它。

评论


请勿与会话变量混淆,会话变量具有速记SET @@ a ='test';,参见。 dev.mysql.com/doc/refman/5.1/en/set-statement.html

–RobM
2012年6月12日在21:08

@RobM,它们称为系统变量,而不是会话变量。

–起搏器
15年4月16日在10:31

@Pacerier:我看错文档了吗? “”“要明确表示变量是会话变量,请在其名称前加上SESSION,@@ session。或@@。”“”

–RobM
2015年4月25日在16:32

@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,并设置会话big_tables = 1,因为big_tables是系统变量。

–起搏器
2015年5月24日23:10

@GovindRai:在Quassnoi的回答中,var2是一个没有@前缀的变量,但它不是系统变量:它是一个过程变量。允许这样做是因为它在存储过程(也称为存储程序)中。在存储过程之外,不带@的变量是系统变量。

– LarsH
16/09/14在15:58



#3 楼

MSSQL要求过程中的变量为DECLAREd,人们使用@Variable语法(DECLARE @TEXT VARCHAR(25)='text')。而且,MS允许在过程的任何块中进行声明,这与mySQL要求在顶部的所有DECLARE不同。

虽然在命令行上不错,但我认为在mySQL的存储过程中使用“ set = @variable”是有风险的。没有作用域,变量跨越作用域边界。这类似于在JavaScript中声明的不带“ var”前缀的变量,然后它们成为全局名称空间并产生意外的冲突和覆盖。

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

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

#4 楼

原则上,我在存储过程中使用UserDefinedVariables(以@开头)。这使工作变得更轻松,尤其是当我在两个或多个存储过程中需要这些变量时。只是当我仅需要一个存储过程中的变量时,我才使用系统变量(不带@)。

@Xybo:
我不明白为什么在StoredProcedures中使用@variables会有风险。您能否简单地解释“作用域”和“边界”(对我来说是新手)?

评论


这违反了基本的软件工程原理。请不要编写另一行代码,直到您确切知道范围是什么,以及为什么使用全局变量通常是一个糟糕的主意。当我参加101个编程课程时,正如我记得为几乎所有内容使用global都会导致自动产生“ F”。有一些特殊的例外,但是作为一般规则-那就不要这样做!

– BuvinJ
17/09/22在13:04

为什么? -@Variables在每本MySQL手册中都是绝对常见的。

–彼得
17年9月24日14:43在

当然,在没有功能调用,过程,触发器等的“扁平”脚本中,如果您只是要执行该简单脚本或有限的命令集,然后结束会话(从而破坏了全局变量)。在这种情况下,请继续使用它们。但是请勿在函数内部使用它们!如果您只是使用Google全局变量或范围,您将立即获得普遍支持它们的想法的广泛支持。这是一个起点:wiki.c2.com/?GlobalVariablesAreBad或更全面的解释:en.wikipedia.org/wiki/Global_variable

– BuvinJ
17-09-24在21:44



在MySQL中,@ variables是全局的。这很容易确认。在函数外部设置一个,然后在一个函数内部求值。相反,在函数内部设置一个,然后在函数外部求值。您将看到该功能不保护此类范围。他们踩着对方的脚趾。

– BuvinJ
17-09-25在12:24



使用MySQL术语,@@ GLOBAL变量甚至更“全局”且更隐蔽。他们跨会议! @变量具有“会话范围”,因此至少它们以这种方式受到限制。但是,在任何普通语言中,您都称其为“全局”范围(当它们跨功能等时)。 MySQL的“全局”概念应该被称为“通用”,因为它超出了运行它的进程的范围。由于进程不共享内存空间,因此“全局”通常无法使用标准语言来执行此操作。这源于SQL的持久性(相对于易变性)。

– BuvinJ
17-09-25在12:34