想要逐行遍历 table,如果在另一个 table 中有匹配的行,则删除限制为 1
Want to iterate over a table row by row, and if there's a matching row in another table, delete with limit 1
我基本上是在尝试手动进行集合减法(不删除重复项,如果存在重复项,我需要保留它们)。我有一个 table 我想逐行迭代,如果在更大的 table 中有匹配项,请使用更大的 table 删除匹配项的单个实例存储过程。我该怎么做?我有三个 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();
使用 MySQL 5.6.
historicDataToDelete
unitADcode bottle_timestamp prepackId
barcode1 timestamp1 id1
barcode1 timestamp1 id1
barcode2 timestamp2 id2
barcode3 timestamp3 id3
barcode3 timestamp3 id3
allBottles
bottleBarcode t_stamp parentPrepackId
barcode1 t_stamp1 id1
barcode1 t_stamp1 id1
barcode3 t_stamp3 id3
因此逐行遍历 allBottles 并为每个实例删除一行将保留 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();
它说结果不止一行。之前 运行 有一段时间,一个多小时后我停止了它,但没有删除任何内容。
看来你只是少了一个cursor
。
参考代码可以在这里找到:MySql Cursors
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;
免责声明:我不熟悉MySql。语法可能略有错误,请根据您的需要进行调整。
我基本上是在尝试手动进行集合减法(不删除重复项,如果存在重复项,我需要保留它们)。我有一个 table 我想逐行迭代,如果在更大的 table 中有匹配项,请使用更大的 table 删除匹配项的单个实例存储过程。我该怎么做?我有三个 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();
使用 MySQL 5.6.
historicDataToDelete
unitADcode bottle_timestamp prepackId
barcode1 timestamp1 id1
barcode1 timestamp1 id1
barcode2 timestamp2 id2
barcode3 timestamp3 id3
barcode3 timestamp3 id3
allBottles
bottleBarcode t_stamp parentPrepackId
barcode1 t_stamp1 id1
barcode1 t_stamp1 id1
barcode3 t_stamp3 id3
因此逐行遍历 allBottles 并为每个实例删除一行将保留 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();
它说结果不止一行。之前 运行 有一段时间,一个多小时后我停止了它,但没有删除任何内容。
看来你只是少了一个cursor
。
参考代码可以在这里找到:MySql Cursors
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;
免责声明:我不熟悉MySql。语法可能略有错误,请根据您的需要进行调整。