source

PDO 준비 스테이트먼트:예상된 결과 대신 NULL 가져오기

gigabyte 2022. 12. 8. 21:21
반응형

PDO 준비 스테이트먼트:예상된 결과 대신 NULL 가져오기

문제가 뭔지 모르겠어요PHP에 SQL 쿼리가 있습니다.PDO를 통해 쿼리를 실행하고 스테이트먼트를 준비했지만 플레이스홀더 없이 원하는 결과를 얻을 수 있습니다.단, 문의의 제품 ID는 외부에서 온 것이므로 플레이스 홀더: product로 대체하겠습니다.아이디. 이렇게 하면 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

플레이스홀더:productId를 데이터베이스 테이블 내의 유효한 ID(예를 들어 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로 설정합니다.종료 필드에 대해 NULL 결과를 가져옵니다.DEFAULT_CONSUM그리고.nameexecute()에서 ID 1을 직접 설정한 경우:

$query->execute(array(':productId' => 1));

NULL이 다시 나옵니다.쿼리의 :productId를 다시 다이렉트 ID 1로 치환하면 다시 예상된 결과가 나타납니다.지금은 문제가 뭔지 모르겠어요.

저는 PHP 8.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 Optimizer에서 버그를 발견한 것 같습니다.가능한 한 빨리 버그 리포트를 제출해 주세요.

이 문제는 PDO와 관련이 없다.다른 결과가 표시되는 이유는 PDO가 기본적으로 모든 값을 문자열로 바인딩하기 때문입니다.스트링으로 바인드하면의 비교가 표시됩니다.WHERE절이 적절하게 평가됩니다.값을 정수로 캐스트하거나 리터럴1 을 사용하면 옵티마이저는 이 값을product.id대신stock.product내부에서 무슨 일이 일어나고 있는지는 잘 모르겠지만, 정수를 사용할 때의 동작은 잘못된 것이 분명합니다.https://dba.stackexchange.com/에서 이 동작에 대한 설명을 듣고 있는지 확인할 수 있지만, 대부분의 경우 MariaDB 팀은 버그로 이 문제를 해결해야 합니다.

다음은 이 버그를 온라인으로 재현할 수 있는 버전입니다.

언급URL : https://stackoverflow.com/questions/66761136/pdo-prepared-statement-fetch-null-instead-of-the-expected-result

반응형