PHP `Create Table` 在 table 名称中包含引号

PHP `Create Table` is including quote marks in the table name

我遇到了一个奇怪的问题,即创建 table 会将反引号添加到数据库中的 table 名称。

public function create_table($name)
{
    $sql = "
        CREATE TABLE IF NOT EXISTS `?` (
          id int(11) NOT NULL AUTO_INCREMENT,
          url varchar(255) NOT NULL,
          resolved tinyint(1) NOT NULL,
          PRIMARY KEY (id)
        )";

    $query = $this->_pdo->prepare($sql);


    $query->bindValue(1, $name);

    if($query->execute())
    {
        print("Created");
    }
    else
    {
        var_dump($query->errorInfo());
    }   
}

我这样做并绑定 $name 的原因是它将由我正在寻找通用文件和目录名称的网络爬虫动态完成,并且由于数量很大我决定为每个站点使用 table 的可收集路径,并根据其主机名生成其名称。 (可能的狡猾主机名示例:https://whe.re/

但是这导致了这个。

所以我在没有它们的情况下进行了尝试,但它抛出了一个错误

"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''random_site'

我没有看到或没有想到什么,自从我使用 PHP 以来已经有一段时间了,我不知所措,因为我所有的搜索都让我明白为什么 table 名字应该是进行查询时被反引号包围,这不是我的问题。

谢谢

信息:MariaDB
PHP: 7.4.6

那是因为你绑定的是一个字符串值,所以它被注入了周围的单引号。但最重要的是,您不能将 table 名称作为查询中的参数传递。绑定机制旨在传递文字值,显然 table 名称不是。

在这种特定情况下,除了字符串连接,您别无选择:

$sql = "
    CREATE TABLE IF NOT EXISTS `$name` (
      id int(11) NOT NULL AUTO_INCREMENT,
      url varchar(255) NOT NULL,
      resolved tinyint(1) NOT NULL,
      PRIMARY KEY (id)
    )";

$query = $this->_pdo->prepare($sql);
if ($query->execute()) { 
    ... 
} else {
    ... 
}

这意味着您需要在将变量传递给查询之前在应用程序端对其进行彻底验证,这不是一件容易的事。

这最终提出了一个问题,即 为什么 每个站点都有一个单独的 table。我不推荐这种违反基本规范化规则的设计,并且会很快变成维护噩梦。相反,您应该有一个列出站点的引用 table,以及一个用于所有路径的 table,以及一个引用站点 table 的外键列。使用适当的架构和索引,您不太可能遇到性能问题,除非您有无数行(在这种情况下可以使用其他选项,例如逻辑分区)。