Solucionado (ver solução)
Solucionado
(ver solução)
15
respostas

Join com uma condição variável

Amigos, tenho uma dúvida. Como fazer a sintaxe correta de uma query, que tem uma varável carregada pela página, como condição? Exemplo: "select p.id, d.* from pedidos as p join detalhes as d on p.id = d.pedido_id and dp.pedido_id = '{$id}' É isso? Pergunto, pois não está dando certo...

15 respostas

O codigo variavel deveria ir no where nao ?

tipo

select p.id, d.* from pedidos as p join detalhes as d on p.id = d.pedido_id where p.id = "$id"

Mas ai depende da linguagem e do jeito que vc esta fazendo, seria legal usar binding

Em c# por exemplo:

static void Main()
    {

        SqlConnection conn   = null;
        SqlDataReader reader = null;

        string idproduto= "Request.QueryString("produto")";

        try
        {
            // instantiate and open connection
            conn =  new
                SqlConnection("Server=(local);DataBase=MeuBanco;Integrated Security=SSPI");
            conn.Open();

            // jeito mongão de fazer facil de usar sqlinjection
            // SqlCommand cmd = new SqlCommand(
            // select p.id, d.* from pedidos as p join detalhes as d on p.id = d.pedido_id where p.id = "+ idproduto +"";

            // Criando o SqlCommand com parâmetro
            SqlCommand cmd = new SqlCommand(
                "select p.id, d.* from pedidos as p join detalhes as d on p.id = d.pedido_id where p.id = @idproduto", conn);

            // Define as informações do parâmetro criado
            SqlParameter param  = new SqlParameter();
            param.ParameterName = "@idproduto";
            param.Value = idproduto;

            // Inserindo o parâmetro no comando
            cmd.Parameters.Add(param);

            // Executando o commando e obtendo o resultado
            reader = cmd.ExecuteReader();

            // Exibindo os registros
            while(reader.Read())
            {
                Console.WriteLine("{0}, {1}", 
                    reader["Nome"], 
                    reader["Quantidade"]);
            }
        }
        finally
        {
            // Fecha o datareader
            if (reader != null)
            {
                reader.Close();
            }

            // Fecha a conexão
            if (conn != null)
            {
                conn.Close();
            }
        }
    }

é nem sei se ta funcional, mas é mais ou menos essa a ideia, vc pega o id do produto por algum recurso , utilzei o queryString no exemplo, e passa no where do select.

Consegue postar o código completo, por favor ?

A página é de "pedidos" e consiste em duas tabelas. A primeira, acima, contém os dados do pedido (número, data, cliente, prazo de pagamento, data prevista, etc ) e a segunda, abaixo, os detalhes deste pedido, que pode ter várias linhas, uma linha para cada produto (código, descrição, quantidade, medidas, preço). O 'id' do pedido vem de uma outra página . Faço um laço com FOREACH dos detalhes do pedido para listá-los e preciso que a query "amarre" o 'id' do pedido com o 'pedido_id' dos detalhes do pedido e só mostre os detalhes daquele referido pedido.

"select p.id, dp.* from detalhesdopedido as dp left join pedidos as p ON p.id = dp.pedido_id AND dp.pedido_id = '{$id}' ";

Segue o código:

<table>
    <tr>
        <td><h3 class="rotulos"><strong>pedido SM Nº:</h3></strong></td>
        <td><strong><?=$pedido['id']?></strong></td>
        <td><h3 class="rotulos"><strong>cliente:</h3></strong></td>
        <td>
            <select class="form-control-sm" name="smcadastro_id">
                <?php foreach($clientes as $cliente) :
                    $esseEhOCliente = $pedido['smcadastro_id'] == $cliente['id'];
                    $selecao = $esseEhOCliente ? "selected='selected'" : "";
                ?>
                    <option value="<?=$cliente['id']?>" <?=$selecao?>>
                        <?=$cliente['cliente']?>
                    </option>
                <?php endforeach ?>
            </select>
        </td>
        <td><h3 class="rotulos"><strong>id:</h3></strong></td>
        <td><strong><?php echo($pedido['smcadastro_id'])?></strong></td>
        <td><h3 class="rotulos">referência:</h3></td>
        <td colspan="6"><input class="form-control-sm" type="text" name="referencia" value="<?=$pedido['referencia']?>" /></td>
        <td><h3 class="rotulos">data do pedido:</h3></td>
        <td><?php echo date("d/m/Y", strtotime($pedido['datadoped'])) ?></td>
        <td></td>
        <td><h3 class="rotulos">prev entrega:</h3></td>
        <td><input class="form-control-sm" type="date" name="dataprevista" value="<?=$pedido['dataprevista']?>" /></td>     
    </tr>
    <tr>
        <td><h3 class="rotulos">romaneionu:</h3></td>
        <td colspan="2"><input class="form-control-sm" type="text" name="romaneionu" value="<?=$pedido['romaneionu']?>" /></td>
        <td><h3 class="rotulos">pedido do cliente:</h3></td>
        <td colspan="3"><input class="form-control-sm" type="text" name="pedcli_num" value="<?=$pedido['pedcli_num']?>" /></td>
        <td></td>
        <td></td>
        <td><h3 class="rotulos">condição de pagto do pedido:</h3></td>
        <td><input class="form-control-sm" type="number" name="condpgtped" value="<?=$pedido['condpgtped']?>" /></td>
        <td><h3 class="rotulos">condição de pagto do cadastro:</h3></td>
        <td><?=$pedido['condpagto']?></td>
        <td><h3 class="rotulos">observações:</h3></td>
        <td colspan="2"><textarea class="form-control-largo-sm" name="observs"><?=$pedido['observs']?></textarea></td>
        <td></td>
        <td></td>    
    </tr>
</table>
<table>
    <tr>
        <th>detped Nº</th>
        <th>pedido Nº</th>
        <th>pedido_id</th>
        <th>codprod</th>
        <th>descricao</th>
        <th>qtdepedido</th>
        <th>qtdevarian</th>
        <th>largura</th>
        <th>altura</th>
        <th>preco</th>
        <th>temp_peca</th>
        <th>simples</th>
        <th>precodofio</th>
    </tr>
<?php
    $detalhesdopedidos = listaDetalhesDoPedido($conexao);
    foreach($detalhesdopedidos as $detalhesdopedido) :
?>
<tr>
    <td><?= $detalhesdopedido['id'] ?></td>
    <td><?= $pedido['id'] ?></td>
    <td><?= $detalhesdopedido['pedido_id'] ?></td>
    <td><?= $detalhesdopedido['codprod']?></td>
    <td><?= $detalhesdopedido['descricao']?></td>
    <td><?= $detalhesdopedido['qtdepedido']?></td>
    <td><?= $detalhesdopedido['qtdevarian']?></td>
    <td><?= $detalhesdopedido['largura']?></td>
    <td><?= $detalhesdopedido['altura']?></td>
    <td><?= $detalhesdopedido['preco']?></td>
    <td><?= $detalhesdopedido['temp_peca']?></td>
    <td><?= $detalhesdopedido['simples']?></td>
    <td><?= $detalhesdopedido['precodofio']?></td>
</tr>
<?php
    endforeach
?>
</table>

Olá Fabrizio,

Acho que basta trocar o AND do seu select por WHERE.

Avisa aí se der certo.

Abraço.

Já tentei... Não deu.

Fabrizio, vamos por partes:

Primeiro: Se você pegar a SQL, trocar o '{$id}' por um ID válido e rodá-la diretamente no console do banco de dados, qual é o resultado ?

Segundo: Se o primeiro passo deu certo, então vamos la, como você esta passado esse parâmetro '{$id}' para a SQL, tente logar a SQL e veja como ela esta sendo montada, copie ela e cole também no console igual no primeiro passo.

Terceiro: Se a mesma esta sendo montada corretamente e foi executada, verifique o valor da variável $clietes e $detalhesdopedidos possuem valor.

Repare que devemos fazer debugar para conseguir verificar onde pode estar o problema.

Matheus, primeiro obrigado pela atenção.

Bem, com relação ao primeiro ponto, quando coloco o número 2, por exemplo, no lugar do da variável '{$id}' na query, ele retorna certinho apenas os detalhes do pedido 2, tanto no cmd como na página.

Quanto ao segundo ponto que você sugeriu, fazendo o teste no cmd, deixando a variável '{$id}", ele retorna "0" (zero). Mas, se eu colocar left join, ele retorna todos os registros de detalhes de todos os pedidos.

Quanto à sua terceira sugestão, não sei se fiz certo, mas na página anterior que encaminha para este formulário do pedido, eu coloquei um INPUT para cada variável ($id e $detalhesdopedido) desta forma:

E na página do pedido é apresentado o valor de cada variável corretamente. Fiz mais um teste colocando "echo query" antes do retorno desta função e como resultado é apresentado nulo no lugar da variável. Desta forma:

select p.id, dp.* from detalhesdopedido as dp left join pedidos as p ON p.id = dp.pedido_id AND dp.pedido_id = ' '

Posso estar enganado, mas acredito ser algum erro de sintaxe muito bobo... O que você acha?

Olá Fabrizio,

Realmente os passos que o Matheus passou para debugar valem a pena, pra ver se o id está chegando da tela ao backend.

Caso estejam chegando, li no seu código a seguinte parte:

$pedido['id']

Logo, com base na sua query passada anteriormente, não seria o seguinte?

SELECT p.id, dp.* 
FROM detalhesdopedido AS dp 
LEFT JOIN pedidos AS p ON p.id = dp.pedido_id 
WHERE dp.pedido_id = '{$pedido['id']}' ;

Avisa aí se der certo.

Abraço.

Oi Rafael, retorna vazio, também...

Rafael, mas trocando o WHERE por AND, retornou todos os detalhes de todos os pedidos.

Opa, Fabrizio! Parece que caminhamos um pouco.

Conforme sua fala, tenta essa então:

SELECT p.id, dp.* 
FROM detalhesdopedido AS dp 
LEFT JOIN pedidos AS p ON p.id = dp.pedido_id 
AND p.id = '{$pedido['id']}' ;

Abraço.

Nada, continua retornando vazio. Pode ser a sintaxe da variável? Quando coloco um número ela aceita e retorna corretamente. Mas, quando coloco '{$id}' , retorna vazio e é como se não tivesse indicado nenhuma condição...

Oi Fabrizio,

Pode sim ser a sintaxe da variável.

Agora que vi: a primeira aspas do id pode estar dando conflito com a primeira antes das chaves.

Vê se isso funciona:

SELECT p.id, dp.* 
FROM detalhesdopedido AS dp 
LEFT JOIN pedidos AS p ON p.id = dp.pedido_id 
AND p.id = '{$pedido[''id'']}' ;

Se continuar vazio, dá uma olhada em como, no PHP, escrevem-se selects com binding, dinâmicos. No java, por exemplo, você usa :valor ou ?, dependendo de como passa os valores ao select.

Avisa aí sobre as novas.

Abraço!

Oi de novo Fabrizio,

Pesquisei um pouco sobre sua dúvida. Talvez estes links te ajudem:

  1. Prepared statements and stored procedures
  2. Prepared Statements
  3. PHP Prepared Statements - W3 Schools
  4. Sql queries binding variables vs specifying them

Avisa aí se funcionar!

Abraço.

solução!

Pessoal, mistério solucionado! Faltava colocar o parâmetro do "id" na função listaDetalhesDoPedido. Eu havia declinado apenas a "$conexao". Foi só colocar também a variável "$id" como o segundo parâmetro, que tudo se encaixou. Sabia que era uma bobeira, mas não teria conseguido sem a ajuda de vocês. Muito obrigado a todos!