[TRY/CATCH] Ta correto fazer assim?

19 respostas
Vingdel

Olá pessoal, posto o seguinte bloco de código e gostaria da análise de vocês. Segue o bloco:

String consulta = "SELECT * FROM dicas"; try{ stm = conn.createStatement(); rs = stm.executeQuery(consulta); }catch(SQLException e){ try{ System.out.println("CATCH --- CRIA TABELA"); stm = conn.createStatement(); stm.executeUpdate("CREATE TEXT TABLE dicas (pri BIGINT NOT NULL IDENTITY, codigo CHAR(3), dica VARCHAR(200))"); stm.execute("SET TABLE dicas SOURCE 'dicas.csv'"); rs = stm.executeQuery(consulta); }catch(SQLException e1){} }
Então eu perguntou, está correto fazer isso, usar TRY dentro de CATCH?

O que acontece é o seguinte, estou usando o HSQLDB e ele não suporta a declaração SQL “CREATE TABLE IF NOT EXISTS …” e eu precisei dar um jeito. Meu jeito foi consultar a tabela em um TRY, se a tabela existe ótimo, o programa segue lindamente, mas se a tabela não existe vai pra o CATCH que trata “SQLExcepion” e cria a tabela e depois disso volta a fazer a consulta, sendo que esse código do CATCH pode lançar uma nova SQLExcepion, sendo assim tenho que usar novo TRY/CATCH.

Achei meio estranho fazer assim, apesar de rodar beleza. Daí vem as perguntas:

  1. Está certo trabalhar assim?
  2. Caso não, como eu deveria fazer?

Obrigado pessoal… Aguardo a ajuda de vocês.

Abraço!

19 Respostas

Adelar

Olá,
é meio estranho, mas se não tem outra alternativa :?
não conheço como é a estrutura do HSQLDB, mas o que eu faria neste caso é ver se a tabela existe com algo como:

select table_name from information_schema.tables where table_name = 'dicas';

se me retornar resultado crio a tabela senão continuo o processo normal.

Att.

E

Acho que está OK. Não gosto quando as pessoas enchem os programas de flags, só para evitar tais coisas.

S

num da pra deixar tdo um try catch só?

E

Não; você não entendeu como ele queria fazer? A estrutura é assim:

tento fazer alguma coisa.
se deu pau
    tento fazer outra coisa
    se der pau nessa outra coisa, faço de conta que não vi

O primeiro “se deu pau” é o primeiro catch. O segundo “se der pau faço de conta que não vi” é o segundo catch.

S

entendi perfeitamente… eu particularmente não faria desse modo… vc faria? isso eh bem individual

Vingdel

Até onde consegui pensar, não da não meu camarada, pois a intenção é testar se a tabela existe no banco, para saber se preciso criá-la ou não.

Então como tenho que fazer uma consulta para preencher um JList, já faço tudo aí.

Tento consultar a tabela (precida ser dentro de um TRY, pois se a SQL tiver errada lança SQLException), no caso de a tabela não existir, vai pro CATCH da SQLException, lá crio a tabela (como mexo com SQL preciso de outro TRY/CATCH para tratar SQLException) e com a tabela criada já faço a consulta que eu queria.

Grande Adelar, como eu usaria o ResultSet da sua sugestão? Como eu testaria a existencia da tabela com a SQL que vc me passou?

Veja se é assim e se puder complete para mim…

try{ ... ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';"); // Como eu uso o ResultSet para testar? }catch(SQLException e){ //Crio Tabela Aqui... }

Grato pela atenção!

Att.

renamed

Cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe. Isso pode criar bugs futuros no seu sistema.
Você realmente precisa criar essa tabela através da sua aplicação? E se você precisar mudar de SGBD terá que recodificar seu sistema?
Nosso amigo deu uma forma menos dependente de BD aqui. Acredito que seja a segunda melhor opção. A primeira ainda é a já criação da estrutura física do seu BD.

Vingdel

Opa souzajhonatan, é exatamente isso que quero saber, as individualidades de cada um… Como você faria?

Conto com sua ajuda…

Att.

Vingdel

renamed:
Cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe. Isso pode criar bugs futuros no seu sistema.
Você realmente precisa criar essa tabela através da sua aplicação? E se você precisar mudar de SGBD terá que recodificar seu sistema?
Nosso amigo deu uma forma menos dependente de BD aqui. Acredito que seja a segunda melhor opção. A primeira ainda é a já criação da estrutura física do seu BD.

Pois então amigo renamed,
Exato, cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe, afinal no TRY não tento criar tabela alguma, mas sim acessar uma tabela. Cair naquele CATCH significa que ou a SQL ta errada ou ela ainda não pode ser usada, como a SQL ta correta, siginifica que a Tabela não existe…Analise melhor e verá que tenho razão no meu reciocinio.

Quanto ao tópico que você indicou, aquele tópico fui eu que criei tb…

Eu tentei fazer usando DatabaseMetaData, mas como postei lá, tava sempre dando que a tabela não existia, talvez por eu não estar fazendo corretamente, coloquei meu código lá, se você puder me dar uma força lá naquele tópico talvez a gente mate dois coelhos com uma cajadada só…

Obrigado pela atenção…

Abração!

Adelar

try{ ... ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';"); // Como eu uso o ResultSet para testar? }catch(SQLException e){ // Crio Tabela Aqui... }

Completando o código:

try{ ... ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';"); if(rs.next()){ // daí o código que vc tinha usado para criar a tabela } }catch(SQLException e){ // ... }
Concordo com o que renamed disse no post acima: a criação e manutençao do banco de forma independente da aplicação é a melhor alterativa.

Att.

S

eu faria no modelo que vc postou ai. eu faço assim.

Vingdel
Adelar:
Vingdel:
souzajhonatan:
num da pra deixar tdo um try catch só?
try{
	...
	ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
	// Como eu uso o ResultSet para testar?
}catch(SQLException e){
	// ...
}

Completando o código:

try{
	...
	ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
	if(rs.next()){
		// daí o código que vc tinha usado para criar a tabela
	}
}catch(SQLException e){
	//Crio Tabela Aqui...
}
Concordo com o que renamed disse no post acima: a criação e manutençao do banco de forma independente da aplicação é a melhor alterativa.

Att.

HUMMM, mas o rs.next() vai me retornar true alguma hora? Pergunto isso pois acredito que se caso a tabela exista, só vai existir ela e não vai haver uma próxima.

Talvez rs.last() como condição fosse a solução, mas pelo que andei lendo, o HSQLDB não suporta o método last().

Me corrija se eu estiver com raciocínio errado...

Mais uma vez, muito obrigado por ajudar!

EDIT: testei assim:

String consulta = "SELECT * FROM dicas";
		try{
			stm = conn.createStatement();
			rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
			if(rs.next()){   
				System.out.println("OK");   
			}else{
				System.out.println("NAO");
			}
		}catch(SQLException e){
			
		}

Testei com a tabela existindo e depois deletei a tabela, em ambos casos tive NAO como saída...
:(

O mesmo caso que aconteceu quando eu useu DatabaseMetaData...

Adelar
Vingdel:
Adelar:
Vingdel:
souzajhonatan:
num da pra deixar tdo um try catch só?
try{
	...
	ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
	// Como eu uso o ResultSet para testar?
}catch(SQLException e){
	// ...
}

Completando o código:

try{
	...
	ResultSet rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
	if(rs.next()){
		// daí o código que vc tinha usado para criar a tabela
	}
}catch(SQLException e){
	//Crio Tabela Aqui...
}
Concordo com o que renamed disse no post acima: a criação e manutençao do banco de forma independente da aplicação é a melhor alterativa.

Att.

HUMMM, mas o rs.next() vai me retornar true alguma hora? Pergunto isso pois acredito que se caso a tabela exista, só vai existir ela e não vai haver uma próxima.

Talvez rs.last() como condição fosse a solução, mas pelo que andei lendo, o HSQLDB não suporta o método last().

Me corrija se eu estiver com raciocínio errado...

Mais uma vez, muito obrigado por ajudar!

EDIT: testei assim:

String consulta = "SELECT * FROM dicas";
		try{
			stm = conn.createStatement();
			rs = stm.executeQuery("select table_name from information_schema.tables where table_name = 'dicas';");
			if(rs.next()){   
				System.out.println("OK");   
			}else{
				System.out.println("NAO");
			}
		}catch(SQLException e){
			
		}

Testei com a tabela existindo e depois deletei a tabela, em ambos casos tive NAO como saída...
:(

O mesmo caso que aconteceu quando eu useu DatabaseMetaData...

Estranho não ter dado certo. Se ele está sempre mostrando não então nunca está encontrando a tabela. Então pode ser que: ou HSQLDB guarda as referências a tabelas em outro local ou o nome da tabela criada não é exatamente 'dicas' (pode ser 'DICAS' ou vir com um prefixo antes, por exemplo). Tenta usar o SQL com like para ver ser funciona: "select table_name from information_schema.tables where table_name like 'dicas';"

Att.

renamed

Vingdel:
renamed:
Cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe. Isso pode criar bugs futuros no seu sistema.
Você realmente precisa criar essa tabela através da sua aplicação? E se você precisar mudar de SGBD terá que recodificar seu sistema?
Nosso amigo deu uma forma menos dependente de BD aqui. Acredito que seja a segunda melhor opção. A primeira ainda é a já criação da estrutura física do seu BD.

Pois então amigo renamed,
Exato, cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe, afinal no TRY não tento criar tabela alguma, mas sim acessar uma tabela. Cair naquele CATCH significa que ou a SQL ta errada ou ela ainda não pode ser usada, como a SQL ta correta, siginifica que a Tabela não existe…Analise melhor e verá que tenho razão no meu reciocinio.

Quanto ao tópico que você indicou, aquele tópico fui eu que criei tb…

Eu tentei fazer usando DatabaseMetaData, mas como postei lá, tava sempre dando que a tabela não existia, talvez por eu não estar fazendo corretamente, coloquei meu código lá, se você puder me dar uma força lá naquele tópico talvez a gente mate dois coelhos com uma cajadada só…

Obrigado pela atenção…

Abração!

Não. Todas os métodos das classes que implementam Connection lançam uma SQLException.
Você ter problemas na rede, autenticação, timeout etc…
Todos esses problemas são lançados através de uma SQLException.

Vingdel

renamed:
Vingdel:
renamed:
Cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe. Isso pode criar bugs futuros no seu sistema.
Você realmente precisa criar essa tabela através da sua aplicação? E se você precisar mudar de SGBD terá que recodificar seu sistema?
Nosso amigo deu uma forma menos dependente de BD aqui. Acredito que seja a segunda melhor opção. A primeira ainda é a já criação da estrutura física do seu BD.

Pois então amigo renamed,
Exato, cair naquele catch não garante que o erro foi tentar criar uma tabela que já existe, afinal no TRY não tento criar tabela alguma, mas sim acessar uma tabela. Cair naquele CATCH significa que ou a SQL ta errada ou ela ainda não pode ser usada, como a SQL ta correta, siginifica que a Tabela não existe…Analise melhor e verá que tenho razão no meu reciocinio.

Quanto ao tópico que você indicou, aquele tópico fui eu que criei tb…

Eu tentei fazer usando DatabaseMetaData, mas como postei lá, tava sempre dando que a tabela não existia, talvez por eu não estar fazendo corretamente, coloquei meu código lá, se você puder me dar uma força lá naquele tópico talvez a gente mate dois coelhos com uma cajadada só…

Obrigado pela atenção…

Abração!

Não. Todas os métodos das classes que implementam Connection lançam uma SQLException.
Você ter problemas na rede, autenticação, timeout etc…
Todos esses problemas são lançados através de uma SQLException.

Sim, renamed, entendo, mas o TRY referente a aquele CATCH só pode lanças essas SQLExceptions que eu citei… Não ta fazendo conexão ou qualquer outra coisa, apenas a consulta ao banco…

:thumbup:

renamed

Você continua podendo ter problema de timeout e outros…
O que eu quero dizer é que não adianta tampar o sol com a peneira. Distribua seu BD com a aplicação .

Jfalca

Rapaz … tenho uma duvida bem parecida!!!

to meio tapado esses dias e não consegui simplificar essa merd… rsrsrs

se trata de uma pesquisa no campo de fornecedor que podera ser feita por nome ou codigo…

tentei fazer a pesquisa desse modo

String sql = "select * from fornecedor where for_codigo = “+tf_fornecedor.getText()+” or for_nomefant like ‘% “+tf_fornecedor.getText()+” %’ ";

mas o resultado não erra satisfatorio…

e então resolvi fazer desse jeito abaixo e deu certissimo!!!

tentei tratar os possiveis erros de entrada de dados…

mas acho esse codigo muito grande pra fazer uma coisa que me parece tão simples… affff dor de cabeça… :shock:

try
    {
        if(!tf_fornecedor.getText().equals(""))
        {
            try
            {
                int num = Integer.parseInt(tf_fornecedor.getText());
                //JOptionPane.showMessageDialog(null, "É um numero " +num);

                 String sql = "select * from fornecedor where for_codigo  = "+tf_fornecedor.getText();

                //JOptionPane.showMessageDialog(null, sql);
                con_fornecedor.executeSQL(sql);

                        if(con_fornecedor.resultset.first())
                            {
                               tf_fornecedor.setText(con_fornecedor.resultset.getString("for_nomefant"));
                            }
                        else
                            {
                              Object[] opcoes ={"Sim","Não"};
                              int opcao =  JOptionPane.showOptionDialog(this,"Cadastrar fornecedor ?","Fornecedor não cadastrado",0,JOptionPane.QUESTION_MESSAGE,null,opcoes,opcoes[0]);

                              if(opcao == 0)
                              {
                                 JOptionPane.showMessageDialog(null, "Cadatro de fornecedor");
                              }

                            }


            }
            catch(NumberFormatException num)
            {
               // JOptionPane.showMessageDialog(null, "Não é um numero " +num);
                String sql = "select * from fornecedor where for_nomefant like '%"+tf_fornecedor.getText()+"%'";
                
               // JOptionPane.showMessageDialog(null, sql);
                con_fornecedor.executeSQL(sql);
                
                        if(con_fornecedor.resultset.first())
                            {
                               tf_fornecedor.setText(con_fornecedor.resultset.getString("for_nomefant"));
                            }
                        else
                            {
                              Object[] opcoes ={"Sim","Não"};
                              int opcao =  JOptionPane.showOptionDialog(this,"Cadastrar fornecedor ?","Fornecedor não cadastrado",0,JOptionPane.QUESTION_MESSAGE,null,opcoes,opcoes[0]);

                              if(opcao == 0)
                              {
                                 JOptionPane.showMessageDialog(null, "Cadatro de fornecedor");
                              }

                            }

        
             }
          }
    }
    catch(SQLException erro)
    {
       JOptionPane.showMessageDialog(null,"erro ao tentar buscar fornecedor "+erro);
    }
ViniGodoy

Eu sigo a opinião do renamed.

Se o BD fica com o cliente, eu geralmente crio uma tabela chamada Meta dentro do BD contendo como informação a versão do banco de dados.

Se o cliente não tem um BD, simplesmente rodo um script de criação.
Se ele já tem um BD, na execução do programa, verifico se a versão do BD é a esperada consultando a tabela meta.

Se a versão da meta for maior que a esperada pelo programa. Dou um erro dizendo que o banco foi gerado numa versão mais nova do software.
Se for menor, rodo todos os scripts, para atualizar o banco.

Por exemplo, meu BD está na versão 5, e aplicação na máquina do cliente está na 3.
O programa roda a atualização da 3 para a 4, e da 4 para a 5.

É uma boa gerar uma cópia do banco para a migração, e também criar um arquivo de log, para caso alguém reclame que a criação não foi possível. Deve ser um inferno manter um banco onde você não tem certeza se tabelas estão ou não presentes. Eu no máximo faria isso para tabelas temporárias mas, como seu BD não suporta o teste de existência, eu criaria essas tabelas e as esvaziaria ao invés de deleta-las.

ViniGodoy

Ah, agora que vi. O JFalca ressuscitou o tópico com uma dúvida que não tem absolutamente nada a ver com o tema do tópico original. ¬¬
Rapaz, cuidado para não ressuscitar tópicos antigos. Se for pouco antigo como esse, tenha certeza de que você está contribuindo com algo 100% relacionado ao problema original, e não postando um novo problema.

Criado 20 de julho de 2010
Ultima resposta 1 de jan. de 2011
Respostas 19
Participantes 7