A maioria dos sistemas comerciais conta com várias telas de consulta, onde o usuário pode localizar registros específicos a partir de filtros pré-definidos. Porém, o comum é que cada janela seja voltada para uma única tabela (ou um conjunto delas).
Neste artigo, desenvolveremos uma tela de consulta genérica, onde o usuário poderá filtrar dados de uma tabela qualquer e definir o filtro dinamicamente, visualizando uma expressão representativa da consulta.
Para isso, utilizaremos o Microsoft SQL Server 2012 (outras versões podem ser utilizadas sem problemas) e o Delphi XE2. Como engine de conexão, usaremos o ADO.
Para iniciar, criemos uma nova aplicação VCL no Delphi a partir do menu File > New > VCL Forms Application.
No form principal, adicione um componente ADOConnection e, antes de tudo, desmarque a propriedade LoginPrompt para que a tela de login não seja exibida sempre que uma conexão como banco for requisitada. Em seguida, dê duplo clique sobre o controle e configure a conexão com o banco de dados, de acordo com as variáveis do seu computador e servidor.
Na tela exibida na Figura 1, clique em “Build...”.
Figura 1: Configurar Connection String
Na tela seguinte, selecione o provedor “Microsoft OLE DB Provider for SQL Server”, como mostra a Figura 2, e clique em “Avançar”.
Figura 2: Seleção do provedor de acesso ao banco
Na tela seguinte, insira as informações requisitadas, selecionando o servidor, o banco de dados e definindo as credenciais de acesso.
Figura 3: Definição de variáveis de conexão
Clique em “OK” e, na tela que voltará a aparecer, clique novamente em “OK”, finalizando a configuração.
Listando as tabelas do banco
O primeiro passo para a criação da consulta genérica, é disponibilizar a lista de tabelas do banco para o usuário escolher em qual deseja pesquisar.
Observação 1: o layout utilizado aqui é apenas uma sugestão, o leitor pode optar por organizar os componentes na tela da forma como preferir.
Adicione um GroupBox com a propriedade “Align” definida como “alTop”. Em seu interior, adicione um Label com “Caption” igual a “Tabelas disponíveis” e um ComboBox com “Name” definido como “cbbTabelas”. Esta configuração é mostrada na Figura 4.
Figura 4: ComboBox para listar as tabelas
Agora, no evento OnShow do formulário, adicione o código constangem na Listagem 1, onde é utilizado um componente ADOQuery instanciado em tempo de execução para listar as tabelas do banco no cbbTabelas.
Listagem 1: Listando as tabelas do banco
cbbTabelas.Items.Clear();
with TADOQuery.Create(Self) do
begin
Connection := ADOConnection1;
SQL.Text := 'SELECT * FROM Sys.Tables';
Open();
First();
while not Eof do
begin
cbbTabelas.Items.Add(FieldByName('name').AsString);
Next();
end;
end;
A tabela Sys.Tables armazena informações referentes às tabelas existentes no banco de dados para o qual a ADOConnection está configurada. A Figura 5 mostra o resultado, no meu caso, ao compilar o programa.
Figura 5: Tabelas listadas
Listando as colunas da tabela selecionada
Para filtrar os dados de uma tabela, é necessário escolher uma coluna pela qual se deseja pesquisar e, para isso, é preciso primeiramente que o usuário tenha acesso à lista de colunas da tabela selecionada. Adicione os mesmos componentes visuais utilizados para a listagem de tabelas (GroupBox, Label e ComboBox) e configure conforme a Figura 6. Altere o nome do ComboBox para “cbbColunas”.
Figura 6: ComboBox para listar as colunas
Em seguida, no evento OnChange do cbbColunas adicione o código da Listagem 2 para que, ao selecionar uma tabela, as suas colunas sejam listadas.
Listagem 2: Listando as colunas da tabela selecionada
cbbColunas.Items.Clear();
with TADOQuery.Create(Self) do
begin
Connection := ADOConnection1;
SQL.Text := 'SELECT '+
' c.name '+
'FROM '+
' Sys.Columns c '+
'LEFT OUTER JOIN '+
' sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id '+
'LEFT OUTER JOIN '+
' sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id '+
'WHERE '+
' c.object_id = OBJECT_ID(:tabela)';
Parameters.ParamByName('tabela').DataType := ftString;
Parameters.ParamByName('tabela').Value := cbbTabelas.Text;
Open();
First();
while not Eof do
begin
cbbColunas.Items.Add(FieldByName('name').AsString);
Next();
end;
end;
A tabela Sys.Columns, semelhante à Sys.Tables, armazena informações sobre as colunas de todas as tabelas do banco de dados em uso. No caso, como desejamos apenas as colunas tabela selecionada, utilizamos um filtro na coluna OBJECT_ID que armazena a tabela a qual a coluna pertence.
Ao compilar a aplicação, o resultado é semelhante ao que é mostrado na figura a seguir, para o meu caso.
Figura 7: Colunas da tabela selecionada listadas
Selecionando o filtro
Agora que já temos as tabelas e colunas, é preciso fornecer ao usuário opções de filtro para que ele possa realizar suas pesquisas como desejar. Para isso utilizaremos alguns filtros padrões da linguagem SQL que são:
- Maior que;
- Menor que;
- Maior ou igual a;
- Menor ou igual a;
- Começa com;
- Termina com;
- Contém.
Disponibilizaremos essa lista também em um ComboBox, então repita os mesmos passos para adicionar os mesmos controles visuais usados nas duas listagens anteriores. Dessa vez, mude o nome do ComboBox para cbbOperador e configure a janela conforme a Figura 7.
Figura 8: ComboBox para selecionar o operador
Altere a propriedade “Items” deste último ComboBox e adicione os filtros listados anteriormente. Ao lado do terceiro do cbbOperador, insira um Label e, em seguida, um TEdit, alterando a propriedade “Name” deste para “edtValor”.
Executando o programa e expandindo os filtros, teremos um resultado semelhante à Figura 8.
Figura 9: Lista de filtros disponíveis
Implementando o filtro
Enfim, chegamos à parte final da consulta genérica. Nesse ponto vamos, de fato, implementar os filtros definidos para realizar uma consulta no banco de dados.
Insira um componente TPanel também alinhado ao topo como os GroupBoxes e remova o conteúdo da propriedade “Caption”. No interior do painel adicione um TButton com a propriedade “Text” contendo o valor “Consultar” ou semelhante.
No espaço restante do form, adicione um TDBGrid e mude a propriedade “Name“ deste para “gridConsulta” e a “Align” para “alClient”. O layout do form agora deve estar como na figura a seguir.
Figura 10: Layout final do form
Com a parte visual já definida, vamos partir para o código de implementação da consulta. Adicione então um componente do tipo TDataSource, defina seu nome como “dsConsulta” e ligue-o ao gridConsultas selecionando-o na propriedade “DataSource” deste último. Por fim, no evento OnClick do botão, adicione o código da Listagem 3.
Listagem 3: Execução da consulta
var
consulta : String;
qry : TADOQuery;
begin
consulta := 'SELECT * FROM ';
consulta := consulta + cbbTabelas.Text;
consulta := consulta + ' WHERE ';
consulta := consulta + cbbColunas.Text + ' ';
case cbbOperador.ItemIndex of
0: consulta := consulta + '> '+ QuotedStr(edtValor.Text);
1: consulta := consulta + '< '+ QuotedStr(edtValor.Text);
2: consulta := consulta + '>= '+ QuotedStr(edtValor.Text);
3: consulta := consulta + '<= '+ QuotedStr(edtValor.Text);
4: consulta := consulta + 'LIKE ' + QuotedStr(edtValor.Text + '%');
5: consulta := consulta + 'LIKE ' + QuotedStr('%' + edtValor.Text);
6: consulta := consulta + 'LIKE ' + QuotedStr('%' + edtValor.Text + '%');
end;
qry := TADOQuery.Create(Self);
qry.Connection := ADOConnection1;
qry.SQL.Text := consulta;
qry.Open();
dsConsulta.DataSet := qry;
Agora já é possível executar a aplicação e testar o funcionamento dos filtros. A figura a seguir ilustra um exemplo.
Figura 11: Aplicação em funcionamento
Conclusão
Busquei, neste artigo, utilizar largamente o código nas consultas ao banco de dados, evitando ao máximo configurar componentes visualmente. Isso facilita a reprodução do exemplo pelo leitor, que pode utilizar o código tal qual é apresentado aqui.
Essa tela poderia ser implementada, por exemplo, com opções de consulta por mais de uma coluna, adicionando o operador AND na instrução SQL, porém, este não é o objetivo desta publicação.
Espero que o conteúdo aqui apresentado possa ser útill. Até a próxima.