【问题标题】:How to get recordset from internal call to stored procedure?如何从内部调用中获取记录集到存储过程?
【发布时间】:2016-06-04 17:57:38
【问题描述】:

我有一个存储过程,内部我想调用另一个返回记录集的过程,如何通过'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

【问题讨论】:

    标签: mysql stored-procedures mariadb


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      在你的内部过程中创建一个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
      

      【讨论】:

      • @SPlatten,尝试一下,亲自看看......绝对会奏效。
      • 我不知道该怎么做,我试过这个:DROP TEMPORARY TABLE IF EXISTS tbl_HeadOfDepts;创建临时表 tbl_HeadOfDepts AS INSERT INTO tbl_HeadOfDepts CALL rsHeadOfAnyDepartments(vcCompKey, biWho_id);
      • @SPlatten,这是错误的。如果有帮助,请参阅答案中的编辑。
      • 我不能用'SELECT'调用这个过程,它是一个返回记录集的存储过程,只能用'CALL'调用
      • recordset 是什么意思?
      猜你喜欢
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-01
      • 2020-01-11
      相关资源
      最近更新 更多