在我的MySQL表上运行一个更新,它将用另一个字段的内容替换1字段的内容

时间:2014-02-06 11:31:24

标签: php mysql

我正在尝试在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中)

非常感谢

3 个答案:

答案 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//

小提琴是http://sqlfiddle.com/#!2/298a7/1