简体   繁体   English

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

[英]Run an update on my MySQL table that will replace the contents of 1 field with the contents of another

I am trying to run an update on a MySQL table that will swap the contents of 1 field with the contents of another (both in the same table). 我试图在MySQL表上运行更新,该表将1字段的内容与另一个字段的内容交换(两者都在同一个表中)。

Here is the basic structure of the table: 这是表的基本结构:

id      SKU     related
==      ===     =======
1234    SKU001  1234,8889,2209
5544    SKU855  2209,1234
2209    SKUYYT  5544

What I need to do is swap the related field for the relavent SKU (so that it lists the sku's instead of the id's). 我需要做的是交换相关SKU的相关字段(以便它列出sku而不是id的)。 So it would end up looking like this: 所以最终看起来像这样:

id      SKU     related
==      ===     =======
1234    SKU001  SKU001,SKU111,SKUYYT
5544    SKU855  SKUYYT,SKU001
2209    SKUYYT  SKU855

So what I'm trying to achieve is the id in the related field would have been replaced with the SKU that relates to that id. 所以我想要实现的是相关字段中的id将被替换为与该id相关的SKU。

What I'm currently doing is this: 我目前正在做的是:

SELECT id, sku FROM my_table

Then looping through all id's with PHP and updating the table like so: 然后使用PHP循环遍历所有id并更新表,如下所示:

UPDATE my_table SET related = REPLACE(related, '5544', 'SKU855');

This seems to work but I have 9000+ rows and multiple id's in the related column and it's taking hours to complete 似乎有效,但我在相关列中有9000多行和多个id,并且需要数小时才能完成

Can anyone suggest a better way of achieving this? 谁能建议更好的方法来实现这一目标? (Ideally in MySQL) (理想情况下在MySQL中)

Many thanks 非常感谢

If you have access to PHP with this update, I would suggest you do the following: 如果您可以通过此更新访问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);

Essentially, doing this in raw SQL is going to be very difficult, and you will be left with a very complex query. 从本质上讲,在原始SQL中执行此操作将非常困难,并且您将面临一个非常复杂的查询。 The best way is to abstract the detecting and replacing of the IDs / SKU numbers into PHP, where this becomes a much easier and more readable platform to work on. 最好的方法是将ID / SKU编号的检测和替换抽象为PHP,这将成为一个更容易和更易读的平台。

The code loads all rows in the table, then loops through each row to cache it's ID and SKU number separately. 代码加载表中的所有行,然后遍历每一行以分别缓存它的ID和SKU编号。

Then, we loop through each row again, break apart the related field into an array of IDs, replace those IDs with their correct SKU code using the cache we created, and insert them back into $rows . 然后,我们再次遍历每一行,将相关字段拆分为一个ID数组,使用我们创建的缓存将这些ID替换为正确的SKU代码,然后将它们插回到$rows

$rows becomes the new updated table set. $rows成为新的更新表集。 From there, it's a case of creating a giant UPDATE statement, or looping through each row and executing a single UPDATE statement for each one. 从那里开始,就是创建一个巨大的UPDATE语句,或循环遍历每一行并为每一行执行单个UPDATE语句。 Looping in PHP and issuing an UPDATE for each row would be slower as making a query has overhead. 在PHP中循环并为每一行发出UPDATE将会变慢,因为查询会产生开销。 But you can also implement the loop in SQL, using stored procedure, avoiding the overhead on communication between your application and database. 但您也可以使用存储过程在SQL中实现循环,从而避免应用程序和数据库之间的通信开销。

/*
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;
*/

When You are asking to do it in mysql , then it would be possible by using CURSOR and dynamic query. 当您要求在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//

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM