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

Configurar Connection String

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

Seleção do provedor de acesso ao banco

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.

Definição de variáveis de conexão

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.

ComboBox para listar as tabelas

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.

Tabelas listadas

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

ComboBox para listar as colunas

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.

Colunas da tabela selecionada listadas

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.

ComboBox para selecionar o operador

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.

Lista de filtros disponíveis

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.

Layout final do form

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.

Aplicação em funcionamento

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.