Mysql中使用select into语句给变量赋值没有匹配记录时的结果

前言

select into语句感兴趣是因为看了项目中的一个存储过程引起的,在程序运行之前看了存储过程的逻辑,本以为没有数据时会报错,结果程序却正常运行,这说明我对select into语句理解的问题,同时也暴露了一个知识盲点,所以写了个小例子测试一下,并把测试的过程记录方便日后查找。

创建测试表格

为了更清楚的表明问题,我们创建的表格尽可能的简单,同时为了测试空值的情况,数据列我们不设置默认值,表格命名为’intotest’,创建语句如下:

1
2
3
4
5
CREATE TABLE `intotest` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`number` int(4),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=binary ROW_FORMAT=DYNAMIC;

插入测试数据

表格建立完成可以使用可视化工具或者insert语句插入测试数据,插入测试数据后查询结果如下:

1
2
3
4
5
6
7
8
9
mysql> select * from intotest;
+----+--------+
| id | number |
+----+--------+
| 1 | 1 |
| 2 | 2 |
| 3 | NULL |
+----+--------+
3 rows in set (0.00 sec)

建立一个存储过程

我们建立一个用于测试的存储过程,主要的逻辑就是看看当select into语句找不到匹配记录时,被赋值的变量会怎么样,建立存储过程的代码如下:

1
2
3
4
5
6
7
CREATE PROCEDURE `select_into_value2`()
BEGIN
DECLARE _value INT DEFAULT 0;

SELECT number FROM intotest WHERE id=1 INTO _value;
SELECT _value;
END

这个存储过程运行正常,配合刚才我们插入表格的记录可以知道,运行后的结果为1:

1
2
3
4
5
6
7
8
9
mysql> call select_into_value();
+--------+
| _value |
+--------+
| 1 |
+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

测试过程

  1. 当查询结果中不存在符合条件的记录时会怎样,修改存储过程定义,然后查看运行结果:

    1
    2
    3
    4
    5
    6
    7
    CREATE PROCEDURE `select_into_value2`()
    BEGIN
    DECLARE _value INT DEFAULT 0;

    SELECT number FROM intotest WHERE id=5 INTO _value;
    SELECT _value;
    END
    1
    2
    3
    4
    5
    6
    7
    8
    9
    mysql> call select_into_value();
    +--------+
    | _value |
    +--------+
    | 0 |
    +--------+
    1 row in set (0.00 sec)

    Query OK, 0 rows affected (0.00 sec)

    结果为0,也就是说当查不到匹配结果时,不会执行select into的赋值效果。

  2. 当匹配到查询结果但是查询出来的数值为null会怎样,修改存储过程定义,然后查看运行结果:

    1
    2
    3
    4
    5
    6
    7
    CREATE PROCEDURE `select_into_value2`()
    BEGIN
    DECLARE _value INT DEFAULT 0;

    SELECT number FROM intotest WHERE id=3 INTO _value;
    SELECT _value;
    END
    1
    2
    3
    4
    5
    6
    7
    8
    9
    mysql> call select_into_value();
    +--------+
    | _value |
    +--------+
    | NULL |
    +--------+
    1 row in set (0.00 sec)

    Query OK, 0 rows affected (0.00 sec)

    结果为NULL,也就是说当查到匹配结果时,不管结果时什么都会赋值到指定的变量中(类型不匹配的sql错误除外)。

  3. 当连续查询赋值中间出现不匹配会怎样,修改存储过程定义,然后查看运行结果:

    1
    2
    3
    4
    5
    6
    7
    8
    CREATE PROCEDURE `select_into_value2`()
    BEGIN
    DECLARE _value INT DEFAULT 0;

    SELECT number FROM intotest WHERE id=2 INTO _value;
    SELECT number FROM intotest WHERE id=5 INTO _value;
    SELECT _value;
    END
    1
    2
    3
    4
    5
    6
    7
    8
    9
    mysql> call select_into_value();
    +--------+
    | _value |
    +--------+
    | 2 |
    +--------+
    1 row in set (0.00 sec)

    Query OK, 0 rows affected (0.00 sec)

    想必明白了前两种情况,这第三种也应该明白了,两条语句顺序执行,找到匹配的就赋值,找不到就放弃操作,结果就保留了上一次成功赋值的结果。

总结

  1. 关于select into语句赋值的规则就一句话,找到了符合条件的记录就赋值,找不到就算了。
  2. 在找到记录的前提下,如果类型不匹配会导致赋值失败并报错,比如查询到字符串赋值给整型变量。
Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客