Dúvida com PreparedStatement

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!

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= ?";

[quote=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![/quote]

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

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.

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

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

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:

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:

não seria algo assim?

SELECT ? FROM ? WHERE ?

onde “?” seriam parametros a passar?

:roll:

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).

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?

[quote=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?
[/quote]

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:

ZehOliveira, mas vc conseguiu resolver? e isso?

desculpa, não é ZehOliveira

Luiz Henrique Coura

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!

não seria algo assim?

SELECT ? FROM ? WHERE ?

onde “?” seriam parametros a passar?

:roll: [/quote]

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!

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

[quote]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! [/quote]

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

bele…

:mrgreen:

Valeu galera!

Valeu pelos artigos Zeh!

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:

[code]
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;
}

}[/code]