MySQL 从另一个存储过程调用存储过程

Posted

技术标签:

【中文标题】MySQL 从另一个存储过程调用存储过程【英文标题】:MySQL calling a stored proc from another stored proc 【发布时间】:2009-11-26 09:15:35 【问题描述】:

我正在处理调用另一个存储过程(子)的存储过程(父)。子进程每次返回一个记录集,其中包含 1 行。

我需要做的是从子进程中提取数据并在父进程中使用它。使用 MSSQL 的方法,我假设我可以填充一个临时表,但我不太确定如何执行此操作。

非常感谢任何帮助。

这是我的 proc 的当前版本。

DELIMITER//

CREATE PROCEDURE CreateTransaction(IN p_TransType tinyint, in p_UserID INT)

BEGIN  

DROP TEMPORARY TABLE IF EXISTS fileData_tmp;

CREATE TEMPORARY TABLE fileData_tmp (t_FilePrefix varchar(5), t_FileSuffix int, t_FileDate varchar(4));

CALL GenerateFileNumber(p_TransType);


END//
DELIMITER;

【问题讨论】:

【参考方案1】:

当您想要返回多个值时,这将起作用。

DROP TABLE IF EXISTS Filename;
CREATE TABLE Filename(
    id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

INSERT INTO Filename(name) VALUES ('AAA'), ('BBB'), ('CCC'), ('DDD'), ('EEE');

DELIMITER //
DROP PROCEDURE IF EXISTS GenerateFileNumber//
CREATE PROCEDURE GenerateFileNumber(p_name VARCHAR(255))
COMMENT 'Gets the file number associated with the given name'
BEGIN
    DECLARE v_id BIGINT;

    DROP TABLE IF EXISTS ReturnValues;
    CREATE TEMPORARY TABLE ReturnValues (
        val1 BIGINT(20) UNSIGNED,
        str1 VARCHAR(255)
    );

    SELECT id INTO v_id FROM Filename WHERE name = p_name;
    INSERT INTO ReturnValues(val1, str1) VALUES (v_id, 'Moop');
END;
//

DROP PROCEDURE IF EXISTS TestCall//
CREATE PROCEDURE TestCall(p_name VARCHAR(255))
COMMENT 'Tests function call within a procedure'
BEGIN
    DECLARE v_id BIGINT;
    DECLARE v_str VARCHAR(255);

    CALL GenerateFileNumber(p_name);

    SELECT val1, str1 INTO v_id, v_str FROM ReturnValues;

    SELECT 'Returns: ' || COALESCE(v_id, 'none') || ', ' || v_str AS msg;
END;
//

DELIMITER ;

不过,一般而言,应尽可能使用先前基于函数的答案。它运行得更快,而且您不必担心意外破坏临时表。

mysql> call TestCall('AAA');
+------------------+
| msg              |
+------------------+
| Returns: 1, Moop |
+------------------+
1 row in set (0.27 sec)

Query OK, 0 rows affected (0.27 sec)

mysql> call TestCall('CCC');
+------------------+
| msg              |
+------------------+
| Returns: 3, Moop |
+------------------+
1 row in set (0.17 sec)

Query OK, 0 rows affected (0.17 sec)

【讨论】:

【参考方案2】:

如果你想返回一个值,为什么不使用函数而不是过程呢?

DROP TABLE IF EXISTS Filename;
CREATE TABLE Filename(
    id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

INSERT INTO Filename(name) VALUES ('AAA'), ('BBB'), ('CCC'), ('DDD'), ('EEE');

DELIMITER //
DROP FUNCTION IF EXISTS GenerateFileNumber//
CREATE FUNCTION GenerateFileNumber(p_name VARCHAR(255))
RETURNS BIGINT
COMMENT 'Gets the file number associated with the given name'
BEGIN
    DECLARE v_id BIGINT;

    SELECT id INTO v_id FROM Filename WHERE name = p_name;

    RETURN v_id;
END;
//

DROP PROCEDURE IF EXISTS TestCall//
CREATE PROCEDURE TestCall(p_name VARCHAR(255))
COMMENT 'Tests function call within a procedure'
BEGIN
    SELECT 'Returns: ' || COALESCE(GenerateFileNumber(p_name), 'none') AS msg;
END;
//

DELIMITER ;

它是这样工作的:

mysql> CALL TestCall('CCC');
+------------+
| msg        |
+------------+
| Returns: 3 |
+------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> CALL TestCall('XXX');
+---------------+
| msg           |
+---------------+
| Returns: none |
+---------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)

【讨论】:

我不使用函数的原因是我需要从GenerateFileNumber返回一个查询集。返回的查询集包含 3 列。我需要在我的父过程的各个地方使用每一列的数据,然后最后将所有 3 连接成一个字符串。 啊,我没有意识到这一点。我将使用临时表添加另一个答案。

以上是关于MySQL 从另一个存储过程调用存储过程的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle 中从另一个存储过程调用一个存储过程

从另一个存储过程调用的存储过程中获取第一个结果集

从另一个存储过程调用具有交叉应用的存储过程会产生错误 SQL 服务器

如何传递逗号分隔的输入参数以从另一个存储过程调用存储过程

如何在没有临时表的情况下从另一个存储过程调用存储过程(带参数)

从另一个不工作的线程调用存储过程 c#, EntityFramework