在存储过程中检索多于一行

Posted

技术标签:

【中文标题】在存储过程中检索多于一行【英文标题】:Retrieving more than one rows in a stored procedure 【发布时间】:2019-03-08 07:43:43 【问题描述】:

我需要执行全表级别扫描,因为它应该根据用户 ID 检索多行。

因为我曾经收到 sqlMessage 声明“子查询返回超过 1 行”。

 Error: ER_SUBQUERY_NO_1_ROW: Subquery returns more than 1 row
  ...
  code: 'ER_SUBQUERY_NO_1_ROW',
  errno: 1242,
  sqlMessage: 'Subquery returns more than 1 row',
  sqlState: '21000',
  index: 0,
  sql: 'CALL GetLocationTag(1)' 

这是对GetLocationTag()代码的调用

DELIMITER $$

CREATE
    DEFINER = `root`@`localhost`
    PROCEDURE `someDB`.`GetLocationTag`(IN `UserId` BIGINT)
    LANGUAGE SQL
    DETERMINISTIC
    READS SQL DATA 
    SQL SECURITY DEFINER 
    COMMENT 'Retrieves Multiple Stored Location Tags, Address, Location, etc. based on User_ID'
    BEGIN
        DECLARE flag INT(11);
        DECLARE locRecord VARCHAR(255);

            IF EXISTS (SELECT * FROM `location_map` WHERE `user_id` = User_Id ) THEN  
                BEGIN
                    SELECT * INTO locRecord FROM `location_map` WHERE `user_id` = User_Id;
                    SET flag = 1;
                END;            
            ELSE
                SET flag = 0;
                SET locRecord = 0;
            END IF;

        SELECT locRecord, flag;
    END$$

DELIMITER ;

对于以下查询,

SELECT * INTO locRecord FROM `location_map` WHERE `user_id` = User_Id;

我需要如何以数组的形式检索所有行并将其存储到变量中,或者我应该如何编写代码以便需要解决错误消息?

【问题讨论】:

【参考方案1】:

使用视图来存储您获取的数据而不是变量

DELIMITER $$

CREATE
    DEFINER = `root`@`localhost`
    PROCEDURE `someDB`.`GetLocationTag`(IN `User_Id` BIGINT)
    LANGUAGE SQL
    DETERMINISTIC
    MODIFIES SQL DATA
    SQL SECURITY DEFINER
    COMMENT 'Retrieves Multiple Stored Location Tags, Address, Location, etc. based on User_ID'
    BEGIN
        DECLARE flag INT(11);
        DECLARE locRecord VARCHAR(255);

            IF EXISTS (SELECT * FROM `location_map` WHERE `user_id` = User_Id ) THEN  
                BEGIN
                    SET @viewQry = CONCAT('CREATE OR REPLACE VIEW `someDB`.`temp` as SELECT *, 1 as flag FROM `location_map` WHERE `user_id` = ',User_Id,';');
                    PREPARE stmt FROM @viewQry; 
                    EXECUTE stmt; 
                    DEALLOCATE PREPARE stmt;
                    SELECT * FROM temp;
                END;            
            ELSE
                SELECT 0 AS locRecord, 0 AS flag;
            END IF;
    END$$

DELIMITER ;

【讨论】:

上面的语法应该是这样 CREATE OR REPLACE VIEW someDB.temp AS SELECT *, 1 AS flag FROM location_map WHERE user_id = User_Id;但不幸的是我得到`代码:'ER_NO_SUCH_TABLE',errno:1146,sqlMessage:'表\'someDB.temp\'不存在',sqlState:'42S02' 在 else 部分中删除“from temp”部分。更新答案 获取错误代码:1351 视图的 SELECT 包含变量或参数 尝试 concat 并作为准备好的语句执行。更新了答案 错误代码:1583 调用本机函数'CONCAT'中的参数不正确

以上是关于在存储过程中检索多于一行的主要内容,如果未能解决你的问题,请参考以下文章

检索和更新存储过程中的第一行 - 由多个进程访问

存储过程多于查询

在存储过程中执行时选择查询不检索记录

从存储过程中检索数据

Oracle 12 PL/SQL 在触发器中检索存储过程名称

如何在一个 SQL 查询中检索值并在存储过程中使用它?