PDO 准备语句:获取 NULL 而不是预期的结果
PDO Prepared Statement: Fetch NULL instead of the expected Result
我不明白这个问题。我在 PHP 中有一个 SQL 查询。如果我通过 PDO 和准备好的语句触发查询,但没有占位符,我会得到预期的结果。但查询中的产品 ID 来自外部,因此我将其替换为占位符:productID。如果我这样做,结果会得到 NULL。
SQL 查询:
SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = :productId
如果我用数据库中的有效 ID 替换占位符 :productId table(例如 1),我会得到预期的结果。
$query = "SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = 1";
$query = $this->db->prepare($query);
$query->execute();
$response = $query->fetch(PDO::FETCH_ASSOC);
var_dump($response);
输出
array(3) {
["COUNT"]=>
string(1) "0"
["NAME"]=>
string(6) "butter"
["DEFAULT_CONSUM"]=>
string(3) "0.1"
}
现在我将替换它:
$query = "SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = :productId";
$query = $this->db->prepare($query);
$query->execute(array(':productId' => $productId));
$response = $query->fetch(PDO::FETCH_ASSOC);
var_dump($response);
输出
array(3) {
["COUNT"]=>
string(1) "0"
["NAME"]=>
NULL
["DEFAULT_CONSUM"]=>
NULL
}
$productId 是来自外部的值。在我的测试中,我将它设置为 1,就像在我的第一个示例中一样。我得到了 to 字段 DEFAULT_CONSUM
和 name
的结果 NULL
如果我直接在 execute() 中设置 ID 1:
$query->execute(array(':productId' => 1));
我又得到了NULL。如果我再次将查询中的 :productId 替换为直接 ID 1,我将再次获得预期的结果。我现在没明白问题。
我使用 PHP 8.0 和 MariaDB。上面的代码在一个单独的函数中运行。目前没有执行其他代码。
感谢您的帮助。我确定,我忽略了一些东西。
创建TABLE
CREATE TABLE`product`(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID of the Product',
`name_en` VARCHAR(255) NOT NULL COMMENT 'Name of the Product in Englisch',
`name_de` VARCHAR(255) NULL COMMENT 'Name of the Product in German',
`name_fr` VARCHAR(255) NULL COMMENT 'Name of the Product in France',
`group` INT(10) UNSIGNED NULL DEFAULT 1 COMMENT 'ID of the Product Group',
`unit` INT(10) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Id of the Unit',
`default_consumption` FLOAT(10) UNSIGNED NOT NULL DEFAULT 0.5 COMMENT 'Value for Default Consumption',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp of creation Time',
`changed_at` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestamp of changed',
`deleted_at` TIMESTAMP NULL COMMENT 'Timestamp of deleted',
PRIMARY KEY(`id`),
INDEX `product_name_en_idx`(`name_en`),
INDEX `product_name_de_idx`(`name_de`),
INDEX `product_name_fr_idx`(`name_fr`),
INDEX `product_group_idx`(`group`),
CONSTRAINT `product_group_fk`
FOREIGN KEY(`group`)
REFERENCES `product_group`(`id`)
ON UPDATE CASCADE
ON DELETE SET NULL,
CONSTRAINT `product_unit_fk`
FOREIGN KEY(`unit`)
REFERENCES `unit`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;
CREATE TABLE `stock`(
`product` INT(10) UNSIGNED NOT NULL COMMENT 'ID of the Product',
`user` INT(10) UNSIGNED NOT NULL COMMENT 'ID of the User',
`stock` FLOAT(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Stock Value',
`individual_consumption` FLOAT(10) UNSIGNED NULL COMMENT 'Individual Consumption Value',
`ki_value` FLOAT(10) UNSIGNED NULL DEFAULT 0.000 COMMENT 'KI Up Down Value',
`last_buy` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestmap of last Buy',
INDEX `stock_product_idx`(`product`),
INDEX `stock_user_idx`(`user`),
CONSTRAINT `stock_product_fk`
FOREIGN KEY(`product`)
REFERENCES `product`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT `stock_user_fk`
FOREIGN KEY(`user`)
REFERENCES `user`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;
您似乎发现了 MariaDB SQL 优化器的错误。请尽早向他们提交错误报告。
该问题与 PDO 无关。您看到不同结果的原因是 PDO 默认将所有值绑定为字符串。当您将其绑定为字符串时, WHERE
子句中的比较会被正确评估。当您将值转换为整数或使用文字 1 时,优化器会将其与 product.id
而不是 stock.product
进行比较。不太确定这里内部发生了什么,但显然使用整数时行为是错误的。您可以在 https://dba.stackexchange.com/ 上提问,看看是否有人对此行为有解释,但很可能这需要由 MariaDB 团队作为错误解决。
我不明白这个问题。我在 PHP 中有一个 SQL 查询。如果我通过 PDO 和准备好的语句触发查询,但没有占位符,我会得到预期的结果。但查询中的产品 ID 来自外部,因此我将其替换为占位符:productID。如果我这样做,结果会得到 NULL。
SQL 查询:
SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = :productId
如果我用数据库中的有效 ID 替换占位符 :productId table(例如 1),我会得到预期的结果。
$query = "SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = 1";
$query = $this->db->prepare($query);
$query->execute();
$response = $query->fetch(PDO::FETCH_ASSOC);
var_dump($response);
输出
array(3) {
["COUNT"]=>
string(1) "0"
["NAME"]=>
string(6) "butter"
["DEFAULT_CONSUM"]=>
string(3) "0.1"
}
现在我将替换它:
$query = "SELECT
COUNT(`stock`.`product`) AS COUNT,
`product`.`name_en` AS NAME,
`product`.`default_consumption` AS `DEFAULT_CONSUM`
FROM `stock`
RIGHT JOIN `product`
ON `stock`.`product` = `product`.`id`
WHERE `product` = :productId";
$query = $this->db->prepare($query);
$query->execute(array(':productId' => $productId));
$response = $query->fetch(PDO::FETCH_ASSOC);
var_dump($response);
输出
array(3) {
["COUNT"]=>
string(1) "0"
["NAME"]=>
NULL
["DEFAULT_CONSUM"]=>
NULL
}
$productId 是来自外部的值。在我的测试中,我将它设置为 1,就像在我的第一个示例中一样。我得到了 to 字段 DEFAULT_CONSUM
和 name
的结果 NULL
如果我直接在 execute() 中设置 ID 1:
$query->execute(array(':productId' => 1));
我又得到了NULL。如果我再次将查询中的 :productId 替换为直接 ID 1,我将再次获得预期的结果。我现在没明白问题。
我使用 PHP 8.0 和 MariaDB。上面的代码在一个单独的函数中运行。目前没有执行其他代码。
感谢您的帮助。我确定,我忽略了一些东西。
创建TABLE
CREATE TABLE`product`(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID of the Product',
`name_en` VARCHAR(255) NOT NULL COMMENT 'Name of the Product in Englisch',
`name_de` VARCHAR(255) NULL COMMENT 'Name of the Product in German',
`name_fr` VARCHAR(255) NULL COMMENT 'Name of the Product in France',
`group` INT(10) UNSIGNED NULL DEFAULT 1 COMMENT 'ID of the Product Group',
`unit` INT(10) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Id of the Unit',
`default_consumption` FLOAT(10) UNSIGNED NOT NULL DEFAULT 0.5 COMMENT 'Value for Default Consumption',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp of creation Time',
`changed_at` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestamp of changed',
`deleted_at` TIMESTAMP NULL COMMENT 'Timestamp of deleted',
PRIMARY KEY(`id`),
INDEX `product_name_en_idx`(`name_en`),
INDEX `product_name_de_idx`(`name_de`),
INDEX `product_name_fr_idx`(`name_fr`),
INDEX `product_group_idx`(`group`),
CONSTRAINT `product_group_fk`
FOREIGN KEY(`group`)
REFERENCES `product_group`(`id`)
ON UPDATE CASCADE
ON DELETE SET NULL,
CONSTRAINT `product_unit_fk`
FOREIGN KEY(`unit`)
REFERENCES `unit`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;
CREATE TABLE `stock`(
`product` INT(10) UNSIGNED NOT NULL COMMENT 'ID of the Product',
`user` INT(10) UNSIGNED NOT NULL COMMENT 'ID of the User',
`stock` FLOAT(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Stock Value',
`individual_consumption` FLOAT(10) UNSIGNED NULL COMMENT 'Individual Consumption Value',
`ki_value` FLOAT(10) UNSIGNED NULL DEFAULT 0.000 COMMENT 'KI Up Down Value',
`last_buy` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestmap of last Buy',
INDEX `stock_product_idx`(`product`),
INDEX `stock_user_idx`(`user`),
CONSTRAINT `stock_product_fk`
FOREIGN KEY(`product`)
REFERENCES `product`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT `stock_user_fk`
FOREIGN KEY(`user`)
REFERENCES `user`(`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;
您似乎发现了 MariaDB SQL 优化器的错误。请尽早向他们提交错误报告。
该问题与 PDO 无关。您看到不同结果的原因是 PDO 默认将所有值绑定为字符串。当您将其绑定为字符串时, WHERE
子句中的比较会被正确评估。当您将值转换为整数或使用文字 1 时,优化器会将其与 product.id
而不是 stock.product
进行比较。不太确定这里内部发生了什么,但显然使用整数时行为是错误的。您可以在 https://dba.stackexchange.com/ 上提问,看看是否有人对此行为有解释,但很可能这需要由 MariaDB 团队作为错误解决。