Sql 要逐行迭代一个表,如果另一个表中有匹配的行,请使用限制1删除

Sql 要逐行迭代一个表,如果另一个表中有匹配的行,请使用限制1删除,sql,mysql-5.6,Sql,Mysql 5.6,我基本上是在不消除重复项的情况下进行手动集减法,如果存在重复项,我需要保留它们。我有一个表,我想逐行迭代,如果在一个更大的表中有匹配项,请使用存储过程在更大的表中删除匹配项的单个实例。我该怎么办?我有三个where标准,并写下以下内容: DROP PROCEDURE deleteOverlappingBottles; DELIMITER ;; CREATE PROCEDURE deleteOverlappingBottles() BEGIN DECLARE n INT default 0; D

我基本上是在不消除重复项的情况下进行手动集减法,如果存在重复项,我需要保留它们。我有一个表,我想逐行迭代,如果在一个更大的表中有匹配项,请使用存储过程在更大的表中删除匹配项的单个实例。我该怎么办?我有三个where标准,并写下以下内容:

DROP PROCEDURE deleteOverlappingBottles;
DELIMITER ;;

CREATE PROCEDURE deleteOverlappingBottles()
BEGIN
DECLARE n INT default 0;
DECLARE i INT default 0;
SELECT 10 FROM allBottles INTO n;
SET i = 0;
WHILE i<n DO
    #
    What goes here?  How can I get the current row of allBottles and specifically the values needed for the proceeding where clause?
    DELETE FROM historicdata2Delete as t
    WHERE t.unitADcode = ab.bottleBarcode AND t.bottle_timestamp = ab.t_stamp
    AND t.prepackId = ab.parentPrepackId LIMIT 1;
    SET i = i+1;
END WHILE;
End;
;;
DELIMITER ;

CALL deleteOverlappingBottles();
因此,逐行遍历所有瓶子并删除每个实例的一行将保留historicData2Delete

historicDataToDelete
unitADcode            bottle_timestamp        prepackId
barcode2              timestamp2              id2
barcode3              timestamp3              id3
这是我到目前为止所做的,但它不起作用,为什么

DELIMITER ;;

CREATE PROCEDURE deleteOverlappingBottles()
BEGIN
DECLARE n INT default 0;
DECLARE i INT default 0;

SELECT 10 FROM allBottles INTO n;
SET i = 0;
WHILE i<n DO
    SET @barcode = (SELECT bottleBarcode FROM allBottles LIMIT i,1);
    SET @tstamp = (SELECT t_stamp FROM allBottles LIMIT i, 1);
    SET @preIdx = (SELECT parentPrepackId FROM allBottles LIMIT i, 1);
    DELETE FROM historicdata2Delete
    WHERE unitADcode = @barcode AND bottle_timestamp = @tstamp AND prepackIdx = @preIdx LIMIT 1;
    SET i = i+1;
END WHILE;
End;
;;
DELIMITER ;

CALL deleteOverlappingBottles();

它说结果由不止一行组成。它确实运行了一段时间,一个多小时后我停止了运行,但没有删除任何内容。

看起来您只是缺少了一个光标

参考代码可在此处找到:


免责声明:我不熟悉MySql。语法可能有点错误,请根据您的需要进行调整。

添加了具有所需结果的示例数据。由于某些原因,第一次运行此操作时它不起作用,但第二次执行此操作时,在将数据库恢复到原始状态后,它工作得非常好。非常感谢你。
DELIMITER ;;

CREATE PROCEDURE deleteOverlappingBottles()
BEGIN
DECLARE n INT default 0;
DECLARE i INT default 0;

SELECT 10 FROM allBottles INTO n;
SET i = 0;
WHILE i<n DO
    SET @barcode = (SELECT bottleBarcode FROM allBottles LIMIT i,1);
    SET @tstamp = (SELECT t_stamp FROM allBottles LIMIT i, 1);
    SET @preIdx = (SELECT parentPrepackId FROM allBottles LIMIT i, 1);
    DELETE FROM historicdata2Delete
    WHERE unitADcode = @barcode AND bottle_timestamp = @tstamp AND prepackIdx = @preIdx LIMIT 1;
    SET i = i+1;
END WHILE;
End;
;;
DELIMITER ;

CALL deleteOverlappingBottles();
CREATE PROCEDURE deleteOverlappingBottles()
BEGIN
DECLARE done INT DEFAULT FALSE;
-- Variables for FETCH (change data types to your needs)
DECLARE vBottleBarcode CHAR(100);
DECLARE vt_stamp TIMESTAMP;
DECLARE vParentPrepackId INT;
-- cursor to iterate through the table
DECLARE cur1 CURSOR FOR SELECT BottleBarcode, t_stamp, ParentPrepackId FROM allBottles;
-- apparently MySql needs this to handle the end of the table
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

OPEN cur1;

read_loop: LOOP
    -- get the three column values for the current row
    FETCH cur1 INTO vBottleBarcode, vt_stamp, vParentPrepackId;
    IF done THEN
      LEAVE read_loop;
    END IF;
    -- use the variables from FETCH to identify the row in historicdataToDelete
    DELETE FROM historicdata2Delete as t
    WHERE t.unitADcode = vBottleBarcode AND t.bottle_timestamp = vt_stamp
    AND t.prepackId = vParentPrepackId
    LIMIT 1; -- delete only 1 row
  END LOOP;

  CLOSE cur1;
END LOOP;
End;