MySQL: controlla se l'utente esiste e rilascialo


84

Non esiste un modo standard per verificare se esiste un utente MySQL e in base a quello rilasciarlo. Ci sono soluzioni alternative per questo?

Modifica: ho bisogno di un modo diretto per eseguirlo senza generare un errore,
ad es

DROP USER test@localhost; :    

1
Intendi un utente MySQL? O un record utente che stai memorizzando in una tabella in MySQL?
Jason Cohen,

Sembra che MariaDB abbia questa funzione: mariadb.com/kb/en/mariadb/drop-user
lmat - Reinstate Monica

1
per futuri lettori: MySQL 5.7 ha la funzione 'DROP USER IF EXISTS', vedere stackoverflow.com/questions/598190/…
Andrei Epure

1
@AndreiEpure, se solo potessi metterla come risposta, la contrassegnerò come quella giusta.
Cherian

Risposte:



87

Questo ha funzionato per me:

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

Questo crea l'utente se non esiste già (e gli concede un privilegio innocuo), quindi lo elimina in entrambi i casi. Soluzione trovata qui: http://bugs.mysql.com/bug.php?id=19166

Aggiornamenti: @Hao consiglia di aggiungere IDENTIFIED BY; @andreb (nei commenti) suggerisce di disabilitare NO_AUTO_CREATE_USER.



6
Questa non è più un'opzione. :( L'attuale versione di MySQL non crea più un nuovo utente per l'istruzione GRANT. Era una "Funzionalità" aggiunta.;) Sembra che l'opzione di Cherian sia l'unica che funziona attualmente.
GazB

1
@Zasurus. dev.mysql.com/doc/refman/5.1/en/grant.html (anche 5.5 e 5.6) sembra suggerire che ti sbagli. C'è un'opzione "nessuna creazione automatica dell'utente". A meno che non fraintenda il manuale, indica che la concessione creerà un utente se non esiste.
andreb

@andreb Forse l'opzione "NO_AUTO_CREATE_USER" era attiva quando l'ho provato o per impostazione predefinita (dato che non l'ho modificata). Se ho tempo proverò a disattivare questa opzione e riproverò. Ci sono alcune segnalazioni di bug aperte con questa opzione, forse uno di questi è anche il problema. :)
GazB

Vedi anche la risposta di @ Hao. Avevo bisogno IDENTIFIED BYdi farlo funzionare davvero.
Matteo

14

Alla risposta di phyzome (quella più votata), mi sembra che se metti "identificato da" alla fine della dichiarazione di sovvenzione, l'utente verrà creato automaticamente. Ma se non lo fai, l'utente non viene creato. Il seguente codice funziona per me,

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

Spero che sia di aiuto.


Avevo alcuni vecchi script senza quella "password" IDENTIFICATA DA; parte che ha funzionato su 5.6. Ma non il 5.7. L'aggiunta della parte IDENTIFICATA DA "password" ha funzionato per me.
joensson

13

Ho trovato la risposta a questo da uno dei forum MySQL. Avremo bisogno di utilizzare una procedura per eliminare l'utente.

L'utente qui è "test" e "databaseName" il nome del database.


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


Grazie @Cherian Non sono sicuro che questo sia ancora il modo migliore di fare le cose nel 2017, ma almeno è una via da seguire! Non posso credere che sia ancora così difficile ...
JMac

Solo per tua informazione dovresti sempre includere l'URL della tua fonte (ad esempio: trovato la risposta da uno dei moduli mysql . O da uno dei moduli mysql (fonte qui)

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

che funziona per me senza generare errori in Maria DB, dovrebbe funzionare anche per te


2
Su MySQL 5.7 e versioni successive, certo. ... Fortunatamente me, la versione più recente che usiamo qui è la 5.5.
tetsujin

4

Aggiornamento: a partire da MySQL 5.7 è possibile utilizzare DROP USER IF EXISTSstatement. Rif: https://dev.mysql.com/doc/refman/5.7/en/drop-user.html

Sintassi: DROP USER [IF EXISTS] user [, user] ...

Esempio: DROP USER IF EXISTS 'jeffrey'@'localhost';

Cordiali saluti (e per la versione precedente di MySQL), questa è una soluzione migliore ... !!!

Il seguente SP ti aiuterà a rimuovere l'utente 'tempuser'@'%'eseguendoCALL DropUserIfExistsAdvanced('tempuser', '%');

Se si desidera rimuovere tutti gli utenti di nome 'tempuser'(per esempio 'tempuser'@'%', 'tempuser'@'localhost'e 'tempuser'@'192.168.1.101') eseguire SP come CALL DropUserIfExistsAdvanced('tempuser', NULL);questo cancellerà tutti gli utenti di nome tempuser!!! sul serio...

Ora per favore dai un'occhiata al menzionato 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 ;

Utilizzo:

CALL DropUserIfExistsAdvanced('tempuser', '%'); per rimuovere l'utente 'tempuser'@'%'

CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101'); per rimuovere l'utente 'tempuser'@'192.168.1.101'

CALL DropUserIfExistsAdvanced('tempuser', NULL);per rimuovere tutti gli utenti nominati 'tempuser'(es., say 'tempuser'@'%', 'tempuser'@'localhost'e 'tempuser'@'192.168.1.101')


3

Ehm ... Perché tutte le complicazioni e i trucchi?

Piuttosto che usare DROP USER ... Puoi semplicemente eliminare l'utente dalla tabella mysql.user (che non genera un errore se l'utente non esiste) e quindi scaricare i privilegi per applicare la modifica.

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

-- AGGIORNARE --

Mi sbagliavo. Non è sicuro eliminare l'utente in questo modo. Devi usare DROP USER. Poiché è possibile impostare le opzioni di mysql in modo da non creare utenti automaticamente tramite le concessioni (un'opzione che uso), non consiglierei comunque questo trucco. Ecco uno snipet da una stored procedure che funziona per me:

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;

Condividi perché "non è sicuro" ...? Sicuro per chi in che modo?
dagelf

Bene, dato che l'ho pubblicato più di un anno fa, non pretendo di ricordare al 100% a cosa mi riferivo. Sono abbastanza sicuro di voler dire che l'affidabilità non rimuove completamente l'utente dal sistema. Penso che DROP USER realizzi molto di più della semplice rimozione di una riga dalla tabella mysql.user. Mi spiace, non riesco a pensare a quali siano questi dettagli ora!
BuvinJ

Se dovessi indovinare direi che i record dei privilegi non vengono rimossi, ma diventano "orfani"? (A seconda delle impostazioni?)
BuvinJ

2

Per quanto riguarda la risposta di @ Cherian, le seguenti righe possono essere rimosse:

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

Questo era un bug precedente alla 5.1.23. Dopo quella versione questi non sono più necessari. Quindi, per comodità di copia / incolla, ecco lo stesso con le righe precedenti rimosse. Ancora una volta, ad esempio, "test" è l'utente e "databaseName" è il database; e questo era da questo bug .

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

2

Ho scritto questa procedura ispirandomi alla risposta di Cherian. La differenza è che nella mia versione il nome utente è un argomento della procedura (e non hardcoded). Sto anche facendo un FLUSH PRIVILEGES molto necessario dopo aver abbandonato l'utente.

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 ;

Ho anche pubblicato questo codice sul sito web CodeReview ( /codereview/15716/mysql-drop-user-if-exists )


2
DROP USER 'user'@'localhost';

Il comando precedente eliminerà l'utente dal database, tuttavia, è importante sapere se lo stesso utente sta già utilizzando il database, quella sessione non terminerà finché l'utente non chiude quella sessione. È importante notare che l'utente abbandonato ANCORA accederà al database ed eseguirà qualsiasi operazione. L'ANNULLAMENTO DELL'UTENTE NON ANNULLA LA SESSIONE UTENTE CORRENTE


0

Combinando la risposta di phyzome (che non ha funzionato subito per me) con il commento di andreb (che spiega perché non l'ha fatto) ho finito con questo codice apparentemente funzionante che disabilita temporaneamente la modalità NO_AUTO_CREATE_USER se è attiva:

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'@'%';

0

nel terminale fai:

sudo mysql -u root -p

inserire la password.

select user from mysql.user;

ora elimina l'utente "the_username"

DROP USER the_unername;

sostituisci "the_username" con l'utente che desideri eliminare.


-1

Nel caso in cui tu abbia un server scolastico in cui gli alunni hanno lavorato molto. Puoi semplicemente ripulire il casino:

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;

-6

Se intendi eliminare una goccia da una tabella, se esiste, puoi utilizzare il DELETEcomando, ad esempio:

 DELETE FROM users WHERE user_login = 'foobar'

Se nessuna riga corrisponde, non è un errore.


2
Penso che l'OP si riferisca a un vero utente del database.
Tomalak

6
Questa è la soluzione più semplice IMO. Ha solo bisogno di SQL corretto: DELETE FROM mysql.user WHERE user = 'foobar'
John Rix
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.