【问题标题】:SELECT MAX(...) incorrectly returns NULL in stored procedureSELECT MAX(...) 在存储过程中错误地返回 NULL
【发布时间】:2019-09-23 14:16:54
【问题描述】:

我有一个表ga_sum_1,其中有一列created_timestamp。当我从 mysql 命令行执行以下查询时:

mysql> select max(created_timestamp) from ga_sum_1;
+------------------------+
| max(created_timestamp) |
+------------------------+
| 2017-11-05 00:59:55    |
+------------------------+
1 row in set (0.00 sec)

如果我从一个非常简单的存储过程中做同样的事情:

delimiter //
create procedure test()
begin
  select max(created_timestamp) from ga_sum_1;
end//
delimiter ;

mysql> call test();
+------------------------+
| max(created_timestamp) |
+------------------------+
| 2017-11-05 00:59:55    |
+------------------------+
1 row in set (0.00 sec)

但是,当我在存储过程中这样做时:

drop procedure if exists test;

delimiter //

create procedure test()
begin
  declare cursor_end condition for sqlstate '02000';
  declare finished int default 0;
  declare game_id int(11);
  declare user_id int(11);
  declare game_instance_id bigint(20);
  declare currency varchar(15);
  declare created_timestamp timestamp;
  declare wager decimal(18,2);
  declare win decimal(18,2);
  -- cursor
  declare game_action_csr cursor for select * from game_action_view;
  declare continue handler for cursor_end set finished=1;

  -- create view dynamically
select max(created_timestamp) from ga_sum_1;

end//

delimiter ;

mysql> call test();
+------------------------+
| max(created_timestamp) |
+------------------------+
| NULL                   |
+------------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

我在最后一个例子中做错了什么?

====编辑====

一些进一步的研究表明它是declare created_timestamp - 显然混淆了同名列上的选择!

【问题讨论】:

  • 请注意...虽然 MySQL 可以更好地处理这些歧义(它至少可以抱怨),但其中许多可以通过养成在字段名称前加上 name/ 的习惯来避免他们表的别名(诚然很难强迫自己处理单表查询)。

标签: mysql sql sql-null


【解决方案1】:

这可能是因为这行:

  declare created_timestamp timestamp;

【讨论】:

  • 是的 - 我只是用同样的观察来更新我的问题 - 谢谢!
  • “我只是用同样的观察来更新我的问题” @j4nd3r53n 最好在 declare 前加上 declare t_created_timestamp timestamp; 这样的前缀,这样你就知道这些是内部的“临时”变量,如果你养成了习惯,你就不太可能再犯这个错误了。
  • 嗯 @j4nd3r53n 我希望 MySQL 优化器更聪明,我认为优化器应该/可以看到 created_timestamp 存在于两个不同的“命名空间”中,一个作为表列名,一个作为存储过程变量。
  • 在某些环境中,这种歧义可以通过查看最近的命名空间来解决。为什么 MySQL 更喜欢范围变量而不是列名,这超出了我的理解。与列名相比,我会认为变量名离查询更远。
  • @SalmanA 可能是因为列名可以通过为其表的名称/别名添加前缀来指定,其中局部变量或参数不存在类似的消歧方法。虽然字段名称是最接近的“命名空间”,但假设该字段将无法表达您打算引用局部变量。
【解决方案2】:

作为另一个答案的替代方案,您可以更具体:

select max(ga_sum_1.created_timestamp) from ga_sum_1

【讨论】:

    猜你喜欢
    • 2013-01-31
    • 1970-01-01
    • 2011-12-19
    • 2018-10-14
    • 2019-01-25
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多