从视图中调用存储过程

时间:2013-01-25 15:21:36

标签: mysql stored-procedures view

我有一个创建表的过程,是否可以有一个视图(或类似的)可以调用该过程然后从表中选择?

我试过这个:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `new_routine`(p1 INT) RETURNS int(1)
BEGIN
    CALL rMergeDateFields();
    RETURN 1;
END


CREATE VIEW `db`.`vIntervals` AS
  SELECT new_routine(0) AS col1;
  SELECT * FROM MergedData;

但我收到此错误

  

错误1422:存储函数或触发器中不允许显式或隐式提交。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

不,你不能。视图通常是只读操作;如果调用存储过程,则无法保证该行为。

相关问题:

How to call Stored Procedure in a View?

Is it possible to call stored procedure in view?

这是规范资源:

http://dev.mysql.com/doc/refman/5.1/en/view-updatability.html

  

某些视图可以更新。也就是说,您可以在UPDATE,DELETE或INSERT等语句中使用它们来更新基础表的内容。要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。还有一些其他构造使视图不可更新。

由于调用存储过程无法确保与视图行的1:1关系,因此不允许更新。

答案 1 :(得分:1)

问题是在视图中调用存储过程。

但问题中的代码是尝试从用户定义的函数中创建视图。

这是两件非常不同的事情。

在PROCEDURE中允许使用CREATE VIEW语句,但在FUNCTION中禁止使用。

错误信息实际上表明了原因。

DDL操作(与DML操作相反)执行COMMIT,并且在用户定义的函数中不允许该操作。

DML(数据操作语言)语句在上运行。这些包括INSERT,UPDATE,DELETE,REPLACE。

DDL(数据定义语言)语句对数据的定义进行操作,例如添加列,创建表,删除索引等。

按照设计,所有DDL语句都执行隐式COMMIT。任何更改都会使我尚未提交的DML语句最终确定,并且当前事务将结束。

用户定义函数的设计问题是它可以在DML语句中使用......

更新mytable       SET mycolumn = my_user_defined_function()

作为我表中的行,函数" my_user_defined_function"将被执行。 UPDATE语句是原子的,要么应用它所做的所有更改,要么都不应用。在执行UPDATE语句时发出COMMIT(来自函数内部)将有效地"中断" DML操作。

出于同样的原因,同样的限制适用于TRIGGER。可以通过DML语句的操作触发触发器。所以再一次,不能发布COMMIT。

另一方面,程序无法从DML语句执行,因此允许使用COMMIT语句,包括DDL语句执行的隐式提交。

答案 2 :(得分:0)

您无法从视图中执行此操作,但存储过程本身可以返回结果集。

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `merge_and_select` ()
BEGIN
    CALL rMergeDateFields();
    SELECT * FROM MergeData;
END $$

如果您调用merge_and_select(),将运行rMergeDateFields过程,然后您将获得返回给您的MergeData表的内容,这一步......听起来就像您想要的那样。

然而,这是一个非常糟糕的实现,因为没有对merge_and_select()的并发调用的控制,所以如果它同时运行多次就会出错。

但是,根据您真正需要rMergeDateFields()来做什么,您可能需要重写rMergeDateFields()来实际执行您需要完成的任何工作并将其直接返回给客户端而不使用使用无界SELECT的MergeData表,如上所示。

在不使用INTO变量的情况下,您在存储过程中选择的任何内容都将作为CALL的响应返回给客户端。