UNEB - LP II – Delphi Professora Lucélia Delphi com Acesso a Banco de Dados Trabalhando com ADOQUERY O componente Query é um componente dataset, assim como o Table, especializado em conexões com tabelas. A diferença entre eles está na forma como acessam as informações. O Table liga-se diretamente a uma única tabela, através da propriedade TableName. O Query faz suas ligações através da linguagem SQL, o que lhe possibilita o acesso a várias tabelas. O Query também possui métodos mais eficientes de acesso aos recursos do servidor do que o Table. Além de fazer uso de uma linguagem mais eficiente, permite o servidor processar requisições mais rapidamente e com menos tráfego de rede. Os exemplos conduzidos por este material serão baseados em um banco de dados Access contendo duas tabelas: Produto e Categoria. As mesmas usadas no material “Uso do Componente ADOConnection”. Mostraremos novamente o modelo e as especificações de tabelas a seguir: Fig. 1 – modelo de dados do cadastro de produtos 1) Criando o Banco de Dados Para definir o banco de dados, usaremos o SGBD Access da Microsoft. Entre no programa, crie um banco de dados vazio e salve em uma pasta Consprod. a) Criação da Tabela Categoria Selecione a opção Criar Tabela no Modo Estrutura e informe os seguintes dados na janela: Chave Nome do campo Tipo de dados Tamanho codigo descricao Autonumeração Texto 40 1 Salve a tabela com o nome “Categoria”. Abra a tabela Categoria no modo dados e informe os seguintes valores para a coluna descricao: Limpeza, Alimentação, Vestuário e Bebidas. Para salvar um registro, basta pressionar seta para baixo ou para cima. Observe que o codigo da Categoria é inserido automaticamente assim que o registro é salvo. b) Criação da Tabela Produto Selecione a opção Criar Tabela no Modo Estrutura e informe os seguintes dados na janela: Chave Nome do campo codigo Tipo de dados nome estoque embalagem frágil Origem Valor codCat Texto Inteiro Texto Texto Texto Moeda Inteiro Longo Tamanho Autonumeração 50 5 1 25 Salve a tabela com o nome “Produto” 2) Criando o Projeto CadProdutos Entre no Delphi, selecione File Save All e salve a unit como uProduto na pasta ConsProduto e em seguida o projeto, como PConsProduto. Altere as seguintes propriedades do formulário: • Name= FconsProduto • Caption = Cadastro de Produtos • Position=poScreenCenter. 3) Definindo o Módulo de Dados Para criar o módulo de dados, acesse a opção File New Data Module. Salve a unit como “UDM”. Em seguida, altere o nome do Datamodule (propriedade name) para DM. a) ADOConection Insira um componente ADOConnection (paleta ADO) no data module e altere as seguintes propriedades 2 ConnectionString: Selecione a propriedade ConnectionString e clique nas reticências. Na janela que se abrirá, verifique se a opção “Use Connection String” está marcada e clique no botão Build para abrir a janela “Propriedade de Vinculação de dados”. Na orelha Provedor, selecione o driver “Microsoft Jet 4.0 OLE DB Provider” e clique em avançar. Na aba Conexão clique nas reticências do item 1 e selecione o banco de dados (consprod.mdb) que será acessado e clique em Ok. Loginprompt: False (inibe a janela de senha do banco de dados) Name: ADOConsProd (padrão ADO + nome_do_programa) Connected: True b) ADOQuery Insira um componente ADOQuery (paleta ADO) e altere as seguintes propriedades • Connection: • Name: selecione o nome do componente ADOConnection (ADOConsProd); QrProd c) Datasource Insira um componente Datasource (paleta Data Access) e altere as seguintes propriedades • Dataset: • Name: selecione o nome do componente ADOquery (QrProd); DsConsProd d) ADOTable Insira um componente AdoTable (paleta ADO) e altere as seguintes propriedades • Connection: • Name: selecione o nome do componente ADOquery (QrProd); TBCat • Tablename: • Active: Categoria True e) Datasource Insira um componente Datasource (paleta Data Access) e altere as seguintes propriedades • Dataset: • Name: TBCat; DsCat 3 Seu data module deve estar semelhante ao da figura abaixo: 4 Exemplo 1 a) Torne o formulário FconsProd ativo. Em seguida, faça-o usar a unit do data module entrando na opção File Use Unit e selecionando Udm; b) insira componente DBGrid (Data Controls) e altere a propriedade Datasource para DM.DsConsProd (nome do datasource ligado ao query) c) insira um botão no formulário, altere seu Caption para “Ver todos” e acrescente o seguinte código no seu evento OnClick: DM.QrProd.Close; // fecha o query DM.QrProd.SQL.Clear; // apaga conteúdo da propriedade Sql // adiciona o comando SQL DM.QrProd.SQL.Add('SELECT * FROM produto'); DM.QrProd.Open; // executa o query Execute o programa e clique no botão para ver o resultado abaixo: Como você pôde perceber, o ADOquery é semelhante ao componente ADOtable no que diz respeito à conexão com os componentes de acesso, pois ambos são datasets. Entretanto, todo ADOquery por padrão retorna um resultset não editável. Exemplo 2 – Consultas parametrizadas Na maioria das situações, ao invés de consultarmos todos os registros de uma tabela, selecionamos apenas uma parte deles, acrescentando uma cláusula WHERE em nosso comando SQL. Entretanto, essa cláusula pode não requerer um valor fixo, mas algo variável provindo da interface com o usuário. Nesse caso, chamamos esse valor de parâmetro. O parâmetro é identificado dentro do comando SQL colocando-se um sinal de dois pontos ( : ) antes do nome de uma variável. Por exemplo: WHERE nome = :cliente -> cliente é um parâmetro WHERE salario > :valor -> valor é um parâmetro Para exemplificar, iremos construir uma consulta que selecione todos os produtos que possuem uma determinada origem. Ao verificarmos os registros da tabela Produto, vemos que a coluna “ORIGEM” pode assumir os seguintes valores: São Paulo e Belo Horizonte. Baseado nisso, iremos inserir um componente de seleção na interface que permita a escolha da origem. a) Insira um label no form e altere seu Caption para “Origem”; b) insira um Combobox (paleta Standard) e altere as seguintes propriedades: • Name: CbOrigem • Items: cada valor em uma linha: São Paulo e Belo Horizonte Escreva o seguinte código no evento OnClick: DM.QrProd.Close; DM.QrProd.SQL.Clear; DM.QrProd.SQL.Add(' SELECT * FROM produto '); DM.QrProd.SQL.Add(' WHERE origem = :origem'); DM.QrProd.Parameters.ParamByName('origem').Value := CbOrigem.Text; DM.QrProd.Open; Nos comandos acima, vemos linhas semelhantes às do exemplo anterior. As mudanças ficam por conta das duas linhas que fazem a inclusão e da passagem de um parâmetro. A inclusão é determinada pela linha ..Add(‘ WHERE funcao = :origem’);, onde origem é o parâmetro. Parâmetros devem ser imediatamente precedidos pelo caractere dois pontos. E a passagem do 5 parâmetro é feita na linha Parameters.ParamByName('origem').Value := CbOrigem.Text, onde o parâmetro receberá o texto da opção selecionada no combobox. A vantagem da utilização de parâmetros é que a cada consulta realizada, pode-se trocar o valor do parâmetro informado e obter resultados diferentes. 6 Nota-se que o código do evento contém uma parte repetitiva representada pelo nome da query (DM.QrProd). É possível utilizar o comando with do Delphi para evitar ter que escrever seu nome em todas as linhas. Observe o mesmo código escrito com auxílio do comando with: with DM.QrProd do Begin Close; SQL.Clear; SQL.Add(' SELECT * FROM produto '); SQL.Add(' WHERE origem = :origem'); Parameters.ParamByName('origem').Value := CbOrigem.Text; Open; end; Exemplo 3 – Parâmetros baseados em combos dinâmicas No exemplo anterior, o campo função era representado por um combobox com os valores fixos. Veremos agora como construir uma consulta parametrizada baseada em um campo de outra tabela que possui um correspondente na tabela principal (chave estrangeira). Criaremos uma consulta que trará todos os produtos de uma categoria informada. Só que ao invés de digitar o código da mesma, será disponibilizado um combo para que seja selecionada a descrição. a) Insira um label no form e altere seu Caption para “Categoria”; b) insira um DbLookupCombobox (paleta Data Controls) e altere as seguintes propriedades: • Name: DblCategoria • Listsource: DM.DsCat • Listfield: descricao • Keyfield: codigo Depois de ter ajustado essas propriedades, verifique se a seta para baixo do componente DbLookupCombobox ficou habilitada. Se não estiver, confira se a propriedade Active do table DM.TbCat está true. Não altere as propriedades Datasource e Datafield do componente. Estas só podem conter valor se a interface for de entrada de dados. Escreva o seguinte código no evento OnClick do DbLookupCombobox with DM.QrProd do begin Close; SQL.Clear; SQL.Add(' SELECT * FROM produto '); SQL.Add(' WHERE codcat = :cat'); Parameters.ParamByName('cat').Value := DM.TBcat.FieldByName('Codigo').Value; Open; end; Podemos ver no código acima que o critério de seleção agora é determinado pelo campo codCat que contém o código da categoria do produto. Como o Dblookup aponta diretamente para a tabela Categoria (determinado pela sua propriedade Listsource), passamos o próprio valor do objeto field (codigo) para o parâmetro “cat” na linha Parameters.ParamByName('cat').Value := DM.TBcat.FieldByName('Codigo').Value; 7 Exemplo 4 – Trabalhando com parâmetros opcionais Agora veremos como criar uma consulta onde o operador poderá efetuar a consulta informando a quantidade que quiser de parâmetros. Se não informar nenhum, traremos todos os registros. Se informar algum, aplicamos aquele filtro individualmente. A lógica consiste em testar se o operador informou algum valor no campo do parâmetro e adicionar o respectivo filtro ao comando SQL. Prepararemos uma interface “especial” para separar este exercício dos demais. Baseie-se na figura abaixo: 8 a) Insira um groupbox (paleta Standard) no form e altere seu Caption para “Parâmetros opcionais”; b) insira um label e altere seu caption para “Nome”. Adicione também um Edit e altere: • Name: EdNome • Text: deixe em branco c) insira um label e altere seu caption para “fragil”. Insira um Radiobutton altere seu nome para Rbnao e seu Caption para “Não”. Insira um segundo Radiobutton ao lado do primeiro e altere seu nome para RbSim e seu Caption para “Sim” d) insira um DbLookupCombobox (paleta Data Controls) e altere as seguintes propriedades: • Name: DblCat (para distinguir do outro DblCategoria que está na tela) • Listsource: DM.DsCat • Listfield: descricao • Keyfield: codigo e) insira um label e altere o Caption para “Preço (>que)”. Adicione também um Edit e altere: • Name : EdValor • Text: deixe em branco. f) insira um Button e altere o Caption para “Pesquisar” g) digite o seguinte trecho no evento OnClick do botão Pesquisar: with DM.QrProd do begin Close; SQL.Clear; SQL.Add(' SELECT * FROM produto '); SQL.Add(' WHERE 1=1 '); //se tiver preenchido o nome, adiciona o filtro if (EdNome.Text <> '') then begin SQL.Add(' AND nome like :nome '); Parameters.ParamByName('nome').Value := '%'+EdNome.Text+'%'; end; //se tiver marcado frágil sim if (RbS.Checked) then begin SQL.Add(' AND fragil = "s" '); end; // se tiver marcado frágil não if (RbN.Checked) then begin SQL.Add(' AND fragil = "n" '); end; // se tiver selecionado a categoria if (DblCat.Text <> '') then begin SQL.Add(' AND codcat = :cat'); Parameters.ParamByName('cat').Value := DM.TBCat.FieldByName('Codigo').Value; end; // se tiver preenchido o preço, adiciona o filtro if (EdValor.Text <> '') then begin SQL.Add(' AND valor > :val '); Parameters.ParamByName('val').Value := StrToFloat(EdValor.Text); end; Open; end; end; 9 Logo no início, foi acrescentado o código “WHERE 1=1” no SQL. Essa condição foi colocada com uma única finalidade: criar uma cláusula where fixa para o select. Isso evita repetidos testes para verificar se o mesmo possui cláusula where antes de adicionar cada um dos filtros. Observe que para cada teste realizado, é inserido um trecho referente ao filtro desejado através do comando SQL.add() seguido da respectiva passagem de parâmetro. Isso permite que o operador tenha uma total flexibilidade na escolha dos parâmetros da tela. É possível passar valores fixos também, como está sendo feito no caso do campo frágil. No caso específico do filtro do campo nome, o recurso de passagem de parâmetros do Delphi não suporta a delimitação dos coringas da cláusula LIKE (caractere “%”) no próprio comando, tendo que ser passados na montagem do parâmetro, como pode ser verificado na linha Parameters.ParamByName('nome').Value := '%'+EdNome.Text+'%'; h) insira um Button e altere o Caption para “Nova Consulta”. Digite o seguinte trecho para evento OnClick EdNome.Clear; EdValor.Clear; DblCat.Keyvalue := -1; RbS.Checked := false; RbN.Checked := false; O seu formulário deverá estar assim: 10