PDO IN deyimini MySQL için değerleri bağlama

6 Cevap php

Ben gerçekten uzun bir süre için onun tarafından boğulmuş sonra bir cevap almak istiyorum PDO ile bir sorunu var.

Bu örneği ele alalım:

Ben MySQL IN deyimi kullanmak için bir PDO açıklamaya kimlikleri bir dizi bağlayıcı ediyorum.

Dizi söylemek olacaktır: $values = array(1,2,3,4,5,6,7,8);

Veritabanı güvenli değişken $products = implode(',' $values); olurdu

'1,2,3,4,5,6,7,8', So, $products sonra bir değeri olan bir STRING olur

Deyimi gibi görünecektir:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)

Tabii ki, $products :products olarak ifadesine bağlı olacaktır.

Deyim derlenmiş ve değerler bağlı olduğunda Ancak, aslında bu gibi görünecektir:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN ('1,2,3,4,5,6,7,8')

Sorun ben açıklamaya bağlamak için virgülle ayrılmış değerler olarak hazırlanmış ki verilen, tek bir dize olarak IN deyimi içindeki her şeyi yürütülüyor olmasıdır.

Ne gerçekten ihtiyacınız olduğunu:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (1,2,3,4,5,6,7,8)

Ben gerçekten bunu tek yolu, ancak ben bazı için bunu yapmak için daha kolay bir yolu olmalı olduğunu biliyorum, onları bağlayıcı olmadan dize kendi içinde değerlerini yerleştirerek gereğidir.

Ben tamamen burada işareti eksik olmalı ve ben cevap ne olduğunu görünce kendimi tekme gidiyorum biliyorum!

Şimdiden teşekkürler.

6 Cevap

Bu durumun üstesinden gelmek için iyi bir yol str_pad to place a ? SQL sorgusunda her değer için kullanmaktır. Sonra çalıştırmak için argüman olarak (sizin durumda $values) değerler dizisi iletebilirsiniz:

$sql = '
SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products.id IN ('.str_pad('',count($values)*2-1,'?,').')
';

$sth = $dbh->prepare($sql);
$sth->execute($values);
$user_ids = $sth->fetchAll();

Eğer hazırlanmış deyimleri kullanmak yerine SQL doğrudan değerleri ekleme daha çok fayda bu şekilde.

PS - Sonuçlar yinelenen kullanıcı kimlikleri dönecektir eğer verilen kimlikleri payı kullanıcı kimlikleri ile ürünleri. Sadece benzersiz kullanıcı kimlikleri isterseniz ben SELECT DISTINCT users.id için sorgunun ilk satırını değiştirerek öneririz

Muhtemelen bu gibi bir durum ile gelebilir iyi hazırlanmış deyimi aşağıdaki benzeyen bir şeydir:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (?,?,?,?,?,?,?,?)

Eğer değerler döngü sonra olur ve bağlayıcıdır değerleri gibi soru işaretleriyle aynı vardır emin hazırlanan açıklamaya onları bağlamak.

Ifadesi bindValue () ile değerleri bağlama olmadan kullanıcı girişi dayalı ise, deneysel SQL harika bir seçim olmayabilir. But, sen MySQL Regexp ile giriş sözdizimi kontrol ederek güvenli yapabilirsiniz.

Örneğin:

SELECT *
FROM table
WHERE id IN (3,156)
AND '3,156' REGEXP '^([[:digit:]]+,?)+$'

You can do so very easily. If you have an array of values for your IN() statement EG:

$test = array(1,2,3);

Sen basitçe yapabilirsiniz

$test = array(1,2,3);
$values = count($test);
$criteria = sprintf("?%s", str_repeat(",?", ($values ? $values-1 : 0)));
//Returns ?,?,?
$sql = sprintf("DELETE FROM table where column NOT IN(%s)", $criteria);
//Returns DELETE FROM table where column NOT IN(?,?,?)
$pdo->sth = prepare($sql);
$pdo->sth->execute($test);

İşte bir insert değerlere rekor sütun sayısı bilinmeyen bağlayıcı bir örnektir.

public function insert($table, array $data)
{
    $sql = "INSERT INTO $table (" . join(',', array_keys($data)) . ') VALUES ('
        . str_repeat('?,', count($data) - 1). '?)';

    if($sth = $this->db->prepare($sql))
    {
        $sth->execute(array_values($data));
        return $this->db->lastInsertId();
    }
}

$id = $db->insert('user', array('name' => 'Bob', 'email' => 'foo@example.com'));