Mysql 从集合字段中删除值的最佳方法是什么?
更新mysql集合字段的最佳方法是从字段中删除特定值 例如,具有值的字段类别:1,2,3,4,5? 我想从列表中删除“2”: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
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 ...