Нет стандартного способа проверить, существует ли пользователь MySQL, и на основании этого его удалять. Есть ли обходные пути для этого?
Изменить: мне нужен прямой способ запустить это, не вызывая ошибку. например.
DROP USER [email protected]; :
Нет стандартного способа проверить, существует ли пользователь MySQL, и на основании этого его удалять. Есть ли обходные пути для этого?
Изменить: мне нужен прямой способ запустить это, не вызывая ошибку. например.
DROP USER [email protected]; :
Начиная с MySQL 5.7 вы можете сделать DROP USER IF EXISTS test
Дополнительная информация: http://dev.mysql.com/doc/refman/5.7/en/drop-user.html
Это сработало для меня:
GRANT USAGE ON *.* TO 'username'@'localhost';
DROP USER 'username'@'localhost';
Это создает пользователя, если он еще не существует (и предоставляет ему безобидную привилегию), а затем удаляет его в любом случае. Найденное решение здесь: http://bugs.mysql.com/bug.php?id=19166
Обновления: @Hao рекомендует добавить IDENTIFIED BY
; @andreb (в комментариях) предлагает отключить NO_AUTO_CREATE_USER
.
Нашел ответ на этот вопрос с одного из форумов MySQL. Нужно использовать процедуру для удаления пользователя.
Пользователь здесь - это "test" и "databaseName" - имя базы данных.
SET @[email protected]@SQL_MODE, SQL_MODE='ANSI';
USE databaseName
;
DROP PROCEDURE IF EXISTS databaseName
.drop_user_if_exists
;
DELIMITER $$
CREATE PROCEDURE databaseName
.drop_user_if_exists
()
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql
.user
WHERE User
= 'test' and Host
= 'localhost';
IF foo > 0 THEN
DROP USER 'test'@'localhost' ;
END IF;
END ;$$
DELIMITER ;
CALL databaseName
.drop_user_if_exists
() ;
DROP PROCEDURE IF EXISTS databaseName
.drop_users_if_exists
;
SET [email protected]_SQL_MODE ;
СОЗДАТЬ ПОЛЬЗОВАТЕЛЬ 'test' @'localhost' IDENTIFIED BY 'a';
ПРЕДОСТАВЛЯЙТЕ ВСЕ ПРИВИЛЕГИИ НА имя базы данных. * TO 'test' @'localhost'
С ОПРОСОМ ГРАНТА
код > Чтобы ответить на phyzome (наиболее сильно проголосовавший), мне кажется, что если вы положите "идентифицированный" в конце инструкции grant, пользователь будет создан автоматически. Но если вы этого не сделаете, пользователь не будет создан. Следующий код работает для меня,
GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
DROP USER 'username'@'localhost';
Надеюсь, что это поможет.
Обновление:
Начиная с MySQL 5.7 вы можете использовать оператор DROP USER IF EXISTS
.
Ссылка: https://dev.mysql.com/doc/refman/5.7/en/drop-user.html
Syntax:
DROP USER [IF EXISTS] user [, user] ...
Example:
DROP USER IF EXISTS 'jeffrey'@'localhost';
К вашему сведению (и для более старой версии MySQL), это лучшее решение... !!!
Следующий SP поможет вам удалить пользователя 'tempuser'@'%'
, выполнив CALL DropUserIfExistsAdvanced('tempuser', '%');
Если вы хотите удалить всех пользователей с именем 'tempuser'
(скажем, 'tempuser'@'%'
, 'tempuser'@'localhost'
и 'tempuser'@'192.168.1.101'
), выполните SP как CALL DropUserIfExistsAdvanced('tempuser', NULL);
. Это приведет к удалению всех пользователей с именем tempuser
!!! серьезно...
Теперь, пожалуйста, взгляните на упомянутый SP DropUserIfExistsAdvanced
:
DELIMITER $$
DROP PROCEDURE IF EXISTS 'DropUserIfExistsAdvanced'$$
CREATE DEFINER='root'@'localhost' PROCEDURE 'DropUserIfExistsAdvanced'(
MyUserName VARCHAR(100)
, MyHostName VARCHAR(100)
)
BEGIN
DECLARE pDone INT DEFAULT 0;
DECLARE mUser VARCHAR(100);
DECLARE mHost VARCHAR(100);
DECLARE recUserCursor CURSOR FOR
SELECT 'User', 'Host' FROM 'mysql'.'user' WHERE 'User' = MyUserName;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET pDone = 1;
IF (MyHostName IS NOT NULL) THEN
-- 'username'@'hostname' exists
IF (EXISTS(SELECT NULL FROM 'mysql'.'user' WHERE 'User' = MyUserName AND 'Host' = MyHostName)) THEN
SET @SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", MyUserName, "'@'", MyHostName, "'") AS mResult) AS Q LIMIT 1);
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END IF;
ELSE
-- check whether MyUserName exists ([email protected]'%' , [email protected]'localhost' etc)
OPEN recUserCursor;
REPEAT
FETCH recUserCursor INTO mUser, mHost;
IF NOT pDone THEN
SET @SQL = (SELECT mResult FROM (SELECT GROUP_CONCAT("DROP USER ", "'", mUser, "'@'", mHost, "'") AS mResult) AS Q LIMIT 1);
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END IF;
UNTIL pDone END REPEAT;
END IF;
FLUSH PRIVILEGES;
END$$
DELIMITER ;
Использование:
CALL DropUserIfExistsAdvanced('tempuser', '%');
удалить пользователя 'tempuser'@'%'
CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101');
удалить пользователя 'tempuser'@'192.168.1.101'
CALL DropUserIfExistsAdvanced('tempuser', NULL);
, чтобы удалить всех пользователей с именами 'tempuser'
(например, скажем, 'tempuser'@'%'
, 'tempuser'@'localhost'
и 'tempuser'@'192.168.1.101'
)
DROP USER IF EXISTS 'user'@'localhost' ;
который работает для меня без каких-либо ошибок в Maria DB, он также должен работать для u
Ум... Почему все сложности и трюки?
Вместо этого с помощью DROP USER... Вы можете просто удалить пользователя из таблицы mysql.user(который не выдает ошибку, если пользователь не существует), а затем сбросить привилегии для применения изменения.
DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost';
FLUSH PRIVILEGES;
- ОБНОВЛЕНИЕ -
Я был неправ. Невозможно удалить такого пользователя. Вам нужно использовать DROP USER. Поскольку возможно, что параметры mysql не позволяют автоматически создавать пользователей через гранты (вариант, который я использую), я все равно не рекомендую этот трюк. Здесь снайпер из хранимой процедуры, которая работает для меня:
DECLARE userCount INT DEFAULT 0;
SELECT COUNT(*) INTO userCount FROM mysql.user WHERE User = userName AND Host='localhost';
IF userCount > 0 THEN
SET @S=CONCAT("DROP USER ", userName, "@localhost" );
PREPARE stmt FROM @S;
EXECUTE stmt;
SELECT CONCAT("DROPPED PRE-EXISTING USER: ", userName, "@localhost" ) as info;
END IF;
FLUSH PRIVILEGES;
Что касается ответа @Cherian, следующие строки могут быть удалены:
SET @[email protected]@SQL_MODE, SQL_MODE='ANSI';
...
SET [email protected]_SQL_MODE;
...
Это была ошибка, предшествующая 5.1.23. После этой версии они больше не требуются. Таким образом, для удобства копирования/вставки, то же самое с удалением указанных строк. Опять же, например, целью "тест" является пользователь, а "databaseName" - это база данных; и это было от эта ошибка.
DROP PROCEDURE IF EXISTS databaseName.drop_user_if_exists ;
DELIMITER $$
CREATE PROCEDURE databaseName.drop_user_if_exists()
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = 'test' and Host = 'localhost';
IF foo > 0 THEN
DROP USER 'test'@'localhost' ;
END IF;
END ;$$
DELIMITER ;
CALL databaseName.drop_user_if_exists() ;
DROP PROCEDURE IF EXISTS databaseName.drop_users_if_exists ;
CREATE USER 'test'@'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES ON databaseName.* TO 'test'@'localhost'
WITH GRANT OPTION
Я написал эту процедуру, вдохновленную Cherian. Разница в том, что в моей версии имя пользователя является аргументом процедуры (а не жесткой). Я также делаю очень необходимые FLUSH PRIVILEGES после удаления пользователя.
DROP PROCEDURE IF EXISTS DropUserIfExists;
DELIMITER $$
CREATE PROCEDURE DropUserIfExists(MyUserName VARCHAR(100))
BEGIN
DECLARE foo BIGINT DEFAULT 0 ;
SELECT COUNT(*)
INTO foo
FROM mysql.user
WHERE User = MyUserName ;
IF foo > 0 THEN
SET @A = (SELECT Result FROM (SELECT GROUP_CONCAT("DROP USER"," ",MyUserName,"@'%'") AS Result) AS Q LIMIT 1);
PREPARE STMT FROM @A;
EXECUTE STMT;
FLUSH PRIVILEGES;
END IF;
END ;$$
DELIMITER ;
Я также разместил этот код на веб-сайте CodeReview (https://codereview.stackexchange.com/questions/15716/mysql-drop-user-if-exists)
DROP USER 'user'@'localhost';
Вышеприведенная команда выведет пользователя из базы данных, однако Важно знать, что тот же пользователь уже использует базу данных, этот сеанс не завершится до тех пор, пока пользователь не закроет этот сеанс. Важно отметить, что упущенный пользователь будет STILL обращаться к базе данных и выполнять любые операции. РАЗДЕЛЕНИЕ ПОЛЬЗОВАТЕЛЯ НЕ СНИМАЕТ СЕССИЮ ТЕКУЩЕГО ПОЛЬЗОВАТЕЛЯ
Объединив ответ phyzome (который не работал сразу для меня) с комментарием andreb (что объясняет, почему это не так), я закончил с этим, казалось бы, рабочим кодом, который временно отключает режим NO_AUTO_CREATE_USER, если он активен:
set @mode = @@SESSION.sql_mode;
set session sql_mode = replace(replace(@mode, 'NO_AUTO_CREATE_USER', ''), ',,', ',');
grant usage on *.* to 'myuser'@'%';
set session sql_mode = @mode;
drop user 'myuser'@'%';
Если у вас есть школьный сервер, где ученики много работали. Вы можете просто очистить беспорядок:
delete from user where User != 'root' and User != 'admin';
delete from db where User != 'root' and User != 'admin';
delete from tables_priv;
delete from columns_priv;
flush privileges;
Если вы хотите удалить падение из таблицы, если оно существует, вы можете использовать команду DELETE
, например:
DELETE FROM users WHERE user_login = 'foobar'
Если строки не совпадают, это не ошибка.