MySQL bir değişken boyutu değişken listesi ifadeleri hazırlanmıştır

5 Cevap php

Nasıl her zaman argümanlar farklı sayıda alır PHP hazırlanmış bir MySQL beyanı yazmak istiyorsunuz. Bir örnek, sorgu:

SELECT age, name {FROM [(2)]} WHERE id IN (12, 45, 65, 33)

IN MADDE id yıllardan farklı bir dizi çalıştırmak her zaman var olacaktır.

Aklımda iki olası çözümler var ama daha iyi bir yolu olup olmadığını görmek istiyorum.

Possible Solution 1 deyimi 100 değişkenler kabul ve tablo için garanti kukla değerlerle kalanını doldurun olun, 100'den fazla değerleri için birden fazla görüşme yapmak.

Possible Solution 2 mümkün enjeksiyon saldırıları için sıkı kontrol sorgu oluşturmak ve çalıştırmak, bir hazır deyimi kullanmayın.

5 Cevap

Ben bir çift çözümler düşünebilirsiniz.

Bir çözüm geçici bir tablo oluşturmak için olabilir. Eğer yan tümcesinde olurdu her parametre için tabloya bir ekleme yapmak. Sonra basit bir geçici tabloya karşı katılırım.

Başka bir yöntem böyle bir şey yapmak olabilir.

$dbh=new PDO($dbConnect, $dbUser, $dbPass);
$parms=array(12, 45, 65, 33);
$parmcount=count($parms);   // = 4
$inclause=implode(',',array_fill(0,$parmcount,'?')); // = ?,?,?,?
$sql='SELECT age, name FROM people WHERE id IN (%s)';
$preparesql=sprintf($sql,$inclause);  // = example statement used in the question
$st=$dbh->prepare($preparesql);
$st->execute($parms);

Ben ilk çözüm daha büyük listeleri için iyi olabilir, ve sonra daha küçük listeleri için çalışmak olacağını, sanıyorum, ama kanıt yok.


@ Burada mutlu orrd yapmak için bir veciz sürümüdür.

$dbh=new PDO($dbConnect, $dbUser, $dbPass);
$parms=array(12, 45, 65, 33);
$st=$dbh->prepare(sprintf('SELECT age, name FROM people WHERE id IN (%s)',
                          implode(',',array_fill(0,count($parms),'?')));
$st->execute($parms);

Masadan 2. alınız. Hazırlanan tablolar SQL enjeksiyon karşı kendinizi korumak düşünmelisiniz tek yoldur.

Ne yapabilirsiniz, ancak bağlayıcı değişkenlerin dinamik bir dizi oluşturmak olduğunu. Eğer 7 (veya 103) gerekiyorsa, yani 100 yapmazlar.

Eğer sadece IN fıkrasında tamsayı değerleri kullanarak yapıyorsanız, SQL parametreleri kullanmadan dinamik sorgu oluşturarak karşı savunuyor şey yok.

function convertToInt(&$value, $key)
{
    $value = intval($value);
}

$ids = array('12', '45', '65', '33');
array_walk($ids, 'convertToInt');
$sql = 'SELECT age, name FROM people WHERE id IN (' . implode(', ', $ids) . ')';
// $sql will contain  SELECT age, name FROM people WHERE id IN (12, 45, 65, 33)

Ancak olmadan çözüm here bu sorunun daha genel bir yaklaşım olduğunu sanmıyorum.

Ben bugün bir benzer sorun vardı ve ben bu konuyu buldum. Cevaplara bakarak ve ben güzel bir çözüm bulundu google çevresinde arama.

Rağmen, benim sorunum biraz daha karmaşıktır. Because I have fixed binding values and dynamic too.

Bu, bir çözümdür.

$params = array()
$all_ids = $this->get_all_ids();

for($i = 0; $i <= sizeof($all_ids) - 1; $i++){
    array_push($params, $all_ids[$i]['id']);
}

$clause = implode(',', array_fill(0, count($params), '?')); // output ?, ?, ?
$total_i = implode('', array_fill(0, count($params), 'i')); // output iiii

$types = "ss" . $total_i; // will reproduce : ssiiii ..etc

// %% it's necessary because of sprintf function
$query = $db->prepare(sprintf("SELECT * 
                                FROM clients    
                                WHERE name LIKE CONCAT('%%', ?, '%%') 
                                AND IFNULL(description, '') LIKE CONCAT('%%', ?, '%%')
                                AND id IN (%s)", $clause));

$thearray = array($name, $description);
$merge    = array_merge($thearray, $params); // output: "John", "Cool guy!", 1, 2, 3, 4

// We need  to pass variables instead of values by reference
// So we need a function to that
call_user_func_array('mysqli_stmt_bind_param', array_merge (array($query, $types), $this->makeValuesReferenced($merge))); 

Ve function makeValuesreferenced:

public function makeValuesReferenced($arr){
    $refs = array();
    foreach($arr as $key => $value)
        $refs[$key] = &$arr[$key];
    return $refs;
}

Bu 'know-how' almak için linkler: https://bugs.php.net/bug.php?id=49946, PHP append one array to another (not array_push or +), [PHP]: Error -> Too few arguments in sprintf();, http://no2.php.net/manual/en/mysqli-stmt.bind-param.php#89171, Pass by reference problem with PHP 5.3.1