首页 > 解决方案 > PHP`Create 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是它将由我正在寻找常见文件和目录名称的网络爬虫动态完成,并且由于我决定为每个表确定的大量路径可收集站点及其名称从其主机名生成。(可能不可靠的主机名示例:https ://whe.re/ )

但这导致了这一点。

在此处输入图像描述

所以我在没有它们的情况下尝试过,它会引发错误

“您的 SQL 语法有错误;请查看与您的 MariaDB 服务器版本相对应的手册,了解在 ''random_site' 附近使用的正确语法

我没有看到或想到什么,自从我使用 PHP 已经有一段时间了,我很茫然,因为我的所有搜索都让我明白为什么在进行不属于我的查询时表名应该用反引号括起来问题。

谢谢

信息:MariaDB
PHP:7.4.6

标签: phpmysqldatabase-designmariadbcreate-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 {
    ... 
}

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

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


推荐阅读