如何根据检索到的列类型为 bind_param 动态分配正确的类型?

Posted

技术标签:

【中文标题】如何根据检索到的列类型为 bind_param 动态分配正确的类型?【英文标题】:How to assign the correct type to bind_param dynamically based on retrieved column types? 【发布时间】:2020-05-22 13:51:10 【问题描述】:

背景信息:

我正在创建一个将为我处理某些查询的类。其中一个查询是 SELECT 查询,用户可以在其中根据子句选择某些内容。我成功检索了列的 TYPES,但不知道如何根据列的 TYPE 实际决定应该给 bind_param()(第一个参数)的 TYPE。

如果检索到的列类型是某种类型,我最初的计划是廉价并简单地硬编码应该给出哪个参数。

我最初想法的例子:

if ($type === "varchar") 
    $aVariable = "s";

//OR USE A SWITCH, BUT YOU GET THE IDEA
bind_param($aVariable, $someOtherVar);

但是,由于许多不同的原因,这不是我满意的事情。所以我的问题是:

问题: 如何使用 TYPES 列(如果可能)来确定提供给 bind_param() 的参数是否应该是以下类型之一:“s、i、d、b”,而不必对检索到的类型进行硬编码= 某个字母。

【问题讨论】:

只需将所有变量绑定为“s” @YourCommonSense 如果一个人可以将所有类型设置为“s”,那么使用其他类型有什么意义?让我换种说法:可以设置所需类型的人与简单地将所有类型设置为字符串的人相比有什么优势? 优势大部分是想象的。一些你几乎没有机会遇到的极端情况 我为 PDO 写了一个答案,描述了issues with parameter data-types,这可能有助于您理解。但除了NULLLOB 数据类型之外,对于大多数查询,使用字符串数据类型应该是安全的。实际上,mysql 会在适当的地方自动转换数字字符串,但是当提供的数据不是适当的类型时,有些实例会产生意外的结果。 @fyrye null 也由 "s" 处理 【参考方案1】:

猜测参数类型总是有味道。而将所有参数设置为“s”在大多数情况下都可以正常工作。

所以让我建议您另一种解决方案。使类型明确但可选。默认情况下它将是“s”,但可以手动定义类型,就像我在 mysqli helper function 中所做的那样:

function prepared_query($mysqli, $sql, $params, $types = "")

    $types = $types ?: str_repeat("s", count($params));
    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    return $stmt;

当您不需要任何特定类型时(大部分时间),只需将它们排除在外:

$sql = "SELECT * FROM tmp_mysqli_helper_test WHERE id > ?";
$res = prepared_query($conn, $sql, [1])->get_result();

但每次你需要它时,它已经在这里并且是明确的,所以你可以设置你想要的确切类型:

$sql = "SELECT * FROM tmp_mysqli_helper_test WHERE id > ?";
$res = prepared_query($conn, $sql, [1], "i")->get_result();

简单、干净、简洁

【讨论】:

【参考方案2】:

您的代码不应该尝试猜测类型。您应该将所有内容绑定为字符串。 99.99% 的时间不会有任何影响。在某些极端情况下,实际类型会有所不同,但在这些情况下,当您知道类型应该是什么时,您可以对类型进行硬编码。如果您猜测类型,那么您只会将更多错误添加到您的软件中。

您从 html 表单收到的所有数据都是字符串类型。 MySQL 根据上下文动态进行类型转换。为什么要费心在 php 中转换值?只需将所有内容按原样发送到 MySQL 并让它决定类型应该是什么。

【讨论】:

以上是关于如何根据检索到的列类型为 bind_param 动态分配正确的类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何检索所有表列、数据类型、数据长度、约束类型以及引用的列和表

mysqli_stmt::bind_param() - 为每个参数指定另一个数据类型而不是“s”

根据从 MySQL 检索到的数据填充 HTML 表头

如何判断 pandas 数据框中的列是不是为 datetime 类型?如何判断一列是不是为数字?

Laravel/VueJs。如何根据传入的列值显示不同颜色的按钮?

如何从flutter中从异步任务中检索到的数据中将图像加载到卡片中?