我想让 MySQL 用户能够创建新的数据库,并拥有这些数据库的所有权限,但不能拥有其他数据库的所有权限。我曾尝试为此创建一个存储过程,但没有成功。这是我的过程 (笔记:更新后的代码如下):
DELIMITER //
CREATE DEFINER = 'root'@'localhost' PROCEDURE createdb(IN newdb VARCHAR(255))
BEGIN
CREATE DATABASE newdb;
SET @newdbuser = USER();
GRANT ALL ON newdb.* TO '@newdbuser';
FLUSH PRIVILEGES;
END //
DELIMITER ;
我使用以下方式调用该过程:
CALL createdb('newtestdb');
但实际上,数据库“newdb”(变量名)已创建。尝试以调用该过程的普通用户身份访问该数据库也不起作用:访问被拒绝。
问题:我的程序有什么问题?还是我从错误的角度来解决问题?
更新 根据 longneck 的回答,我将程序修改为:
DELIMITER //
CREATE DEFINER = 'root'@'localhost' PROCEDURE createdb(IN newdb VARCHAR(255))
BEGIN
PREPARE stmt1 FROM "CREATE DATABASE ?";
PREPARE stmt2 FROM "GRANT ALL ON newdb.* TO '?'";
EXECUTE stmt1 USING @newdb;
SET @newdbuser = USER();
EXECUTE stmt2 USING @newdbuser;
FLUSH PRIVILEGES;
END //
DELIMITER ;
但是,当使用“CALL createdb('testing');”调用该过程时,我得到:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1
我错过了什么?
答案1
这不是权限问题。mysql 不支持变量作为对象名(对象是表、数据库、列等)。您必须使用准备好的语句并将命令构建为字符串。请参阅http://forums.mysql.com/read.php?98,152150,152161#msg-152161
例如,您的 PREPARE 语句需要如下所示:
PREPARE stmt1 FROM concat("CREATE DATABASE ", @dbname);
PREPARE stmt2 FROM concat("GRANT ALL ON newdb.* TO ", @username);
这并不意味着注入是不安全的。在使用这些语句之前,请确保已经清理了你的“参数”(数据库名称、用户名)。
另外,您授予的权限是错误的。TO '@newdbuser'
将权限分配给从名为 的计算机连接的用户newdbuser
。您需要@
在用户名后面加上符号。