2011-08-16 7 views
7
$stmt = $dbh->prepare('SELECT id, name FROM folders WHERE parent_folder_id = :id'); 
$stmt->bindValue(':id', $folder_id, PDO::PARAM_INT); 

Mam powyższy kod. Jeśli folder ma parent_folder_id, oznacza to, że znajduje się w innym folderze. Jeśli ta kolumna ma wartość NULL, oznacza to, że jest to folder główny.Jak powiązać wartość, jeśli chcę, aby akceptowała zarówno INT, jak i NULL z PDO?

Z mojego rozumienia, jeśli $ folder_id ma wartość NULL, wówczas będzie traktować go jako 0 (więc nie otrzymam wyników z kodem, ponieważ jest on wartością w tej kolumnie jest NULL, a nie 0). Jeśli zmienię trzeci argument na PDO :: PARAM_NULL, nadal nie otrzymam wyników. Sądzę, że dzieje się tak dlatego, że zapytanie to "WHERE parent_folder_id = NULL", które nie jest takie samo jak "WHERE parent_folder_id ma wartość NULL".

Czy istnieje sposób, aby PDO traktować to poprawnie, czy powinienem utworzyć moją instrukcję SQL z wbudowanym, jeśli chcesz zmienić "=" z "jest" i zamienić trzeci parametr bindValue na poprawny?

Odpowiedz

6

Jeśli używasz MySQL, możesz użyć niestandardowego NULL-safe equal operator <=>, który może porównywać wartość null lub wartości inne niż null.

$stmt = $dbh->prepare('SELECT id, name FROM folders WHERE parent_folder_id <=> :id'); 
$stmt->bindValue(':id', $folder_id, PDO::PARAM_INT); 

Ten operator zwraca zawsze prawdziwe lub fałszywe, nie NULL, czyli to, co można dostać, jeśli starają się porównać do niczego równa NULL z =.

ANSI SQL definiuje predykat IS [NOT] DISTINCT FROM, który działa podobnie, ale nie jest obsługiwany przez wszystkich dostawców (jeszcze).

+2

Dzięki! To sprawiło, że nauczyłeś mnie czegoś, nigdy wcześniej nie używałem <=> (yikes, trochę na imprezę, co?). Uratuje mnie to wiele bólów głowy w przyszłości, to na pewno :) – Gazillion

0

Może to?

<?php 
    $stmt = $dbh->prepare('SELECT id, name FROM folders WHERE parent_folder_id = :id'); 
    if (is_null($folder_id)) { 
    $stmt->bindParam(':id',null, PDO::PARAM_NULL); 
    } else { 
    $stmt->bindParam(':id', $folder_id, PDO::PARAM_INT); 
    } 

nie testowano chociaż

EDIT:

więcej coś takiego:

<?php 
    if (is_null($folder_id)) {  
     $stmt = $dbh->prepare('SELECT id, name FROM folders WHERE parent_folder_id IS NULL'); 
    } else { 
     $stmt = $dbh->prepare('SELECT id, name FROM folders WHERE parent_folder_id = :id'); 
     $stmt->bindParam(':id', $folder_id, PDO::PARAM_INT); 
    } 

wiem, że to nie jest optymalne, ale PDO jest nadal buggy ...

+0

To nie rozwiązuje problemu, że nie otrzymuję wyników, ponieważ jeśli jest NULL, musiałbym zamiast tego zmienić sposób przygotowania zapytania sql. Wiem, jak bym to zrobił, gdyby tak było (z inline-if), ale mam wrażenie, że PDO jest prawdopodobnie na tyle sprytny, aby zmienić to dla mnie i po prostu nie wiem jak. – Gazillion

+0

Nie ufaj za dużo PDO: główny opiekun opuścił około 2 lata temu, a projekt od tego czasu jest dość opóźniony. –

+0

Dzięki, będę o tym pamiętać :) – Gazillion

2

Można użyć NULL-safe equal operator, <=>. Jeśli kiedykolwiek zmienisz bazę danych na inną i chcesz zaktualizować zapytanie, niektóre z nich mają numer NOT DISTINCT FROM, który dotyczy mniej więcej tej samej rzeczy.

+0

Niestety, nie widziałem odpowiedzi Billa kiedy ją opublikowałem – shesek

+0

Dzięki, była to właściwa odpowiedź, ale byłaś zbyt powolna (o kilka sekund hehehe)! ;) – Gazillion

Powiązane problemy