Не існує стандартного способу перевірити, чи існує користувач MySQL, і виходячи з цього, його відкинути. Чи є для цього обхідні шляхи?
Редагувати: мені потрібен прямий спосіб запустити це, не видаючи помилки,
наприклад
DROP USER test@localhost; :
Не існує стандартного способу перевірити, чи існує користувач MySQL, і виходячи з цього, його відкинути. Чи є для цього обхідні шляхи?
Редагувати: мені потрібен прямий спосіб запустити це, не видаючи помилки,
наприклад
DROP USER test@localhost; :
Відповіді:
З MySQL 5.7 ви можете зробити a 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 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
Оновлення:
станом на 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';
FYI (і для старшої версії MySQL), це краще рішення ... !!!
Наступний ІП допоможе вам видалити користувача 'tempuser'@'%'
, виконавшиCALL DropUserIfExistsAdvanced('tempuser', '%');
Якщо ви хочете видалити всіх користувачів з іменем 'tempuser'
(скажімо 'tempuser'@'%'
, 'tempuser'@'localhost'
та 'tempuser'@'192.168.1.101'
), виконайте SP, як CALL DropUserIfExistsAdvanced('tempuser', NULL);
Це видалить усіх іменованих користувачів tempuser
!!! серйозно ...
Тепер, будь ласка, подивіться на згаданий ІП 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" - база даних; і це було від цієї помилки .
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
Я написав цю процедуру, натхненний відповіддю Черіана. Різниця полягає в тому, що в моїй версії ім’я користувача є аргументом процедури (і не кодується жорстко). Я також роблю вкрай необхідні 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'@'%';
Якщо у вас є шкільний сервер, де учні багато працювали. Ви можете просто прибрати безлад, виконавши:
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'
Якщо жоден рядок не збігається, це не помилка.