[Resolvido]Dúvida SQL

15 respostas
juliocesarss

Tenho esse Código:

AcessoBD bd = new AcessoBD("Banco de dados");

  try {
            ResultSet resultado = bd.consultaTable("SELECT cod_alocacao FROM alocacao WHERE disponivel = '1' ");
            if (resultado != null && resultado.next()) {
                do {                   
                    int cod = (resultado.getInt("cod_alocacao"));
                    String sql = "UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao ='" + cod + "'";
                    bd.updateBase(sql);
                    
                } while (resultado.next());//ele ele o código até aqui e em vez de voltar la em cima ele da erro, porém se eu tiro o "bd.updateBase(sql)" ele funciona perfeitamente
            }

        } catch (SQLException ex) {
            Logger.getLogger(Cadastro.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

Como podem ver eu gostaria de fazer uma pesquisa e conforme o resultado, ja atualizar a tabela, porém ele da erro.. não sei se é possível fazer isso junto ou tem que fazer separado.

Espero ter sido claro.

15 Respostas

von.juliano

Você pode fazer o assim:

"UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao IN (SELECT cod_alocacao FROM alocacao WHERE disponivel = '1')"

Blz? Flw! :thumbup:

A

Olha só, dizer que “dá erro” não é exatamente suficiente pra gente saber o que está acontecendo.
Poste a exception (o stacktrace completo), que terá mais chances de obter uma resposta precisa.

De qualquer forma, se entendi sua lógica, você quer atualizar sua tabela alocacao com o valor disponivel=0 onde disponivel=1, certo?

Usar o código abaixo não daria no mesmo?

String sql  = "UPDATE alocacao SET disponivel ='0' WHERE disponivel = '1'";
bd.updateBase(sql);
juliocesarss

von.juliano:
Você pode fazer o assim:

"UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao IN (SELECT cod_alocacao FROM alocacao WHERE disponivel = '1')"

Blz? Flw! :thumbup:

Vou testar isso ^^

Vou tentar explicar melhor

try {  
             ResultSet resultado = bd.consultaTable("SELECT cod_alocacao FROM alocacao WHERE disponivel = '1' "); //resultado vai receber a pesquisa. Ex: 1 (cod_alocacao) 
             if (resultado != null && resultado.next()) {  //testa pra ver se recebeu algo.. se não esta nulo
                 do {   //Repita. Ele vai repetir tudo que estiver aqui dentro equando o resultado.next                  
                     int cod = (resultado.getInt("cod_alocacao"));  // guardo numa variavel
                     String sql = "UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao ='" + cod + "'";  //crio uma string com o update
                     bd.updateBase(sql);  /chamo o méto que faz o update
                       
                 } while (resultado.next());//nessa parte o "resultado" tem que recebr o próximo registro (Ex: 2) e fazer a mesma coisa até a pesquisa não retornar mais nada, teoricamente está certo, até porque eu uso desse forma em outras pesquisas, o que  eu nunca fiz foi manda ele ficar repetindo a pesquisa com um update dentro... acho que é isso o erro
             }  
   
         } catch (SQLException ex) {  
             Logger.getLogger(Cadastro.class.getName()).log(Level.SEVERE, null, ex);  
         }  
     }

de qualquer forma ta aqui o erro

java.sql.SQLException: Operation not allowed after ResultSet closed at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929) at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:795) at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7146) at transito.Cadastro.limpaAlocacao(Cadastro.java:350) at transito.FormMenu.formWindowOpened(FormMenu.java:420) at transito.FormMenu.access$000(FormMenu.java:14) at transito.FormMenu$1.windowOpened(FormMenu.java:195) at java.awt.AWTEventMulticaster.windowOpened(AWTEventMulticaster.java:322) at java.awt.Window.processWindowEvent(Window.java:1862) at javax.swing.JFrame.processWindowEvent(JFrame.java:274) at java.awt.Window.processEvent(Window.java:1823) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

E

é que quando você faz o bd.updateBase(sql); na mesma conexão, você “fecha” o resultset. Quando dá o next ele não consegue encontrar.

Ou você abre uma nova conexão, ou você usa a solução com subquery do von.juliano.

edit: agora que vi que as tabelas que você faz o update e o select são as mesmas, a solução do AbelBueno é melhor:

String sql = "UPDATE alocacao SET disponivel ='0' WHERE disponivel = '1'"; bd.updateBase(sql); (sem fazer a consulta antes, diretamente esse update)

juliocesarss

evefuji:
é que quando você faz o bd.updateBase(sql); na mesma conexão, você “fecha” o resultset. Quando dá o next ele não consegue encontrar.

Ou você abre uma nova conexão, ou você usa a solução com subquery do von.juliano.

Perfeito Cara !

Como eu disse , imaginei que era algo desse tipo…

Ficou assim

AcessoBD bd, bd2; 
 bd = new AcessoBD("Banco de dados");
 bd2 = new AcessoBD("Banco de dados");   
   
   try {  
             ResultSet resultado = bd.consultaTable("SELECT cod_alocacao FROM alocacao WHERE disponivel = '1' ");  
             if (resultado != null && resultado.next()) {  
                 do {                     
                     int cod = (resultado.getInt("cod_alocacao"));  
                     String sql = "UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao ='" + cod + "'";  
                     bd2.updateBase(sql);// crei outro obejto e funcionou perfeito.  
                       
                 } while (resultado.next());
             }  
   
         } catch (SQLException ex) {  
             Logger.getLogger(Cadastro.class.getName()).log(Level.SEVERE, null, ex);  
         }  
     }
von.juliano

Eu também não tinha visto que era a mesma tabela! :XD:

Pra agregar alguma coisa, duas dicas:

1 - Não é necessário o if e o do-while, você pode fazer apenas um while:

while (resultado.next()) { int cod = (resultado.getInt("cod_alocacao")); String sql = "UPDATE alocacao SET disponivel ='0' WHERE cod_alocacao ='" + cod + "'"; bd2.updateBase(sql);// crei outro obejto e funcionou perfeito. }
2 - Não concatene as Strings. Use o método setString de PreparedStatement, assim como setInt, set Double, etc.

Blz? Flw! :thumbup:

juliocesarss

Ahh nem eu tinha percebido… dava pra usar só o update --’ Burrice minha :oops:


Não concatene as Strings. Use o método setString de PreparedStatement, assim como setInt, set Double, etc.

Por que não fazer isso?

E não entendi direito como funciona o outro método.

E

nesse caso, não vejo porque não fazer (já que o código é você quem gera), mas as boas práticas dizem para você usar o PreparedStatement (setando as entradas por ?, na query), para evitar sql injection.

juliocesarss

Tem alguem exemplo simples ae pra eu entender na pratica?

A

O preparedStatement tem mais de uma vantagem sobre o statement.

Uma delas é evitar o sql injection (que como já dito, não se aplica neste caso).

Outra é em relação a performance.

Imagine no código original dele, que sejam retornados 1000 registros na consulta.
Isto causaria a execução de 1000 updates no banco.

Utilizando o statement o banco entenderia cada update como um comando totalmente diferente.
Com o prepared, o banco pode utilizar alguma otimização, pois ele sabe que é o mesmo comando com valores diferentes.

Não sei se para esse caso a diferença seria gritante, mas como citado, é sempre uma boa prática.

E

algo assim, imagine que você tenha essa consulta, com um parâmetro “nome” que recebe do usuário

rs = bd.executeQuery("select * from tabela where nome = '"+nome+"'");

e no nome, o usuário coloca, por exemplo, “’ or 1=1 or ‘’=’”, o que acontece? A string que o java manda para o banco de dados fica assim:

select * from tabela where nome = '' or 1=1 or ''='''

ou seja, vai trazer todos os registros, inclusive o que ele não teria permissão para ver.

Se você usar um preparedStatement, ele já trata todas as entradas, no caso, substituindo ’ por ‘’ (duas aspas)

juliocesarss

Ahh entendi… nunca tinha pensado por esse lado… realmente… isso pode causar um problema bem grande.

Voce tem um exemplo de como eu usaria o preparedStatement nesse caso?

E
PreparedStatement ps = bd.prepareStatement("select * from tabela where nome = ?");  
     ps.setString(1, nome);
     ResultSet rs = ps.executeQuery();
juliocesarss

Então primeiro eu trato a consulta pelo PreparedStatement pra depois executar a query? isso?

E

juliocesarss:
Então primeiro eu trato a consulta pelo PreparedStatement pra depois executar a query? isso?

exatamente, procura dar uma olhada na documentação do PreparedStatement, vai aprender recursos bem interessantes que ele tem.

Criado 11 de novembro de 2010
Ultima resposta 11 de nov. de 2010
Respostas 15
Participantes 4