19

这是更新 mysql SET 字段的最佳方法,以从字段中删除特定值。

例如。具有值的字段类别:1、2、3、4、5?我想从列表中删除“2”:

UPDATE table 
SET categories = REPLACE(categories, ',2,', ',') 
WHERE field LIKE '%,2,%';

但是如果 '2' 是列表中的第一个或最后一个值呢?

UPDATE table 
SET categories = REPLACE(categories, '2,', '') 
WHERE field LIKE '2,%';

UPDATE table 
SET categories = REPLACE(categories, ',2', '') 
WHERE field LIKE ',2%';

我怎么能用一个查询来处理所有 3 个案例?!

4

7 回答 7

32

如果您需要从集合中删除的值不能多次出现,您可以使用这个:

UPDATE yourtable
SET
  categories =
    TRIM(BOTH ',' FROM REPLACE(CONCAT(',', categories, ','), ',2,', ','))
WHERE
  FIND_IN_SET('2', categories)

看到它在这里工作。如果该值可以多次出现,这将删除它的所有出现:

UPDATE yourtable
SET
  categories =
    TRIM(BOTH ',' FROM
      REPLACE(
        REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',')
    )
WHERE
  FIND_IN_SET('2', categories)
于 2013-02-01T09:26:17.800 回答
8
update TABLE
set COLUMN = COLUMN & ~NUM
where COLUMN & NUM

取自以下评论部分:http ://dev.mysql.com/doc/refman/5.0/en/set.html

但请注意,NUM 不是值 '2',而是它的内部索引。所以如果你定义了像“set ('1,'2','3','4','5')”这样的字段,那么这些值的对应索引是(1,2,4,8,16)。

于 2013-02-01T11:03:54.790 回答
5

最好的方法是不要将用逗号分隔的值保存在表格上。

但要回答你的问题,你可以使用CASE这个,

UPDATE table 
SET categories = CASE WHEN field LIKE '%,2,%'  -- In the middle
                           THEN REPLACE(categories, ',2,', ',')
                      WHEN field LIKE '2,%'    -- At the beginning
                           THEN REPLACE(categories, '2,', '')
                      WHEN field LIKE '%,2'    -- At the end
                           THEN REPLACE(categories, ',2', '') 
                      WHEN field = '2'         -- At whole
                           THEN '' 
                 END
WHERE FIND_IN_SET('2', categories)
于 2013-02-01T09:03:51.930 回答
2

这是另一种方法:

UPDATE table
SET categories = CONCAT_WS(',',
    IF(FIND_IN_SET('1', categories), '1', NULL),
    -- Note that '2' is missing here!
    IF(FIND_IN_SET('3', categories), '3', NULL),
    IF(FIND_IN_SET('4', categories), '4', NULL),
    IF(FIND_IN_SET('5', categories), '5', NULL)
);

CONCAT_WS','如果不是 ,则将其所有参数(参数 1 除外)与第一个参数(在本例中)连接起来NULL。如果字段包含它,我们会查找该字段的每个可能值,SET但跳过我们要删除的那个(2在这种情况下)。如果是,我们返回那个值,否则NULL。这将集合的所有值与 连接起来',',跳过我们要删除的那个,为该SET字段重建一个新值。

这当然只有在你知道 的所有可能值的情况下才有效categories,但由于这是一个SET字段,你知道这一点。

于 2016-10-13T09:22:23.940 回答
2

具有值的字段类别:1、2、3、4、5?我想从列表中删除“2”:

我发现使用按位运算符是最干净的方法。的返回值返回值FIND_IN_SET()的位置,因此您可以使用此计算位来关闭。

UPDATE table
SET categories = CAST(categories AS UNSIGNED) & ~POW(2, FIND_IN_SET('2', categories))
WHERE FIND_IN_SET('2', categories);

请注意,这(categories+0)是将当前值强制为SET整数。您可能会发现这是多余的,但要小心包含大量值的集合。我发现如果你不明确地将集合强制为整数,那么得到的数学可能是错误的——在执行这样的操作时,你绝对不想要错误的值。

于 2018-05-14T05:35:11.460 回答
0

我喜欢 Kris Gielen 的这种方式(https://blog.krisgielen.be/archives/255):

UPDATE table SET categories =
  TRIM(BOTH ',' FROM REPLACE(CONCAT(',', categories, ','),
  CONCAT(',', '2', ','), ','))
WHERE ...

向集合中添加值:

UPDATE table SET categories = 
  CONCAT_WS(',', categories, '2')
WHERE ...
于 2018-10-21T02:05:39.380 回答
0

在这里,@palindrom 和 @JohnWoo 提供了最佳答案。事实上,@palindrom 提供的答案非常好,应该是公认的答案。

但是,在@JohnWoo 提供的答案的情况下,如此大的案例陈述是绝对没有必要的,并且可以用更简短和整洁的编码来完成。我在下面说明了这一点-

UPDATE my_table
    -> SET categories = CASE
    -> WHEN categories LIKE "2"
    -> THEN REPLACE(categories,"2","")
    -> WHEN categories LIKE "2%"
    -> THEN REPLACE(categories,"2,","")
    -> WHEN categories LIKE "%2%"
    -> THEN REPLACE(categories,",2","")
    -> ELSE categories
    -> END;

在这里,研究这篇关于结合两个更新语句的帖子很有帮助。我也在这里提供了答案。

于 2021-09-27T18:16:32.687 回答