Không có cách tiêu chuẩn nào để kiểm tra xem người dùng MySQL có tồn tại hay không và dựa vào đó mà thả. Có bất kỳ giải pháp thay thế cho điều này?
Chỉnh sửa: Tôi cần một cách dễ dàng để chạy nó mà không gặp lỗi,
ví dụ:
DROP USER test@localhost; :
Không có cách tiêu chuẩn nào để kiểm tra xem người dùng MySQL có tồn tại hay không và dựa vào đó mà thả. Có bất kỳ giải pháp thay thế cho điều này?
Chỉnh sửa: Tôi cần một cách dễ dàng để chạy nó mà không gặp lỗi,
ví dụ:
DROP USER test@localhost; :
Câu trả lời:
Kể từ MySQL 5.7, bạn có thể làm DROP USER IF EXISTS test
Thông tin thêm: http://dev.mysql.com/doc/refman/5.7/en/drop-user.html
Điều này đã làm việc cho tôi:
GRANT USAGE ON *.* TO 'username'@'localhost';
DROP USER 'username'@'localhost';
Điều này tạo ra người dùng nếu nó chưa tồn tại (và cấp cho nó một đặc quyền vô hại), sau đó xóa nó theo cách nào đó. Giải pháp tìm thấy ở đây: http://bugs.mysql.com/bug.php?id=19166
Cập nhật: @Hao khuyên bạn nên thêm IDENTIFIED BY; @andreb (trong nhận xét) đề xuất tắt NO_AUTO_CREATE_USER.
IDENTIFIED BYđiều này để thực sự hoạt động.
Đối với câu trả lời của phyzome (câu trả lời được bình chọn cao nhất), có vẻ như với tôi rằng nếu bạn đặt "xác định bởi" vào cuối tuyên bố tài trợ, người dùng sẽ được tạo tự động. Nhưng nếu bạn không làm như vậy, người dùng không được tạo. Đoạn mã sau phù hợp với tôi,
GRANT USAGE ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
DROP USER 'username'@'localhost';
Hi vọng điêu nay co ich.
Tìm thấy câu trả lời cho điều này từ một trong những diễn đàn MySQL. Chúng tôi sẽ cần sử dụng một quy trình để xóa người dùng.
Người dùng ở đây là “test” và “databaseName” là tên cơ sở dữ liệu.
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' ;
hoạt động cho tôi mà không gây ra bất kỳ lỗi nào trong Maria DB, nó cũng sẽ hoạt động cho bạn
Cập nhật:
Kể từ MySQL 5.7, bạn có thể sử dụng DROP USER IF EXISTScâu lệnh. Tham khảo: https://dev.mysql.com/doc/refman/5.7/en/drop-user.html
Cú pháp:
DROP USER [IF EXISTS] user [, user] ...Thí dụ:
DROP USER IF EXISTS 'jeffrey'@'localhost';
FYI (và cho phiên bản MySQL cũ hơn), đây là một giải pháp tốt hơn ... !!!
SP sau đây sẽ giúp bạn xóa người dùng 'tempuser'@'%'bằng cách thực thiCALL DropUserIfExistsAdvanced('tempuser', '%');
Nếu bạn muốn xóa tất cả người dùng có tên 'tempuser'(nói 'tempuser'@'%', 'tempuser'@'localhost'và 'tempuser'@'192.168.1.101') thực thi SP như thế CALL DropUserIfExistsAdvanced('tempuser', NULL);này sẽ xóa tất cả người dùng có tên tempuser!!! nghiêm túc...
Bây giờ hãy xem SP đã đề cập 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 ;
Sử dụng:
CALL DropUserIfExistsAdvanced('tempuser', '%'); xóa người dùng 'tempuser'@'%'
CALL DropUserIfExistsAdvanced('tempuser', '192.168.1.101'); xóa người dùng 'tempuser'@'192.168.1.101'
CALL DropUserIfExistsAdvanced('tempuser', NULL);để xóa tất cả người dùng có tên 'tempuser'(ví dụ:., say 'tempuser'@'%', 'tempuser'@'localhost'và 'tempuser'@'192.168.1.101')
Ừm ... Tại sao tất cả những phức tạp và thủ thuật?
Thay vào đó, sử dụng DROP USER ... Bạn có thể chỉ cần xóa người dùng khỏi bảng mysql.user (bảng này không gây ra lỗi nếu người dùng không tồn tại), rồi xóa các đặc quyền để áp dụng thay đổi.
DELETE FROM mysql.user WHERE User = 'SomeUser' AND Host = 'localhost';
FLUSH PRIVILEGES;
- CẬP NHẬT -
Tôi đã sai. Không an toàn khi xóa người dùng như vậy. Bạn cần sử dụng DROP USER. Vì có thể có các tùy chọn mysql được đặt để không tự động tạo người dùng thông qua các khoản tài trợ (một tùy chọn tôi sử dụng), tôi vẫn sẽ không đề xuất thủ thuật đó. Đây là một đoạn trích từ một quy trình được lưu trữ phù hợp với tôi:
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;
Về câu trả lời của @ Cherian, có thể xóa các dòng sau:
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI';
...
SET SQL_MODE=@OLD_SQL_MODE;
...
Đây là một lỗi trước 5.1.23. Sau phiên bản đó, chúng không còn được yêu cầu nữa. Vì vậy, để thuận tiện sao chép / dán, ở đây là tương tự với các dòng trên được loại bỏ. Một lần nữa, đối với các mục đích ví dụ "kiểm tra" là người dùng và "databaseName" là cơ sở dữ liệu; và đây là từ lỗi này .
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
Tôi đã viết quy trình này lấy cảm hứng từ câu trả lời của Cherian. Sự khác biệt là trong phiên bản của tôi, tên người dùng là một đối số của thủ tục (và không được mã hóa cứng). Tôi cũng đang thực hiện các QUYỀN RIÊNG TƯ VỀ FLUSH rất cần thiết sau khi bỏ người dùng.
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 ;
Tôi cũng đã đăng mã này trên trang web CodeReview ( /codereview/15716/mysql-drop-user-if-exists )
DROP USER 'user'@'localhost';
Lệnh trên sẽ loại bỏ người dùng khỏi cơ sở dữ liệu, tuy nhiên, điều quan trọng là phải biết nếu cùng một người dùng đã sử dụng cơ sở dữ liệu, phiên đó sẽ không kết thúc cho đến khi người dùng đóng phiên đó. Điều quan trọng cần lưu ý là người dùng bị rớt sẽ VẪN truy cập cơ sở dữ liệu và thực hiện bất kỳ hoạt động nào. DROPPING NGƯỜI DÙNG KHÔNG XÓA PHẦN NGƯỜI DÙNG HIỆN TẠI
Kết hợp câu trả lời của phyzome (không hoạt động ngay với tôi) với nhận xét của andreb (giải thích lý do tại sao nó không), tôi đã kết thúc với đoạn mã dường như đang hoạt động này tạm thời tắt chế độ NO_AUTO_CREATE_USER nếu nó đang hoạt động:
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'@'%';
Trong trường hợp bạn có một máy chủ trường học, nơi học sinh làm việc rất nhiều. Bạn chỉ có thể dọn dẹp đống lộn xộn bằng cách:
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;
Nếu bạn muốn xóa một giọt khỏi bảng nếu nó tồn tại, bạn có thể sử dụng DELETElệnh, ví dụ:
DELETE FROM users WHERE user_login = 'foobar'
Nếu không có hàng nào khớp thì đó không phải là lỗi.