PDO kullanarak NULL değerleri nasıl eklerim?


105

Bu kodu kullanıyorum ve hayal kırıklığının ötesine geçiyorum:

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, '', hepsi başarısız olur ve şu hatayı atar:

Önemli hata : Parametre 2, / opt / ... içinde referansla geçirilemiyor

Yanıtlar:


138

Sadece PDO öğreniyorum ama bence kullanman gerek bindValue, değilbindParam

bindParamreferans almak için bir değişkeni alır ve arama anında bir değer çekmez bindParam. Bunu php belgelerinde bir yorumda buldum:

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

DÜZENLEME: Not: Bunu yapmak isteyebilirsiniz, bindValue(':param', null, PDO::PARAM_NULL);ancak herkes için işe yaramadı (rapor ettiğiniz için teşekkür ederim Will Shaver.)


Bu ikisi arasındaki farktan emin değilim, ama bazılarını araştıracağım. Teşekkürler, cevabınız da harikaydı.
Nacho 08

3
Sanırım bu benimkinden daha iyi bir cevap olabilir (eğer gerçekten işe yararsa)
Joe Phillips

2
MySql 5.1.53 üzerinde PDO :: PARAM_NULL ile sorun yaşadım, ancak boş değerli PDO :: PARAM_INT harika çalıştı.
Will Shaver

2
Odin: Bence en önemli kısım üç parametreyi de geçmek :). ign'in sorusunda, PDO :: PARAM_NULL'u tip olarak değil, değer olarak geçiyordu (ve bir tür geçmiyordu)
JasonWoof

1
Bilginize: Çoğu durumda bindValue()over kullanmakta tamamen sorun yoktur bindParam(); her şey için, sadece NULLdeğer için değil . Parametreyi bir PHP değişkeninin referansına bağlamanız gereken tek bir durum düşünemiyorum - ama ne işe bindParam()yarıyor.
low_rents

48

Kullanırken bindParam()bir sabit değil, bir değişkeni iletmelisiniz. Yani bu satırdan önce bir değişken oluşturmanız ve bunu şu şekilde ayarlamanız gerekir:null

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

Eğer deneseydiniz aynı hata mesajını alırsınız:

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

Bunu doğru anladınız, bunu daha önce kodumda yaptığımı fark ettim, $ null = PDO :: PARAM_NULL; Teşekkürler.
Nacho 08

1
Yine de yer tutucular yapacaksanız, bu durumda bindValue () kullanmak daha iyidir. bindParam () başlangıçta bir sorgu yürütmek ve ardından değişkenleri değiştirmek ve parametreleri yeniden bağlamadan yeniden yürütmek için tasarlanmıştır. bindValue () hemen bağlanır, bindParam () yalnızca çalıştırıldığında.
Hugo Zink

1
$ MyNull = null satırında null değerinin küçük harf olması gerektiğini buldum. $ myNull = NULL çalışmadı.
raphael75

28

MySQL'de INTEGERsütunları (bu olabilir NULL) kullanırken , PDO'nun bazı (bana göre) beklenmedik davranışları vardır.

Eğer kullanırsanız $stmt->execute(Array), değişmezi belirtmeniz gerekir NULLve NULLdeğişken referansı ile veremezsiniz . Yani bu işe yaramayacak:

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

Ama bu işe yarayacak:

// $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

Bunu MySQL 5.5.15'te PHP 5.4.1 ile denedim


1
$ stmt-> execute (array (': param' =>! empty ($ val)? $ val: null)); Boş dizge için veritabanında boş değeri de ayarlamak isteyeceğiniz için!
Empty kullanın

1
@ShehzadNizamani Yalnızca sütun türü tamsayı ise, örneğindeki gibi, evet. Ancak bunun dışında isset()daha iyi bir ilişki vardır NULL. Boş bir dizge de bir değerdir.
StanE

8

Hala problem yaşayanlar için (parametre 2'ye referansla geçilemiyor), boş değerli bir değişken tanımlayın, sadece boş değeri PDO'ya iletmeyin:

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

Bu yardımcı olur umarım.


6

Aynı sorunu yaşadım ve bu çözümü bindParam ile çalışırken buldum:

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

3

Eklemek istediğiniz takdirde NULLsadece valuebir emptyveya ''ancak insert valuekullanılabilir olduğunda.

A) POST yöntemini kullanarak form verilerini alır ve bu değerlerle işlev insert'i çağırır.

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

B) Bir alanın kullanıcı tarafından doldurulup doldurulmadığını değerlendirir NULLve durum buysa ekler .

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();      
}

Örneğin, kullanıcı productNameform alanına hiçbir şey girmezse , o $productNamezaman SETancak olacaktır EMPTY. Öyleyse, olup olmadığını kontrol etmeniz empty()ve eğer öyleyse, eklemeniz gerekir NULL.

PHP 5.5.17'de test edildi

İyi şanslar,


3
Veya, IFNULL()sorgu dizesinde MySQL'in işlevini kullanabilirsiniz . Bunun gibi:$sql = "INSERT INTO products ( productId, productName ), VALUES ( IFNULL(:productId, NULL), IFNULL(:productName, NULL) )";
starleaf1

Çözümünüzün temizliği hoşuma gitti. Sadece test ettim, ancak ne yazık ki kullanıcı girişe hiçbir şey yazmadığında NULL yerine boş dizeler ekliyor. Bu sadece bir tercih meselesi, ama boş dizeler yerine NULL'ları tercih ederim.
Arian Acosta

0

Bunu dene.

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

1
Bu kadar eski bir soruyu cevaplamaya çalışmadan önce, önce diğer cevapları okumalısınız. Zaten cevaplanmış olabilir.
Sağduyu

0

Diğer yanıtlara dayanarak, ancak bu çözümün nasıl kullanılacağına dair biraz daha net.

Örneğin, bir zaman değeri için boş bir dizeniz varsa, ancak bunu boş olarak kaydetmek istiyorsanız:

  if($endtime == ""){
    $db->bind(":endtime",$endtime=NULL,PDO::PARAM_STR);
  }else{
    $db->bind("endtime",$endtime);
  }

Zamanlar dizeler olarak saklandığından, zaman değerleri için PARAM_STR kullanacağınıza dikkat edin.


-1

Benim durumumda kullanıyorum:

  • SQLite,

  • bilinmeyen sayıda alanı işlemek için yer tutucularla hazırlanmış ifadeler,

  • Her şeyin bir dizge olduğu ve NULLdeğer gibi bir şeyin olmadığı kullanıcı tarafından gönderilen AJAX isteği

  • Yabancı anahtar kısıtlamalarını (kabul edilebilir değer) NULLihlal etmediği için umutsuzca s eklemem gerekiyor .

Diyelim ki, şimdi kullanıcı post: boş dize veya veya olabilen $_POST[field1]değerle gönderiyor .value1"""null""NULL"

Önce şu açıklamayı yapıyorum:

$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");

{$sColumns}sth nerede field1, field2, ...ve {$sValues}benim yer tutucular ?, ?, ....

Sonra, benim toplamak $_POSTbir dizideki sütun adları ile ilgili verileri $values ve ile değiştirin NULLs:

  for($i = 0; $i < \count($values); $i++)
     if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
        $values[$i] = null;

Şimdi çalıştırabilirim:

$stmt->execute($values);

ve diğer yabancı anahtar kısıtlamalarının atlanması.

Öte yandan, boş bir dizge daha mantıklıysa, o alanın bir yabancı anahtarın parçası olup olmadığını kontrol etmeniz gerekir (daha karmaşık).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.