集合中的MySQL REPLACE()

集合中的MySQL REPLACE(),mysql,Mysql,所以我有一个横幅表,在这个表中有一个字段告诉我这些横幅应该显示在哪些站点上,就像穷人的关系表一样 Banner.jpg | ABC,CDE,FGH Banner2.jpg | IPO,IPOMON,IPOHLM 等等。我使用find_in_set()收集特定站点的横幅 现在,我想写一个脚本来替换这些值,比如说“ABC”应该是“XZY”。所以我运行这个: update banners set sites = replace(sites, 'ABC', 'XZY') 这是一笔成交的交

所以我有一个横幅表,在这个表中有一个字段告诉我这些横幅应该显示在哪些站点上,就像穷人的关系表一样

Banner.jpg    | ABC,CDE,FGH 
Banner2.jpg   | IPO,IPOMON,IPOHLM
等等。我使用
find_in_set()
收集特定站点的横幅

现在,我想写一个脚本来替换这些值,比如说“ABC”应该是“XZY”。所以我运行这个:

update banners set sites = replace(sites, 'ABC', 'XZY')
这是一笔成交的交易。但是,如果我想将“IPO”更改为“APO”,则会出现问题,因为此查询:

update banners set sites = replace(sites, 'IPO', 'APO')
将产生以下数据:

Banner.jpg    | XYZ,CDE,FGH 
Banner2.jpg   | APO,APOMON,APOHLM
这是不可取的。那么,在执行
replace()
或类似函数时,如何只更改“IPO”而不是“IPOMON”?可以说,我想要一个“replace_in_set()”函数


有什么想法吗?

您应该规范化这些表,以便您可以在值等于所需替换值的字段上使用
更新。看看这个例子:

/* create the banner data table and add banner.jpg and banner2.jpg */
CREATE TABLE banner
    (`banner_id` int, `description` varchar(11))
;

INSERT INTO banner
    (`banner_id`, `description`)
VALUES
    (1, 'banner.jpg'),
    (2, 'banner2.jpg')
;

/* create the website data table and:
   ABC, CDE, FGH, IPO, IPOMON, and IPOHLM */
CREATE TABLE website
    (`site_id` int, `banner_id` int, `site` varchar(6))
;

INSERT INTO website
    (`site_id`, `banner_id`, `site`)
VALUES
    (1, 1, 'ABC'),
    (2, 1, 'CDE'),
    (3, 1, 'FGH'),
    (4, 2, 'IPO'),
    (5, 2, 'IPOMON'),
    (6, 2, 'IPOHLM')
;

/* update the website data table to change IPO to APO */
UPDATE `website`
SET `site` = "APO"
WHERE `site` = "IPO";

SELECT * FROM `website`

Fiddle:

您应该规范化这些表,以便您可以在值等于所需替换值的字段上使用
更新。看看这个例子:

/* create the banner data table and add banner.jpg and banner2.jpg */
CREATE TABLE banner
    (`banner_id` int, `description` varchar(11))
;

INSERT INTO banner
    (`banner_id`, `description`)
VALUES
    (1, 'banner.jpg'),
    (2, 'banner2.jpg')
;

/* create the website data table and:
   ABC, CDE, FGH, IPO, IPOMON, and IPOHLM */
CREATE TABLE website
    (`site_id` int, `banner_id` int, `site` varchar(6))
;

INSERT INTO website
    (`site_id`, `banner_id`, `site`)
VALUES
    (1, 1, 'ABC'),
    (2, 1, 'CDE'),
    (3, 1, 'FGH'),
    (4, 2, 'IPO'),
    (5, 2, 'IPOMON'),
    (6, 2, 'IPOHLM')
;

/* update the website data table to change IPO to APO */
UPDATE `website`
SET `site` = "APO"
WHERE `site` = "IPO";

SELECT * FROM `website`

小提琴:

你是否有一个字符串,你可以使用
'IPO'

update banners set sites = replace(sites, 'IPO,', 'APO,') 

你有一个可以使用的字符串吗

update banners set sites = replace(sites, 'IPO,', 'APO,') 

我认为没有一个好的/漂亮的方法可以做到这一点。为了将IPO作为单数,并将IPO作为列表的一部分进行更改,您必须这样做

UPDATE banners SET 
  sites = REPLACE(sites,
    IF(sites LIKE '%IPO,%', 'IPO,', 'IPO'),
    IF(sites LIKE '%IPO,%', 'APO,', 'APO')
  );

要捕捉的东西越多,
就越复杂,如果必须要捕捉的话,但是你知道了。

我认为没有一个好的/漂亮的方法可以做到这一点。为了将IPO作为单数,并将IPO作为列表的一部分进行更改,您必须这样做

UPDATE banners SET 
  sites = REPLACE(sites,
    IF(sites LIKE '%IPO,%', 'IPO,', 'IPO'),
    IF(sites LIKE '%IPO,%', 'APO,', 'APO')
  );

捕获的内容越多,
就越复杂,如果
是必须的,但你得到了想法。

你可以使用这样的查询。首先,它在集合的开头和结尾添加一个“,”。然后,您可以更改设置并修剪删除“,”

UPDATE banners 
SET sites = TRIM(BOTH ',' FROM REPLACE( CONCAT(',',sites,','), ',IPO,', ',APO,') );

您可以使用这样的查询。首先,它在集合的开头和结尾添加一个“,”。然后,您可以更改设置并修剪删除“,”

UPDATE banners 
SET sites = TRIM(BOTH ',' FROM REPLACE( CONCAT(',',sites,','), ',IPO,', ',APO,') );

我对Bernd Buffin的答案给出了+1,因为它至少完成了替换,而无需将数据提取到应用程序中以拆分和重新连接字符串

下面没有回答你的问题,但我想我会把它贴在这里,以便将来对其他读者有所裨益

我尝试在MySQL 8.0.4中测试新功能,因为我认为以下功能可以工作,但它不能:

mysql> SELECT REGEXP_REPLACE('IPO,IPOMON,IPOHLM', '[[:<:]]IPO[[:>:]]', 'APO');
ERROR 3686 (HY000): Illegal argument to a regular expression.
mysql>选择REGEXP_REPLACE('IPO,IPOMON,IPOHLM','[[::]]','APO');
错误3686(HY000):正则表达式的参数非法。

MySQL和新库不支持
[[::]
单词边界模式。

我对Bernd Buffin的答案给出了+1,因为它至少完成了替换,而无需将数据提取到应用程序中拆分和重新连接字符串

下面没有回答你的问题,但我想我会把它贴在这里,以便将来对其他读者有所裨益

我尝试在MySQL 8.0.4中测试新功能,因为我认为以下功能可以工作,但它不能:

mysql> SELECT REGEXP_REPLACE('IPO,IPOMON,IPOHLM', '[[:<:]]IPO[[:>:]]', 'APO');
ERROR 3686 (HY000): Illegal argument to a regular expression.
mysql>选择REGEXP_REPLACE('IPO,IPOMON,IPOHLM','[[::]]','APO');
错误3686(HY000):正则表达式的参数非法。

MySQL和新库不支持<代码> [[::]:/Cord> Word边界模式。

您可能不想听到它,但是如果在一对多表中每行只有一个站点,那么考虑它会有多简单。如果失败,您需要在替换中使用
concat(',',X',,')
强制匹配,这样您就只能进行完整的(完全分隔的)匹配。@AlexK。是的,我充分意识到关系数据库的好处,并且我在很多情况下都使用它。然而,我确实在某些场合使用这些“集合”,现在替换它们是一个相当大的事情,所以不幸的是,现在它不是一个选项。你可能不想听它,但是想想如果一对多表中每行只有一个站点,那么它会有多简单。如果失败,您需要在替换中使用
concat(',',X',,')
强制匹配,这样您就只能进行完整的(完全分隔的)匹配。@AlexK。是的,我充分意识到关系数据库的好处,并且我在很多情况下都使用它。然而,我确实在某些情况下使用这些“集合”,替换它们现在将是一件相当大的事情,所以很遗憾,现在这不是一个选项。是的,我完全了解关系数据库的好处,但这不是我在本例中使用的,所以很遗憾,这对我没有任何帮助。因此,您了解其好处,但你拒绝利用他们。为什么?我的系统中有很多关系型数据库,我充分利用了它们。但在某些情况下,“集合”的这种用法要方便得多。而替换所有这些使用集合的实例恐怕将是一个巨大的爱好,所以这不是一个选项。好吧,为了我的利益,我想说清楚。你只是不想做这项工作?没错,我正在编写一个site replace脚本,它可以更改整个数据库中所有表上的这些代码,而不仅仅是这一个表,我不想为了简化替换而必须更改一些12-15个函数的后端代码。是的,我完全了解关系数据库的好处,但这不是我在这个例子中所用的,所以很不幸,这对我没有任何帮助。所以你理解这些好处,但你拒绝利用它们。为什么?我的系统中有很多关系型数据库,我充分利用了它们。但在某些情况下,“集合”的这种用法要方便得多。而替换所有这些使用集合的实例恐怕将是一个巨大的爱好,所以这不是一个选项。好吧,为了我的利益,我想说清楚。你只是不想做这项工作?没错,我正在编写一个site replace脚本,它可以更改整个数据库中所有表上的代码,而不仅仅是这一个表上的代码,而且我不想