Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 从集合字段中删除值的最佳方法是什么?_Mysql_Sql_Sql Update - Fatal编程技术网

Mysql 从集合字段中删除值的最佳方法是什么?

Mysql 从集合字段中删除值的最佳方法是什么?,mysql,sql,sql-update,Mysql,Sql,Sql Update,更新mysql集合字段的最佳方法是从字段中删除特定值 例如,具有值的字段类别: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

更新mysql集合字段的最佳方法是从字段中删除特定值

例如,具有值的字段类别: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个案例

最好的方法是不要在表中保存以逗号分隔的值。

但要回答您的问题,您可以在这个问题上使用
案例

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)

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

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)
摘自:


但是要注意,NUM不是值“2”,而是它的内部索引。因此,如果您定义了“set('1,'2','3','4','5')之类的字段,那么这些值的对应索引是(1,2,4,8,16)。

下面是另一种方法:

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
。 这会将集合的所有值与
,'
连接起来,跳过我们要删除的值,为
集合
字段重建新值

当然,这只适用于知道
类别
的所有可能值的情况,但由于这是一个
集合
字段,因此您知道这一点

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

UPDATE table 
SET categories = REPLACE(categories, ',2,', ',') 
WHERE field LIKE '%,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)
强制将当前的
设置为整数。您可能会发现这是多余的,但要小心包含大量值的集合。我发现,如果不显式地强制将集合设置为整数,那么得到的数学结果可能是错误的——在执行这样的操作时,您肯定不希望得到错误的值。

我喜欢Kris Gielen()的这种方法:

要向集合中添加值,请执行以下操作:

UPDATE table SET categories = 
  CONCAT_WS(',', categories, '2')
WHERE ...

一个接一个地执行所有3个查询,如果2是第一个,那么第二个查询将更新行,其余查询将运行,但不会对您的数据库产生任何影响等等。这不能重复建议的问题-另一个问题涉及PHP代码,而不是mysql。为什么不在表中使用逗号分隔的值?在某些情况下,这可能比join快。join可以使用索引。这不会。在
字段上有一个小的输入错误,比如,'2%'
,它应该是
字段,比如“%”,2'
,我也会使用
WHERE FIND_IN_SET('2',field)
或者
WHERE CONCAT(','字段','),比如“%”,2,%
,否则WHERE条件也会匹配22。。。但这是一个很好的解决方案@fthiella I纠正了这种情况下的输入错误并添加了处理,其中字段等于所讨论的字符串。使用位运算符可以更有效地操作枚举和集合。请看下面@palindrom的答案。这实际上是最好的解决方案。但是,我必须像
~POW(2,FIND_IN_SET('2',categories)-1)
那样编写,以使其正常工作,否则它会保留值“2”,并从集合中删除后面的值。
UPDATE table SET categories = 
  CONCAT_WS(',', categories, '2')
WHERE ...