如何使用一组记录的值列表中的值更新列

时间:2014-09-03 19:29:20

标签: mysql sql sql-update

我逐行在表格中进行更新:

UPDATE table  
SET col = $value  
WHERE id = $id   

现在,如果我更新,例如每条记录有10000条记录获得$value,但$id获取哪条$value并不重要。我唯一的要求是我正在更新的所有记录都以$value结尾 那么我怎样才能将此更新转换为类似

的更新
UPDATE table  
SET col ?????? what here from a $value_list???
WHERE id IN ($id_list)  

即。传递列表ID,并以某种方式将值和该范围的ID获取 a

1 个答案:

答案 0 :(得分:1)

我们假设您有两个逗号分隔的ID列表以及具有相同项目数的值。然后,您可以使用以下语句进行更新:

-- the list of the ids
SET @ids = '2,4,5,6';
-- the list of the values
SET @vals = '17, 73,55, 12';

UPDATE yourtable
INNER JOIN (
    SELECT
        SUBSTRING_INDEX(SUBSTRING_INDEX(t.ids, ',', n.n), ',', -1) id,
        SUBSTRING_INDEX(SUBSTRING_INDEX(t.vals, ',', n.n), ',', -1) val
    FROM (SELECT @ids as ids, @vals as vals) t 
    CROSS JOIN (
        -- build for up to 1000 separated values
        SELECT 
            1 + a.N + b.N * 10 + c.N * 100 AS n
        FROM
            (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
           ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
           ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
        ORDER BY n
    ) n
    WHERE n <= (1 + LENGTH(t.ids) - LENGTH(REPLACE(t.ids, ',', '')))
) t1
ON
    yourtable.id = t1.id
SET
    yourtable.val = t1.val;

<强>解释

UNIONs的内部系列构建一个数字从1到1000的表。您应该能够根据需要扩展此机制:

-- build for up to 1000 separated values
SELECT 
    a.N + b.N * 10 + c.N * 100 + 1 AS n
FROM
    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
ORDER BY n

我们使用此数字通过嵌套SUBSTRING_INDEX调用

从列表中获取项目
SUBSTRING_INDEX(SUBSTRING_INDEX(t.ids, ',', n.n), ',', -1) id,
SUBSTRING_INDEX(SUBSTRING_INDEX(t.vals, ',', n.n), ',', -1) val

WHERE子句获取(仅确定两个中的一个)列表中的项目数:

WHERE n <= (1 + LENGTH(t.ids) - LENGTH(REPLACE(t.ids, ',', '')))

因为我们发现了一个较少的分隔符,我们将列表长度与分隔符和列表长度的差值加1,而不会出现所有分隔符。

然后我们使用外部UPDATE语句中的id值对JOIN操作执行UPDATE。

this fiddle中查看它。

相信我:这比痛苦的逐行更新要快得多。