没有标准的方法可以检查MySQL用户是否存在并基于该用户删除它。有什么解决方法吗?
编辑:我需要一种直接的方法来运行此而不抛出错误,
例如
DROP USER test@localhost; :
没有标准的方法可以检查MySQL用户是否存在并基于该用户删除它。有什么解决方法吗?
编辑:我需要一种直接的方法来运行此而不抛出错误,
例如
DROP USER test@localhost; :
Answers:
从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
。
IDENTIFIED BY
使它真正起作用。
对于phyzome的回答(获得最高投票的人),在我看来,如果您在Grant声明的末尾加上“ identified by”,则会自动创建用户。但是,如果不这样做,则不会创建用户。以下代码对我有用,
GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
DROP USER 'username'@'localhost';
希望这可以帮助。
从一个MySQL论坛中找到了答案。我们需要使用一个过程来删除用户。
这里的用户是“ test”和“ databaseName”的数据库名称。
SET @OLD_SQL_MODE=@@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 SQL_MODE=@OLD_SQL_MODE ;
CREATE USER 'test'@'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES ON databaseName.* TO 'test'@'localhost'
WITH GRANT OPTION
DROP USER IF EXISTS 'user'@'localhost' ;
它对我有用,而不会在Maria DB中抛出任何错误,它也应该对您有用
更新:
从MySQL 5.7开始,您可以使用DROP USER IF EXISTS
statement。参考:https : //dev.mysql.com/doc/refman/5.7/en/drop-user.html
句法:
DROP USER [IF EXISTS] user [, user] ...
例:
DROP USER IF EXISTS 'jeffrey'@'localhost';
仅供参考(对于旧版本的MySQL),这是一个更好的解决方案... !!!
以下SP将'tempuser'@'%'
通过执行以下操作来帮助您删除用户CALL DropUserIfExistsAdvanced('tempuser', '%');
如果要删除所有名为 'tempuser'
(例如和)的'tempuser'@'%'
,请像这样执行SP,这将删除所有名为!!!的用户!认真地...'tempuser'@'localhost'
'tempuser'@'192.168.1.101'
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 (MyUserName@'%' , MyUserName@'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 ...您可以简单地从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 @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
...
SET SQL_MODE=@OLD_SQL_MODE;
...
这是5.1.23之前的错误。在该版本之后,不再需要这些。因此,为方便复制/粘贴,此处的内容与上述删除的内容相同。同样,出于示例目的,“ test”是用户,“ databaseName”是数据库;这是这个bug引起的。
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网站上(/codereview/15716/mysql-drop-user-if-exists)
DROP USER 'user'@'localhost';
上面的命令将从数据库中删除该用户,但是,重要的是要知道同一用户是否已经在使用该数据库,该会话将不会结束,直到该用户关闭该会话为止。重要的是要注意,被删除的用户将仍然访问数据库并执行任何操作。 删除用户不会删除当前的用户会话
结合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'@'%';