Home > Enterprise >  php PDO fetch zero results for SQL Server
php PDO fetch zero results for SQL Server

Time:03-11

I have the following bit of code that fetches results from a query.

$sql =
"
    SELECT 1 AS bar
    FROM outsource.prodgroup_division
    WHERE
    (
        CASE
            WHEN :division = 'ALL'                       THEN 1
            WHEN prodgroup_division.division = :division THEN 1
                                                         ELSE 0
        END
    ) = 1
";
$stmt = $dw_db->prepare($sql);
$stmt->bindParam(':division', $division, 2); // 2 for strings
$stmt->execute();
$rows = $stmt->fetchAll();
$stmt->closeCursor();

My division parameter is set to 'ALL'. When I run it without the parameters and hardcode in 'ALL' it gives me 22 rows. Why am I getting zero data in my $rows array?

CodePudding user response:

I am not sure why, maybe someone can help me understand. When I changed the syntax from named parameters to the following it worked.

$sql =
"
    SELECT 1 AS bar
    FROM outsource.prodgroup_division
    WHERE
    (
        CASE
            WHEN 'ALL'                    LIKE ? THEN 1
            WHEN prodgroup_division.division = ? THEN 1
                                                 ELSE 0
        END
    ) = 1
";
$stmt = $dw_db->prepare($sql);
$stmt->bindValue(1, $division); // 2 for strings
$stmt->bindValue(2, $division); // 2 for strings
$stmt->execute();
$rows = $stmt->fetchAll();
$stmt->closeCursor();

CodePudding user response:

I'm not sure why you got zero results rather than an error (possibly you have PDO set to an unhelpful error mode?), but I believe the problem is that bound parameters can only be used once, even if you use named parameter syntax.

You can either give each one a distinct name, and bind the same value to both:

$sql =
"
    SELECT 1 AS bar
    FROM outsource.prodgroup_division
    WHERE
    (
        CASE
            WHEN :division1 = 'ALL'                       THEN 1
            WHEN prodgroup_division.division = :division2 THEN 1
                                                          ELSE 0
        END
    ) = 1
";
$stmt = $dw_db->prepare($sql);
$stmt->bindParam(':division1', $division, \PDO::PARAM_STR);
$stmt->bindParam(':division2', $division, \PDO::PARAM_STR);

(Switching to positional parameters works for the same reason - you've bound the same value to multiple placeholders, rather than trying to reuse one.)

Or you can use the bound parameter to populate a Transact-SQL variable, and use that in the query:

$sql =
"
    DECLARE @division INT = :division

    SELECT 1 AS bar
    FROM outsource.prodgroup_division
    WHERE
    (
        CASE
            WHEN @division = 'ALL'                       THEN 1
            WHEN prodgroup_division.division = @division THEN 1
                                                         ELSE 0
        END
    ) = 1
";
$stmt = $dw_db->prepare($sql);
$stmt->bindParam(':division', $division, \PDO::PARAM_STR);

(Side note: I've used the provided constant \PDO::PARAM_STR rather than the magic number 2, as recommended in the manual.)

  • Related