Как убрать спецсимволы в колонке с MySQL? - PullRequest
0 голосов
/ 10 января 2019

Я участвую в проекте и столкнулся с плохим дизайном других, у нас есть таблица с именем task, и у каждой задачи есть много пользователей, таблица задач выглядит следующим образом:

+----------------+---------------+------+-----+---------+-------+
| 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, что означает, что многие идентификаторы пользователя помещены в один столбец, я знаю, что это очень плохой дизайн, но так как это старый проект, я не могу изменить дизайн таблицы .

Теперь у меня проблема, если пользователь удален, как я могу удалить его из столбца task_users?

идентификатор пользователя генерируется UUID и имеет фиксированную длину с 32 символами, поэтому каждый идентификатор пользователя уникален, например 40cf5f01eb2f4d2c954412f27b3bf6eb, но проблема в том, что идентификатор пользователя может появляться в любой позиции task_users столбец, поэтому я не знаю, как его удалить

aaa,40cf5f01eb2f4d2c954412f27b3bf6eb,bbb -- in center
40cf5f01eb2f4d2c954412f27b3bf6eb,aaa,bbb -- in head
aaa,bbb,40cf5f01eb2f4d2c954412f27b3bf6eb -- in end

при удалении идентификатора пользователя обновленный результат выглядит как

   aaa,bbb

Я хочу знать, можем ли мы использовать одно обновление sql для удаления указанного идентификатора пользователя и при этом сохранить тот же формат данных?

Примечание: я делаю это в хранимой процедуре MySQL, может быть полезна дополнительная переменная, но я все же хочу просто использовать один sql для этого, версия MySQL 5.0

Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Вы можете использовать следующее выражение для замены указанного идентификатора пользователя пустой строкой:

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.

0 голосов
/ 10 января 2019

Я думаю, что мы можем сделать это с помощью одного запроса:

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, '[[:>:]]');

enter image description here

Вот ссылка на демоверсию (будет использоваться только для целей тестирования):

Демо

В этом ответе используется хитрость, с помощью которой мы добавляем запятые в начало и конец строки task_users. Затем мы сравниваем данный идентификатор пользователя, также добавляя запятые к его началу и концу. Если совпадение найдено, мы заменим только одну запятую. Но это оставляет замену с начальными и конечными запятыми, поэтому мы удаляем те, у которых есть операция с подстрокой.

Помимо Олимпиады по SQL, мы надеемся, что по сложности этих ответов вы поймете, что работа с данными CSV в базе данных SQL может стать настоящей головной болью. Возможно, вы даже можете использовать эту страницу в качестве доказательства для своих коллег, что дизайн таблицы должен измениться.

0 голосов
/ 10 января 2019

Попробуйте это 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


Оригинал "четыре запроса" ответ ниже

-- 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, ',%');

Демо ~ http://sqlfiddle.com/#!9/8e9b9bb/1

...