MySQL:检查用户是否存在并放弃它

没有标准的方法来检查一个MySQL用户是否存在,并基于这个方法删除它。 有没有解决方法?

编辑:我需要一个直接的方式来运行,而不会抛出一个错误
例如

DROP USER test@localhost; : 

由于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'; 

如果用户不存在(并授予它一个无害的权限),则创build用户,然后删除它。 find解决scheme在这里: http : //bugs.mysql.com/bug.php?id=19166

更新: @浩build议添加IDENTIFIED BY ; @andreb(在评论中)build议禁用NO_AUTO_CREATE_USER

从其中一个MySQL论坛find答案。 我们需要使用一个过程来删除用户。

这里的用户是“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 ; 

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';
授予数据库名称的所有特权。*'testing'@'localhost'
赠与选项

对于phyzome的答案(最高评分之一),在我看来,如果在授权声明的末尾加上“由…确定”,用户将自动创build。 但是,如果你不这样做,用户不会被创build。 下面的代码适用于我,

 GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password'; DROP USER 'username'@'localhost'; 

希望这可以帮助。

 DROP USER IF EXISTS 'user'@'localhost' ; 

这对我而言没有任何错误在玛丽亚DB,它应该为你工作

对于@ Cherian的回答,可以删除以下几行:

 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI'; ... SET SQL_MODE=@OLD_SQL_MODE; ... 

这是5.1.23之前的一个bug。 在版本之后,这些不再是必需的。 所以,为了复制/粘贴的方便,这里是删除上面的行相同。 再次举例来说,“test”是用户,“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 

嗯…为什么所有的复杂和诡计?

而不是使用DROP USER …您可以简单地从mysql.user表中删除用户(如果用户不存在,则不会抛出错误),然后刷新权限以应用更改。

 DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost'; FLUSH PRIVILEGES; 

– 更新 –

我错了。 像这样删除用户是不安全的。 你确实需要使用DROP USER。 由于可以将mysql选项设置为不通过授权(我使用的一个选项)自动创build用户,所以我仍然不会推荐这个技巧。 下面是一个存储过程snipet适用于我:

 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的答案。 不同的是,在我的版本中,用户名是程序的一个参数(而不是硬编码)。 在删除用户之后,我还做了一个非常必要的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

仅供参考,这是一个更好的解决scheme…!

以下SP将通过执行CALL DropUserIfExistsAdvanced('tempuser', '%');来帮助您删除用户'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 (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'

结合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'@'%'; 
 DROP USER 'user'@'localhost'; 

上面的命令将把用户从数据库中删除,但是,知道同一用户是否已经在使用数据库是非常重要的 ,那么在用户closures该会话之前,该会话将不会结束。 请注意,丢弃的用户将仍然访问数据库并执行任何操作。 删除用户不会丢失当前的用户会话

如果你有一个学校的服务器,学生工作很多。 你可以通过以下方式清理垃圾:

 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; 

如果你的意思是你想从表中删除一个drop,你可以使用DELETE命令,例如:

  DELETE FROM users WHERE user_login = 'foobar' 

如果没有行匹配,这不是一个错误。