MySQL: проверьте, существует ли пользователь и отбрасывает его.

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

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

DROP USER [email protected]; :    

Ответ 2

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

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.

Ответ 3

Нашел ответ на этот вопрос с одного из форумов 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'  С ОПРОСОМ ГРАНТА

код >

Ответ 4

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

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

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

Ответ 5

Обновление: Начиная с 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')

Ответ 6

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

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

Ответ 7

Ум... Почему все сложности и трюки?

Вместо этого с помощью 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;

Ответ 8

Что касается ответа @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

Ответ 9

Я написал эту процедуру, вдохновленную 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)

Ответ 10

DROP USER 'user'@'localhost';

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

Ответ 11

Объединив ответ 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'@'%';

Ответ 12

Если у вас есть школьный сервер, где ученики много работали. Вы можете просто очистить беспорядок:

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;

Ответ 13

Если вы хотите удалить падение из таблицы, если оно существует, вы можете использовать команду DELETE, например:

 DELETE FROM users WHERE user_login = 'foobar'

Если строки не совпадают, это не ошибка.