Nie ma standardowego sposobu sprawdzenia, czy użytkownik MySQL istnieje i na tej podstawie go upuść. Czy są jakieś obejścia tego problemu?
Edycja: potrzebuję prostego sposobu, aby to uruchomić bez generowania błędu,
np
DROP USER test@localhost; :
Nie ma standardowego sposobu sprawdzenia, czy użytkownik MySQL istnieje i na tej podstawie go upuść. Czy są jakieś obejścia tego problemu?
Edycja: potrzebuję prostego sposobu, aby to uruchomić bez generowania błędu,
np
DROP USER test@localhost; :
Odpowiedzi:
Od MySQL 5.7 możesz zrobić DROP USER IF EXISTS test
Więcej informacji: http://dev.mysql.com/doc/refman/5.7/en/drop-user.html
To zadziałało dla mnie:
GRANT USAGE ON *.* TO 'username'@'localhost';
DROP USER 'username'@'localhost';
Tworzy to użytkownika, jeśli jeszcze nie istnieje (i zapewnia mu nieszkodliwe przywileje), a następnie usuwa go w obu przypadkach. Znalezione rozwiązanie tutaj: http://bugs.mysql.com/bug.php?id=19166
Aktualizacje: @Hao zaleca dodanie IDENTIFIED BY
; @andreb (w komentarzach) sugeruje wyłączenie NO_AUTO_CREATE_USER
.
IDENTIFIED BY
aby to faktycznie działało.
Odpowiadając phyzome (najwyżej głosowanemu), wydaje mi się, że jeśli na końcu oświadczenia o przyznaniu dotacji wstawisz słowo „zidentyfikowany przez”, użytkownik zostanie utworzony automatycznie. Ale jeśli tego nie zrobisz, użytkownik nie zostanie utworzony. Poniższy kod działa dla mnie,
GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
DROP USER 'username'@'localhost';
Mam nadzieję że to pomoże.
Znalazłem odpowiedź na to jedno z forów MySQL. Będziemy musieli użyć procedury, aby usunąć użytkownika.
Tutaj użytkownik to „test”, a „databaseName” to nazwa bazy danych.
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' ;
to działa dla mnie bez rzucania żadnych błędów w Maria DB, powinno działać również dla ciebie
Aktualizacja:
Od MySQL 5.7 możesz użyć DROP USER IF EXISTS
instrukcji. Odniesienie: https://dev.mysql.com/doc/refman/5.7/en/drop-user.html
Składnia:
DROP USER [IF EXISTS] user [, user] ...
Przykład:
DROP USER IF EXISTS 'jeffrey'@'localhost';
FYI (i dla starszej wersji MySQL), jest to lepsze rozwiązanie ... !!!
Poniższy SP pomoże ci usunąć użytkownika 'tempuser'@'%'
, wykonującCALL DropUserIfExistsAdvanced('tempuser', '%');
Jeśli chcesz usunąć wszystkich użytkowników nazwanych 'tempuser'
(słownie 'tempuser'@'%'
, 'tempuser'@'localhost'
i 'tempuser'@'192.168.1.101'
) wykonywanie SP jak CALL DropUserIfExistsAdvanced('tempuser', NULL);
ta spowoduje usunięcie wszystkich użytkowników nazwanych tempuser
!!! poważnie...
Teraz spójrz na wspomniane 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 ;
Stosowanie:
CALL DropUserIfExistsAdvanced('tempuser', '%');
aby usunąć użytkownika 'tempuser'@'%'
CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101');
aby usunąć użytkownika 'tempuser'@'192.168.1.101'
CALL DropUserIfExistsAdvanced('tempuser', NULL);
usunięcie wszystkich użytkowników nazwanych 'tempuser'
(np., powiedzmy 'tempuser'@'%'
, 'tempuser'@'localhost'
i 'tempuser'@'192.168.1.101'
)
Um ... Po co te wszystkie komplikacje i sztuczki?
Zamiast tego użyj DROP USER ... Możesz po prostu usunąć użytkownika z tabeli mysql.user (co nie powoduje błędu, jeśli użytkownik nie istnieje), a następnie opróżnić uprawnienia, aby zastosować zmianę.
DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost';
FLUSH PRIVILEGES;
-- AKTUALIZACJA --
Myliłem się. Usunięcie takiego użytkownika nie jest bezpieczne. Musisz użyć DROP USER. Ponieważ możliwe jest ustawienie opcji mysql tak, aby nie tworzyły użytkowników automatycznie poprzez grants (opcja, której używam), nadal nie polecałbym tej sztuczki. Oto fragment z procedury składowanej, która działa dla mnie:
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;
Jeśli chodzi o odpowiedź @ Cherian, można usunąć następujące wiersze:
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
...
SET SQL_MODE=@OLD_SQL_MODE;
...
To był błąd sprzed 5.1.23. Po tej wersji nie są już potrzebne. Tak więc, dla wygody kopiowania / wklejania, tutaj jest to samo z usuniętymi powyższymi wierszami. Na przykład w celach „test” jest użytkownikiem, a „databaseName” jest bazą danych; a to było z tego błędu .
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
Napisałem tę procedurę inspirowaną odpowiedzią Cheriana. Różnica polega na tym, że w mojej wersji nazwa użytkownika jest argumentem procedury (a nie zakodowana na stałe). Robię też bardzo potrzebne PRZYWILEJE FLUSH po usunięciu użytkownika.
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 ;
Opublikowałem również ten kod na stronie CodeReview ( /codereview/15716/mysql-drop-user-if-exists )
DROP USER 'user'@'localhost';
Powyższe polecenie spadnie użytkownika z bazy danych, jednak jest ważne , aby wiedzieć, czy ten sam użytkownik korzysta już z bazy danych, że sesja nie zakończy się, dopóki użytkownik nie zamknie tej sesji. Należy pamiętać, że upuszczony użytkownik NADAL będzie uzyskiwał dostęp do bazy danych i wykonywał wszelkie operacje. UPUSZCZENIE UŻYTKOWNIKA NIE PRZESUWA AKTUALNEJ SESJI UŻYTKOWNIKA
Łącząc odpowiedź phyzome (która nie zadziałała od razu dla mnie) z komentarzem andreba (który wyjaśnia, dlaczego tak się nie stało) otrzymałem ten pozornie działający kod, który tymczasowo wyłącza tryb NO_AUTO_CREATE_USER, jeśli jest aktywny:
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'@'%';
Jeśli masz na myśli, że chcesz usunąć drop z tabeli, jeśli istnieje, możesz użyć DELETE
polecenia, na przykład:
DELETE FROM users WHERE user_login = 'foobar'
Jeśli żaden wiersz nie pasuje, nie jest to błąd.