为将表添加到MySQL(PHP)准备的语句

为将表添加到MySQL(PHP)准备的语句,php,mysql,Php,Mysql,这段代码可以工作并将表添加到我的数据库中。我的问题是如何用事先准备好的声明来保护它 require "conn.php"; $MyServer =($_POST["username"]); $sql = ("CREATE TABLE $MyServer ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30) NOT NULL

这段代码可以工作并将表添加到我的数据库中。我的问题是如何用事先准备好的声明来保护它

 require "conn.php";
    $MyServer =($_POST["username"]);
        $sql = ("CREATE TABLE $MyServer (
            id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
            username VARCHAR(30) NOT NULL
            )");
        if($conn->query($sql) === TRUE){
            echo "Table created successfully";
        }
我正在使用MySQLi。 我尝试了这个,但它没有添加表

$MyServer =($_POST["username"]);
    if (!preg_match('^/[A-Za-z][A-Za-z0-9]{0,7}$/', $MyServer)) {
       throw new Exception ('username unsuitable for use as a table name');
    }
    $sql = ("CREATE TABLE `$MyServer` (
        id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
        username VARCHAR(30) NOT NULL
        )");
    if($conn->query($sql) === TRUE){
        echo "Table created successfully";
    } else {
        echo "Table is not created successfully ";
    }

尽管允许用户创建表是否是一个好的计划值得怀疑,但要回答您的问题:

首先,确保变量不包含任何奇怪的字符。虽然是MySQL,但您可能只需要普通的字母和数字:

if (
    !preg_match('/^[a-z0-9]+$/i', $MyServer)
    || preg_match(/^[0-9]+$/, $MyServer) // Identifiers may begin with a digit but unless quoted may not consist solely of digits.
    || strlen($MyServer) > 64 // Limit of table-name length
) {
    // Insert your own error handling
    die('Not allowed');
}
其次,为了确保SQL将其视为标识符,请在backticks中引用它

$sql = "CREATE TABLE `$MyServer` (...etc..."
CREATE TABLE index(…等…
将在MySQL中引发错误,因为
index
是一个关键字

CREATE TABLE `index` (...etc...

不会,因为它被标记为标识符。

我猜您正在考虑如何避免通过示例程序中的
$MyServer
变量向查询中注入SQL

不能使用参数化值在SQL中命名表(或数据库或列)。必须执行程序中显示的变量替换

不过,在将
$MyServer
变量用于替代之前,可以使用php对其进行清理

例如:

您可以这样做,或者类似的操作。这要求变量以字母开头,然后最多再包含七个字母或数字字符。如果变量不匹配,则抛出异常

if (!preg_match('^/[A-Za-z][A-Za-z0-9]{0,7}$/', $MyServer)) {
     throw new Exception ('username unsuitable for use as a table name');
}

老实说,通过从
$\u POST
获取数据,您在这里真正打开了SQL注入的大门

除非您的用户名已经存储在数据库中,并且没有导致SQL注入的特殊字符(如引号),否则您的方法是绝对不可行的

编辑:我在上面看到两个答案,这是对我所说的赞美,你可以使用这两个答案中的一个(O.Jones是我的首选)

如果您希望代码更符合PDO过程(绑定PDO值以避免SQL注入),为什么不创建一个包含列(username、saved_username)的表,并且您可以使用PDO语句有效地与该表中的信息交互

 require "conn.php";
    $MyServer =($_POST["username"]);
        $sql = ("CREATE TABLE $MyServer (
            id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
            username VARCHAR(30) NOT NULL
            )");
        if($conn->query($sql) === TRUE){
            echo "Table created successfully";
        }
例如,要插入数据,您只需执行以下操作:

$query = 'INSERT INTO table (username, saved_username) VALUES (:username, :username_to_save)';
$stmt->bindParam(':username', $_POST['username']);
$stmt->bindParam(':username_to_save', $_POST['username_to_save']);
$stmt->execute()
并选择数据:

$query = 'SELECT * FROM table WHERE username = :username';
$stmt->bindParam(':username', $_POST['username']);
$stmt->execute()
$users_saved_usernames = $stmt->fetchAll();

保护什么?你想保护什么?你的意思是如何避免sql注入以及允许用户基于
$POST
变量创建表?可能不是最好的计划。你至少要清理/清除表名。我想保护它不受注入的影响。你为什么要允许用户在e数据库?对我来说听起来像是糟糕的计划~如果
$\u POST['username']='fred;drop database;';
?我仍然无法理解为什么您会认为(每个用户)有多个表比结构正确的数据库模式更好