【问题标题】:MySQL: gets all of procedure out parameter nullMySQL:获取所有过程输出参数 null
【发布时间】:2014-05-28 02:55:42
【问题描述】:

“选择进入”似乎不适用于以下代码。 我可以从 sql 查询的“select 子句”中获取数据,但是使用测试过程代码,它只为每个 out 参数返回空值。 (应该返回一条记录)

谁能告诉我哪里做错了?

操作系统:Mac OSX DBM:MySQL 工作台 6.1 MySQL:5.6.13

程序代码

DELIMITER $$

CREATE DEFINER= PROCEDURE `POLL_NEW_MESSAGE`(OUT DEVICEID INT, OUT ORGID INT, OUT MSGDATE VARCHAR(8), OUT MSGTIME VARCHAR(6), OUT BODY TEXT, OUT TOKEN VARCHAR(64))
BEGIN
    DECLARE DEVICEID INT        DEFAULT -1;
    DECLARE ORGID INT           DEFAULT -1;
    DECLARE MSGDATE VARCHAR(8)  DEFAULT NULL;
    DECLARE MSGTIME VARCHAR(6)  DEFAULT NULL;
    DECLARE BODY TEXT           DEFAULT NULL;
    DECLARE TOKEN VARCHAR(64)   DEFAULT NULL;
    DECLARE UPDATED INT         DEFAULT 0;

    SELECT msg.device_id, msg.org_id, msg.msg_date, msg.msg_time, msg.body
    INTO DEVICEID, ORGID, MSGDATE, MSGTIME, BODY
    FROM pm_msg msg, pm_org org
    WHERE msg.status = '0'
        AND org.org_id = msg.org_id
        AND org.status = 'G';

END

测试代码1

PREPARE s FROM ' CALL `POLL_NEW_MESSAGE`(@DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN)';
execute s;
SELECT @DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN;

测试代码2

CALL `POLL_NEW_MESSAGE`(@DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN);SELECT @DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN;

【问题讨论】:

  • 不用prepare statement直接调用
  • @Rahul,我也尝试过,但结果相同。 CALL POLL_NEW_MESSAGE(@DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN);SELECT @DEVICEID, @ORGID, @MSGDATE, @MSGTIME, @BODY, @TOKEN;

标签: mysql stored-procedures mysql-workbench


【解决方案1】:

在过程中声明具有相同变量名称的参数会导致问题。 一旦我删除了所有已用作过程输出参数的变量声明,它就会按预期工作。

固定代码

DELIMITER $$

CREATE DEFINER= PROCEDURE `POLL_NEW_MESSAGE`(OUT DEVICEID INT, OUT ORGID INT, OUT MSGDATE VARCHAR(8), OUT MSGTIME VARCHAR(6), OUT BODY TEXT)
BEGIN

    SELECT msg.device_id, msg.org_id, msg.msg_date, msg.msg_time, msg.body
    INTO DEVICEID, ORGID, MSGDATE, MSGTIME, BODY
    FROM pm_msg msg, pm_org org
    WHERE msg.status = '0'
        AND org.org_id = msg.org_id
        AND org.status = 'G'
        LIMIT 1;

END

【讨论】:

  • 尽管这将解决获取 NULL 值的问题,但请考虑一下......你正在做的方式......你最终会得到错误的结果,因为你已经将 OUT 变量声明为标量.看我的回答,我也指出了。
  • @Rahul:只要where 获取单行结果,解决方案就可以了。否则,如果没有限制子句,最后一行值将分配给 OUT 参数。
  • @Ravinder,这就是So long as 的重点,不能保证(非确定性)。 LIMIT 不是解决方案,而是一个指针。建议他使用 TVP 作为 OUT 参数,这将获得所需的结果。
【解决方案2】:

您已将所有 OUT 变量声明为 scalar 类型,但在您的 select into 查询中,您试图让它们存储多个值。你这样做的方式..你最终会得到错误的结果,因为你已经将 OUT 变量声明为标量。因此,如果您的查询返回多行,那么您肯定会得到错误的结果。

SELECT msg.device_id, msg.org_id, msg.msg_date, msg.msg_time, msg.body
INTO DEVICEID, ORGID, MSGDATE, MSGTIME, BODY
FROM pm_msg msg, pm_org org
WHERE msg.status = '0'
    AND org.org_id = msg.org_id
    AND org.status = 'G'
    LIMIT 1;

建议是,有一个表值参数作为 OUT 参数。

【讨论】:

  • NULL 输出不是由于缺少LIMIT 或多行结果集。这是因为定义的名称不明确。见:answer by handicop
  • @Ravinder,是的,看到了。我并不是说这是问题的原因,而是他的解决方案存在缺陷。
  • @Rahul,感谢您的评论,是的,我也在选择中添加了限制 1
【解决方案3】:

存储过程中声明的参数名称必须是唯一的。 (注意:这些名称不区分大小写) 即使声明参数的名称与表中的列名相同,它也会返回 NULL。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多