Posso ligar uma matriz a uma condição IN ()?


562

Estou curioso para saber se é possível vincular uma matriz de valores a um espaço reservado usando o PDO. O caso de uso aqui está tentando passar uma matriz de valores para uso com uma IN()condição.

Eu gostaria de poder fazer algo assim:

<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>

E faça com que o PDO ligue e cite todos os valores na matriz.

No momento eu estou fazendo:

<?php
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
foreach($ids as &$val)
    $val=$db->quote($val); //iterate through array and quote
$in = implode(',',$ids); //create comma separated list
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN('.$in.')'
);
$stmt->execute();
?>

O que certamente faz o trabalho, mas me pergunto se há uma solução embutida que estou faltando?


3
Um guia completo sobre como vincular uma matriz a uma condição IN () , incluindo o caso quando você tiver outros espaços reservados na consulta
— Seu senso comum

A pergunta foi encerrada como uma duplicata desta pergunta . Inverti a flag duplicada porque esta pergunta é 4 anos mais antiga, tem 4 vezes as visualizações, 3 vezes o número de respostas e 12 vezes a pontuação. É claramente o alvo superior.
— miken32 7/03

Qualquer pessoa olhando isso em 2020: você pode tentar o github.com/morris/dop para isso.
— morris4

Respostas:


262

Eu acho que soulmerge está certo. você terá que construir a string de consulta.

<?php
$ids     = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids), '?'));

$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(' . $inQuery . ')'
);

// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();
?>

correção: dan, você estava certo. corrigiu o código (não o testou)

edit: chris (comments) e someoneisintrouble sugeriram que o loop foreach ...

(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();

... pode ser redundante, então o foreachloop e o $stmt->executepodem ser substituídos por apenas ...

<?php 
  (...)
  $stmt->execute($ids);
?>

(novamente, eu não testei)


7
Essa é uma solução interessante e, embora eu prefira iterar sobre os IDs e chamar PDO :: quote (), acho que o índice do '?' espaços reservados ficarão bagunçados se houver outros espaços reservados primeiro em algum lugar da consulta, certo?
— 283 Andru

5
Sim, isso seria um problema. mas, nesse caso, você pode criar parâmetros nomeados em vez de?
— 2828 stefs

9
A pergunta antiga, mas digna de nota, acredito, é que o $foreache bindValue()não é necessário - basta executar com o array. Exemplo:$stmt->execute($ids);
— Chris

2
A geração dos espaços reservados deve ser feita assimstr_repeat('?,', count($array) - 1). '?';
— Xeoncross

8
Apenas uma dica para quem não sabe, você não pode misturar parâmetros com e sem nome. Portanto, se você usar parâmetros nomeados em sua consulta, alterne-os para? E depois aumente o deslocamento do índice bindValue para corresponder à posição dos IN? S com onde quer que eles estejam em relação ao outro? params.
— Justinl

169

Para algo rápido:

//$db = new PDO(...);
//$ids = array(...);

$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)");
$sth->execute($ids);

7
Excelente, não tinha pensado em usar o argumento input_parameters dessa maneira. Para aqueles cujas consultas têm mais parâmetros que a lista IN, você pode usar array_unshift e array_push para adicionar os argumentos necessários à frente e ao final da matriz. Além disso, eu prefiro $input_list = substr(str_repeat(',?', count($ids)), 1);
— orca

7
Você também pode tentar str_repeat('?,', count($ids) - 1) . '?'. Menos uma chamada de função.
— orca

5
@erfling, esta é uma declaração preparada, de onde virá a injeção? Ficarei feliz em fazer as correções se você puder fazer o backup com alguma prova real disso.
— DonVaughn

5
@erfling, sim, isso é correto, e ligar os parâmetros é exatamente o que estamos fazendo neste exemplo através do envio de executeuma matriz de IDs
— DonVaughn

5
Ah, de fato. De alguma forma, perdi o fato de que você estava passando a matriz. Isso realmente parece ser seguro e uma boa resposta. Me desculpe.
— erfling

46

É tão importante usar a INdeclaração? Tente usar FIND_IN_SETop.

Por exemplo, há uma consulta no DOP como essa

SELECT * FROM table WHERE FIND_IN_SET(id, :array)

Então você só precisa vincular uma matriz de valores implodida por vírgula, como esta

$ids_string = implode(',', $array_of_smth); // WITHOUT WHITESPACES BEFORE AND AFTER THE COMMA
$stmt->bindParam('array', $ids_string);

e está feito.

UPD: Como algumas pessoas apontaram nos comentários a esta resposta, há algumas questões que devem ser explicitadas explicitamente.

  1. FIND_IN_SETnão usa índice em uma tabela e ainda não está implementado - veja esse registro no rastreador de erros do MYSQL . Obrigado a BillKarwin pelo aviso.
  2. Você não pode usar uma string com vírgula dentro como um valor da matriz para pesquisa. É impossível analisar essa sequência da maneira correta depois de implodeusar o símbolo de vírgula como separador. Obrigado a @VaL pela nota.

Em resumo, se você não depende muito de índices e não usa seqüências de caracteres com vírgula para pesquisa, minha solução será muito mais fácil, mais simples e mais rápida que as soluções listadas acima.


25
IN () pode usar um índice e conta como uma varredura de intervalo. FIND_IN_SET () não pode usar um índice.
— Bill Karwin

1
Isso é um ponto. Eu não sabia disso. Mas, de qualquer maneira, não há requisitos para desempenho na questão. Para tabelas não tão grandes, é muito mais melhor e mais limpo do que uma classe separada para gerar consultas com diferentes números de espaços reservados.
— Tim Tonkonogov

11
Sim, mas quem tem uma mesa não tão grande hoje em dia? ;-)
— Bill Karwin 8/13

3
Outro problema com essa abordagem é que, se houver string com vírgula dentro? Por exemplo ... FIND_IN_SET(description,'simple,search'), funcionará, mas FIND_IN_SET(description,'first value,text, with coma inside')falhará. Portanto, a função procurará em "first value", "text", "with coma inside" vez do desejado"first value", "text, with coma inside"
— VaL 17/02/2015

33

Como eu faço muitas consultas dinâmicas, essa é uma função auxiliar super simples que eu criei.

public static function bindParamArray($prefix, $values, &$bindArray)
{
    $str = "";
    foreach($values as $index => $value){
        $str .= ":".$prefix.$index.",";
        $bindArray[$prefix.$index] = $value;
    }
    return rtrim($str,",");     
}

Use-o assim:

$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";

Retorna uma string :id1,:id2,:id3e também atualiza suas $bindArrayligações necessárias quando for a hora de executar sua consulta. Fácil!


6
Essa é uma solução muito melhor, pois não quebra a regra de vinculação de parâmetros. Isso é muito mais seguro do que ter sql embutido, conforme proposto por alguns outros aqui.
— Dimitar Darazhanski

1
Maravilha. Elegante. Perfeito.
— Ricalsin

17

A solução da EvilRygy não funcionou para mim. No Postgres, você pode executar outra solução alternativa:


$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id = ANY (string_to_array(:an_array, ','))'
);
$stmt->bindParam(':an_array', implode(',', $ids));
$stmt->execute();

Isso não funciona: ERROR: operator does not exist: integer = text. Pelo menos você precisa adicionar conversão explícita.
— Collimarco

17

Uma maneira muito limpa para o postgres é usar o postgres-array ("{}"):

$ids = array(1,4,7,9,45);
$param = "{".implode(', ',$ids)."}";
$cmd = $db->prepare("SELECT * FROM table WHERE id = ANY (?)");
$result = $cmd->execute(array($param));

bloquear injeção sql?
— Fábio Zangirolami 22/02

1
@ FábioZangirolami é DOP, então sim.
— ESCOBAR

SIM, DOP! depois de 4 anos. Sua resposta foi boa para mim, muito simples e eficaz. obrigado!!!
— Fábio Zangirolami 23/02

14

Aqui está a minha solução:

$total_items = count($array_of_items);
$question_marks = array_fill(0, $total_items, '?');
$sql = 'SELECT * FROM foo WHERE bar IN (' . implode(',', $question_marks ). ')';

$stmt = $dbh->prepare($sql);
$stmt->execute(array_values($array_of_items));

Observe o uso de array_values. Isso pode corrigir os principais problemas de pedidos.

Eu estava mesclando matrizes de IDs e removendo itens duplicados. Eu tinha algo como:

$ids = array(0 => 23, 1 => 47, 3 => 17);

E isso estava falhando.


Esta foi uma excelente solução. Ao contrário da construção da string de consulta, isso usa a ligação corretamente. Eu recomendo fortemente este.
— Lindylead 19/01

Nota: Usando sua solução, você pode adicionar itens à frente ou atrás da matriz, para poder incluir outras ligações. $original_array Adicionar itens antes da matriz original: array_unshift($original_array, new_unrelated_item); Adicionar itens após a matriz original: array_push($original_array, new_unrelated_item); Quando os valores estiverem vinculados, os itens new_unrelated serão colocados nos locais corretos. Isso permite que você misture itens de matriz e não matriz. `
— Lindylead 19/01

12

Estendi a DOP para fazer algo semelhante ao sugerido pelos stefs, e foi mais fácil para mim a longo prazo:

class Array_Capable_PDO extends PDO {
    /**
     * Both prepare a statement and bind array values to it
     * @param string $statement mysql query with colon-prefixed tokens
     * @param array $arrays associatve array with string tokens as keys and integer-indexed data arrays as values 
     * @param array $driver_options see php documention
     * @return PDOStatement with given array values already bound 
     */
    public function prepare_with_arrays($statement, array $arrays, $driver_options = array()) {

        $replace_strings = array();
        $x = 0;
        foreach($arrays as $token => $data) {
            // just for testing...
            //// tokens should be legit
            //assert('is_string($token)');
            //assert('$token !== ""');
            //// a given token shouldn't appear more than once in the query
            //assert('substr_count($statement, $token) === 1');
            //// there should be an array of values for each token
            //assert('is_array($data)');
            //// empty data arrays aren't okay, they're a SQL syntax error
            //assert('count($data) > 0');

            // replace array tokens with a list of value tokens
            $replace_string_pieces = array();
            foreach($data as $y => $value) {
                //// the data arrays have to be integer-indexed
                //assert('is_int($y)');
                $replace_string_pieces[] = ":{$x}_{$y}";
            }
            $replace_strings[] = '('.implode(', ', $replace_string_pieces).')';
            $x++;
        }
        $statement = str_replace(array_keys($arrays), $replace_strings, $statement);
        $prepared_statement = $this->prepare($statement, $driver_options);

        // bind values to the value tokens
        $x = 0;
        foreach($arrays as $token => $data) {
            foreach($data as $y => $value) {
                $prepared_statement->bindValue(":{$x}_{$y}", $value);
            }
            $x++;
        }

        return $prepared_statement;
    }
}

Você pode usá-lo assim:

$db_link = new Array_Capable_PDO($dsn, $username, $password);

$query = '
    SELECT     *
    FROM       test
    WHERE      field1 IN :array1
     OR        field2 IN :array2
     OR        field3 = :value
';

$pdo_query = $db_link->prepare_with_arrays(
    $query,
    array(
        ':array1' => array(1,2,3),
        ':array2' => array(7,8,9)
    )
);

$pdo_query->bindValue(':value', '10');

$pdo_query->execute();

1
Eu lidei com a primeira parte do comentário de Mark, mas, como ele apontou, ainda não é seguro se um token semelhante :arrayestiver em uma sequência na consulta.
— 25413 Chris

4
Uma observação para todos os futuros leitores: Esta solução nunca deve ser usada. Declarações não se destinam ao código de produção
— Seu senso comum

1
YCS: obrigado pelo feedback, interessado em sua opinião sobre a abordagem fora da adequação das declarações.
— 31513 Chris

1
A idéia é a mesma, mas apenas sem declarações e de maneira mais direta e explícita - não como uma exceção para apenas um caso, mas como uma maneira geral de criar todas as consultas. Cada espaço reservado é marcado com seu tipo. Isso torna if (is_array($data))desnecessárias as adivinhações (como uma), mas torna o processamento de dados muito mais preciso.
— Seu senso comum

1
Para qualquer pessoa que esteja lendo os comentários: o problema mencionado por @Your Common Sense foi corrigido na revisão 4 .
— usar o seguinte comando

11

Observando PDO: Constantes Predefinidas, não há PDO :: PARAM_ARRAY que você precisaria, conforme listado em PDOStatement-> bindParam

bool PDOStatement :: bindParam (misto parâmetro $, misto & $ variável [, int $ data_type [, int $ length [, misto $ driver_options]]])

Então, eu não acho que é viável.


1
Não sei se isso funciona. Eu acho que a string implodida é citada.
— soulmerge

2
Você está correto, as aspas são escapadas para que não funcionem. Eu removi esse código.

11

Quando você tem outro parâmetro, pode fazer o seguinte:

$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$query = 'SELECT *
            FROM table
           WHERE X = :x
             AND id IN(';
$comma = '';
for($i=0; $i<count($ids); $i++){
  $query .= $comma.':p'.$i;       // :p0, :p1, ...
  $comma = ',';
}
$query .= ')';

$stmt = $db->prepare($query);
$stmt->bindValue(':x', 123);  // some value
for($i=0; $i<count($ids); $i++){
  $stmt->bindValue(':p'.$i, $ids[$i]);
}
$stmt->execute();

Obrigado pela ótima resposta. Este foi o único de todos que realmente funcionou para mim. No entanto, eu vi 1 erro. A variável $ rs deve ser $ stmt #
— Piet Piet

11

Para mim, a solução mais sexy é construir uma matriz associativa dinâmica e usá-la

// A dirty array sent by user
$dirtyArray = ['Cecile', 'Gilles', 'Andre', 'Claude'];

// we construct an associative array like this
// [ ':name_0' => 'Cecile', ... , ':name_3' => 'Claude' ]
$params = array_combine(
    array_map(
        // construct param name according to array index
        function ($v) {return ":name_{$v}";},
        // get values of users
        array_keys($dirtyArray)
    ),
    $dirtyArray
);

// construct the query like `.. WHERE name IN ( :name_1, .. , :name_3 )`
$query = "SELECT * FROM user WHERE name IN( " . implode(",", array_keys($params)) . " )";
// here we go
$stmt  = $db->prepare($query);
$stmt->execute($params);

É difícil ter certeza sem tentar no cenário real, mas parece bom. + 1
— Anant Singh --- Alive to Die

9

Também sei que esse encadeamento é antigo, mas tive um problema único em que, ao converter o driver mysql que seria preterido em driver PDO, tive que criar uma função que pudesse criar dinamicamente ambos os parâmetros normais e INs do mesmo matriz param. Então eu rapidamente construí isso:

/**
 * mysql::pdo_query('SELECT * FROM TBL_WHOOP WHERE type_of_whoop IN :param AND siz_of_whoop = :size', array(':param' => array(1,2,3), ':size' => 3))
 *
 * @param $query
 * @param $params
 */
function pdo_query($query, $params = array()){

    if(!$query)
        trigger_error('Could not query nothing');

    // Lets get our IN fields first
    $in_fields = array();
    foreach($params as $field => $value){
        if(is_array($value)){
            for($i=0,$size=sizeof($value);$i<$size;$i++)
                $in_array[] = $field.$i;

            $query = str_replace($field, "(".implode(',', $in_array).")", $query); // Lets replace the position in the query string with the full version
            $in_fields[$field] = $value; // Lets add this field to an array for use later
            unset($params[$field]); // Lets unset so we don't bind the param later down the line
        }
    }

    $query_obj = $this->pdo_link->prepare($query);
    $query_obj->setFetchMode(PDO::FETCH_ASSOC);

    // Now lets bind normal params.
    foreach($params as $field => $value) $query_obj->bindValue($field, $value);

    // Now lets bind the IN params
    foreach($in_fields as $field => $value){
        for($i=0,$size=sizeof($value);$i<$size;$i++)
            $query_obj->bindValue($field.$i, $value[$i]); // Both the named param index and this index are based off the array index which has not changed...hopefully
    }

    $query_obj->execute();

    if($query_obj->rowCount() <= 0)
        return null;

    return $query_obj;
}

Ainda não foi testado, no entanto, a lógica parece estar lá.

Espero que ajude alguém na mesma posição,

Edit: Depois de alguns testes, descobri:

  • O DOP não gosta de '.' em seus nomes (o que é meio estúpido se você me perguntar)
  • bindParam é a função errada, bindValue é a função correta.

Código editado para a versão de trabalho.


8

Uma pequena edição sobre o código de Schnalle

<?php
$ids     = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids)-1, '?'));

$db   = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(' . $inQuery . ')'
);

foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();
?>

//implode(',', array_fill(0, count($ids)-1), '?')); 
//'?' this should be inside the array_fill
//$stmt->bindValue(($k+1), $in); 
// instead of $in, it should be $id

1
Eu tive que remover -1 após a contagem ($ ids) para que funcionasse para mim ou sempre haveria um espaço reservado ausente.
— Marcel Burkhard #

7

Qual banco de dados você está usando? No PostgreSQL, eu gosto de usar QUALQUER (array). Então, para reutilizar seu exemplo:

<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id = ANY (:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>

Infelizmente, isso é bastante não portátil.

Em outros bancos de dados, você precisará criar sua própria magia, como outros já mencionaram. Você deseja colocar essa lógica em uma classe / função para torná-la reutilizável em todo o seu programa, é claro. Dê uma olhada nos comentários na mysql_querypágina no PHP.NET para mais algumas reflexões sobre o assunto e exemplos desse cenário.


4

Depois de passar pelo mesmo problema, fui para uma solução mais simples (embora ainda não seja tão elegante quanto uma PDO::PARAM_ARRAY seria):

dada a matriz $ids = array(2, 4, 32):

$newparams = array();
foreach ($ids as $n => $val){ $newparams[] = ":id_$n"; }

try {
    $stmt = $conn->prepare("DELETE FROM $table WHERE ($table.id IN (" . implode(", ",$newparams). "))");
    foreach ($ids as $n => $val){
        $stmt->bindParam(":id_$n", intval($val), PDO::PARAM_INT);
    }
    $stmt->execute();

... e assim por diante

Portanto, se você estiver usando uma matriz de valores mistos, precisará de mais código para testar seus valores antes de atribuir o tipo param:

// inside second foreach..

$valuevar = (is_float($val) ? floatval($val) : is_int($val) ? intval($val) :  is_string($val) ? strval($val) : $val );
$stmt->bindParam(":id_$n", $valuevar, (is_int($val) ? PDO::PARAM_INT :  is_string($val) ? PDO::PARAM_STR : NULL ));

Mas eu não testei este.


4

Como eu sei, não há nenhuma possibilidade de vincular uma matriz à declaração PDO.

Mas existem 2 soluções comuns:

  1. Use espaços reservados posicionais (?,?,?,?) Ou espaços reservados nomeados (: id1,: id2,: id3)

    $ whereIn = implode (',', array_fill (0, count ($ ids), '?'));

  2. Citação de matriz anteriormente

    $ whereIn = array_map (matriz ($ db, 'citação'), $ ids);

Ambas as opções são boas e seguras. Prefiro o segundo porque é mais curto e posso var_dump parâmetros se precisar. Usando espaços reservados, você deve vincular valores e, no final, seu código SQL será o mesmo.

$sql = "SELECT * FROM table WHERE id IN ($whereIn)";

E o último e importante para mim é evitar o erro "o número de variáveis ​​associadas não corresponde ao número de tokens"

Doutrina é um ótimo exemplo de uso de espaços reservados posicionais, apenas porque ele tem controle interno sobre os parâmetros recebidos.


4

Se a coluna puder conter apenas números inteiros, você provavelmente poderá fazer isso sem espaços reservados e apenas colocar os IDs na consulta diretamente. Você só precisa converter todos os valores da matriz para números inteiros. Como isso:

$listOfIds = implode(',',array_map('intval', $ids));
$stmt = $db->prepare(
    "SELECT *
     FROM table
     WHERE id IN($listOfIds)"
);
$stmt->execute();

Isso não deve ser vulnerável a nenhuma injeção de SQL.


3

aqui está a minha solução. Também estendi a classe DOP:

class Db extends PDO
{

    /**
     * SELECT ... WHERE fieldName IN (:paramName) workaround
     *
     * @param array  $array
     * @param string $prefix
     *
     * @return string
     */
    public function CreateArrayBindParamNames(array $array, $prefix = 'id_')
    {
        $newparams = [];
        foreach ($array as $n => $val)
        {
            $newparams[] = ":".$prefix.$n;
        }
        return implode(", ", $newparams);
    }

    /**
     * Bind every array element to the proper named parameter
     *
     * @param PDOStatement $stmt
     * @param array        $array
     * @param string       $prefix
     */
    public function BindArrayParam(PDOStatement &$stmt, array $array, $prefix = 'id_')
    {
        foreach($array as $n => $val)
        {
            $val = intval($val);
            $stmt -> bindParam(":".$prefix.$n, $val, PDO::PARAM_INT);
        }
    }
}

Aqui está um exemplo de uso para o código acima:

$idList = [1, 2, 3, 4];
$stmt = $this -> db -> prepare("
  SELECT
    `Name`
  FROM
    `User`
  WHERE
    (`ID` IN (".$this -> db -> CreateArrayBindParamNames($idList)."))");
$this -> db -> BindArrayParam($stmt, $idList);
$stmt -> execute();
foreach($stmt as $row)
{
    echo $row['Name'];
}

Diz-me o que pensas


Esqueceu-se de mencionar que isso se baseia na resposta do usuário2188977 abaixo.
— Lippai Zoltan

Não sei ao certo o que é getOne (), não parece fazer parte do PDO. Eu só vi isso na PEAR. O que isso faz exatamente?
— Lippai Zoltan

@YourCommonSense, você pode postar sua função definida pelo usuário como resposta?
— nullability

Eu sugeriria passar o tipo de dados para BindArrayParama matriz associativa, pois você parece estar limitando isso a números inteiros.
— 11263 Ian Brindley

2

Não é possível usar uma matriz como essa no PDO.

Você precisa criar uma string com um parâmetro (ou usar?) Para cada valor, por exemplo:

:an_array_0, :an_array_1, :an_array_2, :an_array_3, :an_array_4, :an_array_5

Aqui está um exemplo:

<?php
$ids = array(1,2,3,7,8,9);
$sqlAnArray = join(
    ', ',
    array_map(
        function($index) {
            return ":an_array_$index";
        },
        array_keys($ids)
    )
);
$db = new PDO(
    'mysql:dbname=mydb;host=localhost',
    'user',
    'passwd'
);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN('.$sqlAnArray.')'
);
foreach ($ids as $index => $id) {
    $stmt->bindValue("an_array_$index", $id);
}

Se você quiser continuar usando bindParam, faça o seguinte:

foreach ($ids as $index => $id) {
    $stmt->bindParam("an_array_$index", $ids[$id]);
}

Se você deseja usar ?espaços reservados, faça o seguinte:

<?php
$ids = array(1,2,3,7,8,9);
$sqlAnArray = '?' . str_repeat(', ?', count($ids)-1);
$db = new PDO(
    'mysql:dbname=dbname;host=localhost',
    'user',
    'passwd'
);
$stmt = $db->prepare(
    'SELECT *
     FROM phone_number_lookup
     WHERE country_code IN('.$sqlAnArray.')'
);
$stmt->execute($ids);

Se você não sabe se $idsestá vazio, deve testá-lo e lidar com esse caso de acordo (retornar uma matriz vazia ou retornar um Objeto Nulo ou lançar uma exceção, ...).


0

Eu levei um pouco mais longe para obter a resposta mais próxima da pergunta original de usar espaços reservados para vincular os parâmetros.

Essa resposta precisará fazer dois loops na matriz a serem usados ​​na consulta. Mas resolve o problema de ter outros marcadores de coluna para consultas mais seletivas.

//builds placeholders to insert in IN()
foreach($array as $key=>$value) {
    $in_query = $in_query . ' :val_' . $key . ', ';
}

//gets rid of trailing comma and space
$in_query = substr($in_query, 0, -2);

$stmt = $db->prepare(
    "SELECT *
     WHERE id IN($in_query)";

//pind params for your placeholders.
foreach ($array as $key=>$value) {
    $stmt->bindParam(":val_" . $key, $array[$key])
}

$stmt->execute();

0

você primeiro definiu o número de "?" na consulta e, em seguida, com um "for" envia parâmetros como este:

require 'dbConnect.php';
$db=new dbConnect();
$array=[];
array_push($array,'value1');
array_push($array,'value2');
$query="SELECT * FROM sites WHERE kind IN (";

foreach ($array as $field){
    $query.="?,";
}
$query=substr($query,0,strlen($query)-1);
$query.=")";
$tbl=$db->connection->prepare($query);
for($i=1;$i<=count($array);$i++)
    $tbl->bindParam($i,$array[$i-1],PDO::PARAM_STR);
$tbl->execute();
$row=$tbl->fetchAll(PDO::FETCH_OBJ);
var_dump($row);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.