Mysql中未初始化的变量与NULL有何不同?

rub*_*o77 6 mysql

相关,请先阅读上下文:MySQL存储过程:循环表,删除行。逻辑问题:不会因为查询中的 LIMIT 选项而退出循环

我觉得这真的很奇怪。我不明白为什么那个问题的解决方案是这样工作的,有人可以解释一下解决方案吗?

这是在mysql文档中说明的:

如果引用未初始化的变量,则它的值为 NULL 且类型为字符串。

如果在使用变量之前将变量设置为 NULL,那么为什么它会有所不同,如果这是未初始化变量的默认值呢?

(我知道,这是非常脏的编程,不是初始化变量,但我仍然想了解这种行为。)

Mic*_*bot 10

有两种方法可以从查询中设置变量,它们的行为有所不同,尤其是在没有匹配的记录时。

您可以SELECT ... INTO将变量...

select first_name into @z from actor where actor_id = 999999;
Run Code Online (Sandbox Code Playgroud)

或者您可以将SET其转换为标量子查询返回的值。

set @z = (select first_name from actor where actor_id = 999999);
Run Code Online (Sandbox Code Playgroud)

说明与示例数据库的区别...

mysql> use sakila;
Database changed
Run Code Online (Sandbox Code Playgroud)

我们的变量从NULL.

mysql> select @z;
+------+
| @z   |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

mysql> SELECT first_name INTO @z FROM actor WHERE actor_id = 1;
Query OK, 1 row affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我们匹配了一行并设置了我们的变量。

mysql> select @z;
+----------+
| @z       |
+----------+
| PENELOPE |
+----------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我们尝试选择一个不存在的记录:

mysql> select first_name into @z from actor where actor_id = 999999;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------------+
| Level   | Code | Message                                             |
+---------+------+-----------------------------------------------------+
| Warning | 1329 | No data - zero rows fetched, selected, or processed |
+---------+------+-----------------------------------------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

那么现在我们的变量是什么?

mysql> select @z;
+----------+
| @z       |
+----------+
| PENELOPE |
+----------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我认为这解释了混乱。当没有找到行时,变量与其先前的值保持不变......所以不是你必须“在使用它之前将它设置为空”,而是你必须在再次使用它之前将它重置为空,如果您正在执行类似的操作SELECT ... INTO,则不会在未找到任何内容的情况下重置该值。

另一方面,如果我们使用其他构造,则在没有匹配记录时重置变量。

mysql> select @z;
+----------+
| @z       |
+----------+
| PENELOPE |
+----------+
1 row in set (0.00 sec)

mysql> set @z = (select first_name from actor where actor_id = 999999);
Query OK, 0 rows affected (0.00 sec)

mysql> select @z;
+------+
| @z   |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

mysql>
Run Code Online (Sandbox Code Playgroud)