Подготовленное PDO заявление, похоже, игнорирует предложение HAVING - PullRequest
0 голосов
/ 18 февраля 2019

Я включил DB-скрипку, и вы можете настроить входной параметр соответственно .Это возвращает то, что я ожидал, и отличается от результатов, которые я вижу в PDO.

У меня есть следующие минимизированные табличное представление и запрос:

CREATE TABLE `tagged` {
    `tag` SMALLINT(5) UNSIGNED NOT NULL
}

Таблица имеет ассортиментзначений, но вы можете использовать 1-10 для тегов в БД:

INSERT INTO tagged (tag) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)

запрос:

SELECT tagged.tag,
    (@t := :tag),
    @t AS temp_var,
    (@t IS NULL OR FIND_IN_SET(tagged.tag, @t) > 0) AS is_match
FROM tagged
HAVING is_match = 1
LIMIT 150

Это хорошо работает при запуске в клиенте, командной строке,jdbc и т. д. Если ввести значение '' или NULL, я получу все результаты.Аналогичным образом, ввод '1' дает только теги 1, а ввод '1,4' извлекает все теги с 1 или 4.

Способ, которым запрос ограничивает эти результаты, заключается в is_match = 1в предложении HAVING.При запуске с PDO параметр, кажется, связывается правильно, но он полностью игнорирует условие в предложении:

Array
(
    [0] => stdClass Object
        (
            [tag] => 3
            [(@t := ?)] => 1,4
            [temp_var] => 1,4
            [is_match] => 0               ## this should not have been returned
        )

    [1] => stdClass Object
        (
            [tag] => 4
            [(@t := ?)] => 1,4
            [temp_var] => 1,4
            [is_match] => 1
        )

PHP-код, используемый для запуска этого (упрощенно):

$conn = /* pdo connection object */;
$stmt = $conn->prepare(DB::queryOf('test')); //uses our above query from a file
$stmt->bindValue(':tag', $args['tag'], PDO::PARAM_STR); //hardcode binding '1,4'
$stmt->execute(); //also tried plain #execute($args)
return $stmt->fetchAll(PDO::FETCH_OBJ);

Isтам что-то мне не хватает?Я связываю прямой строковый параметр, и кажется, что временная переменная там и установлена ​​правильно.Почему PDO возвращает результаты для элементов, где is_match = 0?

1 Ответ

0 голосов
/ 18 февраля 2019

Я полагаю, что это поведение зависит от используемой СУБД.

В отсутствие предложения GROUP BY кажется, что при некоторых обстоятельствах весь результат можно рассматривать как "одну группу".Поскольку одна строка в результатах удовлетворяет условию HAVING, все должны пройти.

Дополнительное чтение:

Использование HAVING без GROUP BY в запросах SQL

ИМЕЯ без GROUP BY

ps Я не думаю, что > 0 необходим.

Полагаю, я бы написал ваш запрос примерно так:

SELECT tag,
    @t := '1,4' AS temp_var,
    1 AS is_match
FROM tagged
WHERE @t IS NULL OR FIND_IN_SET(tag, @t)
LIMIT 150;
...