为啥 MySQLi 库本身不支持命名参数?

Posted

技术标签:

【中文标题】为啥 MySQLi 库本身不支持命名参数?【英文标题】:Why doesn't MySQLi library natively support named parameters?为什么 MySQLi 库本身不支持命名参数? 【发布时间】:2017-01-21 08:49:25 【问题描述】:

来自http://php.net/manual/en/mysqli.quickstart.prepared-statements.php 的正确 MySQLi 参数化查询语法:

$stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)");
$stmt->bind_param("i", $id);

但绝不会这样:

$stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (:id_value)");
$stmt->bind_param("i", "id_value", $id);

在我看来,named parameter 替换是在 API 级别实现的合理功能。我很惊讶 MySQLi 只在库中实现了unnamed parameters

有正当理由吗?看到 PDO、DQL、ORM 在查询中都采用了命名参数,这对我来说没有意义。

我希望 MySQLi 开发人员不会出现“我们很懒且不想”的情况。我相信一定有一个很好的理由,我正在寻找那个理由,或者寻找那个理由的方法。 MySQLi扩展库中没有实现命名参数的原因。

【问题讨论】:

mysql数据库引擎没有?它已经准备好查询,但没有命名参数。 mm 离题、太宽泛和基于意见的标记。我没想到关闭标志的多样性。 好吧,丹尼斯;你肯定会从熟悉 PHP.net 核心开发的人那里得到答案,以及他们为什么这样做的根本原因。这是你得到具体答案的唯一方法。我是其中之一,我不是那些人中的一员 ;-) 至少我在这里给了你正确的时间。 以我认为合乎逻辑的方式回答这个问题:冒号 : 占位符将是一个(管道)字符,与 MySQLi_prepared statement 占位符 ? 不同,其中 PDO 更多可跨不同平台传输,然后 MySQLi_ API 是。然而,它更“可移植”,核心开发人员(可能)希望人们能够同时使用:? 占位符作为熟悉的可能手段;我是否接近您正在寻找的答案? @丹尼斯 上述附录:The (PDO) manual on a prepared statement 声明:“PDO 将为不支持原生的驱动程序模拟准备好的语句/绑定参数,并且还可以重写命名或问号样式的参数标记如果驱动程序支持一种风格但不支持另一种风格,则更合适。” 另外,MySQL 也支持它作为核心字符,所以这可能就是他们选择冒号占位符的原因。另请参阅手册中的贡献者说明。 【参考方案1】:

MYSQLi 不支持命名参数有两个主要原因:

    “有意”(我松散地使用这个术语)与包装器一起使用,并且 它的对应物 PDO 确实如此 - 没有必要重新发明***

详细说明第 1 点:mysqli 尽管与PDO 相比有许多缺点,但它很容易与一个好的包装器进行比较——也就是说,命名参数(以及其他)由包装器支持,而不是@987654325 @ 本身。这是出于一个唯一原因的设计:

    Mysqli 旨在成为一个快速灵活的库。

如果开发人员将更多功能集成到基础库中,则直观地相反,它变得不那么灵活,并且需要更长的加载/执行时间。

mysqlipdo 都是随 PHP 5 发布的(我相信 PDO 是 5.3 版),因此它们的用途不同。

您想要更快的执行时间?使用 mysqli 而不使用包装器。你想要命名参数吗?使用 PDO 或构建 mysqli 包装器来处理此类问题 - 但请注意,这会阻碍您的执行时间。

【讨论】:

【参考方案2】:

传统上,MySQLi 是MySQL API 的一个非常薄的包装器。它本身并没有添加任何东西,这是有原因的:添加命名占位符之类的功能将需要,如果您想到的话,SQL 查询解析的整个庞然大物。当然,这不是数据库 API 的工作。就像在另一个答案中所说的那样,API 不是DAL or DBAL;它们用于不同的目的。

PDO 是一项伟大的壮举,您在这门语言中几乎不会再看到了,而 Wes Furlong 是一位天才,几乎单枪匹马地完成了这项任务。但同样,PDO 是另一回事。它是一个数据库访问抽象层,为了实现这个目标,你需要一个查询解析器,不管你喜不喜欢。由于您已经有一个查询解析器并且其中一个驱动程序已经支持命名占位符,因此很自然地将其添加到所有受支持的驱动程序中。如您所见,使用 MySQLi 一切都不同。

简而言之,这与“懒惰”无关;这是关于遵循规范。

【讨论】:

当 PDO::ATTR_EMULATE_PREPARES 设置为 true 时,PDO 只返回字符串是谁的错? @You 为了消除首字母缩略词“DAL”的歧义,请解释或链接您指的是数据访问层或数据库抽象层。我以为是后者,但是当我用谷歌搜索验证时,我找到了前者。

以上是关于为啥 MySQLi 库本身不支持命名参数?的主要内容,如果未能解决你的问题,请参考以下文章

jdbc为啥prepared statement不支持命名参数?

为啥 Python 不支持记录类型? (即可变的命名元组)

为啥 Perl CGI 模块使用连字符来开始命名参数?

为啥参数的顺序保持不变,即使参数作为命名参数传递?在 JavaScript 中

为啥表达式树不能包含命名参数规范?

为啥不能在 Ruby 3 中结合 `...` 和命名参数?