PDOStatement::bindParam

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)

PDOStatement::bindParam为特定变量名绑定一个参数

描述

public PDOStatement::bindParam(
    string|int $param,
    mixed &$var,
    int $type = PDO::PARAM_STR,
    int $maxLength = 0,
    mixed $driverOptions = null
): bool

将一个 PHP 变量绑定到所用于准备语句的 SQL 语句中的一个与之相对应的已命名位置或问号位置占位符。与 PDOStatement::bindValue() 不同,变量被绑定为一个引用,并且只会在调用 PDOStatement::execute() 时得到评估。

大多数参数都是输入参数,也就是,在构建查询时以只读方式使用的参数(但可能会根据 类型 进行转换)。某些驱动程序支持以输出参数形式调用返回数据的存储过程,而某些驱动程序既支持输出参数,也支持输入/输出参数(它们既发送数据,又会被更新以接收数据)。

参数

param

参数标识符。对于使用已命名位置占位符的准备好的语句,这将是要素名称,格式为 :name。对于使用问号位置占位符的准备好的语句,这将是参数的 1 索引位置。

var

要绑定到 SQL 语句参数的 PHP 变量的名称。

type

使用 PDO::PARAM_* constants 的参数的显式数据类型。要从存储过程返回一个 INOUT 参数,请使用按位 OR 操作符来设置 type 参数的 PDO::PARAM_INPUT_OUTPUT 位。

maxLength

数据类型的长度。要表示一个参数是从存储过程中获取的 OUT 参数,您必须显式设置长度。仅当 type 参数是 PDO::PARAM_INPUT_OUTPUT 时才有意义。

driverOptions

返回值

成功时返回 true,失败时返回 false

错误/异常

如果属性E_WARNING设置为PDO::ATTR_ERRMODE,会以PDO::ERRMODE_WARNING级别发出一条错误消息。

如果属性PDO::ATTR_ERRMODE设置为PDO::ERRMODE_EXCEPTION,会抛出一个PDOException

示例

示例 #1 具有命名占位符的准备语句执行

<?php
/* 通过绑定 PHP 变量执行一个准备语句 */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour'
);
$sth->bindParam('calories', $calories, PDO::PARAM_INT);
/* 名称也可以带有冒号“:”前缀(可选) */
$sth->bindParam(':colour', $colour, PDO::PARAM_STR);
$sth->execute();
?>

示例 #2 具有问号占位符的准备语句执行

<?php
/* 通过绑定 PHP 变量来执行预声明部分 */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?'
);
$sth->bindParam(1, $calories, PDO::PARAM_INT);
$sth->bindParam(2, $colour, PDO::PARAM_STR);
$sth->execute();
?>

范例 #3 使用 INOUT 参数调用存储过程

<?php
/* 使用 INOUT 参数调用存储过程 */
$colour = 'red';
$sth = $dbh->prepare('CALL puree_fruit(?)');
$sth->bindParam(1, $colour, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 12);
$sth->execute();
print "经过榨汁之后,颜色变成: $colour";
?>

另请参阅

添加备注

用户贡献的备注 26 条备注

atrandafirc at yahoo dot com
13 年前
我知道之前已经有人说了,但我也要就此写个备注,因为我认为记住这一点很重要

如果你用 PDO 的 bindParam 来执行带有 LIKE 条件的搜索,那么不能将百分号和引号放入到参数占位符 '%:keyword%' 中。

这样是错误的
"SELECT * FROM `users` WHERE `firstname` LIKE '%:keyword%'";

正确的解决方案是这样,让占位符保持干净
"SELECT * FROM `users` WHERE `firstname` LIKE :keyword";

然后将百分号添加到存储关键字的 php 变量中
$keyword = "%".$keyword."%";

最后,PDO 在执行查询的时候会自动添加引号,所以你不用担心这个。

所以完整的示例如下:
<?php
// 从查询字符串中获取关键字
$keyword = $_GET['keyword'];
// 准备命令
$sth = $dbh->prepare('SELECT * FROM `users` WHERE `firstname` LIKE :keyword');
// 在关键字上加上百分号
$keyword = "%".$keyword."%";
// 绑定参数
$sth->bindParam(':keyword', $keyword, PDO::PARAM_STR);
?>
Vili
14 年前
这是有效的($val 按引用传递)
<?php
foreach ($params as $key => &$val) {
$sth->bindParam($key, $val);
}
?>

这将失败(按值传递 $val,因为 bindParam 需要 &$variable)
<?php
foreach ($params as $key => $val) {
$sth->bindParam($key, $val);
}
?>
jcastromail at yahoo dot es
2 年前
PHP 8.1 改变了此方法的工作方式。

现在,第四个方法不能为空。它可以是 0(对于 int),但不能为 null,否则会发出已弃用的警告。

旧的
$sth->bindParam('calories', $calories, PDO::PARAM_INT);
新的
$sth->bindParam('calories', $calories, PDO::PARAM_INT,0);
Steve M
14 年前
请注意,当使用 PDOStatement::bindParam 时,一个整数在 PDOStatement::execute() 执行后会更改为一个字符串值。(在 MySQL 中测试过)。

这会在尝试使用 === 运算符比较值时造成问题。

示例
<?php
$active
= 1;
var_dump($active);
$ps->bindParam(":active", $active, PDO::PARAM_INT);
var_dump($active);
$ps->execute();
var_dump($active);
if (
$active === 1) {
// 在此操作
// 注意:这将失败,因为 $active 现在是 "1"
}
?>

结果
int(1)
int(1)
string(1) "1"
dhammari at q90 dot com
15 年前
关于是否可以将一个值绑定到多个相同占位符似乎存在一些困惑。例如

$sql = "SELECT * FROM user WHERE is_admin = :myValue AND is_deleted = :myValue ";

$params = array("myValue" => "0");

一些用户在尝试将单个参数绑定到多个位置保持器时报告在 PHP 5.2.0 及更早版本中出现了参数不匹配错误。然而,从 5.2.1 版本开始,这似乎就可以正常工作了。

有关详细信息,请参见错误报告 40417
http://bugs.php.net/bug.php?id=40417
pegas1981 at yandex dot ru
10 年前
http://technet.microsoft.com/en-us/library/ff628166(v=sql.105).aspx

将空数据绑定到 varbinary、binary 或 varbinary(max) 类型的服务器列时,您应该使用 $driver_options 指定二进制编码 (PDO::SQLSRV_ENCODING_BINARY)。有关编码常量的更多信息,请参见常量。
在 Microsoft Drivers for PHP for SQL Server 的 2.0 版本中添加了对 PDO 的支持。

<?php
$db
= new PDO('sqlsrv:server=SQLSERVERNAME;Database=own_exchange', 'user', 'password');
$sql = "INSERT INTO dbo.files(file_name, file_source) VALUES(:file_name, :file_source)";
$stmt = $db->prepare($sql);
$stmt->bindParam(":file_name", $files->name, PDO::PARAM_STR);
$stmt->bindParam(":file_source", file_get_contents($files->tempName), PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute();
?>
khkiley at adamsautomation dot com
11 年前
SQL Server 2008 R2

如果在文档中提到过该错误,则这是我之前没有注意到的。在对存储过程使用绑定输出参数时,输出参数将在处理完最后一个行集 AFTER 后更新。

如果您的存储过程不返回任何行集(没有 SELECT 语句),那么您的输出参数在存储过程处理完成后将立即准备好。

否则,您需要处理各行,然后
<?php $stmt->nextRowset(); ?>

在为每个返回的行集完成此操作后,您可以访问输出参数。
cyrylas at gmail dot com
13 年前
请注意,PDO 根据当前语言环境格式化数字。因此,如果语言环境将数字格式设置为标准以外的格式,则该查询将无法正常工作。

例如
在波兰语语言环境(pl_PL)中,正确的十进制分隔符是逗号(“,”),因此:123,45,而不是 123.45。如果我们尝试将 123.45 绑定到查询,最终会在查询中出现逗号。

<?php
setlocale
(LC_ALL, 'pl_PL');
$sth = $dbh->prepare('SELECT name FROM products WHERE price < :price');
$sth->bindParam(':price', 123.45, PDO::PARAM_STR);
$sth->execute();
// result:
// SELECT name FROM products WHERE price < '123,45';
?>
匿名
18 年前
对于在以下占位符中使用 bindParam() 的用户:

LIKE '%...%' 子句,以下代码可能无法工作

<?php
$q
= "SELECT id, name FROM test WHERE name like '%:foo%'";
$s = "carrot";
$sth = $dbh->prepare($q);
$sth->bindParam(':foo', $s);
$sth->execute();
?>

需要如下内容

<?php
$s
= "%$s%";
$sth->bindParam(':foo', $s);
?>

这样就可以正常工作。针对 mysql 4.1、PHP 5.1.3 进行了测试。
Mike Robinson
11 年前
请注意,使用 bindParam 时,第二个参数按照引用方式传递。这意味着如果启用了 E_STRICT,以下操作将会产生一个警告

<?php
$stmt
->bindParam('type', $object->getType());

// Strict Standards: 仅变量可以在 /path/to/file.php 的 123 行处按照引用方式传递
?>

如果第二个参数不是一个实际变量,请将 $object->getType(); 的结果设置到一个变量中并在 bindParam 中使用该变量,或者改用 bindValue。
Filofox
18 年前
请勿尝试在单个 SQL 语句中两次使用同一种命名的参数,例如

<?php
$sql
= 'SELECT * FROM some_table WHERE some_value > :value OR some_value < :value';
$stmt = $dbh->prepare($sql);
$stmt->execute( array( ':value' => 3 ) );
?>

...这不会返回任何行,也不会返回任何错误 -- 您必须只使用每次参数一次。很明显,这是预料中的行为(根据这篇 bug 报告:http://bugs.php.net/bug.php?id=33886),这是因为存在可移植性问题。
jeffwa+php at gmail dot com
17 年前
我花了好长时间才在手册的注释中的其他地方找到了这一点,所以我想把它放在这里,帮助未来的其他人。

在 MySQL 中使用 LIKE 检索时,在 bindParam() 语句之前,*value* 必须附加适当的括号,如下所示

<?php
$dbc
= $GLOBALS['dbc'];
$sql = "SELECT * FROM `tbl_name` WHERE tbl_col LIKE ?";
$stmt = $dbc->prepare($sql);

$value = "%{$value}%";
$stmt->bindParam($i, $value, PDO::PARAM_STR);
?>

尝试使用
<?php
$stmt
->bindParam($i, "%{$value}%", PDO::PARAM_STR);
?>

将会失败。
geompse at gmail dot com
14 年前
如果你正在存储文件(或二进制数据),使用 PARAM_LOB(而且还在尝试使用 Oracle 进行此操作),请不要错过此页面

https://php.net/manual/en/pdo.lobs.php

你将在那里注意到 PDO-PGSQL 和 PDO-OCI 的工作方式完全不同:既不是相同的参数,也不是相同的行为。
heather dot begazo at gmail dot com
9 年前
文档关于 bindParam 的 length 参数写道

"要指示某个参数是存储过程中的 OUT 参数,你必须显式设置长度。"

对于 db2,我发现为 "INPUT_OUTPUT" 参数设置长度会导致 input 参数的 varchar 参数出现问题。我发现的问题是,存储过程已调用,但 varchar 输入参数在我的存储过程中被设置为 null,因此存储过程无法正常工作。

以下是我的存储过程签名

CREATE OR REPLACE PROCEDURE MY_SCHEMA_NAME.MY_STORED_PROCEDURE_NAME ( IN RUN_ID INTEGER,IN V_SCHEMA_NAME VARCHAR(128),
OUT out_rc INTEGER,OUT out_err_message VARCHAR(100),OUT out_sqlstate CHAR(5) ,OUT out_sqlcode INT)

以下是起作用的 php 代码

$command = "Call MY_SCHEMA_NAME.MY_STORED_PROCEDURE_NAME (?,?,?,?,?,?,?)";
$stmt = $this->GuestDb->prepare($command);
$stmt->bindParam(1, $RUN_ID, PDO::PARAM_INT);
$stmt->bindParam(2, $V_SCHEMA_NAME, PDO::PARAM_STR);
$stmt->bindParam(3, $V_TABNAME, PDO::PARAM_STR);
$stmt->bindParam(4, $out_rc, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(5, $out_err_message, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(6, $out_sqlstate, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(7, $out_sqlcode, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);

下面是无法正常工作的PHP代码

$command = "Call MY_SCHEMA_NAME.MY_STORED_PROCEDURE_NAME (?,?,?,?,?,?,?)";
$stmt = $this->GuestDb->prepare($command);
$stmt->bindParam(1, $RUN_ID, PDO::PARAM_INT,12);
$stmt->bindParam(2, $V_SCHEMA_NAME, PDO::PARAM_STR,128);
$stmt->bindParam(3, $V_TABNAME, PDO::PARAM_STR,100);
$stmt->bindParam(4, $out_rc, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT,12);
$stmt->bindParam(5, $out_err_message, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT,100);
$stmt->bindParam(6, $out_sqlstate, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT,6);
$stmt->bindParam(7, $out_sqlcode, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT,12);
gilhildebrand at gmail dot com
9 年前
如果命名占位符中包含连字符,MySQL会返回一个错误
UPDATE wardrobe SET `T-Shirt`=:T-SHIRT WHERE id=:id

将返回以下错误:PDOExcetpion',并带有消息“SQLSTATE[HY093]:无效参数号:未定义参数”

要解决此问题,只需从命名占位符中删除连字符即可
UPDATE wardrobe SET `T-Shirt`=:TSHIRT WHERE id=:id
Ofir Attia
10 年前
/*
有关pdo类连接的方法,您可以自行添加用例并使用它。
*/
class Conn{
....
....
private $stmt;
public function bind($parameter, $value, $var_type = null){
if (is_null($var_type)) {
switch (true) {
case is_bool($value)
$var_type = PDO::PARAM_BOOL;
break;
case is_int($value)
$var_type = PDO::PARAM_INT;
break;
case is_null($value)
$var_type = PDO::PARAM_NULL;
break;
default
$var_type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($parameter, $value, $var_type);
}
Vladimir Kovpak
9 年前
<?php
/**
* 绑定位值:
*/

$sql = 'SELECT * FROM myTable WHERE level & ?';
$sth = \App::pdo()->prepare($sql);
$sth->bindValue(1, 0b0101, \PDO::PARAM_INT);
$sth->execute();
$result = $sth->fetchAll(\PDO::FETCH_ASSOC);
flannell
11 年前
整天撞墙

尝试在 XAMPP 上使用 Mysql v5.5.16 时使用 INOUT 或 OUT 并将返回变量带入 PHP。

"MySQL 不支持通过其 C API 绑定输出参数。您必须使用 SQL 级别变量:"

<?php
$stm
= $db->prepare("CALL sp_mysp(:Name, :Email, @sp_result)");

$outputArray = $db->query("select @sp_result")->fetch(PDO::FETCH_ASSOC);
?>

因此,MySQL 和 PDO 的“解决方法”是使用两个 SQL 调用。

希望这能帮助到某些人。
Ejaz Ansari
8 年前
对于那些对使用 PDO-bindparam 的插入查询感到困惑的人

$sql = $db->prepare("INSERT INTO db_fruit (id, type, colour) VALUES (? ,? ,?)");

$sql->bindParam(1, $newId);
$sql->bindParam(2, $name);
$sql->bindParam(3, $colour);
$sql->execute();
marco dot marsala at live dot it
8 个月前
举例没有突出说明它按预期的方式工作

<?php
/* 通过绑定 PHP 变量执行准备好的语句 */
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour'
);
$sth->bindParam('calories', $calories, PDO::PARAM_INT);
/* 名称也可以带有冒号 ":" 前缀(可选) */
$sth->bindParam(':colour', $colour, PDO::PARAM_STR);
$calories = 150;
$colour = 'red';
$sth->execute();
?>

卡路里在 db 中被设置为 150,颜色在 db 中被设置为红色,因为,正如文档中指出的那样:“变量被绑定为引用,并且只会在调用 PDOStatement::execute() 时才进行评估。”
1 年前
🧨🧨🧨



17 年前
9 年前
避免使用带点的参数,例如 “:table.column”。
它将返回错误 'PDOException',其中包含错误消息 'SQLSTATE[HY093]: 参数编号无效: 未定义参数'...
6 年前
以下是在用户可以提交 n 个关键词时在运行时构建动态 WHERE LIKE 的方法

<?php

if (array_key_exists('storyPieces', $_POST)) {
$story_pieces = explode(',' $_POST['storyPieces']);
foreach(
$story_pieces as $piece) {
if (
$conditional_count == 0) {
$where_clause .= 'story LIKE ? ';
$conditional_count++;
} else {
$where_clause .= 'AND story LIKE ? ';
$conditional_count++;
}
}
}

// 然后在您准备之后

if (isset($story_pieces)) {
foreach(
$story_pieces as $key => &$piece) {
$piece = "%" . $piece . "%";
$sth->bindParam($key + 1, $piece, PDO::PARAM_STR);
}
}

?>
ReK_
13 年前
这让我困惑了一段时间,因为它从未明确提及,但 PDO 会自动为您封装参数,因此以如下所示手动转义的已准备查询

"INSERT INTO 表格 (列名) VALUES (':值');"

实际上最终会加上双引号并可能造成问题。
sergiy dot sokolenko at gmail dot com
14 年前
请注意,您不能在同一个查询中混合命名参数和位置参数

<?php
$stmt
= $conn->prepare('SELECT * FROM employees WHERE name LIKE :name OR email LIKE ?');
$name = 'John%';
$email = 'john%';

$stmt->bindParam(':name', $name);
$stmt->bindParam(1, $email);

$stmt->execute();
?>

致命错误:未捕获到异常“PDOException”,其中包含消息:“SQLSTATE[HY093]:无效的参数编号:混合命名的和位置的参数”在...中

在 Linux x86-64 上运行 PHP 5.3.2
To Top