Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php PDO准备语句:获取NULL而不是预期结果_Php_Pdo_Mariadb_Prepared Statement - Fatal编程技术网

Php PDO准备语句:获取NULL而不是预期结果

Php PDO准备语句:获取NULL而不是预期结果,php,pdo,mariadb,prepared-statement,Php,Pdo,Mariadb,Prepared Statement,我不明白这个问题。我在PHP中有一个SQL查询。如果我通过PDO和prepared语句启动查询,但没有占位符,我会得到预期的结果。但是查询中的产品ID来自外部,因此我将用一个占位符替换它:productID。如果我这样做,结果会得到NULL SQL查询: SELECT COUNT(`stock`.`product`) AS COUNT, `product`.`name_en` AS NAME, `product`.`default_consumption` AS `DEFAULT_CONSUM

我不明白这个问题。我在PHP中有一个SQL查询。如果我通过PDO和prepared语句启动查询,但没有占位符,我会得到预期的结果。但是查询中的产品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
如果在数据库表(例如1)中用有效ID替换占位符:productId,则会得到预期结果

$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"
}
array(3) {
  ["COUNT"]=>
  string(1) "0"
  ["NAME"]=>
  NULL
  ["DEFAULT_CONSUM"]=>
  NULL
}
现在我将替换它:

$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"]=>
  string(6) "butter"
  ["DEFAULT_CONSUM"]=>
  string(3) "0.1"
}
array(3) {
  ["COUNT"]=>
  string(1) "0"
  ["NAME"]=>
  NULL
  ["DEFAULT_CONSUM"]=>
  NULL
}
$productId是来自外部的值。在我的测试中,我将其设置为1,就像在我的第一个示例中一样。我为to字段
DEFAULT\u CONSUM
name
如果我在execute()中直接设置ID 1:

我又得到空值。如果我将查询中的:productId再次替换为直接ID 1,我将再次得到指定的结果。我现在不明白这个问题

我使用PHP8.0和MariaDB。上面的代码在一个单独的函数中运行。目前没有执行其他代码

谢谢你的帮助。我肯定,我忽略了一些东西

创建表格

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优化器中发现了一个bug。请在方便的时候尽早向他们提交错误报告

该问题与PDO无关。您看到不同结果的原因是PDO默认将所有值绑定为字符串。当您将其绑定为字符串时,
WHERE
子句中的比较将正确计算。当您将值强制转换为整数或使用文字1时,优化器会将其与
product.id
进行比较,而不是与
stock.product
进行比较。不太确定这里内部发生了什么,但很明显,当使用整数时,行为是错误的。您可以继续询问,看看是否有人对这种行为有解释,但最有可能的是,这需要由MariaDB团队作为一个bug来解决


如果将其写成
其中product='1'
,它会返回什么结果?@yourcomsense我得到的结果为空。我尝试了intval():
$query->execute(数组(':productId'=>intval($productId))
No,change。那么字符串值不匹配的情况非常罕见。然后您需要在execute中使用bindValue而不是数组。虽然我仍然觉得你的第一个观察结果不正确,但这个例子说明了一切。有些人说,使用错误的数据类型提供数据会产生错误的结果。但直到今天我才在野外看到它。将数组发送到execute显式地将值绑定为字符串,使其成为
'1'
。因此,您的问题是为什么
其中product=1
给出结果而
其中product='1'
不给出结果。您可以在一些与数据库相关的堆栈交换站点上问这个问题。如果你愿意,请在这里分享一个链接,我对这个问题非常感兴趣