我正在尝试在MySQL表上运行更新,该表将1字段的内容与另一个字段的内容交换(两者都在同一个表中)。
以下是该表的基本结构:
id SKU related
== === =======
1234 SKU001 1234,8889,2209
5544 SKU855 2209,1234
2209 SKUYYT 5544
我需要做的是交换相关SKU的相关字段(以便它列出sku而不是id)。所以它最终看起来像这样:
id SKU related
== === =======
1234 SKU001 SKU001,SKU111,SKUYYT
5544 SKU855 SKUYYT,SKU001
2209 SKUYYT SKU855
所以我想要实现的是相关字段中的id将被替换为与该id相关的SKU。
我目前正在做的是:
SELECT id, sku FROM my_table
然后使用PHP循环遍历所有id并更新表格如下:
UPDATE my_table SET related = REPLACE(related, '5544', 'SKU855');
此似乎可以正常工作,但我在相关列中有9000多行和多个ID,并且需要数小时才能完成
有人能建议更好的方法吗? (理想情况下在MySQL中)
非常感谢
答案 0 :(得分:2)
如果您可以通过此更新访问PHP,我建议您执行以下操作:
$rows = some_method_to_load_all_rows_from_your_table();
$id_to_sku = array();
// Loop through all rows to cache their SKU numbers and directly associate them to their row's PK.
foreach ($rows as $row) {
$id_to_sku[$row['id']] = $row['SKU'];
}
// Loop through all rows a second time to then break apart, find, and replace the related IDs.
foreach ($rows as $index => $row) {
$related_ids = explode(',', $row['related']);
foreach($related_ids as &$related_id) {
if (isset($id_to_sku[$related_id]]) {
$related_id = $id_to_sku[$related_id]];
} // else the ID couldn't be found.
}
$rows[$index]['related'] = implode(',', $related_ids);
}
// $rows now contains the related string with the SKU numbers instead of ID numbers.
method_to_update_all_rows_with_new_related_value($rows);
基本上,在原始SQL中执行此操作将非常困难,并且您将面临非常复杂的查询。最好的方法是将ID / SKU编号的检测和替换抽象为PHP,这将成为一个更容易和更易读的平台。
代码加载表中的所有行,然后遍历每一行以分别缓存它的ID和SKU编号。
然后,我们再次遍历每一行,将相关字段拆分为一个ID数组,使用我们创建的缓存将这些ID替换为正确的SKU代码,然后将它们插回$rows
。
$rows
成为新的更新表集。从那里开始,就是创建一个巨大的UPDATE
语句,或循环遍历每一行并为每一行执行单个UPDATE
语句。在PHP中循环并为每一行发出UPDATE
会慢一些,因为查询会产生开销。但是你也可以使用存储过程在SQL中实现循环,避免应用程序和数据库之间通信的开销。
答案 1 :(得分:0)
/*
create my_table_temp with same structure as in my_table
*/
$mapping = array();
$sth = $dbh->prepare("SELECT id, SKU FROM my_table");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row) {
$mapping[$row['id']] = $row['SKU'];
}
$sql = 'insert into my_table_temp(id, SKU, related) VALUES ';
$params = array();
$sth = $dbh->prepare("SELECT * FROM my_table");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row) {
$related = explode(',', $row['related']);
foreach($related as &$val) {
$val = $mapping[$val];
}
$sql .= '(?, ?, ?),';
$params[] = $row['id'];
$params[] = $row['SKU'];
$params[] = implode(',', $related);
}
$sql = rtrim($sql, ',');
$sth = $dbh->prepare($sql);
$sth->execute($params);
/*
update my_table
set related = q.related
from (
select sku, related
from my_table_temp
) q
where my_table.sku = q.sku;
drop table my_table_temp;
*/
答案 2 :(得分:0)
当您要求在mysql中执行此操作时,可以使用CURSOR和动态查询。
DELIMITER //
CREATE PROCEDURE `all_update`()
BEGIN
DECLARE ids INT;
DECLARE sname VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE cursor1 CURSOR FOR SELECT id,SKU FROM testing;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN cursor1;
update_table: LOOP
FETCH cursor1 INTO ids,sname;
IF finished = 1 THEN
LEAVE update_table;
END IF;
SET @s = CONCAT('UPDATE testing SET related = REPLACE(related,', ids,', "',sname,'")');
PREPARE stmt1 FROM @s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP update_table;
CLOSE cursor1;
END//