如何在BIT(1)列中使用PDO预处理语句?

时间:2014-02-12 06:01:52

标签: php mysql pdo prepared-statement bit-manipulation

我有一个包含几个BIT(1)类型列的数据库表。如果我忘记准备好的陈述,我可以轻易做到这样的事情:

UPDATE tablename SET
bit_column_1 = b'1',
bit_column_2 = b'0'

这将完美无缺。但是,无论我尝试什么,在使用预准备语句时,值始终为“1”。

我已完成以下操作,如果$_POST['bit_col']0,则不会有任何效果:

$stmt = $dbh->prepare("UPDATE tablename SET
    bit_col = :bit_col ");
// First attempt
$stmt->bindValue('bit_col', $_POST['bit_col']);
// Second attempt
$stmt->bindValue('bit_col', $_POST['bit_col'], PDO::PARAM_INT);
// Third attempt
$stmt->bindValue('bit_col', "b'{$_POST['bit_col']}'");

然后我尝试更改准备好的语句以将b放在那里,但我得到number of bound variables does not match number of tokens

$stmt = $dbh->prepare("UPDATE tablename SET
    bit_col = b:bit_col ");
$stmt->bindValue('bit_col', $_POST['bit_col']);

$stmt = $dbh->prepare("UPDATE tablename SET
    bit_col = b':bit_col' ");
$stmt->bindValue('bit_col', $_POST['bit_col']);

值得一提的另一件事是PDO::ATTR_EMULATE_PREPARES设置为true。将其设置为false将需要我重构一些事情,因为我不知不觉地管理数据库连接。

所以我的问题是,是否可以在MySQL中使用带有BIT列的预准备语句,如果是,如何使用?

2 个答案:

答案 0 :(得分:2)

PDO::ATTR_EMULATE_PREPARES导致PDO与BIT列的交互略有不同。如果它设置为false,您只需正常插入值,MySQL将在幕后进行必要的转换:

$stmt = $dbh->prepare("UPDATE tablename SET
    bit_col = ? ");
$stmt->bindValue(1, $_POST['bit_col']);

但是,如果PDO正在模拟准备好的语句,则需要在其中放置一个b以指示它是BIT类型。如果你将b放在绑定参数中,PDO将转义单引号,你最终会发送一些像'b\'0\''发送到MySQL的东西,这显然是行不通的。因此b需要在查询中,而不是在绑定参数中。使用命名参数执行此操作会产生“绑定变量数量与令牌数量不匹配”错误,因为PDO无法识别带有b后跟:作为命名参数的字符串。但是,当您使用问号参数标记时,PDO 将其识别为参数,如下所示:

$stmt = $dbh->prepare("UPDATE tablename SET
    bit_col = b? ");
$stmt->bindValue(1, $_POST['bit_col']);

由于我们最终需要将b'1'发送给MySQL,因此在绑定值时使用PDO::PARAM_INT将导致查询失败,因为它将变为UPDATE tablename SET bit_col = b1(没有引号周围的引号,因此您必须保留数据类型或使用PDO::PARAM_STR

另请注意,如果禁用模拟预准备语句,则此查询将失败并出现语法错误,因此不幸的是,查询需要完全不同,具体取决于您是否模拟准备。

答案 1 :(得分:0)

如果我没弄错的话,语法应该是:

$stmt->bindValue(':bit_col', $_POST['bit_col']);

引用:bit_col:

$stmt = $dbh->prepare("UPDATE tablename SET bit_col = :bit_col ");