Dúvida com PreparedStatement

19 respostas
Luiz_Henrique_Coura

ae Pessoal!

Estou utilizando PreparedStatement para fazer minhas queries no banco, porém eu preciso fazer uma query um pouco mais “inteligente”.

Tenho umas tabelas no banco q tem praticamente a mesma estrutura onde a única coisa de diferente é o nome.

Como eu faço, se tiver como, para fazer uma query utilizando essa estrutura?

SELECT * FROM ? WHERE status=?

Reparem q o nome da tabela eu tb mascarei.

Valew!

19 Respostas

Z

Não sei se alguém aqui tem alguma carta na manga pra esse tipo de coisa. Mas eu sempre fiz “na mão” mesmo esse tipo de coisa, e não vejo outro modo de fazer.

String tabela = "usuarios"; String sql = "SELECT * FROM "+ tabela +" WHERE status= ?";

Mauricio_Linhares

Luiz Henrique Coura:
ae Pessoal!

Estou utilizando PreparedStatement para fazer minhas queries no banco, porém eu preciso fazer uma query um pouco mais “inteligente”.

Tenho umas tabelas no banco q tem praticamente a mesma estrutura onde a única coisa de diferente é o nome.

Como eu faço, se tiver como, para fazer uma query utilizando essa estrutura?

SELECT * FROM ? WHERE status=?

Reparem q o nome da tabela eu tb mascarei.

Valew!

Você já tentou isso e não funcionou?

Z

Com certeza isso não funciona, Maurício.

Até pela própria natureza de bind variables, que são usadas para que o banco de dados mantenha um plano de acesso para consultas iguais com parametros diferentes.

É impossível (pelo menos no meu entendimento da coisa) bindar o nome de uma tabela.

Mauricio_Linhares

Eu sei lá como é que o driver JDBC faz isso, quem sabe num funciona, só sabe tentando :mrgreen:

Luiz_Henrique_Coura

São parâmetros q vem direto da linha de comando. Preciso deixar isso bem protegido. O usuário vai passar os parâmetros e os resultados serão armazenados em arquivos.

Qd tento isso direto, ele acusa erro:

Syntax error or access violation message from server: "You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near ''eta20' WHERE forecast='2005-06-20 00:00:00' ORDER BY idStation"

Esse é o trecho do código:

preparedStatement = connection.prepareStatement( QUERY ); preparedStatement.setObject( 1, query.getModel() ); //String preparedStatement.setObject( 2, query.getDate() ); //Date

Z

Quem vai reclamar não é driver JDBC, até pq ele não tem inteligência pra dizer se a query tá certa ou errada. Quem vai reclamar é o banco de dados mesmo, dizendo que não pode bindar (alguém tem uma tradução melhor pra isso?) a variável.

No Oracle eu sei que não funciona. Pode ser que em outros SGDBs, que não usem bind variables, funcione. Enfim… :mrgreen:

Mauricio_Linhares

Ah é, quando ele vê que o objeto é um string ele dá um setString e faz o escape do String. Bem que o ZehOliveira falou :mrgreen:

Mas se você souber o nome de todas as tabelas que são assim, ou pelo menos tiver como saber o nome de todas elas quando a aplicação iniciar, inicializa todos os prepared statements e mantém um Map ou uma collection qualquer com eles, assim quando você precisar, é só ir lá no map e pegar denovo :smiley:

Kleber_Santos

não seria algo assim?

SELECT ? FROM ? WHERE ?

onde “?” seriam parametros a passar?

:roll:

Z

Acho que o MySQL se encaixa no exemplo de SGDBs que eu citei acima. :smiley:

Quando você faz: setString(1, "tabela");

Ao invés de ser gerado: “SELECT *FROM tabela …”
Ele gera: “SELECT * FROM ‘tabela’ …”

(Veja bem, isso no caso do driver do MySQL. Pode ser que ele passasse as consulta com ? para o banco e deixasse o trabalho de bindagem com o banco de dados.)

Creio que o erro venha daí. Mas, nome de tabela não é pra ser passado como bind variable, mas sim como literal. Você deve fornecer uma query válida já com o nome da tabela e setar somente as variáveis.

Continuo batendo na tecla de fazer na mão. Tomando as devidas precauções, já que o dado vem de uma fonte não confiável (usuário).

Luiz_Henrique_Coura

Utilizo MySQL e ele acusou esse erro.

Pensei nessa solução do Maurício. O problema é q terei q ficar adicionando uma query nova para cada tabela nova q entrar.

Estou pensando em fazer filtrar os parâmetros passados pelo o usuário.

Zeh, gostaria de ler mais sobre bind variables, enfim, sobre essa característica do banco. Onde consigo encontrar?

Mauricio_Linhares

Luiz Henrique Coura:
Utilizo MySQL e ele acusou esse erro.

Pensei nessa solução do Maurício. O problema é q terei q ficar adicionando uma query nova para cada tabela nova q entrar.

Estou pensando em fazer filtrar os parâmetros passados pelo o usuário.

Zeh, gostaria de ler mais sobre bind variables, enfim, sobre essa característica do banco. Onde consigo encontrar?

Use Hibernate :mrgreen:
Use Hibernate :mrgreen:
Use Hibernate :mrgreen:
Use Hibernate :mrgreen:
Use Hibernate :mrgreen:

E bind variables é o que você faz quando dá um setQualquerCoisa() num prepared statement, você está “ligando” ou “posicionando” variáveis dentro da sua query.

Mas…

Use Hibernate :mrgreen:
Use Hibernate :mrgreen:
Use Hibernate :mrgreen:

Kleber_Santos

ZehOliveira, mas vc conseguiu resolver? e isso?

Kleber_Santos

desculpa, não é ZehOliveira

Luiz Henrique Coura

Z

Seja simples. Do it. :smiley:

Um link interessante sobre o assunto é http://www.mhavila.com.br/topicos/bd/sqlbind.html

Procurando por bind variables no Google você vai achar muita, muita coisa mesmo!

Luiz_Henrique_Coura

não seria algo assim?

SELECT ? FROM ? WHERE ?

onde “?” seriam parametros a passar?

:roll:

Kleber isso não funciona!

Maurício eu estou estudando Hibernate, inclusive baixei seu artigo sobre Hibernate 3 aqui do GUJ. Confesso q não pensei nesse caso.

Valew!

Mauricio_Linhares

Espero que ele seja o suficiente pra convencer você a usar o Hibernate :mrgreen:

Kleber_Santos

Kleber isso não funciona!

Maurício eu estou estudando Hibernate, inclusive baixei seu artigo sobre Hibernate 3 aqui do GUJ. Confesso q não pensei nesse caso.

Valew!

qto mais a gente discutir todos chegam numa solução

bele…

:mrgreen:

Luiz_Henrique_Coura

Valeu galera!

Valeu pelos artigos Zeh!

black_fire

Kra vc já tentou usar o MessageFormat.format em conjunto com o PreparedStatement.

Dá uma olhada no exemplo que fiz abaixo... Não testei, mas pela lógica deve funcionar... Espero que ajude Um abraço :wink:
import static java.text.MessageFormat.format;

public class NomeClasse {
	public ResultSet queryTableByStatus(Connection con, String table,
			Integer status) throws SQLException {
		
		// Cria o seu patern
		String sqlPatern = new String("select * from {0} where status = ?");

		// Muda o primeiro parâmetro com o nome da tabela
		String sql = format(sqlPatern, (Object) new String[] { table });
		
		// Faz a chamada para o prepare
		PreparedStatement ps = con.prepareStatement(sql);
		
		// Preenche as variáveis do statement
		ps.setInt(1, status);
		
		// Executa a sua query
		ResultSet rs = ps.executeQuery();
		return rs;
	}
}
Criado 24 de junho de 2005
Ultima resposta 25 de jun. de 2005
Respostas 19
Participantes 5