如何删除 MySQL 列中的特殊字符?
How to remove special characters in column with MySQL?
我参与了一个项目,遇到了别人设计的不好,我们有一个table任务,每个任务有很多用户,任务table如下:
+----------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------+------+-----+---------+-------+
| id | varchar(40) | NO | PRI | NULL | |
| name | varchar(100) | YES | | NULL | |
| task_users | varchar(1000) | YES | | NULL | |
并且用户像 aaa,bbb,ccc
一样存储在 task_users
列中,这意味着许多用户 ID 被放入一列中,我知道这是一个非常糟糕的设计但是因为它是一个旧项目,我无法修改 table 设计。
现在我有一个问题,如果用户被删除了,我怎样才能将其从task_users
列中删除?
用户id由UUID生成,固定长度32个字符,所以每个用户id都是唯一的,如40cf5f01eb2f4d2c954412f27b3bf6eb
,但问题是用户id可能出现在任意位置task_users
列,所以我不知道如何删除它
aaa,40cf5f01eb2f4d2c954412f27b3bf6eb,bbb -- in center
40cf5f01eb2f4d2c954412f27b3bf6eb,aaa,bbb -- in head
aaa,bbb,40cf5f01eb2f4d2c954412f27b3bf6eb -- in end
删除用户id后,更新结果如
aaa,bbb
我想知道我们可以使用一次更新 sql 来删除指定的用户 ID 并仍然保持相同的数据格式吗?
注意:我在 MySQL 存储过程中执行此操作,附加变量可能会有帮助,但我仍然想只使用一个 sql 来执行此操作,MySQL版本是 5.0
提前致谢!
试试这个 CASE
表达式,其中 uid
是存储过程的参数...
UPDATE `task` SET `task_users` = CASE
-- at the start
WHEN `task_users` LIKE CONCAT(uid, ',%')
THEN REPLACE(`task_users`, CONCAT(uid, ','), '')
-- at the end
WHEN `task_users` LIKE CONCAT('%,', uid)
THEN REPLACE(`task_users`, CONCAT(',', uid), '')
-- in the middle
WHEN `task_users` LIKE CONCAT('%,', uid, ',%')
THEN REPLACE(`task_users`, CONCAT(',', uid, ','), ',')
-- only that user
ELSE ''
END
WHERE `task_users` LIKE CONCAT('%', uid, '%');
演示 ~ http://sqlfiddle.com/#!9/1d2baa/1
原文"four queries"下面回答
-- only that user
UPDATE `task`
SET `task_users` = ''
WHERE `task_users` = uid;
-- at start
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(uid, ','), '')
WHERE `task_users` LIKE CONCAT(uid, ',%');
-- at end
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(',', uid), '')
WHERE `task_users` LIKE CONCAT('%,', uid);
-- in the middle
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(',', uid, ','), ',')
WHERE `task_users` LIKE CONCAT('%,', uid, ',%');
您可以使用以下表达式将指定的用户标识符替换为空字符串:
SET @userID = '40cf5f01eb2f4d2c954412f27b3bf6eb';
UPDATE `task`
SET task_users = REGEXP_REPLACE(task_users, CONCAT('(,', @userID, '|', @userID, ',?)'), '');
或添加WHERE
子句过滤更新记录:
UPDATE `task`
SET task_users = REGEXP_REPLACE(task_users, CONCAT('(,', @userID, '|', @userID, ',?)'), '');
WHERE task_users RLIKE CONCAT('(^|,)', @userID,'(,|$)')
注意,REGEXP_REPLACE()
函数是在MySQL 8.0 中添加的。
我想我们可以用一个查询来做到这一点:
UPDATE yourTable
SET task_users = SUBSTRING(
REPLACE(CONCAT(',', task_users, ','), CONCAT(',', uid, ','), ','),
2,
LENGTH(task_users) - LENGTH(uid) - 1)
WHERE task_users REGEXP CONCAT('[[:<:]]', uid, '[[:>:]]');
这是一个 link 演示(仅 用于测试目的):
这个答案使用了一个技巧,我们将逗号附加到 task_users
字符串的开头和结尾。然后,我们通过在其开头和结尾附加逗号来比较给定的用户 ID。如果找到匹配项,我们只用一个逗号替换。但是,这会使替换仍然保留其开始和结束逗号,因此我们使用子字符串操作删除它们。
SQL 除了奥运会,希望您能从这些答案的复杂性中看出,在 SQL 数据库中处理 CSV 数据确实令人头疼。也许您甚至可以使用此页面向您的同事证明 table 设计需要更改。
我参与了一个项目,遇到了别人设计的不好,我们有一个table任务,每个任务有很多用户,任务table如下:
+----------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------+------+-----+---------+-------+
| id | varchar(40) | NO | PRI | NULL | |
| name | varchar(100) | YES | | NULL | |
| task_users | varchar(1000) | YES | | NULL | |
并且用户像 aaa,bbb,ccc
一样存储在 task_users
列中,这意味着许多用户 ID 被放入一列中,我知道这是一个非常糟糕的设计但是因为它是一个旧项目,我无法修改 table 设计。
现在我有一个问题,如果用户被删除了,我怎样才能将其从task_users
列中删除?
用户id由UUID生成,固定长度32个字符,所以每个用户id都是唯一的,如40cf5f01eb2f4d2c954412f27b3bf6eb
,但问题是用户id可能出现在任意位置task_users
列,所以我不知道如何删除它
aaa,40cf5f01eb2f4d2c954412f27b3bf6eb,bbb -- in center
40cf5f01eb2f4d2c954412f27b3bf6eb,aaa,bbb -- in head
aaa,bbb,40cf5f01eb2f4d2c954412f27b3bf6eb -- in end
删除用户id后,更新结果如
aaa,bbb
我想知道我们可以使用一次更新 sql 来删除指定的用户 ID 并仍然保持相同的数据格式吗?
注意:我在 MySQL 存储过程中执行此操作,附加变量可能会有帮助,但我仍然想只使用一个 sql 来执行此操作,MySQL版本是 5.0
提前致谢!
试试这个 CASE
表达式,其中 uid
是存储过程的参数...
UPDATE `task` SET `task_users` = CASE
-- at the start
WHEN `task_users` LIKE CONCAT(uid, ',%')
THEN REPLACE(`task_users`, CONCAT(uid, ','), '')
-- at the end
WHEN `task_users` LIKE CONCAT('%,', uid)
THEN REPLACE(`task_users`, CONCAT(',', uid), '')
-- in the middle
WHEN `task_users` LIKE CONCAT('%,', uid, ',%')
THEN REPLACE(`task_users`, CONCAT(',', uid, ','), ',')
-- only that user
ELSE ''
END
WHERE `task_users` LIKE CONCAT('%', uid, '%');
演示 ~ http://sqlfiddle.com/#!9/1d2baa/1
原文"four queries"下面回答
-- only that user
UPDATE `task`
SET `task_users` = ''
WHERE `task_users` = uid;
-- at start
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(uid, ','), '')
WHERE `task_users` LIKE CONCAT(uid, ',%');
-- at end
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(',', uid), '')
WHERE `task_users` LIKE CONCAT('%,', uid);
-- in the middle
UPDATE `task`
SET `task_users` = REPLACE(`task_users`, CONCAT(',', uid, ','), ',')
WHERE `task_users` LIKE CONCAT('%,', uid, ',%');
您可以使用以下表达式将指定的用户标识符替换为空字符串:
SET @userID = '40cf5f01eb2f4d2c954412f27b3bf6eb';
UPDATE `task`
SET task_users = REGEXP_REPLACE(task_users, CONCAT('(,', @userID, '|', @userID, ',?)'), '');
或添加WHERE
子句过滤更新记录:
UPDATE `task`
SET task_users = REGEXP_REPLACE(task_users, CONCAT('(,', @userID, '|', @userID, ',?)'), '');
WHERE task_users RLIKE CONCAT('(^|,)', @userID,'(,|$)')
注意,REGEXP_REPLACE()
函数是在MySQL 8.0 中添加的。
我想我们可以用一个查询来做到这一点:
UPDATE yourTable
SET task_users = SUBSTRING(
REPLACE(CONCAT(',', task_users, ','), CONCAT(',', uid, ','), ','),
2,
LENGTH(task_users) - LENGTH(uid) - 1)
WHERE task_users REGEXP CONCAT('[[:<:]]', uid, '[[:>:]]');
这是一个 link 演示(仅 用于测试目的):
这个答案使用了一个技巧,我们将逗号附加到 task_users
字符串的开头和结尾。然后,我们通过在其开头和结尾附加逗号来比较给定的用户 ID。如果找到匹配项,我们只用一个逗号替换。但是,这会使替换仍然保留其开始和结束逗号,因此我们使用子字符串操作删除它们。
SQL 除了奥运会,希望您能从这些答案的复杂性中看出,在 SQL 数据库中处理 CSV 数据确实令人头疼。也许您甚至可以使用此页面向您的同事证明 table 设计需要更改。