bindParam和bindValue有什么区别?

428
7个回答

715

来自PDOStatement::bindParam的手册条目

[使用bindParam]与PDOStatement::bindValue()不同,变量被绑定为引用,只有在调用PDOStatement::execute()时才会被评估。

例如:

$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindParam(':sex', $sex); // use bindParam to bind the variable
$sex = 'female';
$s->execute(); // executed with WHERE sex = 'female'
或者
$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindValue(':sex', $sex); // use bindValue to bind the variable's value
$sex = 'female';
$s->execute(); // executed with WHERE sex = 'male'

19
好的,明白了。问题是:为什么你会想要使用其中之一而不是另一个?在什么情况下有必要或有用只在执行时评估绑定参数? - Coldblackice
44
如果你需要用不同的数据执行查询多次,使用 bindValue 每次都需要重新绑定数据,而使用 bindParam 只需要更新变量即可。使用 bindValue 的主要原因是静态数据,例如字面字符串或数字。 - lonesomeday
2
例如,您想使用bindValue与函数返回值:$stmt->bindValue(':status',strtolower($status),PDO :: PARAM_STR); - paidforbychrist
6
想要给它点赞,但因为它是666,我就不点了。 - eddy147

232

以下是我能想到的:

  • 使用 bindParam,只能传递变量而不能传递值;
  • 使用 bindValue,既可以传递变量也可以传递值;
  • bindParam 只能与变量一起使用,因为它允许参数通过“引用”进行输入/输出 (而在 PHP 中,值不是有效的“引用”):它对于支持调用存储过程返回数据作为输出参数的驱动程序很有用,并且一些驱动程序还支持同时作为输入/输出参数来发送和更新数据。

有些数据库引擎的存储过程具有可以用于输入 (从 PHP 向过程中传递一个值) 和输出 (从存储过程返回一个值给 PHP) 的参数;为了绑定这些参数,必须使用 bindParam 而不是 bindValue。


@PascalMartin,正是我想知道的,你能用bindParam绑定值吗?干杯。 - yehuda
2
我仍然不清楚那到底是什么意思,变量和值分别是什么。我使用bindParam将一个值绑定到占位符上,而使用bindValue也可以做到同样的事情!- 至少在我的例子中是这样... - Richard
@Richard 变量: $stmt->bindParam(':id', $id); 值: $stmt->bindValue(':id', 1);。请注意,如果在 bindParam 中将 $id 替换为 1,则会发出错误提示。 - Rain

228
答案在bindParam文档中:

与PDOStatement::bindValue()不同,变量绑定为引用,并且仅在调用PDOStatement::execute()时才会进行评估。

并且,execute

使用PDOStatement::bindParam()将PHP变量绑定到参数标记:绑定变量将其值作为输入传递,并接收其关联参数标记的输出值(如果有)。

例子:
$value = 'foo';
$s = $dbh->prepare('SELECT name FROM bar WHERE baz = :baz');
$s->bindParam(':baz', $value); // use bindParam to bind the variable
$value = 'foobarbaz';
$s->execute(); // executed with WHERE baz = 'foobarbaz'
或者
$value = 'foo';
$s = $dbh->prepare('SELECT name FROM bar WHERE baz = :baz');
$s->bindValue(':baz', $value); // use bindValue to bind the variable's value
$value = 'foobarbaz';
$s->execute(); // executed with WHERE baz = 'foo'

我感觉有必要指出,这些示例是从@lonesomeday的答案中提取的,而不是相反,因为答案中没有给出任何信用。 - Adrian Wiik

34

来自预处理语句和存储过程

使用bindParam进行一次绑定以插入多行:

<?php

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();

30

最常见的目的,您应该使用bindValue

bindParam有两个棘手或意外的行为:

  • bindParam(':foo', 4, PDO::PARAM_INT)不起作用,因为它需要传递一个变量(作为引用)。
  • bindParam(':foo', $value, PDO::PARAM_INT)在运行execute()后会将$value更改为字符串。这当然可能导致难以捕获的微妙错误。

来源:http://php.net/manual/en/pdostatement.bindparam.php#94711


5

将其转化为行为记忆的最简单方法(以 PHP 为例):

  • bindParam:引用
  • bindValue:变量

bindValue接受一个_value_。 - user2864740

4
你不需要再苦苦挣扎,因为有这样一种方法存在:
$stmt = $pdo->prepare("SELECT * FROM someTable WHERE col = :val");
$stmt->execute([":val" => $bind]); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接