mysqli_stmt :: bind_param()-为每个参数指定除“ s”之外的另一种数据类型

时间:2018-07-02 14:27:32

标签: php mysql mysqli bindparam

mysqli_stmt没有query_params()函数,我必须编写自己的函数。参数arry绑定到带有bind_param()的语句。我需要动态指定变量类型。我可以用类似的方法做到这一点:

$sType = '';
foreach ($aParameters as $iIndex => $mParameter) {
  if     (is_string($mParameter)) {$sType .= 's';}
  elseif (   is_int($mParameter)) {$sType .= 'i';}
  elseif ( is_float($mParameter)) {$sType .= 'd';}
  elseif (  is_null($mParameter)) {$sType .= 's';}
  elseif (  is_bool($mParameter)) {
    $sType .= 'i';
    $aParameters[$iIndex] = boolval($mParameter);}
  else {
    // trow new Exception(...);
  }
}

但事实证明,mysql / mariadb将发送布尔值,整数和浮点数作为字符串,数据库服务器将在其中高兴地将它们强制转换为列的相应数据类型。看来我可以跳过此步骤,默认情况下将每个参数作为字符串发送。

是否有理由为每个参数指定"s"以外的其他数据类型?

编辑:我刚刚找到this SO主题,该主题显示了二进制数据包超过mysqli_stmt::send_long_data设置时如何使用“ b”类型和max_allowed_packet。我还读过它会比采用bin2hex()来将字节字符串作为文本发送的解决方案提高性能。

2 个答案:

答案 0 :(得分:1)

我唯一发现使用整数参数很重要的是在LIMIT子句中。

SELECT
...
LIMIT ?, ?

MySQL在这种情况下不接受带引号的字符串文字,也不接受带有字符串类型的参数。您必须使用整数。

有关此方面的测试,请参见Parametrized PDO query and `LIMIT` clause - not working。那是一个关于PDO的问题,我没有测试mysqli,但我认为在这种情况下使用整数参数是服务器端MySQL的要求。因此,它也应适用于mysqli。

在所有其他情况下(AFAIK),MySQL可以通过读取字符串中的前导数字并忽略任何后续字符来将字符串转换为整数。

答案 1 :(得分:1)

  

似乎我可以跳过此步骤,默认情况下将每个参数作为字符串发送。

是的。

  

是否有任何理由为每个参数指定除“ s”之外的其他数据类型?

极为稀有和含糊。到目前为止,我能够找到尽可能多的

  • bigint值最好绑定为整数而不是字符串
  • 一些报道称强制转换可能导致错误的执行计划,但我无法在野外找到证据
  • 您已经发现自己的二进制类型,尽管我会质疑在数据库中存储BLOB的想法本身
  • 按数字大小写mentioned by Dharman的奇数顺序。

无论情况如何,我都建议保留类型绑定,但避免这种类型的嗅探,虽然这样做没有好处,但可能会破坏数据库。

相反,只需像我在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();

简单,干净,优雅!