【问题标题】:How can I select out parameters in a MySQL procedure as table columns?如何在 MySQL 过程中选择参数作为表列?
【发布时间】:2011-12-06 05:46:35
【问题描述】:

环境:MySQL 5.1,Linux

我有一个从单个输入值计算多个值的存储过程。这些值作为 OUT 参数返回。我想为每个行集调用此过程,并将值显示为结果集中的列。这些值具有复杂的关系,因此不容易为每个值构造不同的函数

问题:如何让 OUT 参数显示为表格中的列?

这是我目前所拥有的:

DELIMITER $_$
DROP PROCEDURE IF EXISTS in_out;
CREATE PROCEDURE in_out (
       IN s TEXT, 
       OUT op TEXT, 
       OUT opn INT,
       OUT opd TEXT,
       OUT len INT
       )
BEGIN
        SET op = 'del';
        SET opn = 1;
        SET opd = substr(s,4);
        SET len = LENGTH(SUBSTR(s,4));
END
$_$
DELIMITER ;

然后:

mysql> call in_out('delACT',@op,@opn,@opd,@len);
Query OK, 0 rows affected (0.00 sec)

mysql> select @op,@opn,@opd,@len;
+------+------+------+------+
| @op  | @opn | @opd | @len |
+------+------+------+------+
| snv  |    1 | ACT  |    3 |
+------+------+------+------+
1 row in set (0.00 sec)

到目前为止一切顺利,但我不知道如何为每一行调用此过程并在结果集中返回结果。我想要的是这样的:

dream> select mycol,in_out(mycol) from mytable
+---------+------+------+------+------+
| mycol   | @op  | @opn | @opd | @len |
+---------+------+------+------+------+
| delACT  | del  |    1 | ACT  |    3 |
+---------+------+------+------+------+

谢谢!

【问题讨论】:

  • 你想要来自 SQL Server 的 CROSS APPLY 之类的东西,但我不知道 MySQL 是否有等价物。
  • 其实,我真正想要的是 PostgreSQL 表函数,但这就是我开始哭泣的地方。

标签: mysql sql stored-procedures


【解决方案1】:

你混淆了存储过程和存储函数:

  • 存储的函数会返回一个值,结果可以用在 表达式(如 COS() 和其他 mysql 内置函数)。
  • 存储过程需要使用CALL,是一个独立的操作,不能 用在表达式中。

如果你想“从 mytable 中选择 mycol,in_out(mycol)”,你必须:

CREATE FUNCTION in_out( ...

【讨论】:

  • 我理解其中的区别并且没有混淆它们,但我应该更清楚地说明这一点。 (关于无法构造不同函数的句子旨在激发为什么函数对于这种特定用途来说很尴尬。)
  • 我希望有一个 MySQL 等效于 PostgreSQL 的表函数。粗略地说,这些函数返回一个关系(可能只有一行),其行为就像表一样。示例:pastebin.com/DZVJAvD6。注意:此评论只是为了澄清我所追求的解决方案。对于所有关注的人,这个线程不是关于 MySQL v. PostgreSQL;而是关于 MySQL v. PostgreSQL。请仅对原始问题发表评论。
【解决方案2】:

这似乎是一个棘手的问题:不能在 MySQL 中根据函数/过程结果创建表关系。我最终重构为单独的函数(如 Michał 建议的那样)。我一直希望有一个与 PostgreSQL 的表函数 (http://goo.gl/77QVE) 等效的 MySQL。

【讨论】:

    【解决方案3】:

    我建议在存储过程中为每个可能的值准备数据:

    select distinct mycol
    from mytable
    where <... condition that you would use anyway in final result ...>
    

    其中mycol 是存储过程的参数,将其保存到临时表中,然后加入此值。

    -- way the temp table may look in your sp
    create temporary table tmptable (
        mycol text
        op text, 
        opn int,
        opd text,
        len int
    )
    

    之后使用join:

    select m.mycol, t.op, t.opn, t.opd, t.len
    from mytable m
    join tmptable t on m.mycol = t.mycol
    where <... condition that you would use anyway in final result ...>
    

    有点不同的问题,你确定没有比使用存储过程不同的方式来处理你的最终结果吗?

    【讨论】:

    • 我绝对确定我可以重构为四个不同的函数,但它们几乎肯定会降低效率,即使我将重复的代码与 DETERMINISTIC 函数合并。对于 MySQL,这似乎是唯一的途径。
    • 每个“列”的存储函数将是最简单的方法,并且可能最慢,填充临时表的存储过程可能会更快。如果您一次只处理几行,请使用最简单的方法 - 存储函数。
    猜你喜欢
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 2010-12-10
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    相关资源
    最近更新 更多