MySQL:ユーザーが存在するかどうかを確認し、ドロップします


84

MySQLユーザーが存在するかどうかを確認し、それに基づいてドロップする標準的な方法はありません。これに対する回避策はありますか?

編集:私は、エラー投げせずにこれを実行するためのまっすぐな方法必要
などを

DROP USER test@localhost; :    

1
MySQLユーザーのことですか?または、MySQLのテーブルに保存しているユーザーレコードですか?
ジェイソンコーエン

MariaDBには次の機能があるようです:mariadb.com/kb/en/mariadb/drop-user
限定的贖罪

1
将来の読者のために:MySQLの5.7は機能'IFは、EXISTSのDROP USER'が、参照stackoverflow.com/questions/598190/...を
アンドレイEpure

1
@AndreiEpureこれを答えとしていただければ、正しいものとしてマークします。
チェリアン2017

回答:



87

これは私のために働いた:

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ます。


5
MySQLのマニュアルページを付与する「権限なし」の同義語:USAGE:それは言う、実際に
stivlo

6
これはもはやオプションではありません。:(現在のバージョンのMySQLは、GRANTステートメントの新しいユーザーを作成しなくなりました。これは彼らが追加した「機能」でした。;)現在機能しているのはCherianのオプションだけのようです。
GazB 2011

1
@Zasurus。dev.mysql.com/doc/refman/5.1/en/grant.html(5.5および5.6も)は、あなたが間違っていることを示唆しているようです。「自動ユーザー作成なし」オプションがあります。マニュアルを誤解しない限り、grantが存在しない場合はユーザーを作成することを示しています。
andreb 2012年

@andrebおそらく、これを試したとき、またはデフォルトで「NO_AUTO_CREATE_USER」オプションがオンになっていた(変更していないため)。時間がある場合は、これを試してこのオプションをオフにして、再試行します。このオプションを使用した未解決のバグレポートがいくつかありますが、そのうちの1つも問題である可能性があります。:)
GazB 2012年

@Haoの回答も参照してください。IDENTIFIED BYこれを実際に機能させるには、が必要でした。
マシュー

14

phyzomeの答え(最も投票数の多いもの)に対して、助成金ステートメントの最後に「identified by」を付けると、ユーザーが自動的に作成されるように思われます。ただし、そうでない場合、ユーザーは作成されません。次のコードは私のために働きます、

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

お役に立てれば。


IDENTIIFIED BY'password 'のない古いスクリプトがいくつかありました。5.6で動作した部分。しかし、5.7ではありませんでした。IDENTIFIED BY'password 'の部分を追加すると、うまくいきました。
joensson 2016年

13

MySQLフォーラムの1つからこれに対する答えを見つけました。プロシージャを使用してユーザーを削除する必要があります。

ここでのユーザーは「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


ありがとう@Cherianこれが2017年でも物事を行うための最良の方法であるかどうかはわかりませんが、少なくともそれは前進する方法です!私は...これはとても難しいまだ信じることができない
JMAC

参考までに、常にソースのURLを含める必要があります(例:mysqlフォームの1つから回答が見つかりました。またはmysqlフォームの1つから(ソースはこちら)

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

これは、Maria DBでエラーをスローすることなく機能しますが、uでも機能するはずです。


2
MySQL 5.7以降では、確かに。...幸運なことに、ここで使用する最新バージョンは5.5です。
鉄人2016

4

更新: 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'


3

ええと...なぜすべての合併症とトリック?

DROP USERを使用するのではなく... mysql.userテーブルからユーザーを削除し(ユーザーが存在しない場合でもエラーはスローされません)、権限をフラッシュして変更を適用できます。

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

-更新-

私は間違っていた。そのようなユーザーを削除することは安全ではありません。DROPUSERを使用する必要があります。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;

それが「安全ではない」理由を共有してください...?どのように誰にとって安全ですか?
dagelf 2016

ええと、1年以上前にこれを投稿したので、私が言及していたことを100%覚えているとは言いません。信頼性がユーザーをシステムから完全に削除するわけではないことを意味していると確信しています。DROP USERは、mysql.userテーブルから行を削除するだけではありません。申し訳ありませんが、それらの詳細が今何であるかを考えることができません!
BuvinJ 2016

推測した場合、特権レコードは削除されないが、「孤立」すると言うでしょうか。(設定によって異なりますか?)
BuvinJ 2016

2

@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

2

私はチェリアンの答えに触発されてこの手順を書きました。違いは、私のバージョンでは、ユーザー名がプロシージャの引数である(ハードコードされていない)ことです。また、ユーザーを削除した後、非常に必要なFLUSHPRIVILEGESを実行しています。

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 ;

このコードはCodeReviewWebサイト(/codereview/15716/mysql-drop-user-if-exists)にも投稿しました


2
DROP USER 'user'@'localhost';

上記のコマンドはユーザーをデータベースから削除しますが、同じユーザーがすでにデータベースを使用しているかどうかを知ることは重要です。ユーザーがそのセッションを閉じるまで、そのセッションは終了しません。ドロップされたユーザーは引き続きデータベースにアクセスし、すべての操作を実行することに注意することが重要です。 ユーザーを削除しても、現在のユーザーセッションは削除されません


0

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

0

ターミナルで行う:

sudo mysql -u root -p

パスワードを入力します。

select user from mysql.user;

ここで、ユーザー 'the_username'を削除します

DROP USER the_unername;

'the_username'を削除するユーザーに置き換えます。


-1

あなたが生徒がたくさん働いた学校のサーバーを持っている場合。あなたはただ次の方法で混乱を片付けることができます:

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

ドロップが存在する場合はテーブルから削除する場合は、DELETE次のコマンドを使用できます。

 DELETE FROM users WHERE user_login = 'foobar'

一致する行がない場合、それはエラーではありません。


2
OPは実際のデータベースユーザーを指していると思います。
Tomalak 2009

6
これは最も単純なソリューションIMOです。正しいSQLが必要です:DELETE FROM mysql.user WHERE user = 'foobar'
John Rix 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.