MySQL:@variable和variable有什么区别?

4szc88ey  于 5个月前  发布在  Mysql
关注(0)|答案(6)|浏览(61)

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

@variable

字符串
以及:

variable


在MySQL中。他还提到MSSQL有批处理作用域,MySQL有会话作用域。有人能为我详细说明一下吗?

j8yoct9x

j8yoct9x1#

MySQL有一个 * user-defined variables * 的概念。
它们是松散类型的变量,可以在会话中的某个地方初始化,并保持其值直到会话结束。
它们前面加上一个@符号,如下所示:@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(会话特定变量)则不会。
(In除了用户定义的变量,MySQL * 还 * 有一些预定义的“系统变量”,它们可能是“全局变量”,如@@global.port或“会话变量”,如@@session.sql_mode;这些“会话变量”与特定于会话的用户定义变量无关。

7kqas0il

7kqas0il2#

在MySQL中,@variable表示user-defined variable。您可以定义自己的。

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

字符串
在存储程序之外,没有@variablesystem variable,您无法自己定义。
这个变量的作用域是整个会话。这意味着当你与数据库的连接存在时,这个变量仍然可以使用。
这与MSSQL相反,MSSQL中的变量仅在当前批查询(存储过程、脚本或其他)中可用,而在同一会话的不同批中不可用。

4xy9mtcn

4xy9mtcn3#

MSSQL要求过程中的变量必须是DECLAREd,人们使用@Variable语法(DECLARE @TEXT VARCHAR(25) = 'text')。此外,MS允许在过程中的任何块中声明,不像MySQL需要所有的DECLARE在顶部。
虽然在命令行上很好,但我觉得在MySQL的存储过程中使用set = @variable是有风险的。没有作用域,变量跨越作用域边界。这类似于JavaScript中的变量在声明时没有var前缀,然后是全局命名空间,并产生意外的冲突和覆盖。
我希望MySQL的优秀人员能够在存储过程中的各个块级别上允许DECLARE @Variable。注意@(at符号)。@符号前缀有助于将变量名与表列名分开-因为它们通常是相同的。当然,人们总是可以添加“v”或“l_”前缀,但是@符号是一种方便而简洁的方式,可以让变量名与您可能从中提取数据的列相匹配,而不会破坏它。
MySQL是存储过程的新成员,他们的第一个版本做得很好。很高兴看到他们在这里采取的形式,并观看语言的服务器端方面的成熟。

pu82cl6c

pu82cl6c4#

原则上,我在存储过程中使用UserDefinedVariables(前缀为@)。这使得生活更容易,特别是当我需要在两个或更多存储过程中使用这些变量时。当我只需要一个存储过程中的变量时,我使用系统变量(没有前缀@)。
@Xybo:我不明白为什么在StoredProcedures中使用@variables会有风险。你能更简单地解释一下“scope”和“boundaries”吗?

nwo49xxi

nwo49xxi5#

@variable在从Java、Python等编写的应用程序中调用 * 存储过程 * 时非常有用。有些情况下,变量值在第一次调用中创建,而在后续调用的函数中需要。

PL/SQL(Oracle)旁注

优势可以在 Oracle PL/SQL 中看到,其中这些变量有3个不同的作用域:

*函数变量,当函数退出时其作用域结束。
*包体变量定义在包的顶部,所有作用域为会话、可见性为包的函数之外。
*包变量,变量为session,可见性为全局。

PL/SQL使用心得

我已经开发了一个架构,其中完整的代码是在PL/SQL编写的。这些都是从Java编写的中间件调用。有两种类型的中间-ware。一个用于满足来自客户端的调用,也是用Java编写的。另一个用于满足来自浏览器的调用。客户端功能100%用JavaScript实现。使用命令集代替HTML和JavaScript,用PL/SQL写应用程序。
我一直在寻找同样的工具来将PL/SQL编写的代码移植到另一个数据库。我找到的最近的一个是Postgres。但是所有的变量都有函数作用域。

对MySQL中@的看法

我很高兴看到MySQL中至少有这个@功能。我不认为Oracle会在PL/SQL中为MySQL存储过程构建相同的功能,因为这可能会影响Oracle数据库的销售。

pbgvytdp

pbgvytdp6#

User-defined variables(例如,@name@age):

SET @name = 'John', @age := 27;
SELECT @name := 'John', @age := 27;
SELECT 'John', 27 INTO @name, @age;
  • 可以在会话范围内使用,以便在注销后将其删除。
  • 不受事务处理影响,因此无法回滚其更改值。* My question and the answers对此进行了详细解释。

Local variables(例如,v1v2):

  • 都有类型。
  • 可以使用DECLARE statement进行设置,如下所示。* 您必须指定类型,并且可以使用DEFAULT初始化局部变量,而不使用DEFAULT的局部变量的初始值为NULL:
DECLARE v1, v2 INT DEFAULT 2; -- v1 and v2 are 2.
DECLARE v1, v2 INT;           -- v1 and v2 are NULL.

相关问题