Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Estou fazendo uma consulta com o pdo usando o operador... so q n funciona... a consulta n fica formatada de forma correta....
$cgc é um array de checkbox q vem no seguinte formato:
[0]=>unidade1
[1]=>unidade2
[2]=>unidade3
[3]=>unidade4
public function findUnidadeVinculada($cgc){
$sql = "SELECT c.numero_contrato, c.excluido, uc.unidade FROM contrato_unidade as uc
INNER JOIN contratos AS c ON uc.contrato = c.id_contrato
WHERE c.excluido = 'NAO' AND uc.unidade in (select cgc from unidades where cgc in(:cgc))
LIMIT 1";
$stmt = $this->con->prepare($sql);
$stmt->execute(($cgc));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result;
}
se puderam ajudar fico grato.
-----------------------------
seria so trocar o ':cgc' por '?'
a consulta n retorna valor. estou usando o postgres. depois q mudei o :cgc para ?, apareceu o seguinte erro:
no match bound... [HY9300] algo assim...
"no match bound" indica que os placeholders (named ou não) não batem com a quantidade de valores que está sendo atribuído ao statement.
Você está passando o array $cgc direto?
Você poderia tratá-lo, como uma string normal, utilizando implode para juntar com ',' (vírgulas), no final das contas PDO ainda trata a SQL como um string normal.
$stmt->execute(implode(',' , $cgc));
O que isso acima não é correto, pois não vai tratar parâmetro por parâmetro '-'
leia isso, do manual:
>
Citar
You cannot bind multiple values to a single parameter; for example, you cannot bind two values to a single named parameter in an IN() clause.
Você deve definir um placeholder para cada valor no IN.
Gabriel Heming, daqui a pouco testo o implode q você passou.
Eu tive de alterar a minha resposta antes. Mas isso foi antes de você responder. Repetindo, não seri nada aconselhável utilizar implode.
Conte o número de parâmetros utilizados no IN, e coloque a quantidade de marked placeholders ("?").
pode passar de 200.... é variavel pode ser 5, 10, 300, 400....
Infelizmente, "é a vida".
Você pode usar a função array_fill para "preencher" os marked placeholders.
Segue:
$quantidade = count($cgc);
$markedPlaceholders = array_fill(0 , $quantidade , '?');
$markedPlaceholders = implode(',' , $markedPlaceholders);
Com esse pequeno código acima, você possuirá a quantidade adequada de marked placeholders. Basta inserir no SQL.
$statement = $pdo->prepare('SELCT * FROM tabela WHERE id IN ('.$markedPlaceholders.');');
shini...
Apenas curiosidade, esse SELECT faz sentido pra você?
select cgc from unidades where cgc in(:cgc)
Tipo... Selecione a coluna CGC em unidades que tenham CGC com essa lista de CGC.
A pergunta é igual a resposta, não?
AND uc.unidade in (select cgc from unidades where cgc in(:cgc))
no caso uc.unidade seria td as unidades na tabela uc.. e cgc in(:cgc) seria somente os checkbox marcado pelo usuario.
seria assim uma unidade so pode estar vinculada a um contrato, dai fiz essa consulta para executa antes de inserir.
>
AND uc.unidade in (select cgc from unidades where cgc in(:cgc))
no caso uc.unidade seria td as unidades na tabela uc.. e cgc in(:cgc) seria somente os checkbox marcado pelo usuario.
seria assim uma unidade so pode estar vinculada a um contrato, dai fiz essa consulta para executa antes de inserir.
Em alguns SGDB's, você pode informar os valores quotados
$stmt->execute('"' . implode('", "', $cgc) . '"');
O que isso acima não é correto, pois não vai tratar parâmetro por parâmetro '-'
Mas que é contornável, isso é:
$cgc = array_map(
array( $this -> conn, 'quote' ),
$cgc
);
$cgc = implode( ', ', $cgc );
Agora, $cgc é uma string vinda de um array já tratado.
Mas ainda assim depende do SGBD.
Veja que, segundo o manual, o método execute trata os parâmetros passados como PDO::PARAM_STR.
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
Sendo assim, digamos que possuimos os valores 1, 5 e 10.
A sql normal seria:
'SELECT * FROM tabela WHERE id IN (1 , 5 , 10);'
Entretanto, como passa-se o valor 1 , 5 , 10 em um único marked placeholder tratado como string. Dependendo do SGBD, por não ser apenas números passados, a SQL pode ser gerada da seguinte maneira:
"SELECT * FROM tabela WHERE id IN ('1 , 5 , 10');"
Utilizando quotes no único valor passado.
Não possuo certeza absoluta sobre isso. Mas conhecendo o comportamento dos SGBDs, isso é algo que eu esperaria acontecer.
Sei que o Postgre não quota dessa maneira, nem o MSServer. Mas já o mysql é outra história.
são inteiros os parametros passados para o in
Tem como você dar um var_dump ou reconstruir a query manualmente para vermos como fica a consulta final?
Quanto a função in()
Creio que uso dela é assim:
in('string1', 'string2', 'string3');
ou
in(1,2,3); // com int
mangakah, quando postei a duvida imaginei q passado uma array para o excute(); ele converteria o array em uma string separando os valores por virgula. n esperava ter q passar uma ? para cada valor no IN(), pq nesse caso pode variar podem ser 5 valores, 10, 200, 300
>
são inteiros os parametros passados para o in
Nunca!!!!
Pode passar envolvido em aspas que o MySQL se encarrega da conversão.
>
Nunca!!!!
Pode passar envolvido em aspas que o MySQL se encarrega da conversão.
rsrs no meu caso são inteiros.
Gabriel Heming, testei hj seu codigo funcinou, mtooooo obrigado a todos q ajudaram.
[Resolvido]
shini...
O que exatamente funcionou? Mostre como ficou.
ficou assim, essa é outra consulta mas o problema era o mesmo.... o numero de '?' a passar para o IN()
public function listByUF($uf, $unidadesFora=null){
$in = "";
if($unidadesFora){
$qtd = count($unidadesFora);
$placeHolder = array_fill(0, $qtd, '?');
$placeHolder = implode(',', $placeHolder);
$in = "AND cgc NOT IN($placeHolder)";
}
$sql = "SELECT * FROM unidades WHERE uf = '$uf'". $in ."ORDER BY cgc";
$stmt = $this->con->prepare($sql);
$stmt->bindValue(':uf', $uf);
$stmt->execute($unidadesFora);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
Primeiro, eEsse fragmento, dentro da sua query:
in(:cgc))
Caracteriza que você está usando named placeholders e, sendo assim, aquilo que você informa à PDOStatement::execute() deve ser um array associativo onde os índices refletem os apelidos utilizados sem os dois pontos:
$stmt -> execute(
array( 'cgc' => $cgc )
);
Segundo. $cgc é um array mas até onde eu sei MySQL IN() espera receber uma string e, normalmente, separada por vírgulas. Mesmo que tal parâmetro seja aceito por PDOStatement::execute(), quando transitando para o banco, apenas o valor Array irá, pois é isso que acontece quando um Array normal é convertido forçadamente para string.
Terceiro. Você viu algum erro? "Não funciona" é muito vago, faça a PDO gritar alguns erros para saber o que está doendo nela. :P