【问题标题】:MySQL stored procedure returns multiple parametersMySQL存储过程返回多个参数
【发布时间】:2016-05-11 13:49:43
【问题描述】:

我不喜欢存储过程。现在我有一个可以工作的,但我想学习如何优化它。

CREATE DEFINER=`simonh`@`%` PROCEDURE `get_normalized_client_id`(IN source_id INT, IN source_division VARCHAR(255), IN source_currency VARCHAR(255), OUT NORMALIZED_ID INT, OUT NAME VARCHAR(255), OUT ADDRESS VARCHAR(255))
BEGIN

IF source_id > 100000 THEN SET source_id = source_id - 100000; END IF;

SELECT
CLIENT.NEW_GROUP_REFERENCE_NUMBER INTO NORMALIZED_ID
FROM ccis_vendors.client_id SOURCE
INNER JOIN ccis_vendors.receivable CLIENT ON CLIENT.id = SOURCE.ACCOUNT_ID
WHERE SOURCE.number = source_id AND SOURCE.division = source_division;

SELECT
CLIENT.name INTO NAME
FROM ccis_vendors.client_id SOURCE
INNER JOIN ccis_vendors.receivable CLIENT ON CLIENT.id = SOURCE.ACCOUNT_ID
WHERE SOURCE.number = source_id AND SOURCE.division = source_division;

SELECT
CONCAT(IFNULL(CLIENT.OPERATION_STREET,''), ' ', IFNULL(CLIENT.OPERATION_CITY,''), ' ', 
IFNULL(CLIENT.OPERATION_STATE_PROVINCE, ''), ' ', IFNULL(CLIENT.OPERATION_ZIP, '')) INTO ADDRESS
FROM ccis_vendors.client_id SOURCE
INNER JOIN ccis_vendors.receivable CLIENT ON CLIENT.id =  SOURCE.ACCOUNT_ID
WHERE SOURCE.number = source_id AND SOURCE.division = source_division;

END

如您所见,我使用相同的查询 3 次来填充 3 个 OUT 参数。

我的问题是,有没有办法只用一个查询来做到这一点?

谢谢。

编辑: 我明白为什么 INTO 现在不适合我了。语法错误。

这是工作版本:

CREATE PROCEDURE `t_get_normalized_client_id`(IN source_id INT, IN source_division VARCHAR(255), IN source_currency VARCHAR(255), OUT NORMALIZED_ID INT, OUT NAME VARCHAR(255), OUT ADDRESS VARCHAR(255))
BEGIN

IF source_id > 100000 THEN SET source_id = source_id - 100000; END IF;

SELECT
CLIENT.NEW_GROUP_REFERENCE_NUMBER, 
CLIENT.name,  
CONCAT(IFNULL(CLIENT.OPERATION_STREET,''), ' ',    IFNULL(CLIENT.OPERATION_CITY,''), ' ', 
IFNULL(CLIENT.OPERATION_STATE_PROVINCE, ''), ' ', IFNULL(CLIENT.OPERATION_ZIP, ''))

INTO 
NORMALIZED_ID,
NAME,
ADDRESS

FROM ccis_vendors.client_id SOURCE
INNER JOIN ccis_vendors.receivable CLIENT ON CLIENT.id = SOURCE.ACCOUNT_ID
WHERE SOURCE.number = source_id AND SOURCE.division = source_division;

END

谢谢大家!

【问题讨论】:

    标签: mysql database stored-procedures


    【解决方案1】:

    你不能这样吗?

     CREATE DEFINER=`simonh`@`%` PROCEDURE `get_normalized_client_id`(IN source_id INT, IN source_division VARCHAR(255), IN source_currency VARCHAR(255), OUT NORMALIZED_ID INT, OUT NAME VARCHAR(255), OUT ADDRESS VARCHAR(255))
        BEGIN
    
    IF source_id > 100000 THEN SET source_id = source_id - 100000; END IF;
    
    SELECT
    CLIENT.NEW_GROUP_REFERENCE_NUMBER INTO NORMALIZED_ID,
    CONCAT(IFNULL(CLIENT.OPERATION_STREET,''), ' ', IFNULL(CLIENT.OPERATION_CITY,''), ' ', 
    IFNULL(CLIENT.OPERATION_STATE_PROVINCE, ''), ' ', IFNULL(CLIENT.OPERATION_ZIP, '')) INTO ADDRESS,
    CLIENT.name INTO NAME
    FROM ccis_vendors.client_id SOURCE
    INNER JOIN ccis_vendors.receivable CLIENT ON CLIENT.id = SOURCE.ACCOUNT_ID
    WHERE SOURCE.number = source_id AND SOURCE.division = source_division;
    
    
    END
    

    【讨论】:

    • 我试图这样做,但我收到一条错误消息,指出 CLIENT 不存在,这是在 INNER JOIN 中声明的。
    • 奇怪,您确定您的查询有效吗?尝试执行你在问题中写在这里的查询,看看你得到了什么。
    • 我有这个存储过程工作,我只想做一个优化。
    • mysql版本重要吗? AFAIK,这是一个相当旧的版本。
    • MySQL客户端版本:5.5.29
    【解决方案2】:

    您可以将选择简化为一个。而且,我建议对参数使用一致的命名约定——因此不太可能与列混淆:

    DELIMITER $$
    CREATE DEFINER=`simonh`@`%` PROCEDURE `get_normalized_client_id`(
        IN in_source_id INT,
        IN in_source_division VARCHAR(255),
        IN in_source_currency VARCHAR(255),
        OUT out_NORMALIZED_ID INT,
        OUT out_NAME VARCHAR(255),
        OUT out_ADDRESS VARCHAR(255)
    )
    BEGIN
        IF in_source_id > 100000 THEN
            SET in_source_id = in_source_id - 100000;
        END IF;
    
        SELECT out_NORMALIZED_ID := CLIENT.NEW_GROUP_REFERENCE_NUMBER,
               out_Name := CLIENT.NAME,
               out_Address := CONCAT_WS(' ', CLIENT.OPERATION_STREET, CLIENT.OPERATION_CITY,
                                        CLIENT.OPERATION_STATE_PROVINCE, CLIENT.OPERATION_ZIP
                                       )
        FROM ccis_vendors.client_id SOURCE INNER JOIN
             ccis_vendors.receivable CLIENT
             ON CLIENT.id = SOURCE.ACCOUNT_ID
        WHERE SOURCE.number = in_source_id AND SOURCE.division = in_source_division;
    
    END;$$
    DELIMITER ;
    

    另外:

    • 我将IF 放在多行上。更清楚的是END IF 在那里。一般来说,我会将事情的“结束”放在“开始”的下方,以确保正确结束。
    • CONCAT_WS() 似乎比 CONCAT() 更好。作为奖励,它还处理 NULL 值。
    • 我更喜欢:= 的内联语法而不是INTO。这真的只是风格问题。 INTO 用于其他用途,例如文件访问,所以我认为:= 更清晰。

    【讨论】:

    • 可能我的mysql已经过时了,我收到一条错误信息:#1064 - 你的SQL语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 12 行的 ':= CLIENT.NEW_GROUP_REFERENCE_NUMBER, out_Name := CLIENT.NAME, ' 附近使用正确的语法
    • MySQL客户端版本:5.5.29
    • 如果我将 := 更改为 INTO,mysql 会抛出另一个错误:未声明的变量:CLIENT
    【解决方案3】:

    Begin 和 End 语句之间 选择 CLIENT.name INTO NAME, CLIENT.NEW_GROUP_REFERENCE_NUMBER 到 NORMALIZED_ID, CONCAT(IFNULL(CLIENT.OPERATION_STREET,''), '', IFNULL(CLIENT.OPERATION_CITY,''), '', IFNULL(CLIENT.OPERATION_STATE_PROVINCE, ''), ' ', IFNULL(CLIENT.OPERATION_ZIP, '')) 进入地址 FROM ccis_vendors.client_id SOURCE 内部连接 ​​ccis_vendors.receivable CLIENT ON CLIENT.id = SOURCE.ACCOUNT_ID WHERE SOURCE.number = source_id AND SOURCE.division = source_division;

    【讨论】:

      猜你喜欢
      • 2012-12-17
      • 2014-01-04
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 2011-01-17
      • 2021-12-13
      相关资源
      最近更新 更多