【问题标题】:mysql procedure not deleting datamysql程序不删除数据
【发布时间】:2020-08-04 18:51:01
【问题描述】:

我在下面有一个简单的 mysql 过程,可以根据传递的参数从表中删除数据。 由于未删除依赖数据,我收到外部约束失败异常。 我正在形成要删除的 ID 列表,因为我想避免对表进行全表扫描 使用子查询时。 任何帮助表示赞赏。

CREATE PROCEDURE `deleteService`(IN serviceID LONG)
BEGIN
    DECLARE rpslist varchar(512) DEFAULT "";
        DECLARE finished INTEGER DEFAULT 0;
    DECLARE rpsid varchar(512) DEFAULT "";
    DECLARE rpsidcursor 
        CURSOR FOR 
              select id from rpsa where so_id in (select id from rpso where rps_id = serviceID);
    DECLARE CONTINUE HANDLER 
        FOR NOT FOUND SET finished = 1;
 
        OPEN rpsidcursor; //fetch ids to delete
        getRPSId: LOOP       
            FETCH rpsidcursor INTO rpsid;
            IF finished = 1 THEN 
                LEAVE getRPSId;
            END IF;
        SET rpsid = concat("'",rpsid,"'"); -- form concatenated string of IDs
        SET rpslist = CONCAT(rpsid,",",rpslist);
        END LOOP getRPSId;
        CLOSE rpsidcursor;
        SET rpslist = substring(rpslist,1,length(rpslist) -1); -- remove last comma
        DELETE from uach where rpsa_id in (rpslist); -- delete dependent data . forming the list to hit index

    -- this statement fails bcos the delete above did not work and there is foreign constraint
        DELETE from rpsa where rpselectedso_id in (select id from rpselectedso where rpaxnservice_id = serviceID); 
END

【问题讨论】:

  • 为什么要使用游标并将 ID(我假设为整数类型)连接到字符串?为什么你不能把你的 ID 放到一个临时表中并在你的 delete 语句中使用它?如果您试图避免表扫描,那么您的索引是错误的。
  • WHERE .. IN (...) 需要一个字符串文字列表(许多参数文字用逗号分隔),而 rpslist 是一个带有 CSV 的字符串文字。请改用WHERE FIND_IN_SET(rpsa_id, rpslist)
  • 我已经尝试了上述两种方法,并且在这两种情况下它都会进行全表扫描。索引在 id rpsa_id 列上正确定义。在本地工作而不是在有百万多行的产品中工作。

标签: mysql


【解决方案1】:

传递像IN (variable) 这样的CSV 字符串变量将不起作用,因为MySQL 会将变量视为单个元素而不是多个ID。 如果你想做这样的事情,你应该使用动态查询。

【讨论】:

  • 你能分享一篇文章或一个例子来做到这一点吗?我希望每个 id 都被视为 id 而不是字符串变量。非常感谢你
  • 通过动态查询找到答案。谢谢你的指点。
【解决方案2】:

为什么不直接使用直接查询:

CREATE PROCEDURE `deleteService`(IN serviceID LONG)
BEGIN

delete
from uach 
  join rpsa on rpsa.id=uach.rpsa_id
  join rpso on rpso.id=rpsa.so_id
where rpso.rps_id=serviceID;

delete 
from rpsa 
  join rpselectedso on rpselectedso.id=rpsa.rpselectedso_id
where rpselectedso.rpaxnservice_id=serviceID;

END

【讨论】:

  • 这是我的第一选择。我在 uach 表上的 rpsa_id 上有一个显式索引,但对该查询的解释是进行全表扫描。生产中的该表有数百万行。
  • 你也可以使用joins
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 2016-11-26
  • 2011-01-09
  • 2023-04-07
  • 2014-01-19
  • 1970-01-01
相关资源
最近更新 更多