MySQL: проверьте, существует ли пользователь, и отбросьте его - PullRequest
79 голосов
/ 28 февраля 2009

Не существует стандартного способа проверить, существует ли пользователь MySQL, и основываясь на этом. Есть ли обходные пути для этого?

Редактировать: мне нужен прямой способ запустить это, не выдавая ошибку
например,

DROP USER test@localhost; :    

Ответы [ 13 ]

88 голосов
/ 14 июля 2010

Это сработало для меня:

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

Это создает пользователя, если он еще не существует (и предоставляет ему безвредную привилегию), затем удаляет его в любом случае. Найденное решение здесь: http://bugs.mysql.com/bug.php?id=19166

Обновления: @ Хао рекомендует добавление IDENTIFIED BY; @andreb (в комментариях) предлагает отключить NO_AUTO_CREATE_USER.

37 голосов
/ 22 апреля 2016

Начиная с MySQL 5.7 вы можете сделать DROP USER IF EXISTS test

Подробнее: http://dev.mysql.com/doc/refman/5.7/en/drop-user.html

13 голосов
/ 04 апреля 2014

Что касается ответа phyzome (наиболее высоко оцененного), мне кажется, что, если вы поставите «идентифицировано» в конце оператора предоставления, пользователь будет создан автоматически. Но если вы этого не сделаете, пользователь не будет создан. У меня работает следующий код,

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

Надеюсь, это поможет.

13 голосов
/ 03 марта 2009

Нашел ответ на это на одном из форумов MySQL. Нам нужно использовать процедуру для удаления пользователя.

Пользователь здесь «test» и «databaseName» имя базы данных.

<code>
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
USE <code>databaseName</code> ;
DROP PROCEDURE IF EXISTS <code>databaseName</code>.<code>drop_user_if_exists</code> ;
DELIMITER $$
CREATE PROCEDURE <code>databaseName</code>.<code>drop_user_if_exists</code>()
BEGIN
  DECLARE foo BIGINT DEFAULT 0 ;
  SELECT COUNT(*)
  INTO foo
    FROM <code>mysql</code>.<code>user</code>
      WHERE <code>User</code> = 'test' and  <code>Host</code> = 'localhost';
   IF foo > 0 THEN
         DROP USER 'test'@'localhost' ;
  END IF;
END ;$$
DELIMITER ;
CALL <code>databaseName</code>.<code>drop_user_if_exists</code>() ;
DROP PROCEDURE IF EXISTS <code>databaseName</code>.<code>drop_users_if_exists</code> ;
SET SQL_MODE=@OLD_SQL_MODE ;</p>

<p>CREATE USER 'test'@'localhost' IDENTIFIED BY 'a';
GRANT ALL PRIVILEGES  ON databaseName.* TO 'test'@'localhost'
 WITH GRANT OPTION
4 голосов
/ 04 мая 2016
DROP USER IF EXISTS 'user'@'localhost' ;

, который работает для меня без каких-либо ошибок в Maria DB, он должен работать и для вас

3 голосов
/ 20 июля 2015

Гм ... Почему все сложности и хитрости?

Вместо использования 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;
3 голосов
/ 20 сентября 2012

Обновление: Начиная с MySQL 5.7 вы можете использовать оператор DROP USER IF EXISTS. Ссылка: 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'@'%', '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')

2 голосов
/ 12 марта 2016
DROP USER 'user'@'localhost';

Приведенная выше команда удалит пользователя из базы данных, однако Важно знать, что этот же пользователь уже использует базу данных, этот сеанс не завершится, пока пользователь не закроет этот сеанс. Важно отметить, что удаленный пользователь все еще будет иметь доступ к базе данных и выполнять любые операции. УДАЛЕНИЕ ПОЛЬЗОВАТЕЛЯ НЕ УДАЛЯЕТ ТЕКУЩУЮ СЕССИЮ ПОЛЬЗОВАТЕЛЯ

2 голосов
/ 19 сентября 2012

Я написал эту процедуру, вдохновленную ответом Чериана. Разница в том, что в моей версии имя пользователя является аргументом процедуры (а не жестко закодировано). Я также делаю очень необходимые привилегии FLUSH после удаления пользователя.

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)

2 голосов
/ 23 августа 2012

Относительно ответа @ Cherian, следующие строки могут быть удалены:

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

Это была ошибка до 5.1.23. После этой версии они больше не требуются. Итак, для удобства копирования / вставки, то же самое с удаленными выше линиями. Опять же, для примера, «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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...