【发布时间】:2010-11-03 20:12:53
【问题描述】:
在我发布的另一个问题中,有人告诉我:
@variable
和:
variable
在 MySQL 中。他还提到了 MSSQL 如何具有批处理范围而 MySQL 具有会话范围。有人可以为我详细说明一下吗?
【问题讨论】:
-
我对 MsSQL 很熟悉,所以我从未想过要问这样的问题。这里提供的答案让我知道了一些我不知道的事情!谢谢..
在我发布的另一个问题中,有人告诉我:
@variable
和:
variable
在 MySQL 中。他还提到了 MSSQL 如何具有批处理范围而 MySQL 具有会话范围。有人可以为我详细说明一下吗?
【问题讨论】:
MSSQL 要求声明过程中的变量,人们使用@Variable 语法 (DECLARE @TEXT VARCHAR(25) = 'text')。此外,MS 允许在过程中的任何块内进行声明,这与 MySQL 要求所有声明都在顶部不同。
虽然在命令行上很好,但我觉得在 MySQL 的存储过程中使用 set = @variable 是有风险的。没有范围,变量跨越范围边界。这类似于在 JavaScript 中声明的变量没有 var 前缀,然后是全局命名空间并会产生意外的冲突和覆盖。
我希望 MySQL 的优秀人员将允许 DECLARE @Variable 在存储过程中的各个块级别。注意@(符号)。 @ 符号前缀有助于将变量名与表列名分开——因为它们通常是相同的。当然,总是可以添加“v”或“l_”前缀,但@ 符号是一种方便且简洁的方法,可以让变量名称与您可能从中提取数据的列匹配,而不会破坏它。
MySQL 是存储过程的新手,他们的第一个版本做得很好。很高兴看到他们在这里采取的形式,并看到语言在服务器端方面的成熟。
【讨论】:
@variable 如果从用 Java、Python 等编写的应用程序调用 存储过程 非常有用。
在某些情况下,变量值在第一次调用中创建,而在后续调用的函数中需要。
优势可以在 Oracle PL/SQL 中看到,其中这些变量有 3 个不同的范围:
我开发了一个架构,其中完整的代码是用 PL/SQL 编写的。这些是从用 Java 编写的中间件调用的。有两种类型的中间件。一种用于满足客户端的调用,该客户端也是用 Java 编写的。另一个用于满足来自浏览器的调用。 客户端工具 100% 用 JavaScript 实现。使用命令集代替 HTML 和 JavaScript 在 PL/SQL 中编写应用程序。
我一直在寻找相同的工具将 PL/SQL 编写的代码移植到另一个数据库。我发现最近的一个是 Postgres。但是所有的变量都有函数作用域。
@ 的看法我很高兴看到至少这个@ 设施存在于MySQL 中。我认为 Oracle 不会在 PL/SQL 中为 MySQL 存储过程构建相同的设施,因为它可能会影响 Oracle 数据库的销售。
【讨论】:
@variable,拜托!
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(特定于会话的变量)则不会。
(除了用户定义的变量,MySQL也有一些预定义的“系统变量”,可能是“全局变量”如@@global.port或“会话变量”如@987654332 @;这些“会话变量”与特定于会话的用户定义变量无关。)
【讨论】:
SELECT @@version;。这也是为什么使用DELIMITER @@ 并不是一个好主意的原因。
@而不是?
:= 和= 之间有一个显着的区别,那就是:= 在任何地方都可以作为变量赋值运算符,而= 只能工作SET 语句中的这种方式,并且在其他任何地方都是比较运算符。所以SELECT @var = 1 + 1; 将保持@var 不变并返回一个布尔值(1 或0 取决于@var 的当前值),而SELECT @var := 1 + 1; 将@var 更改为2,并返回2。
在 MySQL 中,@variable 表示 user-defined variable。你可以自己定义。
SET @a = 'test';
SELECT @a;
在存储程序之外,没有@ 的variable 是system variable,您无法自行定义。
这个变量的作用域是整个会话。这意味着当您与数据库的连接存在时,该变量仍然可以使用。
这与 MSSQL 不同,在 MSSQL 中,变量仅在当前批次的查询(存储过程、脚本或其他)中可用。它不会在同一会话的不同批次中提供。
【讨论】:
SET @@a = 'test';,参见。 dev.mysql.com/doc/refman/5.1/en/set-statement.html
@@ 设置用户定义的会话变量。例如,set@@my_var=1、set@@session.my_var=1 和 set session my_var=1 不起作用,因为 my_var 不是 system 变量,而我们可以使用 set@@big_tables=1、set@@session.big_tables=1 和 @ 987654336@ 因为big_tables 是系统变量。
var2 是一个没有 @ 前缀的变量,但它不是系统变量:它是一个过程变量。这是允许的,因为它位于存储过程(也称为存储程序)中。在存储过程之外,没有@ 的变量是系统变量。
原则上,我在存储过程中使用 UserDefinedVariables(以 @ 开头)。这让生活更轻松,尤其是当我在两个或更多存储过程中需要这些变量时。就在我只需要一个存储过程中的变量时,我使用系统变量(不带@)。
@Xybo: 我不明白为什么在 StoredProcedures 中使用 @variables 应该是有风险的。您能否稍微解释一下“范围”和“边界”(对我来说是新手)?
【讨论】:
@@GLOBAL 变量更加“全局”和阴险。他们跨越会议! @variables 具有“会话范围”,因此至少他们以这种方式受到限制。但是,在您所谓的“全局”范围内的任何普通语言中(当它们跨函数等时)。 MySQL 的“全局”概念或许应该被称为“通用”,因为它超越了运行它的进程的边界。 “全局”通常不能用标准语言做到这一点,因为进程不共享内存空间。这源于 SQL 的持久(相对易变)趋势。