E aí, galera, tudo bem?
Hoje vou dar uma dica rapidinha, sobre como montar de forma simplificada filtros
dinâmicos para consultas SQL em C# com o mesmo conceito aplicável em Stored
Procedures.
Construir um filtro dinâmico para uma consulta SQL é basicamente concatenar
strings montando-se a cláusula Where desejada. Por exemplo, em uma tabela com a
seguinte estrutura:
CREATE TABLE EXEMPLO (
ID integer not null primary key,
NOME varchar(200),
RG varchar(9),
CPF varchar(11),
SEXO char(1)
);
Suponhamos que será feita uma pesquisa em que a nossa tabela EXEMPLO será filtrada
pelos campos NOME, CPF e SEXO com as seguintes condições: O campo somente será incluído
na filtragem se o usuário digitar algum valor (ou selecionar, caso ele não seja
um campo livre, como em combo-boxes e afins), caso contrário, ele não será incluído
na query.
A princípio, montaríamos a nossa instrução de pesquisa em C# assim:
public DataView MinhaPesquisa(string Nome, string CPF, string Sexo)
{
string isql = "select * from EXEMPLO ";
string strWhere = "";
ArrayList filtros = new ArrayList();
//Aqui verificamos se o usuáro digitou algo nos campos de pesquisa para montarmos o Where
if(!Nome.Trim().Equals(""))
filtros.Add(String.Format("(NOME like '{0}%') ",Nome.ToUpper().Trim()));
if(!Sexo.Trim().Equals(""))
filtros.Add(String.Format("(SEXO = '{0}') ",Sexo.ToUpper().Trim()));
if(!CPF.Trim().Equals(""))
filtros.Add(String.Format("(CPF like '{0}') ",CPF.ToUpper().Trim()));
foreach(string s in filtros)
where += s + " and ";
where = where.Equals("")?"":(" where " + where.Substring(0,where.Length - 4));
isql = isql + where;
... //Aqui você executa a instrução SQL...
}
Não é muito complicado depois que pega o jeito, o modelo de montagem para qualquer
filtro é o mesmo. Declaramos a string que será a nossa instrução SQL (variável isql),
nossa cláusula where montada (variável where) e um ArrayList
que irá receber os nossos filtros parciais: se o usuário digitar o valor correspondente
ao filtro, ele é incluído no ArrayList. Em seguida, essa matriz é varrida e os valores
parciais são concatenados em where seguido de um operador SQL and.
Quando terminar o foreach, note que ficará sobrando um "and" no final da string.
Então, com o código abaixo do foreach, removemos esse and que ficou sobrando, caso
tenha alguma coisa em where (se for vazio, e não fizermos a checagem de string vazia,
a instrução Substring irá dar pau).
Mas, para evitar tudo isso, tem uma aplicação prática da POG.
Isso mesmo, a famosa Programação Orientada a Gambiarras! Veja como
vai ficar a nossa instrução de pesquisa:
public DataView MinhaPesquisa(string Nome, string CPF, string Sexo)
{
string isql = "select * from EXEMPLO where (1 = 1) ";
isql += Nome.Trim().Equals("")?"":(String.Format(" and NOME like '{0}%' ",Nome.Trim().ToUpper()));
isql += CPF.Trim().Equals("")?"":(String.Format(" and CPF = '{0}' ",CPF.Trim().ToUpper()));
isql += Sexo.Trim().Equals("")?"":(String.Format(" and SEXO = '{0}' ",Sexo.Trim().ToUpper()));
...//Execução do SQL
}
O que fizemos: Acrescentamos diretamente em isql uma cláuslua Where que retornará
todas as tuplas da tabela se não for especificado nenhum filtro. Caso o usuário
digite algo nos campos de pesquisa, a concatenação das cláusulas where serão feitas
diretamente em isql e note também que o operador AND foi movido para o início de
cada filtro.
Com isso, eliminamos os "if", ArrayList, foreach...
Só não escapamos dos "if" se a nossa query for parametrizada.
Ah, também podemos montar nesse mesmo esquema uma Stored Procedure que retornará
um resultset, montando a instrução SQL e os filtros dentro da SP. Vou mostrar o
exemplo de uma em FireBird:
CREATE PROCEDURE SP_MINHA_PESQUISA (
nome varchar(200),
cpf varchar(11),
sexo char(1))
as
declare variable "ISQL" varchar(1000);
begin
ISQL = 'select * from EXEMPLO where (1=1) ';
if(not (NOME is null) ) then
ISQL = ISQL || ' and NOME like ''' || nome || '''%)';
if(not (CPF is null) ) then
ISQL = ISQL || ' and CPF = ''' || CPF || ''')';
if(not (SEXO is null) ) then
ISQL = ISQL || ' and SEXO = ''' || SEXO || ''')';
for execute statement ISQL into ... do
begin
--faça o que tiver que fazer :-)
end
end
Viu como o processo é simples? A mesma "técnica" que usamos no C# fizemos em PSQL
também :-)
Espero que eu tenha ajudado!