如何从内部调用到存储过程获取记录集?

时间:2016-06-04 17:57:38

标签: mysql stored-procedures mariadb

我有一个存储过程,在内部我想调用另一个返回记录集的过程,如何通过'CALL'导航存储过程返回的记录集?

[edit]我一直在尝试按照建议使用TEMPORARY TABLE,但遇到问题:

    DROP TEMPORARY TABLE IF EXISTS tbl_HeadOfDepts;
    CREATE TEMPORARY TABLE tbl_HeadOfDepts (biDept_id tinyint(4))
    INSERT INTO tbl_HeadOfDepts CALL rsHeadOfAnyDepartments(vcCompKey, biWho_id);

我需要使用CALL,因为'rsHeadOfAnyDepartments'不是函数,但不会被接受。

正在进行中,但到目前为止我还没有被编辑接受:

    BEGIN
    #--
    # Procedure:
    #   rsWhoCanIaccess
    #
    # Parameters:
    #   vcCompKey, the key corresponding to the company
    #   biWho_id, the id of the person to check access for
    #
    # Returns:
    #   recordset containing all the people this person can access
    #--
        DECLARE tiSuperUser tinyint(4); 
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
            BEGIN
                GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, 
                @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
                CALL procLogError(vcCompKey, CONCAT("rsWhoCanIaccess: "
                                        ,@errno, " (", @sqlstate, "): ", @text));
            END;        
    #Is this user a super user?
        SELECT tiIsSuperUser(vcCompKey, biWho_id) INTO tiSuperUser;
        SET tiSuperUser = 0;#Hack for testing
        IF (tiSuperUser = 1) THEN
    #The user is a superuser, return everyone in the company
            SELECT 
                t1.biPerson_id 
            FROM 
                tbl_people t1
            INNER JOIN
                tbl_companies t2
            ON
                t1.biCompany_id=t2.biCompany_id
            AND
                t2.vcKey=vcCompKey;         
        ELSE            
    #User is not a superuser, is the user head of any departments?
            DROP TEMPORARY TABLE IF EXISTS tbl_HeadOfDepts;
            CREATE TEMPORARY TABLE tbl_HeadOfDepts (biDept_id tinyint(4))
            INSERT INTO tbl_HeadOfDepts CALL rsHeadOfAnyDepartments(vcCompKey, biWho_id);

            SELECT * FROM tbl_HeadOfDepts;
        END IF;
    END

2 个答案:

答案 0 :(得分:2)

不,存储过程可以生成结果集,但不能直接将它们作为内部调用输出到其他存储过程。您可以在性能方面做得最好的是填充非临时工作表并使用结果。

根据您的软件和多个调用者的实际情况,您可能需要在某个控制表中包含一个带有auto_increment(AI)列的会话ID概念。这将确保通过并发性,多个调用者不会在彼此的行上踩踏,从而使其不可行。

该会话如何在高层次上发挥作用如下。内部存储过程将从控制表中传递AI值(theSession),用它来填充工作表中安全分段的会话,并作为out参数返回外(调用)存储过程。那个外面的那个可以安全地使用那些行,并在最后清理(delete from workTable where sessionId=theSession)。

为什么我建议使用非临时工作台?需要明确的是,工作台将是非临时的。首先,让if exists drop工作有麻烦。但最重要的是,它与性能有关。创建临时表的DDL调用并不便宜。当你进行性能测试以了解我的意思时,你才会相信这一点。这可能看起来微不足道,但是在琐碎的操作中,那些DDL创建调用很可能会占据内部存储过程完成所需时间的大部分时间。

答案 1 :(得分:1)

  

内部我想调用另一个返回记录集的过程,

在您的内部过程中创建一个TEMPORARY TABLE并填充该临时表,说insert into your_temp_table select query。那么你可以在任何地方的外部查询中使用相同的临时表。

它甚至可以是普通表,也不必是临时表。一旦程序计算完成清理,也要确保DROP表格。

根据你的评论,这是错误的。您应该像下面这样(示例代码)

create procedure rsHeadOfAnyDepartments(vcCompKey varchar(10), biWho_id int)
as
begin
DROP TEMPORARY TABLE IF EXISTS tbl_HeadOfDepts; 
CREATE TEMPORARY TABLE tbl_HeadOfDepts(col1 int, col2 varchar(10), col3 varchar(30));

INSERT INTO tbl_HeadOfDepts
SELECT col1, col2, col3
FROM tblTest;    
end
相关问题