2009-09-08 7 views
90

Używam tego kodu i jestem poza frustracją:Jak wstawić wartości NULL przy użyciu PDO?

try { 
    $dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS); 
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'"); 
} 
catch(PDOException $e) 
{ 
    ... 
} 
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)'); 
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem 

PDO::PARAM_NULL, null, '', wszystkie z nich nie i wyrzucić ten błąd:

Fatal error: Cannot pass parameter 2 by reference in /opt/...

Odpowiedz

116

Właśnie uczę PDO, ale myślę, trzeba użyć bindValue, nie bindParam

bindParam pobiera zmienną, odniesienia, a nie ciągnąć na wartości w momencie wywoływania bindParam. Znalazłem to w komentarzu do dokumentu php:

bindValue(':param', null, PDO::PARAM_INT); 

EDYCJA: P.S. Można pokusić się o to bindValue(':param', null, PDO::PARAM_NULL); zrobić, ale to nie działa dla wszystkich (dziękuję Czy golarka do raportowania.)

+0

Nie jestem pewien różnicy między tymi dwoma, ale zbadam niektóre. Dzięki, twoja odpowiedź też była wspaniała. – Nacho

+3

Myślę, że to może być lepsza odpowiedź niż moja (jeśli rzeczywiście działa) –

+0

moje testy PHP 5.3.8 + Mysql pokazują, że nie ma różnicy w wygenerowanym zapytaniu między tymi dwoma. Wydaje się, że ważną częścią jest przekazywana wartość NULL, a nie "0" lub "0". – Odin

42

Podczas korzystania bindParam() należy zdać w zmiennej, nie stała. Więc przed tą linią trzeba utworzyć zmienną i ustawić go null

$myNull = null; 
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL); 

Można by uzyskać ten sam komunikat o błędzie, jeśli próbowałem:

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL); 
+0

Masz rację, właśnie zdałem sobie sprawę, że zrobiłem to wcześniej w moim kodzie, $ null = PDO :: PARAM_NULL; dzięki. – Nacho

+1

Lepiej używać bindValue() w tym przypadku, jeśli masz zamiar zrobić placeholder. Metoda bindParam() jest pierwotnie przeznaczona do wykonania zapytania, a następnie zmiany zmiennych i ponownego wykonania bez ponownego wiązania parametrów. bindValue() wiąże się natychmiast, bindParam() tylko przy wykonywaniu. –

+0

Znalazłem, że wartość null musi być pisana małymi literami w wierszu $ myNull = null. $ myNull = NULL nie działa. – raphael75

24

Podczas korzystania INTEGER kolumn (które mogą być NULL) w MySQL PDO ma pewne (do mnie) nieoczekiwane zachowanie .

Jeśli używasz $stmt->execute(Array), musisz podać literał NULL i nie można podać NULL przez odniesienie do zmiennej. Więc to nie będzie działać:

// $val is sometimes null, but sometimes an integer 
$stmt->execute(array(
    ':param' => $val 
)); 
// will cause the error 'incorrect integer value' when $val == null 

Ale to będzie działać:

// $val again is sometimes null, but sometimes an integer 
$stmt->execute(array(
    ':param' => isset($val) ? $val : null 
)); 
// no errors, inserts NULL when $val == null, inserts the integer otherwise 

Tried to na MySQL 5.5.15 PHP 5.4.1

+0

$ stmt-> execute (array ( ': param' =>! Empty ($ val)? $ Val: null )); Użyj! Empty, ponieważ dla pustego ciągu powinieneś także ustawić wartość null w bazie danych –

+0

@ShehzadNizamani Tylko jeśli typ kolumny jest liczbą całkowitą, tak jak w jego przykładzie, tak. Ale inaczej 'isset()' koreluje lepiej do 'NULL'. Pusty ciąg jest także wartością. – StanE

5

Dla tych, którzy nadal mają problemy (Nie można przekazać parametru 2 przez odniesienie), zdefiniować zmienną o wartości pustej, a nie tylko przekazać wartość null do PDO:

bindValue(':param', $n = null, PDO::PARAM_INT); 

Mam nadzieję, że to pomoże.

3

Jeśli chcesz wstawić NULL tylko wtedy, gdy value jest empty lub '', ale włóż value gdy jest ona dostępna.

A) Odbiera dane formularza za pomocą metody POST i wywołuje funkcję wstawiania z tymi wartościami.

insert($_POST['productId'], // Will be set to NULL if empty  
     $_POST['productName']); // Will be to NULL if empty         

B) Sprawdza czy pole nie zostało wypełnione przez użytkownika, i wstawia NULL jeśli o to chodzi.

public function insert($productId, $productName) 
{ 
    $sql = "INSERT INTO products ( productId, productName) 
       VALUES (:productId, :productName)"; 

    //IMPORTANT: Repace $db with your PDO instance 
    $query = $db->prepare($sql); 

    //Works with INT, FLOAT, ETC. 
    $query->bindValue(':productId', !empty($productId) ? $productId : NULL, PDO::PARAM_INT); 

    //Works with strings. 
    $query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR); 

    $query->execute();  
} 

Na przykład, jeśli użytkownik nie wejściowego nic na polu formularza productName, następnie $productName będzie SET ale EMPTY. Musisz więc sprawdzić, czy jest to empty(), a jeśli tak, to wstaw NULL.

Testowane na PHP 5.5.17

Powodzenia

+1

Lub możesz użyć funkcji 'IFNULL()' w MySQL w ciągu zapytania. W ten sposób: '$ sql =" INSERT INTO products (productId, productName), VALUES (IFNULL (: productId, NULL), IFNULL (: productName, NULL)) ";' – starleaf1

+0

Podoba mi się czystość rozwiązania. Właśnie go przetestowałem, ale niestety wstawia puste ciągi zamiast NULL, gdy użytkownik nie pisze niczego na wejściu. To tylko kwestia preferencji, ale raczej mam wartości NULL zamiast pustych łańcuchów. –

6

miałem ten sam problem i znalazłem ten roztwór roboczy z bindParam:

bindParam(':param', $myvar = NULL, PDO::PARAM_INT); 
-1

spróbować.

$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null 
+0

Zanim spróbujesz odpowiedzieć na tak stare pytanie, najpierw powinieneś przeczytać inne odpowiedzi. Być może to już zostało wysłuchane. –