ClientDataSetcom DBExpress e Firebird Módulo II Explorando o Banco de Dados Por Eduardo Rocha
[email protected] www.edudelphipage.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Sumário Preparando o ambiente........................................................................................... 3 Migrando o banco de Paradox para Firebird ........................................................... 7 Utilizando Alias para conexão com o banco de dados .......................................... 20 Utilizando a função COALESCE do Firebird ......................................................... 24 Utilizando a função NULLIF do Firebird ................................................................ 26 Utilizando a função CASE do Firebird ................................................................... 27 Utilizando domínios no banco de dados................................................................ 29 Utilizando o ISQL para criação e manipulação do banco de dados ...................... 33 Realizando Backups e Restores no Banco de Dados ........................................... 37 Criando e utilizando UDF's.................................................................................... 39 Uma visão geral sobre Stored Procedures............................................................ 46 Criando e implementando Stored Procedures....................................................... 49 Criando Stored Procedures no IBExpert ............................................................... 64 Utilizando Stored Procedures no Delphi................................................................ 69 Trabalhando com Stored Procedures que não retornam valores .......................... 70 Trabalhando com Stored Procedures que retornam um registro........................... 73 Trabalhando com Stored Procedures que retornam mais de um registro ............. 76 Executando a Stored Procedure que gera Exception............................................ 79 Criando e implementando Triggers ....................................................................... 82 Criando Triggers no IBExpert ................................................................................ 86 Utilizando Triggers no Delphi ................................................................................ 95 Criando e definindo Views................................................................................... 100 Criando e utilizando Views no IBExpert .............................................................. 104 Relatórios Mestre/Detalhe com performance ...................................................... 111 Criando Relatório Mestre/Detalhe utilizando NestedDataSet .............................. 113 Criando o Relatório utilizando Joins .................................................................... 122 Instalando e utilizando driver DBExpress de terceiros ........................................ 130 Trocando a senha do usuário SYSDBA .............................................................. 136 Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br -2- Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Preparando o ambiente Em quase todos os tópicos da apostila utilizaremos o IBExpert e o Delphi, portanto, sugiro já deixarmos preparada a conexão com o banco de dados através do IBExpert e o projeto básico no Delphi contendo apenas um formulário e um data module principal já conectado com o banco, assim quando entrarmos nos tópicos não precisaremos nos preocupar com estes detalhes. Criando a pastas No CD temos duas pastas chamada Diversos e Projeto, copie-as para C:\CursoClientDataSet2. A estrutura de diretórios deverá ficar da seguinte forma: Figura 1 – Estrutura de diretórios Na pasta Projeto tem tudo o que foi feito ao longo do curso, caso queira seguir passo a passo desde o início, sugiro que deixe apenas os arquivos abaixo excluindo os demais. cliente.* exemplo.fdb vendedor.* Figura 2 – Excluindo arquivos da pasta projeto e deixando apenas o básico Criando a conexão no IBExpert O instalador do IBExpert está disponível na pasta Diversos, portanto, caso não tenha instalado ainda aproveite este momento para realizar esta tarefa. Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br -3- Active Delphi - http//www.activedelphi.com.br http://www. vamos apenas preencher os campos da seguinte forma: Server: Local Server Version: Firebird 1.com.edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Estando com o IBExpert instalado em sua máquina.br -4- Active Delphi . execute-o e logo em seguida acesse o menu Database->Register Database.edudelphipage. pois isso já foi abordado no primeiro módulo deste curso.fdb Database Alias: VideoAulaCds2 User Name: SYSDBA Password: masterkey Charset: WIN1252 Verifique se esta apostila possui uma licença registrada www.br .5 Database File: C:\CursoClientDataSet2\Projeto\exemplo.com.activedelphi. Figura 3 – Acessando o item de menu Register Database Será exibida a seguinte janela: Figura 4 – Registrando o banco no IBExpert Não entrarei em detalhes sobre o registro do banco no IBExpert. portanto.http//www.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . edudelphipage.pas.edudelphipage.com.com. Em seguida podemos visualizar a conexão registrada no IBExpert conforme demonstra a figura a seguir: Figura 6 – Banco de Dados registrado no IBExpert Preparando o projeto no Delphi Abra o Delphi e inicie uma nova aplicação.http//www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 5 – Preenchendo os dados para registrar o banco de dados no IBExpert Após o preenchimento devemos clicar no botão Register para confirmar.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi.http://www.dpr em C:\CursoClientDataSet2\Projeto e o formulário principal salve como ufrmPrincipal. nomeie como dmPrincipal e salve-o com o nome udmPrincipal. Adicione um data module ao projeto.br -5- Active Delphi . No datamodule adicione um componente TSqlConnection e ajuste as seguintes propriedades: Verifique se esta apostila possui uma licença registrada www. Salve o projeto como CursoCds2.pas.br .com. com.fdb Dialect: 3 Charset: WIN1252 No evento OnCreate do datamodule adicione o seguinte código: procedure TdmPrincipal.com. Pronto.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . begin SqlConnPrincipal..DataModuleCreate(Sender: TObject).com.http://www.http//www.. agora podemos fechar o Delphi e partir para os próximos tópicos.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados TSQLConnection Name: SqlConPrincipal LoginPrompt: False DriverName: Interbase Params: DataBase: c:\CursoClientDataSet2\projeto\exemplo.Connected := True. já crie automaticamente o DataModule e o formulário principal. Verifique se esta apostila possui uma licença registrada www.edudelphipage. Agora vá ao menu Project->Options e na aba Forms ajuste o Auto-create forms e Available forms da seguinte forma: Figura 7 – Ajustando o Auto-Create forms do projeto Definimos esta ordem para que ao iniciar a aplicação. .br -6- Active Delphi . Agora no formulário principal adicione a unit udmPrincipal na cláusula uses: implementation uses udmPrincipal.edudelphipage. end. Confirme clicando no botão OK e logo em seguida salve o projeto.activedelphi. edudelphipage. portanto.com. pois o IBDataPump precisa do alias para selecionarmos nosso banco de origem. Esta ferramenta possui custo apenas para aquisição do código fonte ou suporte que são opcionais. A mesma pode ser baixada diretamente do site: http://www. Outro aspecto importante desta ferramenta é que ela nos permite fazer qualquer migração de dados que suporte ADO. Partindo para prática Para podermos migrar as tabelas paradox precisamos primeiramente criar um alias.br . Temos uma ferramenta gratuita no mercado chamada IBDataPump que nos permite fazer esta migração de forma bastante simples.exe e a seguinte tela será exibida.http//www.activedelphi. porém isso daria muito trabalho. DB2 entre outros).br -7- Active Delphi .com. conforme demonstra a figura a seguir: Figura 1 .edudelphipage. Sybase. Para demonstração utilizaremos duas tabelas paradox que acompanham o projeto e migraremos para o banco Firebird. apenas executar o utilitário. MSSQL.Criando o alias MigracaoParadox no BDEAdministrator Em seguida execute o IBDataPump. Access. Oracle.asp O mais interessante é que após baixá-la não é necessário instalar.com/products/datapump/ibdatapump. BDE e ODBC (DBbase.com. Verifique se esta apostila possui uma licença registrada www.http://www.clevercomponents. Paradox. vá até o BDE Administrator e crie um alias com o nome MigracaoParadox apontando para o diretório em que estão as tabelas paradox: C:\CursoClientDataSet2\Projeto.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Migrando o banco de Paradox para Firebird A migração poderia ser feita de modo manual gerando scripts SQL do banco para criação e inserção dos dados. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 2 - Tela inicial do IBDataPump O processo de migração deve ser feito em 2 etapas: primeiro criamos o banco em seguida migramos os dados. Criando o Banco de Dados No campo Source Database Properties selecione a opção BDESource. Em seguida no campo Source DB selecione o alias que criamos: MigracaoParadox. Perceba que ao selecionar, o botão Build SQL Script é exibido, veja na figura abaixo: Figura 3 - Selecionando o banco de origem Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br -8- Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Agora podemos clicar no botão Build SQL Script e a seguinte tela será exibida: Figura 4 - Tela para gerar o Script de criação do banco Nesta tela podemos ajustar diversos parâmetros para conversão dos tipos de campos, nome de tabelas, Charset entre outros detalhes. Em nosso exemplo ajustaremos o caminho onde o script será gerado para C:\CursoClientDataSet2\diversos\script_migracao.sql, o caminho onde o banco será criado C:\CursoClientDataSet2\diversos\testemigracao.fdb e também o Charset para WIN1252 por recomendação para compatibilidade com caracteres acentuados. Veja a seguir como ficarão os ajustes: Figura 5 - Ajustando os parâmetros para migração do banco Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br -9- Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Agora basta clicarmos no botão Start e o script para criação do banco de dados será gerado no caminho informado. Note que será exibida uma mensagem de conclusão. Figura 6 – Mensagem de conclusão da geração do script Confirme clicando no botão OK. Em seguida será aberto automaticamente o bloco de notas com o conteúdo do script gerado. Figura 7 – Bloco de notas sendo aberto automaticamente com o script Podemos fechar o bloco de notas, pois utilizaremos o próprio IBExpert para executar este script. Neste momento podemos fechar também a tela do IBDataPump clicando no botão Close. Agora abra o IBExpert e vá até o menu Tools e clique na opção Script Executive... Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 10 - Active Delphi - http//www.activedelphi.com.br 11 - Active Delphi . Clique no botão LoadFromFile conforme demonstra a seta em destaque (na imagem acima) para carregarmos o arquivo que contém o script de criação do banco que geramos anteriormente em C:\CursoClientDataSet2\diversos\script_migracao.Acessando a opção de menu Tools->Script Executive Em seguida será exibida a tela para execução de scripts. Verifique se esta apostila possui uma licença registrada www.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 8 .edudelphipage.br .edudelphipage.br .com.sql.activedelphi.http://www.http//www.com. com.edudelphipage.http://www.12 - Active Delphi .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .Carregando o arquivo de Script Figura 10 – Abrindo o script de migração Verifique se esta apostila possui uma licença registrada www.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 9 .com.com.br .http//www.edudelphipage.activedelphi. Script de criação do banco carregado Após termos carregado o script precisamos apenas executá-lo clicando no botão Run conforme demonstra a figura a seguir: Verifique se esta apostila possui uma licença registrada www.com.http://www.br .edudelphipage.com.http//www.13 - Active Delphi .com.edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 11 .br .activedelphi.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Migrando os dados Abra novamente o IBDataPump e vamos ajustar os parâmetros para indicar que agora queremos migrar os dados das tabelas paradox para o nosso banco recém criado em Firebird.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br . portanto devemos ajustar os seguintes parâmetros: Source Database Properties: BDESource Source DB: MigracaoParadox Destination DB: C:\CursoClientDataSet2\Diversos\TESTEMIGRACAO. o que precisamos fazer agora é executar o próximo passo que é a migração dos dados.http//www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 12 .com.com.com.activedelphi.Executando o script para criação do banco Neste momento já temos o banco de dados criado na mesma estrutura das tabelas em Paradox.edudelphipage.http://www.br .FDB (este foi o arquivo criado na execução do script que vimos anteriormente) CharSet: WIN1252 Os ajustes deverão ficar igual à figura a seguir: Verifique se esta apostila possui uma licença registrada www.edudelphipage.14 - Active Delphi . ou seja.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 13 .com.Step2 do IBDataPump Nesta tela criamos os vínculos entre as tabelas de origem e destino.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com. Verifique se esta apostila possui uma licença registrada www.Ajustando o IBDataPump para fazermos a migração dos dados Depois de ajustar os parâmetros podemos partir para o 2.br .http//www.o passo clicando na aba Step 2 localizada na parte superior da tela conforme demonstra a seta na figura anterior.activedelphi.edudelphipage. assim como seus respectivos campos.com.br . aqui informamos que os dados da tabela X serão enviados para tabela Y. Veja a seguir a tela a ser exibida ao clicar: Figura 14 .http://www.15 - Active Delphi .edudelphipage. 16 - Active Delphi .com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http//www.activedelphi. Para fazermos os vínculos manualmente poderíamos arrastar as tabelas do lado direito até o lado esquerdo. mas isso não é necessário. fazendo a respectiva associação e o mesmo poderíamos fazer para os campos.edudelphipage.br . teremos o seguinte resultado: Figura 15 . Verifique se esta apostila possui uma licença registrada www. precisamos trazer as definições das tabelas de origem e destino.http://www.com. para isso devemos clicar no botão Get Definitions.Carregando as definições das tabelas de origem e destino No lado esquerdo são exibidas as tabelas de destino e do lado direito as tabelas de origem.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Pode ficar tranqüilo que o IBDataPump já possui um recurso que faz este vínculo automaticamente analisando os nomes e tipos de campos de origem procurando-os na tabela de destino e fazendo o vínculo automaticamente.br .com. Ao clicar neste botão. Antes de tudo. Como criamos o banco de destino com a mesma estrutura do banco de origem então basta clicarmos no botão Build Relations e o IBDataPump realizará todos os vínculos automaticamente.edudelphipage. Veja a seguir o resultado após ter clicado no botão Build Relations. edudelphipage.com.http//www. por exemplo.br . Neste momento já podemos partir para o último passo clicando na aba Step 3.com.edudelphipage.17 - Active Delphi .http://www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Ao clicar será exibida a seguinte tela: Verifique se esta apostila possui uma licença registrada www. O que está em azul é a origem.Criando o relacionamento entre as tabelas de origem e destino Figura 17 – Vínculos feitos automaticamente após ter clicado em Build Relations Note na primeira coluna as setas do lado esquerdo e direito indicando destino e origem. isso significa que este campo receberá o valor do campo CLI_CODIGO da tabela de origem.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 16 . o mesmo conceito se aplica às tabelas. o campo CLI_CODIGO (em preto) possui um destaque do seu lado direito em azul com a palavra CLI_CODIGO.br .com.activedelphi. Verifique se esta apostila possui uma licença registrada www. mas não há problemas. podemos confirmar clicando no botão YES.Step3 do IBDataPump Nesta tela clicamos no botão Start para iniciar o processo de migração.br .br . Ao clicar será exibida a seguinte mensagem: Figura 19 – Mensagem exibida ao clicar no botão start.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .18 - Active Delphi .edudelphipage.com.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 18 .com.http://www.http//www. Esta mensagem é apenas um alerta informando que o banco está no modo ForcedWrites e por este motivo o processo poderá demorar.activedelphi. Ao final será exibida uma mensagem informando que a migração foi executada com sucesso.edudelphipage. com. nos permite migrarmos dados de outros bancos de dados.com. além disso.edudelphipage. Verifique se esta apostila possui uma licença registrada www.edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http//www.br .activedelphi.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 20 – Mensagem confirmando que o script foi executado com sucesso Conclusão Nosso objetivo neste capítulo foi explicar passo a passo o processo de migração de um banco Paradox para Firebird.19 - Active Delphi . porém sabemos que o IBDataPump possui muitos parâmetros que podem ser configurados na migração e vale a pena explorá-los para extrair ao máximo seus recursos e.com.http://www. br .http//www. isso será informado na string de conexão.5 do Firebird e acrescentou mais uma segurança é a possibilidade de utilizarmos um alias para conexão com o banco de dados representando o path do arquivo FDB.conf Veja abaixo o que temos neste arquivo: Figura 1 – Conteúdo original do arquivo aliases.http://www.br .conf e está localizado na raiz do diretório de instalação do Firebird. por exemplo: C:\Arquivos de programas\Firebird\Firebird_1_5\aliases.fdb. A idéia é criarmos um alias no servidor apontando para o caminho do banco e na aplicação utilizamos este alias.edudelphipage.edudelphipage.com.20 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando Alias para conexão com o banco de dados Um recurso muito interessante que surgiu na versão 1.activedelphi.fdb Perceba que definimos apenas o caminho físico do banco e não informamos o IP ou nome da máquina.conf Cada alias é criado em uma linha na seguinte estrutura: Nome do alias = caminho do banco Definindo um alias O exemplo abaixo define um alias com o nome SisExemploAlias apontando para o banco c:\sistema\exemploalias.com.com. A segurança está no fato de ocultarmos o caminho do banco na string de conexão substituindo pelo alias. desta forma evitamos que intrusos vejam o caminho do banco para executar alguma tarefa maliciosa. Verifique se esta apostila possui uma licença registrada www. O arquivo que contém a definição dos aliases chama-se aliases.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . SisExemploAlias = c:\sistema\exemploalias. 1:SisExemploAlias Note que utilizando alias ocultamos o caminho do banco. Partindo para prática Vá até a pasta C:\Arquivos de programas\Firebird\Firebird_1_5 e abra o arquivo aliases.1:c:\sistema\exemploalias. Inclua a seguinte linha no arquivo: ExemploAlias = c:\CursoClientDataSet2\projeto\exemplo.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .168.com. Neste momento já temos o alias.br .fdb Utilizando o alias: 192.1 e utilizando o protocolo padrão TCP para conexão com o banco.http//www.activedelphi.0.fdb O arquivo deverá ficar da seguinte forma: Figura 2 – Modificando o arquivo aliases.edudelphipage. a string de conexão seria: Não utilizando o alias: 192. esta é a grande vantagem.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Exemplo de utilização do alias na aplicação Supondo que o servidor onde o Firebird está instalado esteja com o IP 192.0. Abra o Delphi e inicie uma nova aplicação: Verifique se esta apostila possui uma licença registrada www.edudelphipage.conf do Firebird Salve o arquivo e feche-o.168.com.21 - Active Delphi .0.br .com. portanto iremos testar a partir de uma aplicação no Delphi.http://www.168.conf em algum editor de texto. http://www.br .com.http//www.edudelphipage.com. clique na propriedade Params e no parâmetro Database informe: localhost:ExemploAlias Verifique se esta apostila possui uma licença registrada www.edudelphipage.activedelphi.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 3 – Criando uma nova aplicação no Delphi Insira o componente SQLConnection e ajuste a propriedade DriverName para “Interbase”.br .22 - Active Delphi . Figura 4 – Definindo o driver interbase para conexão Em seguida.com. Conclusão Neste capítulo abordamos a utilização de alias para conexão com o banco de dados a fim de obtermos uma segurança a mais.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 5 – Ajustando o parâmetro Database para utilizar o Alias Confirme e faça o teste ativando a propriedade Connected do componente. onde o Firebird estaria em outra máquina substituiríamos o “localhost” pelo endereço IP do servidor.br .com.activedelphi. a própria restrição de acesso ao arquivo FDB e a pasta onde o Firebird está instalado.edudelphipage.edudelphipage. porém não podemos esquecer que outros aspectos de segurança também são importantes e não devem ser esquecidos como por exemplo. mas em um ambiente Client/Server. Em nosso exemplo utilizamos “localhost” por estarmos executando o teste na própria máquina que possui o servidor Firebird instalado.com.com.http://www.br . Verifique se esta apostila possui uma licença registrada www.23 - Active Delphi .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http//www. retornará o valor do último parâmetro da lista. neste exemplo retornaria o valor 0 (zero). Por exemplo.PROD_DESCONTO FROM PRODUTO Esta query funcionará perfeitamente desde que um dos campos PROD_VALOR e PROD_DESCONTO não sejam nulos em nenhuma situação. um representando o preço de venda padrão e outro promocional. porém só foi implementada a partir da versão 1.http://www. ao contrário do que muitos imaginam um valor NULO não é considerado ZERO. isto é muito útil em casos onde precisamos retornar valor X se não for nulo ou Y se o valor X for nulo. porém se precisássemos fazer isso diretamente no banco? Para este caso utilizamos a função COALESCE diretamente no SELECT.edudelphipage.24 - Active Delphi .edudelphipage. caso contrário. imagine que precisamos fazer um SELECT exibindo o valor dos produtos subtraindo seu desconto: SELECT PROD_VALOR . Se todos forem nulos. Nossa regra seria: se tiver um preço promocional. ela faz parte do padrão SQL92. logo poderíamos imaginar: . verificará o próximo campo (PROD_VALOR).5. caso contrário o preço padrão.http//www.br .br . A decisão se isto deve ser feito diretamente no SELECT ou em um campo calculado dependerá muito da situação. a operação retornará NULL. Neste exemplo a função verificará se o campo PROD_VALORPROMO é nulo. Esta função retorna o primeiro valor não nulo de uma lista de valores.com. Vejamos um exemplo: SELECT COALESCE(PROD_VALORPROMO. porém existe um caso em que a utilização da função COALESCE é muito importante. se tiver valor no campo promocional. 0) AS PRECO FROM PRODUTO A função COALESCE recebe N parâmetros e retorna o primeiro valor não nulo seguindo a seqüência da esquerda para direita. qualquer operação com NULO resulta em NULL. Certamente isso funcionaria. PROD_VALOR. exibimos este campo.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . caso contrário exibimos o valor padrão. Vamos analisar um exemplo prático: Imagine que temos uma tabela de produtos com dois campos de valores.Vamos criar um campo calculado no ClientDataSet e fazer a verificação. se não for retornará este valor.com. pois se em algum registro um dos campos forem nulos. deverá ser visualizado este preço.activedelphi. se não for nulo retornará o valor deste campo.com. Utilizando a função COALESCE isto pode ser resolvido facilmente: Verifique se esta apostila possui uma licença registrada www. Pensando nisso. se for nulo seguira a seqüência de verificação até encontrar um valor não nulo.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando a função COALESCE do Firebird A função COALESCE não é específica do Firebird. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados SELECT COALESCE(PROD_VALOR.com.0) FROM PRODUTO Desta forma antes de ser efetuada a operação os campos serão analisados e se algum deles for NULL será “substituído” (apenas na operação) pelo valor zero.25 - Active Delphi . Verifique se esta apostila possui uma licença registrada www.com.http//www.edudelphipage.br .0) .COALESCE(PROD_DESCONTO. Conclusão Neste capítulo podemos perceber o quanto é simples a utilização da função COALESCE e ao mesmo tempo o quanto ela pode ser importante em determinadas situações.com.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www. em seguida a operação é realizada com base nestas “substituições” e não teremos mais o problema de retornar NULL na operação.activedelphi.edudelphipage. Verifique se esta apostila possui uma licença registrada www. Conclusão A utilização da função NULLIF em um primeiro momento pode não parecer ser tão útil.edudelphipage. pois é o primeiro da lista.PROD_VALOR) AS PRECOPROMO FROM PRODUTO Neste exemplo será retornado NULL quando o campo PROD_VALORPROMO for igual ao campo PROD_VALOR.com. Poderíamos aplicar esta função em um UPDATE.26 - Active Delphi . por exemplo.br .br .edudelphipage. NULLIF(PROD_VALORPROMO. Imagine que precisamos definir NULL para o campo PROD_VALORPROMO quando o mesmo for igual ao campo PROD_VALOR. Vejamos um exemplo: SELECT PROD_VALOR.com.http://www.activedelphi. pois certamente em algumas situações sua utilização será de grande importância.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . quando forem diferentes será retornado o valor do campo PROD_VALORPROMO.http//www.com. neste caso podemos fazer da seguinte forma: UPDATE PRODUTO SET PROD_VALORPROMO = NULLIF(PROD_VALORPROMO.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando a função NULLIF do Firebird Esta função é utilizada para retornar NULL quando os dois valores passados no parâmetro forem iguais e quando forem diferentes será retornado o valor do primeiro parâmetro. mas vale a pena sabermos de sua existência. PROD_VALOR). br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . como faríamos? Logo poderíamos pensar em criar um campo calculado no ClientDataSet de modo que verificasse o campo Tipo de Produto e retornasse a respectiva descrição. CASE WHEN (PROD_TIPO = 'D') THEN 'DVD' WHEN (PROD_TIPO = 'L') THEN 'LIVRO' WHEN (PROD_TIPO = 'I') THEN 'INSTR. SELECT PROD_DESCRICAO. Esta função analisará o valor do campo PROD_TIPO e retornará a descrição de acordo com o seu valor. Vejamos um exemplo: SELECT PROD_DESCRICAO.com. CASE PROD_TIPO WHEN 'D' THEN 'DVD' WHEN 'L' THEN 'LIVRO' WHEN 'I' THEN 'INSTR. L=LIVRO e assim por diante. MUSICAIS' ELSE 'PRODUTO DESCONHECIDO' END AS PROD_TIPO FROM PRODUTO Podemos perceber que a estrutura é semelhante ao CASE do Pascal. Isto funciona perfeitamente.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando a função CASE do Firebird A função CASE é bastante semelhante ao comando CASE que utilizamos no Delphi ou mais precisamente na linguagem Pascal.activedelphi. vamos analisar o exemplo a seguir e logo entenderemos as diferenças. Se precisássemos exibir uma coluna com a descrição do Tipo de Produto.edudelphipage.edudelphipage. Sua função é retornar valores com base em condições. MUSICAIS' WHEN (PROD_TIPO IS NULL AND PROD_ATIVO <> 'S') THEN 'PRODUTO INATIVO' WHEN (PROD_TIPO IS NULL) THEN 'TIPO NAO DEFINIDO' ELSE 'TIPO DESCONHECIDO' END AS PROD_TIPO FROM PRODUTO Verifique se esta apostila possui uma licença registrada www.http//www.http://www. mas podemos fazer isso diretamente no banco de dados através da utilização da função CASE no SELECT.com.27 - Active Delphi . Existe uma outra forma de utilizarmos o comando CASE.br . Um exemplo prático de utilização é aquele caso onde temos uma tabela de produtos e possuímos um campo que representa o Tipo de Produto onde armazenamos apenas um “código” como D=DVD.br . com. podemos fazer qualquer tipo de comparação com qualquer campo inclusive verificando se o mesmo é nulo. além disso. por exemplo.edudelphipage. etc. ordenações. Verifique se esta apostila possui uma licença registrada www.activedelphi.28 - Active Delphi .edudelphipage. Conclusão Com a utilização da função CASE podemos evitar criar campos calculados na aplicação e.br . enquanto que na primeira forma isso não é possível e fazemos a comparação em apenas um campo.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Analisando esta segunda forma.br . pode nos beneficiar em outros aspectos. podemos fazer um agrupamento por este campo.com. notamos uma diferença.http//www.com. 29 - Active Delphi . /* recriando o campo PROD_VALORPROMO */ ALTER TABLE PRODUTO DROP PROD_VALORPROMO. alterarmos apenas o DOMINIO e conseqüentemente todos os campos que o utilizam.com. Agora vamos alterar a estrutura da nossa tabela definindo que os campos PROD_VALOR e PROD_VALORPROMO utilizarão o domínio. ALTER TABLE PRODUTO ADD PROD_VALORPROMO DOM_VALOR. Verifique se esta apostila possui uma licença registrada www.http//www. o que teremos que fazer é verificar todas a tabelas que possuem o campo Razão Social e alterar o tamanho do campo para cada tabela. Por exemplo.2). Transportadoras.com.2). Caso estivéssemos apenas adicionando um campo seria simples: ALTER TABLE PRODUTO ADD NOVO_CAMPO DOM_VALOR.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Fornecedores. ao invés de especificarmos que o campo é do tipo NUMERIC definimos que o mesmo é do tipo DOM_VALOR. criaremos da seguinte forma: CREATE DOMAIN DOM_VALOR NUMERIC(9.http://www. ALTER TABLE PRODUTO ADD PROD_VALOR DOM_VALOR. Imagine que amanhã percebemos que o campo Razão Social está muito curto e precisamos ajustar. Note que logo após o nome do campo.activedelphi. portanto. Podemos resolver esta situação facilmente utilizando domínios. serão modificados. Em nosso exemplo. Utilizando a primeira opção faríamos da seguinte forma: /* recriando o campo PROD_VALOR */ ALTER TABLE PRODUTO DROP PROD_VALOR. Em nosso exemplo estaremos alterando campos já existentes. é muito comum existência de tabelas de Clientes. e sempre utilizamos um campo Razão Social para todos estes casos. indicaríamos que os campos Razão Social são do tipo DOM_RAZAO_SOCIAL. criaríamos um domínio chamado DOM_RAZAO_SOCIAL especificando seu tipo como VARCHAR(50). por isso teremos um pouco mais de trabalho. etc. Quando precisarmos alterar o tamanho ou tipo dos campos Razão Social das tabelas.br . e na criação da tabela especificamos o tamanho do campo para cada tabela.edudelphipage. Partindo para prática Utilizaremos como exemplo nossa tabela de produtos que possui dois campos representando valores.edudelphipage. este é outro caso muito comum de criarmos um domínio representando valores. e na criação das tabelas. A instrução SQL acima criará um domínio chamado DOM_VALOR sendo do tipo NUMERIC(9.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando domínios no banco de dados A utilização de domínios no banco de dados é extremamente importante principalmente quando pensamos em ganho de tempo na manutenção do banco em situações onde precisamos alterar estruturas de campos. Podemos excluí-los e criá-los novamente ou alterá-los pelo IBExpert que o mesmo já executa uma instrução SQL para alterar os campos sem ter de recriá-los.br . http://www. Figura 2 – Campos da tabela de produtos. poderá optar pela segunda alternativa utilizando o IBExpert. Figura 1 – Editando a tabela de Produto Serão exibidos todos os campos da tabela de produtos. Verifique se esta apostila possui uma licença registrada www.br .activedelphi. Será exibida uma janela para podermos definir o domínio do campo.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .30 - Active Delphi .. com o IBExpert aberto e conectado no banco de dados.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Se preferir. Selecione o campo PROD_VALOR e de um duplo clique.edudelphipage.edudelphipage. portanto.http//www..br .com. clique na opção Tables na árvore selecionando a tabela PRODUTO e clique com o botão direito do mouse acessando o item de menu Edit Table.com.com. br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.br .com.31 - Active Delphi .com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 3 – Alterando o tipo do campo para utilizar o domínio Nesta tela clique no ComboBox de Domínios (Domain) e selecione o domínio que criamos: DOM_VALOR.http//www.edudelphipage.br .http://www. Em seguida basta clicar no botão OK e outra tela será exibida: Figura 4 – Confirmando a utilização do domínio no campo Este seria o SQL que deveríamos utilizar para alterarmos um campo definindo que o mesmo deverá utilizar um domínio. Agora clique no botão Commit e o campo será alterado conforme podemos observar na lista de campos a seguir: Verifique se esta apostila possui uma licença registrada www.activedelphi.edudelphipage. http//www.br .edudelphipage. a propriedade Size passou para 10: Figura 6 – Campos alterados automaticamente após a modificação da estrutura do domínio Conclusão Neste capítulo vimos que a utilização de domínios é simples e ao mesmo tempo extremamente importante permitindo-nos alterarmos a estrutura dos campos facilmente e com maior segurança.edudelphipage.com. Depois disso se precisar alterar a estrutura do domínio poderíamos executar a seguinte instrução SQL e todos os campos que utilizarem o domínio serão alterados: ALTER DOMAIN DOM_VALOR TYPE NUMERIC(10.com. Verifique se esta apostila possui uma licença registrada www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .32 - Active Delphi .2).http://www. ou seja. Executando a instrução acima comprovamos que os campos que utilizam o domínio tiveram sua estrutura modificada.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 5 – Lista de campos atualizada com o campo PROD_VALOR utilizando o domínio Repita o mesmo procedimento para o campo PROD_VALORPROMO para que ambos possam estar utilizando o domínio.activedelphi.com.br . http//www.activedelphi. digite a seguinte linha de comando: isql -user sysdba -pass masterkey Ao pressionar ENTER. Tudo se torna simples quando temos uma ferramenta visual.edudelphipage.com. Vamos exemplificar utilizando-o para criar um banco de dados e em seguida manipulá-lo.edudelphipage.33 - Active Delphi . será exibida a janela de linha de comando do ISQL: Figura 1 .http://www.com.com. é executado pelo prompt e sua versão para Linux é idêntica à versão para Windows. mas se um dia precisarmos criar ou manipular um banco de dados em um cliente onde não tivesse o IBExpert nem mesmo Internet para baixá-lo.br . Partindo para prática Através do prompt de comando programas\Firebird\Firebird_1_5\bin vá até o diretório: C:\Arquivos de Estando neste diretório.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando o ISQL para criação e manipulação do banco de dados No primeiro módulo deste curso vimos como criar e manipular um banco de dados através do IBExpert.ISQL sendo executado no prompt de comando Para criamos um banco utilizamos o comando CREATE DATABASE seguido do caminho: CREATE DATABASE “c:\CursoClientDataSet2\Projeto\NovoBanco. como faríamos? E se estivéssemos em um ambiente Linux? Resolvemos isso facilmente utilizando o ISQL que é um utilitário que já acompanha o Firebird. Verifique se esta apostila possui uma licença registrada www.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Com este utilitário criamos e manipulamos o banco de dados através da sua janela de linha de comando.fdb”. podemos visualizar os dados executando um SELECT: Digite a seguinte linha no prompt: SELECT * FROM CLIENTE.” (ponto-e-vírgula) ao final da linha. isso é o que indica o término de um comando.com.com. CLI_NOME VARCHAR(50)).edudelphipage. ‘CLIENTE 1’).com.34 - Active Delphi .activedelphi. Digite o seguinte comando SQL: CREATE TABLE CLIENTE (CLI_ID INTEGER NOT NULL PRIMARY KEY. agora podemos executar as instruções SQL para criar as tabelas.br . veja abaixo como ficou nossa seqüência de comandos executados: Figura 3 .edudelphipage. Após ter digitado a linha acima.br .http://www. Aperte o ENTER e digite: COMMIT.Banco sendo criado pelo ISQL Neste momento já temos o banco de dados criado.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Não esqueça de colocar “.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Vamos criar apenas uma tabela para demonstrarmos sua utilização. aperte o ENTER para executar este comando.Criando a tabela de cliente e inserindo dados Agora que já temos a tabela criada e com um registro inserido.http//www. Em seguida pressione ENTER para confirmar o último comando. Pressione ENTER e será exibido o seguinte resultado: Verifique se esta apostila possui uma licença registrada www. Figura 2 . Aperte o ENTER em seguida digite a linha abaixo: INSERT INTO CLIENTE VALUES (1. procedures. Ao pressionar ENTER teremos o seguinte resultado: Figura 6 . para visualizarmos a estrutura da tabela CLIENTE utilizamos a seguinte linha de comando: SHOW TABLE CLIENTE.edudelphipage.http//www. Por exemplo. etc.Executando um SELECT para visualizar os dados da tabela Note que podemos executar qualquer instrução SQL neste prompt.edudelphipage.Exibindo informações de uma tabela Verifique se esta apostila possui uma licença registrada www.com.activedelphi.br .br .com. ou seja.35 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 4 .Executando o comando HELP Temos diversos comandos que podemos utilizar no ISQL. um comando importante de ser comentado é o SHOW que nos permite visualizar informações de diversos objetos como cita o help: banco. O ISQL possui alguns comandos em particular que podem ser visualizados digitando HELP na linha de comando: Figura 5 .com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www. podemos manipular o banco de dados por completo. tabelas. br .com.com. Verifique se esta apostila possui uma licença registrada www.edudelphipage. no prompt do ISQL utilizamos o comando CONNECT informando o caminho do banco.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Para sair do ISQL basta digitar: EXIT. porém podemos entrar no ISQL e conectar em um banco de dados já existente da seguinte forma: Entramos no ISQL através da linha de comando já demonstrada: isql –user SYSDBA –pass MASTERKEY Em seguida.activedelphi. Todos os SQL acima foram executados no banco em que criamos.fdb e agora podemos executar SQL's. Vale a pena explorar o ISQL para saber de todos seus recursos que certamente serão importantes em momentos como este. etc.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . por exemplo: CONNECT "C:\CursoClientDataSet2\projeto\exemplo.com. Em seguida pressionar ENTER para confirmar.http://www. Conclusão Apesar de termos ferramentas visuais que auxiliam na manipulação do banco podemos perceber o quanto o ISQL pode ser útil em momentos que não temos estas ferramentas disponíveis principalmente quando estamos em um ambiente Linux.br .edudelphipage. pois logo após a criação do banco ficamos conectados no mesmo.http//www. visualizar tabelas. Para sair utilizamos o mesmo comando EXIT.fdb".36 - Active Delphi . Figura 7 – Conectando em um banco já existente Neste momento estamos conectados ao banco C:\CursoClientDataSet2\projeto\exemplo. Ao executar podemos verificar que em C:\CursoClientDataSet2\Projeto foi gerado o arquivo de backup exemplo. conseqüentemente ao final teremos um arquivo menor inclusive na restauração.edudelphipage.http://www. digite a seguinte linha de comando: gbak -c -USER SYSDBA -PASS masterkey c:\cursoclientdataset2\projeto\exemplo.br .bak .activedelphi. logo em seguida informamos o banco de origem e o caminho de destino onde será gerado o backup.bak Estando na pasta bin do Firebird.edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Realizando Backups e Restores no Banco de Dados Todos nós sabemos da importância que é realizar backups constantes do banco de dados.bak Figura 1 . Para realizarmos backups do banco Firebird não é recomendável apenas copiar o arquivo FDB.bak c:\cursoclientdataset2\projeto\exemplo_restaurado.br .http//www.com. ou até mesmo de uma versão do banco para outra. Vamos realizar um backup e logo em seguida um restore do banco de dados para visualizarmos na prática esse processo.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .37 - Active Delphi . Em nosso exemplo será: C:\Arquivos de programas\Firebird\Firebird_1_5\bin Nesta pasta digite a seguinte linha de comando: gbak -USER SYSDBA -PASS masterkey c:\CursoClientDataSet2\Projeto\exemplo. Partindo para prática No prompt de comando vá até o diretório de instalação do Firebird e entre na pasta bin.fdb Verifique se esta apostila possui uma licença registrada www. Como sabemos. os utilitários que acompanham o Firebird não possuem uma IDE. Quando realizamos um backup através do GBAK ele faz uma compactação do banco e exclui linhas de registros não mais utilizáveis.com. É recomendável também utilizarmos os processo de backup e restore quando precisamos transferir o banco de dados de uma máquina para outra. portanto o GBAK é utilizado também através do prompt de comando.fdb C:\CursoClientDataSet2\Projeto\exemplo. é muito mais seguro fazer um backup através do utilitário que acompanha o Firebird chamado GBAK. Vamos agora executar um restore do banco de dados utilizando o exemplo.Realizando o Backup do Banco de Dados O que passamos como parâmetro para o GBAK é o nome do usuário e a senha. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 2 .com.com.br .edudelphipage.Executando um Restore do Banco A diferença ao executarmos o GBAK para restore é que passamos o parâmetro –c indicando que o banco deverá ser criado a partir do arquivo exemplo.com.http://www. porém particularmente falando prefiro utilizar o parâmetro –c que cria o banco do zero ao invés de sobrescrevê-lo.http//www.bak. neste caso utilizaríamos o parâmetro –r ao invés do –c. Verifique se esta apostila possui uma licença registrada www.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi. Podemos executar um restore fazendo um replace no banco ao invés de um create. Conclusão O gbak possui muitas opções de parâmetros que podem ser exploradas. demonstramos aqui a forma mais simples que já é o suficiente para utilizarmos no dia-a-dia nos permitindo realizar backups e restore de forma segura.edudelphipage.38 - Active Delphi . Vejamos um exemplo de uma UDF já existente no Firebird: DECLARE EXTERNAL FUNCTION rtrim CSTRING(255) RETURNS CSTRING(255) FREE_IT ENTRY_POINT 'IB_UDF_rtrim' MODULE_NAME 'ib_udf'. mas talvez poucos exploraram ou conheceram o poder que pode nos trazer dependendo de como utilizamos. por exemplo. Vejamos um exemplo prático para entendermos melhor: SELECT CALCULA_VALOR(PROD_VALOR.edudelphipage. vamos apenas explicar como seria a declaração de uma UDF no Firebird. no Delphi podemos criar uma função que recebe N parâmetros e retorna um determinado valor.br . vejamos algumas: .http//www. porém esta função seria utilizada no banco de dados. já que precisamos garantir que elas sejam thread safe. ou seja. etc.edudelphipage. A criação desta biblioteca pode ser feita em qualquer linguagem que gere uma biblioteca compartilhada. em casos de utilização de blobs entre outros. Verifique se esta apostila possui uma licença registrada www. etc.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando e utilizando UDF's Muitos podem já ter ouvido falar em UDF. Com UDF podemos fazer o mesmo. SP’s.com. Para registrarmos uma função utilizamos o comando DECLARE EXTERNAL FUNCTION. Antes de partimos para prática.O retorno da função deverá ser um tipo de dado natural da linguagem C Existem outras regras mais detalhadas e técnicas no que diz respeito a tratamento de strings. UPDATE’s. em uma Stored Procedure.activedelphi. UDF (User Defined Functions) são funções definidas pelo usuário para serem utilizadas no banco de dados. Por exemplo. A criação de uma UDF resume em gerarmos uma DLL com as funções que gostaríamos de utilizar.Os tipos de dados devem ser somente aqueles suportados pelo Firebird .39 - Active Delphi .br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com. porém outros exemplos podem ser obtidos na Internet com mais detalhes. em um SELECT.Só é permitido ter no máximo 10 parâmetros . PROD_DESCONTO) FROM PRODUTO A função CALCULA_VALOR não existe no Firebird.http://www. assim poderemos utilizá-las livremente em SELECT’s. Neste capítulo demonstraremos dois exemplos de funções utilizando inteiros e strings que é o mais comum.com. no caso do ambiente Windows seria a DLL e no Linux um Shared Object. ela seria uma função que poderíamos ter criado em uma UDF e utilizada em um SELECT. por exemplo. Algumas regras devem ser obedecidas ao criarmos uma UDF. Depois de criada a UDF devemos registrar as funções. criamos uma função que recebe alguns parâmetros e nos retorna um determinado valor. Neste último exemplo podemos perceber que não foi utilizado o FREE_IT.so.edudelphipage. Na indicação do nome do arquivo é recomendável que não seja declarado a extensão. logo em seguida são declarados os tipos de parâmetros que esta função recebe. Outro detalhe importante é que não precisamos informar o path completo da biblioteca. neste caso rtrim. pois a mesma deverá estar dentro da pasta UDF do Firebird. A declaração FREE_IT indica que o Firebird deverá liberar a memória alocada dinamicamente.activedelphi.com. neste caso chama-se ib_udf.. Foi utilizado também o BY VALUE indicando que o tipo de retorno é por valor e não por referência. Após o ENTRY_POINT é declarado o nome da função contida na biblioteca. no caso é apenas um parâmetro do tipo CSTRING(255).http//www. Abra o Delphi e clique no Menu File->New->Other. pois no Windows o servidor Firebird estaria utilizando a extensão .dll e no Linux ..br . SMALLINT. Um outro exemplo de UDF utilizando mais de um parâmetro de entrada: DECLARE EXTERNAL FUNCTION substr CSTRING(255). por exemplo: DROP EXTERNAL FUNCTION CALCULA_VALOR Partindo para prática Vamos agora criar nossa UDF no Delphi e logo após registraremos e utilizaremos no Firebird. Na tela exibida escolha a opção DLL Wizard. pois assim não teríamos problemas se migrássemos o servidor de um ambiente Windows para Linux ou viceversa.edudelphipage. pois não está sendo retornado um tipo string.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . neste caso é a função IB_UDF_rtrim e ao final temos o nome da biblioteca que contém as funções.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Após o comando DECLARE EXTERNAL FUNCTION temos o nome da função a ser registrada. Excluindo o registro de uma UDF Para excluirmos o registro de uma UDF utiliza-se o comando DROP EXTERNAL FUNCTION e logo após informamos o mesmo nome indicado no registro. Logo após é declarado o tipo de retorno (RETURNS) sendo CSTRING(255).http://www. Um exemplo que não retorna string: DECLARE EXTERNAL FUNCTION tan DOUBLE PRECISION RETURNS DOUBLE PRECISION BY VALUE ENTRY_POINT 'IB_UDF_tan' MODULE_NAME 'ib_udf'. SMALLINT RETURNS CSTRING(255) FREE_IT ENTRY_POINT 'IB_UDF_substr' MODULE_NAME 'ib_udf'. isto é utilizado sempre que retornamos strings.com.40 - Active Delphi .com. Verifique se esta apostila possui uma licença registrada www.br . 41 - Active Delphi . A unit final deverá ficar da seguinte forma: unit uFuncoes. com o nome exemplo_udf.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . cdecl. iPos)).pas.com.http://www. export. Desconto: PDouble): Double. if iPos = 0 then iPos := Length(Pchar(nome)). export. export. function primeiro_nome(nome: pchar): pchar. end. 1. cdecl. porém antes vamos criar uma nova unit para centralizarmos e ficar mais organizado. end. export.http//www. implementation function calcula_valor(Valor: PDouble. end. Pchar(nome)).Criando uma nova DLL Ao confirmar já vamos gravar o projeto C:\CursoClientDataSet2\Projeto\UDF.edudelphipage. begin Result := Valor^ . begin iPos := Pos(#32.edudelphipage. cdecl.br . interface function calcula_valor(Valor: PDouble.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 1 .dpr na pasta Neste momento já podemos dar início à criação das nossas funções. function primeiro_nome(nome: pchar): pchar. function primeiro_nome(nome: pchar): pchar. Desconto: PDouble): Double. cdecl. Desconto: PDouble): Double. Result := Pchar(Copy(Pchar(nome). Agora vamos implementar duas funções: function calcula_valor(Valor: PDouble.com.com. var iPos: Integer. initialization IsMultiThread := true. Vá até o menu File->New->Unit e logo em seguida salve a unit como uFuncoes. Verifique se esta apostila possui uma licença registrada www.br .Desconto^.activedelphi. onde passaremos o valor e o desconto como parâmetros.com. porém na Internet. pois tornaria este capítulo muito extenso e complexo. O que há de diferente nas declarações é a utilização das diretivas cdecl e export ao final das funções. Depois de declarado e criado as funções. Clique no menu Project->View Source.edudelphipage. inclusive possibilitando o tratamento de valores nulos.edudelphipage. será exibido o código fonte do projeto conforme demonstra figura a seguir: Figura 2 . em diversos sites e na Firebase (www. portanto fazemos isso no Source do Projeto. A segunda função retornará o primeiro nome utilizando como base o caractere #32 (espaço) a partir da string passada como parâmetro.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . precisamos exportá-las.com.com.com.br . Utilizaremos esta função para retornar o primeiro nome do produto. devemos utilizar ponteiros para os respectivos tipos de dados. Não entraremos em detalhes sobre descritores.Código fonte do projeto Devemos alterar o código do projeto incluindo as seguintes linhas antes do begin: exports calcula_valor. Poderíamos utilizar descritores que nos permite trabalhar com qualquer tipo de dado. A última observação é que utilizamos a declaração IsMultiThread ao final da unit de modo que o gerenciador de memórias possa trabalhar com threads.http://www. isto deverá ser sempre utilizado para podermos exportar a função e utilizar banco de dados. primeiro_nome.br) temos bastante artigos sobre este assunto.firebase.activedelphi. Perceba também que utilizamos os tipos PChar e PDouble ao invés do tipo String ou Double. Utilizaremos esta função para calcular o valor do produto. Verifique se esta apostila possui uma licença registrada www.42 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados O objetivo da primeira função é apenas retornar o valor fazendo a subtração entre os dois valores passados no parâmetro.http//www. isso também é necessário. activedelphi. portanto em nosso exemplo copiaremos a DLL exemplo_udf.br . portanto.edudelphipage.http://www.http//www.43 - Active Delphi . para isso devemos executar as seguintes instruções SQL: DECLARE EXTERNAL FUNCTION CalculaValor DOUBLE PRECISION.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.dll para C:\Arquivos de programas\Firebird\Firebird_1_5\UDF Figura 4 – Copiando a dll para o diretório UDF do Firebird O último passo é registrá-la.com. não precisariam ser exportadas. pois poderíamos ter outras funções apenas para auxílio.br . O código final do projeto deverá ficar da seguinte forma: Figura 3 .edudelphipage. DOUBLE PRECISION RETURNS DOUBLE PRECISION BY VALUE ENTRY_POINT 'calcula_valor' MODULE_NAME 'exemplo_udf'.Exportando as funções a serem utilizadas Agora já podemos compilar o projeto para que seja gerada a DLL. Verifique se esta apostila possui uma licença registrada www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Devemos informar quais funções queremos exportar para podermos registrá-las no banco Firebird. O próximo passo será copiar a DLL para o diretório de UDF's do Firebird. PrimeiroNome(PROD_DESCRICAO).http://www.. já podemos realizar os testes utilizando as funções em um SELECT: SELECT PROD_DESCRICAO. conforme demonstra figura a seguir: Figura 5 – Executando as instruções SQL para registrar as funções Para fins didáticos o nome da função declarada no banco (após o FUNCTION) é diferente do nome da função que criamos no Delphi (declarada após o ENTRY_POINT). Estes nomes poderiam ser iguais. PROD_DESCONTO) FROM PRODUTO Figura 6 – Analisando o resultado com o uso das funções Verifique se esta apostila possui uma licença registrada www.com. CalculaValor(PROD_VALOR..ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados DECLARE EXTERNAL FUNCTION primeironome CSTRING(255) RETURNS CSTRING(255) FREE_IT ENTRY_POINT 'primeiro_nome' MODULE_NAME 'exemplo_udf'.com.com.br . Estas instruções SQL's poderão ser executadas no IBExpert através do menu Tools->Script Executive. apenas foi exemplificado desta forma para demonstrar que não é obrigatório registrar a função com o mesmo nome.44 - Active Delphi . PROD_DESCONTO.http//www. Depois de executada as instruções. PROD_VALOR.edudelphipage.edudelphipage.activedelphi.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br . http//www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note que no grid temos os dados do produto e o resultado das funções PrimeiroNome (pegando o primeiro nome do produto) e CalculaValor (valor do produto . Verifique se esta apostila possui uma licença registrada www. Apenas devemos prestar bastante atenção ao utilizarmos UDF’s principalmente quando o assunto é strings para não termos problemas de gerenciamento de memória.activedelphi.edudelphipage.45 - Active Delphi .desconto) da UDF.com. Conclusão A utilização de UDF's pode nos trazer grandes benefícios já que muitas rotinas que as vezes precisamos não estão disponíveis no Firebird.br .http://www. mas podem ser criadas no Delphi e utilizadas no banco.com.edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.br . com. executar cálculos. etc.br . Verifique se esta apostila possui uma licença registrada www. A estrutura de uma SP é um pouco semelhante a uma procedure do Delphi. implementamos e utilizamos no ambiente Delphi com o ClientDataSet em conjunto com a DBExpress. • Utilizando SP’s os processos estarão centralizados no servidor. chamar outras SP's. nossa proposta agora é criar as regras de negócio no banco de dados através da utilização de Stored Procedures e Triggers. varrer dados de uma tabela. ou mais precisamente. Na implementação de uma SP podemos criar variáveis.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Uma visão geral sobre Stored Procedures Até este momento trabalhamos com todas as regras de negócio diretamente na aplicação. em alguns casos estarei abreviando para “SP”. Uma Stored Procedure pode executar determinadas tarefas e também retornar valores.edudelphipage. estas SP's são chamadas de Stored Procedures Selecionáveis.46 - Active Delphi .br . isso quer dizer que devemos investir mais em hardware na máquina onde estará o servidor de banco de dados. para não ficar repetitivo citar “Stored Procedure”. O que é uma Stored Procedure? Antes de tudo. onde temos um cabeçalho informando os parâmetros de entrada e saída e o corpo contendo sua implementação. Vantagens • • • • • Aplicações mais leves Redução de tráfego em rede Regras de negócio centralizadas no banco Compartilhamento das regras para outras aplicações Ganho de performance na execução de processos Desvantagens Citar as desvantagens é algo bastante complicado. O objetivo deste capítulo é explicar o que é uma Stored Procedure e quando devemos utilizá-la para que logo em seguida possamos demonstrar como criamos. apenas devemos estar cientes de algumas questões: • Stored Procedures são dependentes do banco. executar instruções SQL's.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . pois por experiência própria e opinião particular não vejo nenhuma desvantagem em sua utilização. ok? Stored Procedures são rotinas armazenadas no banco de dados podendo ser disparadas pelo banco ou por aplicações e são executadas através de SELECT’s quando retornam valores ou através de um EXECUTE PROCEDURE quando não retornam valores.http//www. atualizar registros. isso significa que uma troca de banco de dados implicará em uma grande manutenção.com.edudelphipage. da linguagem Pascal.com.http://www. sendo utilizado para isso uma linguagem específica (PSQL).activedelphi. No Delphi apenas executaríamos a Stored Procedure e todo processo seria executado no servidor. Utilizando SP este processo é realizado apenas uma vez no momento em que criamos a SP no banco.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . pois seremos obrigados a carregar todos os produtos que precisamos alterar. Se optássemos por fazer isso na aplicação.http//www. Vamos analisar uma situação onde a utilização de uma SP seria mais eficiente que um processo sendo executado na aplicação.com. Obviamente que em aplicações pequenas não notaremos tanta diferença. Utilizando uma SP Ao utilizarmos uma SP podemos fazer esta varredura de produtos diretamente no servidor de banco de dados sem a necessidade de trafegar os registros pela rede.com. Podemos perceber que neste caso a utilização de uma SP é muito mais eficaz que a execução do processo na aplicação. o servidor tem a responsabilidade de analisar o SQL.edudelphipage. fazer um parser.edudelphipage. poderíamos fazer de algumas formas: Utilizando o ClientDataSet: Montaríamos uma query que retornaria todos os produtos. Utilizando Querys Abririíamos uma Query com todos os produtos. pois dependemos das informações de cada produto para podermos alterar seu preço. mesmo não havendo tráfego teríamos uma performance melhor do que executar estas instruções diretamente pela aplicação. fazer um plano de execução etc.com. Uma outra vantagem de SP interessante Podemos implementar uma SP que apenas executa determinadas instruções SQL no banco de dados. Nestes dois casos podemos perceber que um tráfego em rede será gerado. faríamos uma varredura em todos produtos analisando cada um e logo em seguida editaríamos o registro no ClientDataset e gravaríamos. por exemplo.http://www. Imagine que você tenha uma aplicação que precise atualizar uma lista de preço de produtos e este processo envolve analisar alguns dados do produto e com base nisso atualizar seu valor.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Quando utilizar uma SP? Não existe uma regra para isso. somente em um ambiente onde há um grande número de querys sendo executadas a todo instante.activedelphi.br . Isso ocorre pelo seguinte fato: quando a aplicação executa uma query no banco.47 - Active Delphi . abriríamos o ClientDataSet ligado a esta query. depois de armazenada podemos executar e este trabalho não será mais necessário.br . devemos analisar caso a caso e verificar se determinado processo seria possível ser rodado diretamente no banco ou parte dele passando parâmetros. faríamos um loop analisando cada produto e logo em seguida executaríamos uma outra query atualizando o preço do produto com base nos dados analisados. verificar se está tudo correto. Verifique se esta apostila possui uma licença registrada www. activedelphi.com. se você não pensa em trocar de banco de dados.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . A seguir abordaremos a prática demonstrando como criamos e implementamos Stored Procedures no Firebird.br . será que valeria a pena fazer tudo no banco? Como nosso foco neste momento é a utilização de SP. já que ele nos traz grandes benefícios e facilidades. então a utilização de SP sempre será mais eficaz. largar de vez o ClientDataSet.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados . “desvantagens” e casos de uso recomendados para sua utilização. Não precisamos chegar a este ponto. por exemplo.Legal.edudelphipage.Será que vale a pena tanto trabalho para coisas mais simples? Algumas pessoas são “viciadas” em SP’s e acabam utilizando inclusive em casos de cadastros de registros no banco. Conclusão Neste capítulo abordamos a teoria sobre Stored Procedures citando vantagens. então devo fazer tudo através de SP. portanto é muito importante que haja um bom investimento de hardware no servidor.com.48 - Active Delphi . Utilizar SP (regras no banco) ou aplicações multicamadas Este é um assunto que gera muitas dúvidas e é muito difícil decidir qual o melhor caminho. gostamos e confiamos no FB e não pretendemos mudar ☺ então iremos falar de SP e numa próxima oportunidade falaremos de Aplicações multicamadas. Verifique se esta apostila possui uma licença registrada www.br . Sempre que me perguntam digo que depende muito do caso.edudelphipage. podemos continuar a utilizar o ClientDataSet tranqüilamente.Calma. por que não usar SP’s centralizando as regras no banco? Mas e se você pensa em trocar. O objetivo ao longo do curso é demonstrar as metodologias e tecnologias e a partir disso termos conhecimentos suficientes para decidirmos o que é melhor para nós. Um fato que não devemos esquecer é a questão de performance do servidor.http//www.com. etc? .http://www. não é bem por este caminho ☺ . na maioria dos casos o ideal é utilizarmos as SP's para regras de negócios (processos) e em alguns casos para querys mais complexas ou que são executadas a todo instante. pois temos diversas vantagens e desvantagens comparando cada um desses. pois utilizando SP todo processo estará centralizado. http://www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . a diferença é que ao invés de estarmos utilizando CREATE PROCEDURE estaremos utilizando o ALTER PROCEDURE. e no caso de uma SP selecionável. DROP PROCEDURE SP_AJUSTA_VALORES. executaríamos da seguinte forma: EXECUTE PROCEDURE SP_AJUSTA_VALORES(10.edudelphipage.49 - Active Delphi .edudelphipage.com. NOVO_PARAMETRO INTEGER) AS BEGIN /* aqui vem a NOVA implementação */ END Até poderíamos dropar a SP e criar novamente. Vejamos um exemplo de uma SP não selecionável.com.br .http//www. saída e a implementação como se estivéssemos criando do zero. os parâmetros de retorno. que não retorna valores: CREATE PROCEDURE SP_AJUSTA_VALORES (INDICE_AJUSTE FLOAT. Note que passamos os parâmetros logo após o nome da procedure separando-os com vírgula. ou seja.1). mas isso não seria possível caso a mesma esteja sendo utilizada (executada) por outra SP ou Trigger. Excluindo uma Stored Procedure A exclusão de uma SP é feita através do comando DROP PROCEDURE. os parâmetros de entrada.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando e implementando Stored Procedures A criação de uma Stored Procedure é feita através do comando CREATE PROCEDURE onde informamos o nome da SP. ALTER PROCEDURE SP_AJUSTA_VALORES (INDICE_AJUSTE FLOAT. Utilizando como exemplo a SP criada anteriormente. CATEGORIA INTEGER) AS BEGIN /* aqui vem a implementação */ END Neste exemplo declaramos uma Stored Procedure com o nome SP_AJUSTA_VALORES recebendo dois parâmetros de entrada: INDICE_AJUSTE do tipo FLOAT e CATEGORIA do tipo INTEGER. Verifique se esta apostila possui uma licença registrada www. Alterando uma Stored Procedure Para alterarmos a implementação ou cabeçalho de uma Stored Procedure. CATEGORIA INTEGER.activedelphi. muito semelhante ao que fazemos no Delphi.com. Executando a Stored Procedure Para executarmos uma Stored Procedure utilizamos o comando EXECUTE PROCEDURE.br . utilizamos o comando ALTER PROCEDURE NOME_DA_PROCEDURE e logo após informamos os parâmetros de entrada. activedelphi. Executando uma Stored Procedure Selecionável Para extrairmos os valores retornados por uma SP utilizamos SELECT * FROM NOME_DA_PROCEDURE como se ela fosse uma tabela. Executando esta instrução será retornado um registro contendo o campo QTDE_PRODS_ATUALIZADOS (parâmetro de retorno definido na SP) com valor igual a 10 conforme implementamos na SP. Criando uma Stored Procedure que executa outra Stored Procedure É possível uma Stored Procedure executar outra SP.1).ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando uma Stored Procedure Selecionável (que retorna valores) SET TERM ^. SUSPEND.br .1). SET TERM ^. CREATE PROCEDURE SP_EXEC_OUTRA_SP AS BEGIN /* aqui poderíamos ter outros códigos. ^ Verifique se esta apostila possui uma licença registrada www. e assim por diante.50 - Active Delphi . Poderíamos ter mais parâmetros de retorno. neste caso temos apenas um: QTDE_PRODS_ATUALIZADOS. como dito. Se tivéssemos dois parâmetros de retorno.edudelphipage. Mais adiante veremos como retornar mais de um registro. por exemplo. END ^ SET TERM . ^ Neste segundo exemplo declaramos a SP utilizando o RETURNS indicando que temos parâmetros de retorno. todos parâmetros de saída da SP são retornados como campos no SELECT. seriam retornados 2 campos no SELECT.edudelphipage. executaríamos da seguinte forma: SELECT * FROM SP_AJUSTA_VALORES_COM_RETORNO(10. bastaria separá-los por virgula da mesma forma que é feita para os parâmetros de entrada. para isto utilizamos o comando EXECUTE PROCEDURE.http://www. No exemplo da SP criada anteriormente.http//www. explicarei isso mais adiante.*/ EXECUTE PROCEDURE SP_AJUSTA_VALORES(10. CATEGORIA INTEGER) RETURNS (QTDE_PRODS_ATUALIZADOS INTEGER) AS BEGIN QTDE_PRODS_ATUALIZADOS = 10. para não complicar o meio de campo agora ☺.com. Note que neste caso utilizamos dois novos comandos: SET TERM e SUSPEND.com. END ^ SET TERM ..br . onde os parâmetros de saída serão retornados como campos. CREATE PROCEDURE SP_AJUSTA_VALORES_COM_RETORNO (INDICE_AJUSTE FLOAT.com..br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Este é um exemplo de uma SP executando outra SP que não retorna valores. no caso de SP’s selecionáveis utilizamos outro comando que veremos mais adiante. como indicaremos ao banco o início e fim do nosso comando CREATE PROCEDURE já que temos um ponto-e-vírgula aparecendo antes do final deste comando? O servidor irá achar que seu comando CREATE PROCEDURE termina no primeiro terminador (ponto-e-vírgula) que ele encontrar. tivemos que utilizar o comando SET TERM. ^).activedelphi.br . if’s. while’s.http://www. Desta forma ao executarmos o comando CREATE PROCEDURE o servidor saberá que o final deste comando será ao encontrar o caractere ^ (acento circunflexo).) logo no início dizendo que não utilizaremos o terminador padrão para criar a SP e sim um novo que no caso é o ^ (acento circunflexo).comentário de uma linha Particularmente prefiro utilizar a primeira opção que é o padrão SQL. etc e na implementação de uma SP também contamos com isso. podemos utilizar também em SP’s utilizando a mesma regra: /* exemplo de um comentário podendo estar em mais de uma linha */ No firebird 1. for’s.com. Agora é que vem o problema: Se utilizarmos este terminador na implementação da SP.5 podemos ter comentários de apenas uma linha utilizando o sinal --.edudelphipage. (ponto-e-vírgula).br . agora vamos entender a razão disto. Comentários Da mesma forma que utilizamos comentários em instruções SQL. Veremos agora como aplicamos nas SP’s. O comando SET TERM determina o “terminador” SQL.http//www.com.edudelphipage.com. Implementando uma SP Em linguagens de programação temos declarações de variáveis. Verifique se esta apostila possui uma licença registrada www.51 - Active Delphi . Set Term Como vimos na criação da Procedure SP_AJUSTA_VALORES_COM_RETORNO. O terminador é o que indica o final de um comando SQL e o padrão é o .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . e isso não está correto! Então o que fazemos é algo bem simples: Definimos um novo terminador (SET TERM ^ . ao final terminamos o comando CREATE PROCEDURE com este novo terminador (END ^) e voltamos o terminador padrão ponto-e-vírgula (SET TERM . Declaração de variáveis Podemos declarar qualquer tipo de variável desde que seja um tipo de dados suportado pelo Firebird.edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note que o SET TERM utilizado no início é diferente do utilizado no fim.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Neste caso estamos declarando uma variável do tipo INTEGER. A declaração é feita através do comando DECLARE VARIABLE.2)) AS DECLARE VARIABLE NOME VARCHAR(50). Ao final definimos o terminador anterior (ponto-e-vírgula) e finalizamos o comando com o terminador atual (^). Na implementação de uma SP as declarações de variáveis são feitas após o AS e antes do BEGIN: SET TERM ^.com.com.:DESCONTO END Utilizamos esta forma para indicar que queremos fazer acesso ao parâmetro ou variável ao invés de um campo da tabela. vejamos um exemplo: DECLARE VARIABLE QTDE INTEGER.edudelphipage. ^ Acessando e atribuindo valores a variáveis ou parâmetros Diferente da linguagem pascal que atribuímos valores com := em PSQL utilizamos apenas o sinal de = para atribuição: BEGIN VALORFINAL = VALOR – DESCONTO.activedelphi. Veja o exemplo abaixo e logo em seguida vamos entender a diferença: BEGIN VALORFINAL = :VALOR .br . BEGIN /* implementação da SP */ END ^ SET TERM .br .http://www. DECLARE VARIABLE IDADE INTEGER. END Existe uma outra forma de fazermos referência a uma variável ou parâmetro utilizando o sinal : (dois pontos) antes do nome. No início indicamos o novo terminador (^) e finalizamos o comando com o terminador padrão (ponto-e-vírgula).com. CREATE PROCEDURE EXEMPLO (VALOR NUMERIC(9. Exemplo: Na implementação da SP poderíamos ter um SELECT da seguinte forma: SELECT * FROM PRODUTO WHERE PROD_CODIGO = CODIGO Verifique se esta apostila possui uma licença registrada www.http//www.52 - Active Delphi . Vale lembrar que neste exemplo a utilização do “:” (dois pontos) para fazer referência à variável é opcional. Então o correto seria utilizar da seguinte forma: SELECT * FROM PRODUTO WHERE PROD_CODIGO = :CODIGO IF/ELSE A regra para utilização do IF é simples. na realidade até existe. e quando não utilizamos BEGIN/END a linha após o IF deve ser terminada com ponto-e-vírgula. ELSE CONDICAO = ‘FALSA’. porém é utilizado para percorrer os registros de uma tabela.com.br . Não é isso que gostaríamos. diferenciando apenas que quando utilizamos o BEGIN/END no último END não temos o ponto-e-vírgula. Neste caso utilizamos o sinal de dois pontos antes do nome do parâmetro para o servidor saber que CODIGO é um parâmetro e não uma coluna. queremos que retorne o produto cujo valor da coluna PROD_CODIGO seja igual ao valor do parâmetro CODIGO.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi. Podemos perceber que é semelhante à linguagem Pascal. Verifique se esta apostila possui uma licença registrada www. LOOPS A única forma que temos para fazer um loop é através do comando WHILE. vamos agora verificar como é a sintaxe para utilização do WHILE: CONTADOR = 1 WHILE (:CONTADOR < 10) DO BEGIN CONTADOR = :CONTADOR + 1. END ou IF (:VALOR = 1) THEN CONDICAO = ‘VERDADEIRA’. END ELSE BEGIN CONDICAO = ‘FALSA’. END Vale lembrar que neste exemplo a utilização do “:” (dois pontos) para fazer referência à variável também é opcional.edudelphipage. Veremos sua utilização mais a seguir.53 - Active Delphi .br .com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Se utilizarmos desta forma o servidor entendera que você está tentando retornar o produto cujo valor da coluna PROD_CODIGO seja igual ao valor da coluna CODIGO.http//www. Não temos o comando FOR.edudelphipage.com. basta que a condição esteja entre parênteses: IF (:VALOR = 1) THEN BEGIN CONDICAO = ‘VERDADEIRA’.http://www. .. PROD_VALORPROMO FROM PRODUTO WHERE PROD_CODIGO = :CODIGO INTO :VALOR. é feito um SELECT na tabela PRODUTO extraindo os campos PROD_VALOR e PROD_VALORPROMO e seus valores são armazenados nas variáveis VALOR e PROMOCAO na respectiva ordem. BEGIN SELECT PROD_VALOR. :PROMOCAO.. Note que utilizamos o sinal de dois pontos para fazer referência às variáveis.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage ..edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados SELECT.edudelphipage.INTO armazenando os dados retornados em variáveis.54 - Active Delphi .br . Vejamos um exemplo SET TERM ^ . CREATE PROCEDURE SP_EXEMPLO_SELECT_INTO(CODIGO INTEGER) AS DECLARE VARIABLE VALOR NUMERIC(9.activedelphi.http//www.com. é atualizado a tabela PRODUTO.. teríamos a seguinte mensagem de erro sendo exibida ao executar esta SP: Figura 1 – Erro exibido quando utilizamos select’s que retornam mais de um registro Verifique se esta apostila possui uma licença registrada www.com.INTO para podermos avaliar valores de campos e tomar determinadas decisões. Será muito comum a utilização do SELECT. DECLARE VARIABLE PROMOCAO NUMERIC(9.. ^ Analisando esta SP passo a passo. Cuidado com SELECT’s que podem retornar mais de um registro! Note que nosso SELECT retorna apenas um registro..com. Ao final é verificado o valor da variável PROMOCAO e caso seja maior que zero.INTO podemos armazenar em variáveis valores de campos obtidos de SELECT’s que retornam apenas um registro. IF (:PROMOCAO>0) THEN UPDATE PRODUTO SET PROD_VALOR = :PROMOCAO WHERE PROD_CODIGO = :CODIGO.2).br . END ^ SET TERM ..INTO Através do comando SELECT. por esta razão conseguimos utilizá-lo no comando SELECT. Se tirássemos a condição WHERE ou colocássemos outra condição que resultasse em mais um registro.http://www.2). a diferença é que ele nos permite trabalhar com SELECT’s que retornam mais de um registro. No bloco BEGIN/END fazemos o tratamento necessário para cada registro..INTO que vimos anteriormente. 2) ) AS DECLARE VARIABLE CODIGO INTEGER. PROD_VALOR FROM PRODUTO INTO :CODIGO. ou seja. DECLARE VARIABLE VALOR NUMERIC(9. BEGIN VALOR_TOTAL = 0.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Para armazenarmos em variáveis dados de mais de um registro utilizamos o FOR SELECT. não temos a possibilidade de voltar o cursor. ^ Neste exemplo será realizada uma varredura em todos registros retornados pelo SELECT e para cada registro os valores dos campos serão armazenados nas variáveis (informadas após o INTO) declaradas na respectiva ordem..http//www.http://www. FOR SELECT PROD_CODIGO.2). FOR SELECT. ou seja..INTO e executamos tarefas dentro do bloco BEGIN/END. END SUSPEND.activedelphi. :VALOR DO BEGIN VALOR_TOTAL = :VALOR_TOTAL + :VALOR.INTO é muito semelhante ao SELECT.INTO que veremos a seguir. Vamos verificar um exemplo para entendermos melhor: SET TERM ^...br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .INTO O comando FOR SELECT. CREATE PROCEDURE CALCULA_TOTAL_PRODUTOS RETURNS ( VALOR_TOTAL NUMERIC(9.. A seguir será explicada melhor sua utilização.com.br . para isso incrementamos utilizando como base a variável VALOR que estará com o valor do produto naquele ciclo. O comando SUSPEND é necessário neste caso por se tratar de uma SP que retorna valor.edudelphipage.com..edudelphipage. Neste exemplo estamos totalizando os valores dos produtos na variável VALOR_TOTAL (que na realidade é um parâmetro de retorno da SP).br . É importante sabermos que a leitura dos registros é feita de forma unidirecional.55 - Active Delphi .com. END ^ SET TERM .. Verifique se esta apostila possui uma licença registrada www.. podemos percorrer as linhas resultadas do SELECT e em cada ciclo armazenamos os valores dos campos em variáveis da mesma forma que fazemos no SELECT. percorremos apenas para frente. br . Sua função é suspender a execução da SP retornando os valores e continuar a SP (do ponto em que parou) quando o próximo FETCH for requisitado. Vamos analisar os dois exemplos: Verifique se esta apostila possui uma licença registrada www. pois executamos o SUSPEND duas vezes.com.br .. END ^ SET TERM . CAMPO2 INTEGER) AS BEGIN CAMPO1 = 1.edudelphipage. No exemplo anterior utilizamos o SUSPEND ao final da SP. CREATE PROCEDURE SP_TESTE_SUSPEND RETURNS (CAMPO1 INTEGER. ^ Ao executarmos esta SP através de um SELECT * FROM SP_TESTE_SUSPEND teríamos como retorno exatamente 2 registros.com.com. pois após termos percorrido os registros retornamos o valor contido na variável VALOR_TOTAL.. SUSPEND.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados SUSPEND A utilização do SUSPEND é necessária quando utilizamos SP's que retornam valores. Com base no que comentamos sobre o comando SUSPEND. pois é isso que nos permitirá retornar mais de um registro em uma SP selecionável.56 - Active Delphi .http//www.http://www. CAMPO1 = 10. vamos analisar o que aconteceria se utilizássemos este comando mais de uma vez na SP: SET TERM ^ . Acho que agora ficou mais claro como ele funciona ☺ Então com isso já podemos imaginar como poderíamos retornar N registros através de um loop com o comando WHILE ou através de um FOR SELECT. Retornando mais de um registro em SP selecionável É interessante entendermos bem o conceito do SUSPEND. CAMPO2 = 20. SUSPEND. CAMPO2 = 2.activedelphi.INTO.edudelphipage. br .2). ^ Executaríamos esta SP da seguinte forma: SELECT * FROM SP_TESTE_SELECIONAVEL_FORSELECT Note que em cada ciclo.http//www. ou seja. END END ^ SET TERM . SUSPEND. dentro do bloco BEGIN/END alimentamos o valor do parâmetro de retorno e executamos o SUSPEND para que o registro seja retornado. Retornando com FOR SELECT.br ..INTO SET TERM ^..com. END END ^ SET TERM . CREATE PROCEDURE SP_TESTE_SELECIONAVEL_FORSELECT RETURNS ( VALOR_RETORNO NUMERIC(9.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Retornando com While SET TERM ^. WHILE (:CONTADOR < 10) DO BEGIN VALOR_RETORNO = :CONTADOR. ^ Executaríamos esta SP utilizando: SELECT * FROM SP_TESTE_SELECIONAVEL_WHILE Como retorno teríamos 10 registros com a coluna VALOR_RETORNO contendo valores de 0 a 9. Verifique se esta apostila possui uma licença registrada www. CREATE PROCEDURE SP_TESTE_SELECIONAVEL_WHILE RETURNS ( VALOR_RETORNO INTEGER ) AS DECLARE VARIABLE CONTADOR INTEGER. BEGIN FOR SELECT PROD_VALOR FROM PRODUTO INTO :VALOR DO BEGIN VALOR_RETORNO = :VALOR * 1.activedelphi.10.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage.com.http://www.com. pois estamos preenchendo este parâmetro de saída com o valor da variável CONTADOR.57 - Active Delphi .2) ) AS DECLARE VARIABLE VALOR NUMERIC(9.edudelphipage. CONTADOR = :CONTADOR + 1. BEGIN CONTADOR = 0. SUSPEND. Vejamos o exemplo a seguir: SET TERM ^..br .. FOR SELECT. END Utilizando em um FOR SELECT... LEAVE O comando LEAVE nos permite interromper um loop gerado por um WHILE.br . ^ Perceba que montamos a instrução SQL dinamicamente com base nos parâmetros passados para a SP e logo em seguida executamos através do EXECUTE STATEMENT. END ^ SET TERM .http//www.edudelphipage.INTO ou FOR EXECUTE.http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Como resultado teremos todos registros da tabela PRODUTO com uma coluna VALOR_RETORNO contendo o valor do produto com 10% de acréscimo.INTO (veremos mais adiante).com.. CAMPO VARCHAR(10). Verifique se esta apostila possui uma licença registrada www. VALOR VARCHAR(20) ) AS BEGIN EXECUTE STATEMENT 'UPDATE ' || TABELA || ' SET ' || CAMPO || ' = ''' || VALOR || ''''.58 - Active Delphi . CREATE PROCEDURE SP_ATUALIZA_CAMPO_TABELA ( TABELA VARCHAR(10).activedelphi. CONTADOR = :CONTADOR + 1. WHILE (:CONTADOR < 10) DO BEGIN IF (:CONTADOR = 5) LEAVE.edudelphipage. END EXECUTE STATEMENT O comando EXECUTE STATEMENT nos permite executar uma instrução SQL montada dinamicamente.com.com.INTO FOR SELECT PROD_VALOR FROM PRODUTO INTO :VALOR DO BEGIN IF (:VALOR=200) LEAVE..br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . A utilização deste comando é simples: Utilizando em um While CONTADOR = 1. 59 - Active Delphi . SUSPEND.. para isso utilizamos o sinal de dois pipe || que é o utilizado em SQL. 'TESTE').activedelphi.com. Vejamos um exemplo: Verifique se esta apostila possui uma licença registrada www. ^ Exemplo de utilização: SELECT * FROM SP_EXEMPLO_EXECUTE_STAT_INTO('PROD_DESCRICAO'.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note também que foi necessário concatenar a string.INTO. pois nos permite montar um SELECT dinamicamente armazenando os valores dos campos em variáveis.INTO Este comando é uma união do EXECUTE STATEMENT e SELECT. CREATE PROCEDURE SP_EXEMPLO_EXECUTE_STAT_INTO ( CAMPO VARCHAR(20). 'PROD_DESCRICAO'. seria recomendável a utilização de uma cláusula WHERE. CODIGO INTEGER) RETURNS ( VALOR_CAMPO VARCHAR(50)) AS BEGIN EXECUTE STATEMENT 'SELECT ' || CAMPO || ' FROM PRODUTO WHERE PROD_CODIGO = ' || :CODIGO INTO :VALOR_CAMPO. algo que não é viável. 10).edudelphipage.INTO. pois nos permite montar um SELECT (que retorna mais de um registro) dinamicamente armazenando os valores dos campos em variáveis. Vale lembrar que este exemplo é apenas para fins didáticos. Vejamos um exemplo: SET TERM ^. FOR EXECUTE STATEMENT.com.INTO Este comando é uma união do EXECUTE STATEMENT e FOR SELECT...br ..http://www.. EXECUTE STATEMENT.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Como retorno teríamos a descrição do produto de código 10..http//www..edudelphipage. sabemos que sua execução atualizaria o campo PROD_DESCRICAO de todos os registros da tabela PRODUTO. END ^ SET TERM .. Poderíamos utilizar esta SP da seguinte forma: EXECUTE PROCEDURE SP_ATUALIZA_CAMPO_TABELA('PRODUTO'. exemplo: EXCEPTION NOME_DA_EXCEPTION 'MINHA MENSAGEM DE ERRO' Vejamos um exemplo de utilização em uma SP: CREATE EXCEPTION VALOR_NEGATIVO ‘Valor negativo’. para isso utilizamos o comando CREATE EXCEPTION: CREATE EXCEPTION NOME_DA_EXCEPTION 'MENSAGEM DE ERRO'.60 - Active Delphi . Para gerarmos uma exception precisamos antes criá-la. CAMPO VARCHAR(20)) RETURNS (VALOR_CAMPO VARCHAR(50)) AS BEGIN FOR EXECUTE STATEMENT ' SELECT ' || CAMPO || ' FROM ' || TABELA INTO :VALOR_CAMPO DO BEGIN SUSPEND.edudelphipage. logar o erro em uma tabela.com.edudelphipage. como por exemplo.0 do Firebird tínhamos que criar uma exception para cada mensagem de erro. ou até mesmo ignorar caso necessário. Para gerarmos a exception utilizamos: EXCEPTION NOME_DA_EXCEPTION Até a versão 1. a mesma idéia poderia ser feita em uma SP barrando a execução do processo em determinada situação. END END ^ SET TERM .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br . Na versão 1.br . Verifique se esta apostila possui uma licença registrada www. geramos uma exception anulando a respectiva inclusão e uma mensagem definida por nós seria exibida para o usuário. Assim estaríamos retornando o campo PROD_DESCRICAO de todos registros tabela PRODUTO.activedelphi. Podemos também verificar se alguma exceção foi gerada e com isso tomar outras decisões. Por exemplo.com.com. 'PROD_DESCRICAO'). em uma Trigger antes da inclusão de um registro. poderíamos verificar determinadas condições e caso não atenda. CREATE PROCEDURE SP_RETORNA_CAMPO_TABELA(TABELA VARCHAR(20).ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados SET TERM^.5 podemos criar a exception com a mensagem de erro padrão ou em branco e ao chamála passamos outra mensagem. EXCEPTION Na implementação de uma Stored Procedure ou Trigger podemos gerar exceptions em determinadas situações.http://www.http//www. ^ Poderíamos utilizar esta SP da seguinte forma: SELECT * FROM SP_RETORNA_CAMPO_TABELA('PRODUTO'. . por exemplo..com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .. (gerada pelo banco).activedelphi. onde em XXX informamos uma constante. END Perceba que agora está sendo informada uma mensagem de erro específica ao gerar a exception concatenando com o valor passado no parâmetro. onde XXX é o código de erro..ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados CREATE PROCEDURE TESTE_EXCEPTION(VALOR INTEGER) AS BEGIN IF (:VALOR < 0) THEN EXCEPTION VALOR_NEGATIVO.DO Através do comando WHEN SQLCODE.. se executarmos esta SP utilizando o comando: EXECUTE PROCEDURE TESTE_EXCEPTION_2(-1) teríamos a seguinte mensagem de erro: Valor negativo: -1.http://www. as instruções existentes no bloco BEGIN/END serão executadas. WHEN SQLCODE XXX DO BEGIN /* aqui vem o tratamento */ END Neste exemplo verificamos se ocorreu algum erro de código (SQLCODE) XXX.br .DO Semelhante ao bloco acima.DO tratamos uma exception específica (gerada pelo banco) através do SQLCODE. WHEN GDSCODE XXX DO BEGIN /* aqui vem o tratamento */ END Verifique se esta apostila possui uma licença registrada www.http//www.com.com.DO podemos verificar também uma exception específica.br . EXCEPTION – Tratando erros Podemos verificar se alguma exception foi gerada de várias formas: Utilizando WHEN SQLCODE.61 - Active Delphi ... através do comando WHEN GDSCODE.edudelphipage. foreign_key ou o próprio código de erro..edudelphipage. Poderíamos então personalizar a mensagem da seguinte forma: CREATE PROCEDURE TESTE_EXCEPTION_2(VALOR INTEGER) AS BEGIN IF (:VALOR < 0) THEN EXCEPTION VALOR_NEGATIVO 'Valor negativo: ' || Valor. caso tenha ocorrido. logo. Utilizando WHEN GDSCODE. END Se executarmos esta procedure utilizando EXECUTE PROCEDURE TESTE_EXCEPTION(-1) seria gerada a mensagem de erro: Valor negativo. porém utilizando o GDSCODE. http//www. mas poderíamos utilizar qualquer um dos blocos demonstrados anteriormente.net/doc/contrib/fb_1_5_errorcodes.br .com.activedelphi. semelhante ao que acontece quando utilizamos try/except no Dephi..DO podemos tratar qualquer exception.com. podemos “soltar” a exception novamente após fazermos o tratamento específico. independente do erro e se foi gerada pelo banco ou por nós.DO Com a utilização do comando WHEN ANY.context_variables). END Utilizamos como exemplo o bloco WHEN ANY DO.. WHEN ANY DO BEGIN /* aqui vem o tratamento */ END Neste caso.. Verifique se esta apostila possui uma licença registrada www.edudelphipage. GDSCODE e suas constantes: http://firebird. navegando pela Internet achei um PDF que documenta estas mensagens com os respectivos códigos SQLCODE... poderíamos avaliar o código de erro dentro do bloco BEGIN/END utilizando apenas a variável SQLCODE.. portanto.edudelphipage..ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Em documentações do Firebird existem as mensagens de erros com suas respectivas descrições. para isso utilizamos o comando EXCEPTON dentro do bloco: WHEN ANY DO BEGIN /* aqui vem o tratamento */ /* gerando a exception novamente */ EXCEPTION. fora do bloco ambas sempre estarão com valor zero.pdf Uma observação importante descrita na própria documentação existente no Firebird (README. pois a variável GDSCODE estaria com valor zero.com.sourceforge.http://www. utilize a própria variável informada no WHEN.62 - Active Delphi .DO a variável GDSCODE contém valor e SQLCODE fica com valor zero. Utilizando WHEN ANY. se precisar avaliar o código de erro dentro do tratamento. portanto. quando utilizamos WHEN SQLCODE. Gerando a exception novamente Quando utilizamos um dos blocos acima. o que estamos fazendo na realidade é segurando a exception. vejamos um exemplo: WHEN ANY DO BEGIN IF (SQLCODE=-803) THEN BEGIN /* tratando o erro -803 */ END END É importante saber que as variáveis SQLCODE e GDSCODE só possuem valores dentro do bloco de tratamento.br .DO a variável SQLCODE contém valor e GDSCODE fica com valor zero e quando utilizamos WHEN GDSCODE.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .. Verifique se esta apostila possui uma licença registrada www.edudelphipage. etc.63 - Active Delphi .com. mas vale a pena explorá-los depois de praticado bastante o básico. cursores.edudelphipage. se “soltarmos” a exception.com.br . Conclusão Neste capítulo foram abordados os principais comandos utilizados na implementação de Stored Procedures.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Independentemente se iremos “segurar” ou “soltar” a exception. serão cancelados todos os processos executados anteriormente. ou seja. se segurarmos a exception quem originou a execução do processo não saberá do erro e continuará a execução dos processos seguintes.http//www.http://www.br . porém existem comandos mais avançados nos permitindo realizar outras tarefas como controle de transação.activedelphi. caso contrário. não são comuns de serem utilizados.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . é importante sabermos que o conceito é semelhante ao que temos em Delphi utilizando o try/except. br .com.edudelphipage.http//www. ^ Em seguida clique no botão Run para executar o script conforme demonstra a figura a seguir: Figura 2 – Criando a Stored Procedure SP_ATUALIZA_VALORES no IBExpert Após a criação a SP já estará disponível para ser utilizada. Partindo para prática Execute o IBExpert e abra a conexão com o nosso banco de dados.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Vale lembrar que poderíamos criar as Stored Procedures em outras ferramentas.64 - Active Delphi .activedelphi. mas utilizaremos o IBExpert pelo fato de já utilizarmos ao longo do curso. a terceira retornará mais de um registro e a última ira gerar uma exception para visualizarmos o erro no Delphi.edudelphipage.com. vá até o menu Tools->Script Executive. a segunda retornará apenas um registro. CREATE PROCEDURE SP_ATUALIZA_VALORES ( INDICE FLOAT) AS BEGIN UPDATE PRODUTO SET PROD_VALOR = PROD_VALOR * ( 1 + (:INDICE / 100)).com. inclusive podemos visualizá-la no IBExpert: Verifique se esta apostila possui uma licença registrada www.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando Stored Procedures no IBExpert Estaremos criando 4 exemplos de Stored Procedures: a primeira executará uma atualização no banco de dados.http://www. END^ SET TERM . Depois de conectado. Figura 1 – Acessando o item de menu Script Executive No editor de script coloque o seguinte código: SET TERM ^ . http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 3 .Visualizando a Stored Procedure no IBExpert Se clicarmos com o botão direito do mouse. e a seguinte tela será exibida: Figura 5 – Editando a Stored Procedure Verifique se esta apostila possui uma licença registrada www.br .65 - Active Delphi . editar ou excluir uma Stored Procedure.Opções existentes no IBExpert para manipulação de Stored Procedures Podemos editar a Stored Procedure clicando no item de menu Edit Procedure.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Figura 4 .. temos opções de criar.br ..http//www.edudelphipage.edudelphipage.activedelphi.com.com.com. br .br .edudelphipage.com. será exibida uma outra janela: Verifique se esta apostila possui uma licença registrada www.http//www.activedelphi. para visualizarmos inclusive o cabeçalho devemos clicar no botão Lazy mode conforme demonstra a figura a seguir: Figura 6 – Clicando no botão Lazy Mode para visualizar inclusive o cabeçalho da Stored Procedure Caso queira voltar ao modo anterior.com.edudelphipage. basta clicar novamente no botão Lazy mode.http://www.66 - Active Delphi .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note que por padrão é exibida apenas a implementação da Stored Procedure.com. Nesta tela podemos alterar a implementação da SP e para confirmar clicamos no botão Compile Procedure conforme demonstra a figura: Figura 7 – Clicando no botão Compile Procedure para confirmar a alteração Ao clicar neste botão. Vale lembrar que poderíamos criar nossa Stored Procedure através do item de menu New Procedure onde seria exibida a mesma tela da figura 5 e poderíamos informar os parâmetros de entrada e saída pela IDE do IBExpert. portanto.67 - Active Delphi . poderíamos alterar uma Stored Procedure manualmente executando este script.com. Verifique se esta apostila possui uma licença registrada www.2)) AS BEGIN UPDATE PRODUTO SET PROD_VALOR = PROD_VALOR * ( 1 + (:INDICE / 100)). Portanto.br . repita os procedimentos de criação de Stored Procedures vistos anteriormente utilizando os seguintes scripts: SET TERM ^ . também retornar um registro com o maior valor existente na tabela de produtos. SELECT MAX(PROD_VALOR) FROM PRODUTO INTO :MAIOR_VALOR.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 8 – Confirmando a alteração da Stored Procedure Para confirmar basta clicar no botão Commit e as alterações serão comitadas no banco de dados. ^ O objetivo desta Stored Procedure é além de atualizar os valores dos produtos com base no índice passado no parâmetro.edudelphipage.http//www. END^ SET TERM . apenas teríamos que codificar a implementação da Stored Procedure.http://www. Antes de partimos para o Delphi.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.br .edudelphipage. Note que nesta tela é exibido o script necessário para alteração da SP. CREATE PROCEDURE SP_RETORNA_MAIOR_VALOR (INDICE FLOAT) RETURNS (MAIOR_VALOR NUMERIC(9.activedelphi. vamos aproveitar e criar as demais Stored Procedures que propomos no início para realização de testes. algo que ele não pode nos ajudar muito.br . SET TERM ^. CREATE PROCEDURE SP_RETORNA_VALOR_AJUSTADO (INDICE FLOAT) RETURNS (CODIGO INTEGER.com. CREATE PROCEDURE SP_TESTE_EXCEPTION_PRODUTO(CODIGO INTEGER) AS BEGIN INSERT INTO PRODUTO (PROD_CODIGO) VALUES (:CODIGO). SUSPEND. Verifique se esta apostila possui uma licença registrada www. enquanto que nas duas SP's criadas anteriormente utilizaremos o componente SQLStoredProc. END END^ SET TERM .2)) AS BEGIN FOR SELECT PROD_CODIGO.com.http//www.com.activedelphi. :VALOR DO BEGIN VALOR = :VALOR * (1 + (INDICE/100)). WHEN SQLCODE -625 DO BEGIN EXCEPTION EXCEPTION_GENERICA 'ERRO AO INSERIR O PRODUTO COM VALOR NULO'. E por último criaremos nossa SP que irá gerar uma exception para visualizarmos o erro no Delphi: CREATE EXCEPTION EXCEPTION_GENERICA ''.edudelphipage.68 - Active Delphi . END END ^ SET TERM . porém o trabalho maior está na implementação. por esta razão optamos por utilizar a execução de scripts diretamente.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Agora vamos criar a 3. ^ Conclusão Notamos que o IBExpert até possui alguns recursos na IDE para criação e edição de Stored Procedures.br . END WHEN ANY DO BEGIN EXCEPTION EXCEPTION_GENERICA 'ERRO DESCONHECIDO:' || SQLCODE. VALOR NUMERIC(9.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . PROD_VALOR FROM PRODUTO INTO :CODIGO.a Stored Procedure responsável por retornar mais de um registro: SET TERM ^ .http://www.edudelphipage. ^ Nesta SP estamos percorrendo a tabela de produtos e retornando o valor ajustado com base no índice passado no parâmetro. Será neste caso que utilizaremos o componente SQLQuery no Delphi para extrair os registros desta Stored Procedure. até mesmo porque é o foco do curso.com. Na propriedade onde informamos a query. no qual informamos o nome da Stored Procedure na propriedade StoredProcName e na propriedade Params definimos os parâmetros de entrada e saída. como por exemplo.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando Stored Procedures no Delphi Em nossos exemplos estaremos utilizando os componentes da DBExpress.activedelphi.69 - Active Delphi . utilizamos o componente TSQLStoredProc.http//www. executamos a SP chamando o método ExecProc do componente e no caso de SP’s que retornam um registro. como ADO.edudelphipage. Feito isto. fazemos um SELECT * FROM NOME_STORED_PROCEDURE passando os parâmetros de entrada. avaliamos os parâmetros de saída.br .com. Partindo para prática Chega de teoria ☺ e vamos implementar nossa aplicação em Delphi para fazer uso das SP’s. É importante saber que este modelo poderia ser aplicado também com SP’s que retornam apenas um registro. etc. Já no caso de SP’s que retornam mais de um registro. BDE. o SQLQuery e o TSQLDataSet. Para executarmos Stored Procedure’s que não retornam valores ou que retornam no máximo um registro. Verifique se esta apostila possui uma licença registrada www. no caso da DBExpress.com.http://www.edudelphipage. utilizamos qualquer componente que execute querys.br . portanto. porém vale lembrar que poderíamos utilizar qualquer engine de acesso.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . esteja com o projeto aberto e vamos seguir os passos dos próximos capítulos que foram divididos para um melhor entendimento. portanto vamos clicar na propriedade Params e a seguinte janela será exibida: Figura 2 – Verificando a propriedade Params do componente sspAtualizaValores Verifique se esta apostila possui uma licença registrada www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Trabalhando com Stored Procedures que não retornam valores No datamodule principal adicione um componente TSQLStoredProc localizado na paleta dbExpress: Figura 1 – Adicionando o componente TSQLStoredProc ao datamodule Ajuste as seguintes propriedades do componente: TSQLStoredProc Name: sspAtualizaValores SqlConnection: SqlConnPrincipal StoredProcName: SP_ATUALIZA_VALORES Obs: Note que a propriedade StoredProcName é um ComboBox que deveria listar o nome das Stored Procedures existentes no banco de dados.br . devemos então ajustar a propriedade Params do componente.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi.edudelphipage. infelizmente só é exibido os nomes quando utilizamos uma conexão nomeada.br .http://www. mas é importante confirmarmos para ver se está tudo ok.com.com. Mas isto não é um problema para nós. Como esta Stored Procedure recebe parâmetros. ou seja. porém temos a vantagem desta propriedade já ser preenchida no momento em que informamos o nome da SP na propriedade StoredProcName do componente SQLStoredProc. quando utilizamos a propriedade ConnectionName do componente SQLConnection.70 - Active Delphi .http//www. Neste caso não está sendo exibido devido a um bug :( da DBExpress. pois temos a possibilidade de digitar o nome da Stored Procedure diretamente na propriedade.com.edudelphipage. AsFloat := 10.activedelphi.71 - Active Delphi .ExecProc. begin dmPrincipal. Vamos acompanhar passo a passo. Entendendo o código Na primeira linha definimos o valor do parâmetro INDICE para 10 em seguida executamos a Stored Procedure chamando o método ExecProc do componente.sspAtualizaValores.sspAtualizaValores.edudelphipage. SP_ATUALIZA_VALORES No evento OnClick do botão insira o seguinte código: procedure TfrmPrincipal.com. poderíamos alterar. Abra o formulário principal e insira um botão ajustando as seguintes propriedades: TButton Name: btnExeSP1 Caption: Exec.ParamByName('INDICE'). Verifique se esta apostila possui uma licença registrada www. Testando aplicação Se rodarmos a aplicação e clicarmos neste botão. faremos isso através do formulário principal. dmPrincipal. btnExeSP1Click(Sender: TObject). Primeiro precisamos analisar os dados atuais da tabela de produtos e logo em seguida executamos a SP e visualizamos os resultados. Figura 3 – Visualizando dados dos produtos no IBExpert antes a execução da SP Agora executamos a SP a partir da aplicação.com. precisamos apenas executálo. Neste momento o componente já está configurado para ser utilizado.edudelphipage.br . end. Se necessário. muito simples ☺.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . os parâmetros são carregados automaticamente.http://www. pois como vimos. excluir ou incluir parâmetros nesta tela.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note que temos apenas um parâmetro. É só isso que precisamos fazer.com.http//www. porém não é necessário. o mesmo definido na Stored Procedure sendo do tipo entrada (propriedade ParamType = ptInput).br . a Stored Procedure será executada recebendo o parâmetro INDICE com o valor igual 10 e atualizará a tabela de produtos aumentado o valor em 10%. neste caso utilizaríamos o comando ExecProc do componente ao invés do comando Open.72 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 4 – Executando a SP a partir da aplicação Após a execução podemos conferir o resultado da atualização através do IBExpert. Conclusão Neste capítulo vimos que a execução de SP's que não retornam registros é feita através do componente SQLStoredProc.br .br .com.com.http//www.edudelphipage. porém vale lembrar que poderíamos executar o comando EXECUTE PROCEDURE manualmente através do componente SQLQuery.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi. Figura 5 – Visualizando dados dos produtos no IBExpert após a execução da SP Note que o valor dos produtos teve um acréscimo de 10% após a execução da SP.edudelphipage.http://www. Verifique se esta apostila possui uma licença registrada www.com. devemos ler os parâmetros de saída para podermos extrair os valores de retorno.http://www. ou seja. Neste momento o componente já está configurado para ser utilizado.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Abra o formulário principal e insira um botão ajustando as seguintes propriedades: TButton Name: btnExeSP2 Caption: Exec.com. um de entrada e outro de saída: Figura 1 – Visualizando os parâmetros do componente sspRetornaValor Note que o parâmetro INDICE está com a propriedade ParamType definida como ptInput (parâmetro de entrada) e o parâmetro MAIOR_VALOR está definido como ptOutput indicando que é um parâmetro de saída.com. faremos isso através do formulário principal.br . o valor de retorno. a única diferença é que após a execução da Stored Procedure.73 - Active Delphi .http//www.edudelphipage.br .com.edudelphipage.activedelphi. precisamos apenas executálo. SP_RETORNA_MAIOR_VALOR No evento OnClick do botão insira o seguinte código: Verifique se esta apostila possui uma licença registrada www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Trabalhando com Stored Procedures que retornam um registro A utilização de Stored Procedures que retornam um registro não difere muito do que vimos anteriormente. Insira outro componente TSQLStoredProc no datamodule e ajuste as seguintes propriedades: TSQLStoredProc Name: sspRetornaValor SqlConnection: SqlConnPrincipal StoredProcName: SP_RETORNA_MAIOR_VALOR Em seguida clique na propriedade Params para verificar se existem dois parâmetros. continuaríamos obtendo os valores através da função ParamByName. a SP atualizará os produtos aumentando os valores em 10% e resultará o maior valor entre eles.activedelphi. Figura 2 – Executando a SP a partir da aplicação Figura 3 – Aplicação exibindo o resultado da SP com o maior valor dos produtos Verifique se esta apostila possui uma licença registrada www. A diferença está na última linha. dmPrincipal.btnExeSP2Click(Sender: TObject). begin dmPrincipal.http//www.sspRetornaValor.ParamByName('MAIOR_VALOR').edudelphipage. ShowMessage(dmPrincipal. Testando aplicação Vamos executar a aplicação e clicar no botão. end. O que não podemos é ter mais de um registro de retorno.edudelphipage. não há diferença.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados procedure TfrmPrincipal. Poderíamos ter mais de um valor de retorno.74 - Active Delphi .sspRetornaValor.br . abordaremos este caso no próximo capítulo.com. Entendendo o código Nas duas primeiras linhas fizemos o mesmo procedimento aplicado anteriormente. onde obtemos o valor de retorno acessando o parâmetro MAIOR_VALOR.com.AsString).com.ParamByName('INDICE').ExecProc. informamos o valor do parâmetro INDICE e logo em seguida executamos a Stored Procedure.sspRetornaValor.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .AsFloat := 10.http://www. edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.75 - Active Delphi .activedelphi. Verifique se esta apostila possui uma licença registrada www.edudelphipage. um método que veremos no próximo capítulo utilizado para SP’s que retornam mais de um registro.http://www.com. Conclusão Utilizamos o mesmo componente visto no capítulo anterior.http//www.br .00” que foi exibido na aplicação.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 4 – Analisando a tabela de produtos no IBExpert após a execução da SP Nesta última figura pudemos comprovar que os produtos tiveram um acréscimo de 10% com base nos valores vistos na última atualização e o maior valor entre eles é “363.com.br . mas é importante sabermos que poderíamos utilizar uma Query extraindo o valores através de um SELECT * FROM NOME_DA_PROCEDURE. Como a nossa Stored Procedure exige um parâmetro de entrada. Clique na propriedade Params do componente qryRetornaValorAjustado e ajuste as seguintes propriedades do parâmetro: DataType: ftFloat ParamType: ptInput Verifique se esta apostila possui uma licença registrada www. precisaremos utilizar o ClientDataSet para fazer o cachê. Ajuste as propriedades da seguinte forma: TSQLQuery Name: qryRetornaValorAjustado SQLConnection: SqlConnPrincipal TDataSetProvider Name: dspRetornaValorAjustado DataSet: qryRetornaValorAjustado TClientDataSet Name: cdsRetornaValorAjustado ProviderName: dspRetornaValorAjustado SQL: SELECT * FROM SP_RETORNA_VALOR_AJUSTADO(:INDICE) Note que fizemos um SELECT como se a SP fosse uma tabela. para visualizarmos o resultado em um dbgrid.com. portanto. porém.com. para trabalharmos com Stored Procedures que retornam mais de um registro. temos de usar algum DataSet que permita a execução de Querys.activedelphi. pois faremos um SELECT em nossa SP como se fosse uma tabela. sabemos que a DBExpress trabalha com cursores unidirecionais.http://www. então passamos este parâmetro no SQL e conseqüentemente será criado um parâmetro na propriedade Params do componente.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Trabalhando com Stored Procedures que retornam mais de um registro Como dissemos anteriormente.br . por exemplo. Adicione no datamodule aquele conjunto de componentes que já estamos acostumados: TClientSataSet + TDataSetProvider + TSqlQuery.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . da mesma forma que já vimos com tabelas no primeiro módulo.com. portanto devemos ajustar seu tipo.76 - Active Delphi .edudelphipage. Neste caso estaremos utilizando o componente SQLQuery.br .edudelphipage.http//www. 77 - Active Delphi . abrimos o ClientDataSet.cdsRetornaValorAjustado.http://www.br .cdsRetornaValorAjustado TDBGrid Name: dbgrdSpRetornaValorAjustado DataSource: dtsRetornaValorAjustado Verifique se esta apostila possui uma licença registrada www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .AsFloat := 10.com.br .edudelphipage.com. dmPrincipal.cdsRetornaValorAjustado. SP_RETORNA_VALOR_AJUSTADO No evento OnClick do botão insira o seguinte código: procedure TfrmPrincipal.btnExeSP3Click(Sender: TObject).ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 1 – Ajustando os parâmetros da Query Agora no formulário principal insira um botão ajustando as seguintes propriedades: TButton Name: btnExeSP3 Caption: Exec.Params. portanto insira os seguintes componentes no formulário principal ajustando suas respectivas propriedades: TDataSource Name: dtsRetornaValorAjustado DataSet: dmPrincipal. em seguida alimentamos o parâmetro INDICE no ClientDataSet com valor 10 para que seja transferido para Query e conseqüentemente enviado para a Stored Procedure e por final.ParamByName('INDICE'). end.com. Entendendo o código Na primeira linha carregamos para o ClientDataSet os parâmetros da Query.http//www. dmPrincipal.Open.cdsRetornaValorAjustado.FetchParams. begin dmPrincipal. Agora precisamos de um DBGrid para visualizarmos o resultando.edudelphipage.activedelphi. br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .78 - Active Delphi .br .com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Pronto. porém isso não foi gravado fisicamente no banco de dados. como sabemos não poderíamos utilizar em um DataControl. agora podemos executar a aplicação e clicar no botão.com. porém. O Resultado será os produtos com seus valores ajustados. Testando aplicação Figura 2 – Visualizando o resultado da Stored Procedure SP_RETORNA_VALOR_AJUSTADO a partir da aplicação Note os valores dos produtos com acréscimo de 10%. podemos conferir analisando os dados reais da tabela através do IBExpert: Figura 3 – Visualizando os dados reais da tabela de produtos no IBExpert Conclusão Podemos perceber que a visualização de registros retornados por uma SP é simples.http://www.activedelphi.edudelphipage.br .http//www.com. Verifique se esta apostila possui uma licença registrada www. Poderíamos utilizar uma Query diretamente. porém não fisicamente. já que utilizamos o ClientDataSet da mesma forma que em tabelas.edudelphipage. somente na visualização. já que a DBEXpress trabalha com cursores unidirecionais. é apenas um retorno da SP. logo veremos os registros no DBGrid. apenas leríamos os registros para frente. begin dmPrincipal. SP_TESTE_EXCEPTION_PRODUTO Neste momento já temos tudo pronto para executar os testes.activedelphi. insira um botão ajustando as seguintes propriedades: TButton Name: btnExeSP4 Caption: Exec. dmPrincipal.Value := null. end.79 - Active Delphi .edudelphipage. visualizaremos a mensagem de erro sendo exibida diretamente na aplicação.com. Para realizarmos o primeiro teste.br . simularemos 3 testes: O primeiro tentaremos inserir um produto com código nulo. codifique o evento OnClick do botão da seguinte forma: procedure TfrmPrincipal.http://www.sspTesteException. desta forma visualizaremos as mensagens de erros nos dois primeiros testes e ao final concluiremos inserindo o produto com sucesso.br .edudelphipage. logo após um produto com código já existente e por final um produto com código inexistente. Adicione um componente TSQLStoredProc no datamodule principal ajustando as seguintes propriedades: TSQLStoredProc Name: sspTesteException SqlConnection: SqlConnPrincipal StoredProcName: SP_TESTE_EXCEPTION_PRODUTO Agora no formulário principal.sspTesteException. portanto.com.com.ExecProc.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ParamByName('VALOR').http//www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Executando a Stored Procedure que gera Exception Agora vamos executar a 4.a e última Stored Procedure que criamos como exemplo na qual gera uma exception. Testando aplicação Figura 1 – Realizando o primeiro teste Verifique se esta apostila possui uma licença registrada www.btnExeSp4Click(Sender: TObject). poderíamos ajustar a SP para começar a tratar este código de erro também.br .com. Testando aplicação Figura 3 – Erro ao tentar inserir um produto com código já existente Note a mensagem de erro ao tentarmos inserir um produto com código já existente.edudelphipage.ParamByName('VALOR'). begin dmPrincipal. portanto. o código SQLCODE é -803. ajuste o evento OnClick do botão da seguinte forma: procedure TfrmPrincipal.ExecProc.com.edudelphipage. portanto.sspTesteException.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . end. ajuste o evento OnClick do botão da seguinte forma: Verifique se esta apostila possui uma licença registrada www.80 - Active Delphi .br .http//www.Value := 1. Agora partiremos para o segundo teste.activedelphi.com.http://www. dmPrincipal. onde incluiremos um produto sem gerar exception.sspTesteException. Agora faremos o teste final.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 2 – Mensagem de erro ao tentar inserir um produto com valor nulo Note a mensagem de erro sendo a mesma mensagem que definimos na SP no caso de ocorrer um erro de inserção de produto com código nulo.btnExeSp4Click(Sender: TObject). Verifique se esta apostila possui uma licença registrada www.ExecProc. por exemplo.http://www.81 - Active Delphi . seja diretamente pelo banco através do IBExpert.com.com. ou através de uma aplicação. begin dmPrincipal.br .edudelphipage.br .sspTesteException. Testando aplicação Rodando a aplicação e clicando no botão o produto será inserido no banco de dados com sucesso conforme demonstra a figura a seguir no IBExpert: Figura 4 – Produto inserido com sucesso no banco de dados Conclusão Podemos perceber que a mensagem de erro definida na exception é exibida independentemente da forma que foi executada a SP. desta forma concluímos que no ambiente Delphi não precisamos nos preocupar com nenhum tipo de codificação específica.btnExeSp4Click(Sender: TObject).ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados procedure TfrmPrincipal.Value := 100 dmPrincipal.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi.edudelphipage.sspTesteException.ParamByName('VALOR'). end.com.http//www. Por final temos o valor do POSITON igual a zero.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . logo após informamos o nome da tabela que iremos tratar o evento. no Firebird 1. pois podemos desativá-la em determinado momento.edudelphipage. A utilização de Triggers nos permite capturarmos estes eventos e fazermos algum tipo de tratamento. BeforeUpdate: Disparado antes da atualização de registros na tabela. Os eventos que podemos manipular são: BeforeInsert: Disparado antes da inserção de registros na tabela. apenas alguns comandos são específicos para SP’s. Depois indicamos que esta Trigger está ativa através do ACTIVE. Em seguida definimos a qual evento esta Trigger está associada.82 - Active Delphi . AFTER DELETE.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando e implementando Triggers Triggers são “gatilhos” disparados pelo banco de dados quando algum evento ocorre em alguma tabela. AfterInsert: Disparado após a inclusão de registros na tabela. para isso trataríamos o evento BeforeUpdate da tabela.http://www. AFTER UPDATE. poderíamos gravar uma data em um campo da tabela quando a mesma tivesse algum registro modificado simulando um log de alteração. porém temos algumas características específicas que são aplicadas somente em Triggers.5 temos a possibilidade de ter mais de uma Trigger para a mesma tabela e mesmo evento. Vejamos um exemplo de criação de Trigger: CREATE TRIGGER NOME_DA_TRIGGER FOR NOME_DA_TABELA ACTIVE BEFORE INSERT POSITION 0 AS BEGIN /* implementacao da Trigger */ END Analisando a sintaxe Primeiro executamos o comando CREATE TRIGGER definindo o nome da Trigger. por este motivo indicamos o valor do POSITION determinando a ordem de execução das Triggers para este caso. BeforeDelete: Disparado antes da exclusão de registros na tabela.http//www. A linguagem utilizada para codificar uma Trigger é a mesma utilizada em SP’s (PSQL). AFTER INSERT.activedelphi. Implementação de uma Trigger Como dissemos.edudelphipage.com. BEFORE DELETE.com.br .br . AfterDelete: Disparado após a exclusão de registros na tabela Podemos utilizar Triggers em diversas situações. por exemplo. a linguagem para implementarmos uma Trigger é a mesma utilizada na implementação de uma SP.com. para isso utilizaríamos o INACTIVE. neste exemplo estamos associando ao evento BEFORE INSERT. AfterUpdate: Disparado após a atualização de registros na tabela. vejamos: Verifique se esta apostila possui uma licença registrada www. além deste poderia ser um dos seguintes eventos: BEFORE UPDATE. PROD_ATIVO='S' AND NEW. BEGIN /* verificando se tornou o produto inativo */ IF (OLD. isso varia de acordo com a variável/evento: Variável New Leitura e Escrita: BeforeInsert.edudelphipage. etc. após termos comparado o campo PROD_ATIVO verificando se o produto foi ativado ou desativado.PROD_ATIVO='N') THEN BEIGN NEW. loops. atribuímos um novo valor ao campo DATA_ATIVO ou DATA_INATIVO através da variável NEW. declaramos uma variável neste exemplo para demonstrarmos que podemos utilizar os mesmos conceitos vistos na implementação de uma SP utilizando variáveis.edudelphipage. PRODUTO_FOI_ATIVADO = 'S'.83 - Active Delphi .br . Exemplo: CREATE TRIGGER PRODUTO_BU FOR PRODUTO ACTIVE BEFORE UPDATE POSITION 0 AS DECLARE VARIABLE PRODUTO_FOI_ATIVADO CHAR(1).http//www. END END Note que verificamos o valor anterior do campo PROD_ATIVO através da variável OLD e verificamos o novo valor atribuído utilizando a variável NEW. ifs.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Variáveis New e Old Quando implementamos uma Trigger podemos acessar a variável new e old para verificarmos o valor do campo antes e após sua modificação respectivamente e no caso da variável new podemos também definir um novo valor para o campo dependendo do evento em que estivermos.br . porém é importante sabermos que podemos atualizar campos de outras tabelas. já que somos livres de executar instruções SQL’s na implementação de uma Trigger inclusive os comandos já vistos para implementação de SP’s. BeforeDelete. Para fins didáticos. PRODUTO_FOI_ATIVADO = 'N'.com. Determinando a variável correta a ser utilizada de acordo com evento Apesar de termos disponíveis a todo momento as variáveis NEW e OLD devemos saber que em determinado evento a leitura das variáveis NEW o OLD não retornarão valores ou a atribuição de valor a variável NEW não refletirá na tabela. Foi o que fizemos. Neste exemplo atualizamos um campo da própria tabela ao qual a Trigger é associada. neste caso utilizamos a variável NEW. BeforeUpdate Somente Leitura: AfterInsert e AfterUpdate Variável Old Sempre Somente Leitura: BeforeUpdate. AfterDelete Verifique se esta apostila possui uma licença registrada www. AfterUpdate.activedelphi.DATA_ATIVO = current_time_stamp. Da mesma forma que podemos ler as variáveis OLD e NEW podemos também atribuir um novo valor.com. END ELSE BEGIN NEW.DATA_INATIVO = current_time_stamp.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www.com. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Associando mais de um evento para mesma Trigger Na versão 1.5 do Firebird podemos associar mais de um evento para mesma Trigger, por exemplo, poderíamos ter uma Trigger para tratar os eventos Before Update e After Update da tabela. Neste caso temos 3 variáveis para utilizarmos e saber que tipo de vento está ocorrendo naquele instante: INSERTING, UPDATING e DELETING. CREATE TRIGGER PRODUTO_BUI FOR PRODUTO ACTIVE BEFORE UPDATE OR INSERT OR DELETE POSITION 0 AS BEGIN IF (inserting) THEN BEGIN /* implementacao para o caso de estar ocorrendo um insert */ END IF (updating) THEN BEGIN /* implementacao para o caso de estar ocorrendo um update */ END IF (deleting) THEN BEGIN /* implementacao para o caso de estar ocorrendo um delete */ END END Note que na declaração da Trigger definimos o tipo: BEFORE e logo após os eventos: UPDATE OR INSERT OR DELETE, isto significa que esta Trigger será disparada quando acontecer um dos eventos: BEFORE UPDATE, BEFORE INSERT ou BEFORE DELETE. Não seria possível tratar dois tipos (BEFORE e AFTER) de eventos ao mesmo tempo, por exemplo, BEFORE UPDATE e AFTER INSERT, por isso primeiro definimos o tipo se é BEFORE ou AFTER e logo após os eventos. Em nosso exemplo associamos a Triggers aos três eventos, mas vale lembrar que não somos obrigados a utilizar os três ao mesmo tempo, poderíamos fazer referência a 2 eventos, por exemplo. Alterando uma Trigger Não temos um comando ALTER TRIGGER, portanto, para alterarmos uma Trigger devemos excluía e criá-la novamente. Excluindo uma Trigger A exclusão de uma Trigger é feita utilizando o comando DROP TRIGGER. DROP TRIGGER PRODUTO_BIU Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 84 - Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Conclusão Com a utilização de Trigger podemos centralizar as regras no banco de dados, independente de quem está fazendo a manutenção na tabela, seja uma aplicação desktop, ou até mesmo uma aplicação Web, a Trigger será disparada e suas regras de negócios serão sempre mantidas. Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 85 - Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando Triggers no IBExpert Para criarmos Triggers através do IBExpert, podemos utilizar a opção Script Executive... como vimos na criação de uma SP ou utilizar a opção específica para criação de Triggers através da IDE. Como já vimos a primeira opção em Stored Procedures, utilizaremos a segunda opção para fins didáticos, mas ao final veremos o código completo da Trigger. Como exemplo criaremos uma Trigger para tabela PRODUTO associada ao evento Before Insert e Before Update, onde estaremos armazenando a data de alteração no campo PROD_DATAALTERACAO (quando estiver atualizando) e a data de inclusão no campo PROD_DATACADASTRO (quando estiver incluindo). Partindo para prática Abra o IBExpert, em seguida abra a conexão com o nosso banco de dados. Vá até o menu Database e clique no item New Triggers... Figura 1 – Selecionando a opção New Trigger do menu Database A seguinte tela será exibida: Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 86 - Active Delphi - http//www.activedelphi.com.br portanto.com. na opção For Table selecione a tabela PRODUTO. Clique no ComboBox do campo Type selecionando a opção Before em seguida marque os checkbox’s INSERT e UPDATE.edudelphipage.com.br .http://www. Desta forma estamos informando que esta Trigger estará associada aos eventos BEFORE UPDATE e BEFORE INSERT.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage.http//www.87 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 2 – Tela de criação de Triggers Nesta tela devemos informar para qual tabela estaremos criando a Trigger.com. Figura 3 – Selecionando a tabela onde será criada a Trigger Em seguida devemos informar os eventos que estaremos associando a esta Trigger. Figura 4 – Selecionando os eventos que estarão associados a Trigger Verifique se esta apostila possui uma licença registrada www.activedelphi.br . PROD_DATACADASTRO = CURRENT_TIMESTAMP.activedelphi. Neste momento já podemos partir para implementação da Trigger.edudelphipage. O padrão de nomenclatura é: NOME_DATA_TABELA + _ + EVENTO + POSITION.br . Se fosse apenas para o evento Before Insert.http://www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage. No quadro branco insira o seguinte código: IF (INSERTING) THEN BEGIN NEW.br .com. END Figura 5 – Implementando a Trigger Depois de implementado.com.88 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Note que o nome da Trigger no campo Name vai sendo preenchido automaticamente. por exemplo.PROD_DATAALTERACAO = CURRENT_TIMESTAMP. Figura 6 – Clicando no botão Compile para compilar a Trigger Verifique se esta apostila possui uma licença registrada www.com. seria: BI.http//www. podemos compilá-la clicando no botão Compile. por exemplo. END ELSE IF (UPDATING) THEN BEGIN NEW. Onde o EVENTO é uma abreviação. BIU = Before Insert e Update. Ao confirmarmos voltaremos para tela anterior. podemos ignorar esta janela clicando no botão YES para continuar. será exibida uma janela com uma mensagem de erro em nosso código: Figura 7 – Janela exibida informando erros na implementação da Triggers Isto acontece pelo fato de o IBExpert não reconhecer as variáveis INSERTING.5 do Firebird.com. assim notaremos a mensagem de erro do IBExpert informando que não reconheceu a variável INSERTING.89 - Active Delphi .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Assim a seguinte tela será exibida: Figura 8 – Cogitando a criação da Trigger Nesta tela basta clicarmos no botão Commit para confirmarmos a criação da Trigger.com. Verifique se esta apostila possui uma licença registrada www.br . UPDATING e DELETING.com. pois foi implementado somente na versão 1.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Ao clicarmos neste botão.edudelphipage.edudelphipage.http//www. portanto.br .activedelphi.http://www. 90 - Active Delphi . isso não é um problema.activedelphi.http//www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . ^ Verifique se esta apostila possui uma licença registrada www.com. CREATE TRIGGER PRODUTO_BIU0 FOR PRODUTO ACTIVE BEFORE INSERT OR UPDATE POSITION 0 AS BEGIN IF (INSERTING) THEN BEGIN NEW. poderíamos utilizar o seguinte código: SET TERM ^.br . END ELSE IF (UPDATING) THEN BEGIN NEW.com.com.edudelphipage.PROD_DATAALTERACAO = CURRENT_TIMESTAMP.PROD_DATACADASTRO = CURRENT_TIMESTAMP.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 9 – IBExpert informando que não reconheceu a variável INSERTING Mas como já dissemos.http://www. END END ^ SET TERM . neste momento já temos nossa Trigger criada pronta para ser utilizada.br .edudelphipage. Caso optássemos em executar o script da Trigger diretamente através do menu Script Executive. com.http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Testando a Trigger Antes de partirmos para o ambiente Delphi. Agora vamos fazer uma alteração neste registro e verificar se o campo PROD_DATAALTERACAO também será preenchido automaticamente. execute a seguinte query: UPDATE PRODUTO SET PROD_DESCRICAO = 'NOVO PRODUTO ALTERADO' WHERE PROD_CODIGO = 100 Verifique se esta apostila possui uma licença registrada www. pois executamos uma inclusão. Pelo fato de ser disparada pelo banco de dados.edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi.com.91 - Active Delphi . portanto.com. No próprio IBExpert entre no SQLEditor teclando F12 ou através do menu Tools->SQLEditor.http//www. 'NOVO PRODUTO') Figura 10 – Incluindo um produto para que a Trigger seja disparada Em seguida execute um SELECT para verificarmos quais campos foram preenchidos: SELECT * FROM PRODUTO WHERE PROD_CODIGO = 100 Figura 11 – Verificando que o campo PROD_DATACADASTRO foi preenchido automaticamente pela Trigger Note que o campo PROD_DATACADASTRO foi preenchido automaticamente pela Trigger.br . qualquer query de atualização executada na tabela disparará a Trigger. vamos verificar se nossa Trigger está funcionando corretamente. Em seguida execute a seguinte query: INSERT INTO PRODUTO (PROD_CODIGO. PROD_DESCRICAO) VALUES (100.edudelphipage.br . com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 12 – Atualizando o produto para que a Trigger seja disparada Em seguida execute um SELECT para verificarmos como estão os campos do produto.http://www.br .edudelphipage. SELECT * FROM PRODUTO WHERE PROD_CODIGO = 100 Figura 13 – Verificando que o campo PROD_DATAALTERACAO foi preenchido automaticamente pela Trigger após a atualização Note que desta vez o campo PROD_DATAALTERACAO foi atualizado.92 - Active Delphi . pois fizemos um UPDATE na tabela e na Trigger havíamos implementado uma regra de atualizar este campo quando estiver ocorrendo uma atualização.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Alterando uma Trigger Para alterarmos a implementação de uma Trigger basta acessar o item de menu Edit Trigger no IBExpert conforme demonstra a figura a seguir: Verifique se esta apostila possui uma licença registrada www.edudelphipage.activedelphi.com.http//www.br . ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 14 – Acessando o item de menu para alterar uma Trigger Em seguida será exibida a mesma tela que vimos na criação de uma Trigger Figura 15 – Alterando uma Trigger Portanto.br . Excluindo uma Trigger Utilizando o IBExpert esta tarefa é realizada através do item de menu Drop Trigger: Verifique se esta apostila possui uma licença registrada www.http//www.edudelphipage.edudelphipage. basta alterar o que for necessário e executar o mesmo procedimento de compilação para efetivar a alteração.com.http://www.activedelphi.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .93 - Active Delphi .com.com. activedelphi.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 16 – Excluindo uma Trigger Conclusão O IBExpert possui uma IDE muito interessante que nos permite criar Triggers de forma rápida.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . mas é interessante estudarmos a sintaxe de criação para eventuais casos onde podemos estar sem uma ferramenta visual.edudelphipage.http//www.94 - Active Delphi .com.br . Verifique se esta apostila possui uma licença registrada www.br .edudelphipage.http://www.com. alteração ou exclusão ocorre na tabela. DBClient. Fazemos isso para visualizarmos as mensagens de erro que acontecerão na atualização da tabela. utilizaremos apenas para exemplificação.com.Message. Classes. adicione o seguinte código: procedure TdmPrincipal.com. Verifique se esta apostila possui uma licença registrada www. porém existem algumas dicas que veremos para que possamos visualizar o campo alterado pela Trigger e evitar problemas comuns quando esquecemos de alguns detalhes na utilização do ClientDataSet. end. DB.com.http//www.edudelphipage. TDataSetProvider Name: dspTesteTrigger DataSet: qryTesteTrigger TClientDataSet Name: cdsTesteTrigger ProviderName: dspTesteTrigger No evento OnReconcileError do ClientDataSet.br . [mbOk].edudelphipage. Estaremos utilizando o ClientDataSet para fazermos a manutenção na tabela de produtos. mtError.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Utilizando Triggers no Delphi Como vimos no capítulo anterior. basta que o mesmo faça a manutenção na tabela e a Trigger será disparada automaticamente pelo banco de dados. no datamodule principal adicione os seguintes componentes ajustando suas respectivas propriedades: TSQLQuery Name: qryTesteTrigger SQLConnection: SqlConnPrincipal SQL: SELECT * FROM PRODUTO Obs: Sabemos que este tipo de select não é recomendável.activedelphi. var Action: TReconcileAction). Para que o método MessageDlg possa ser utilizado. 0). E: EReconcileError.br . FMTBcd.http://www. begin MessageDlg(E.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . isso significa que não precisamos utilizar componentes especiais. SqlExpr. as Triggers são disparadas pelo próprio banco de dados quando alguma inclusão. UpdateKind: TUpdateKind.cdsTesteTriggerReconcileError( DataSet: TCustomClientDataSet. Partindo para prática Com o projeto aberto. devemos adicionar a unit Dialogs na cláusula uses do datamodule: uses SysUtils. Dialogs. DBXpress.95 - Active Delphi . Provider. cdsTesteTriggerAfterPost(DataSet: TDataSet). begin cdsTesteTrigger.br .cdsTesteTriggerAfterCancel(DataSet: TDataSet).edudelphipage.br . codifique desta forma: procedure TdmPrincipal.cdsTesteTriggerAfterDelete(DataSet: TDataSet).edudelphipage.96 - Active Delphi .http//www.com. end. Para o evento AfterCancel. begin with cdsTesteTrigger do begin if ApplyUpdates(0) <> 0 then CancelUpdates. Codifique o evento AfterPost da seguinte forma: procedure TdmPrincipal.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Para facilitar executaremos o método ApplyUpdates e CancelUpdates automaticamente através dos eventos do ClientDataSet.cdsTesteTrigger TDBGrid Name: dbgrdTesteTrigger DataSource: dtsTesteTrigger Adicione também um botão para que possamos abrir o ClientDataSet: TButton Name: btnAbrirTesteTrigger Caption: Abrir cdsTesteTrigger Veja abaixo como ficará a parte do formulário referente a estes componentes: Verifique se esta apostila possui uma licença registrada www. assim evitamos ter que adicionar botões específicos para isso.CancelUpdates. end.activedelphi.com.com. end. O evento AfterDelete é codificado da mesma forma que o evento AfterPost: procedure TdmPrincipal.http://www. Ajustando o formulário principal Agora vamos ajustar o formulário principal para que possamos visualizar e fazer as manutenções dos registros em um dbgrid: Adicione os seguintes componentes: TDataSource Name: dtsTesteTrigger DataSet: dmPrincipal.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . end. begin with cdsTesteTrigger do begin if ApplyUpdates(0) <> 0 then CancelUpdates. end. com. Recordando um pouco. Neste momento já temos tudo preparado para fazermos manutenções na tabela de produtos. porém apenas no banco de dados e não está sendo refletido no ClientDataSet.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . na realidade ele está sendo atualizado sim.97 - Active Delphi .com.activedelphi. aparece a mensagem de erro: Record not found or changed by another user Figura 3 – Tentando alterar o produto que acabamos de inserir Este problema é conseqüência do problema anterior. Figura 2 – Incluindo um produto e o campo PROD_DATACADASTRO não é atualizado no DBGrid Ao tentar alterar/gravar o registro inserido. begin dmPrincipal.cdsTesteTrigger. lembra que o padrão é o ClientDataSet utilizar todos os campos na cláusula where para montar a query de atualização? Verifique se esta apostila possui uma licença registrada www. end.http://www.edudelphipage. mas agora vamos falar dos problemas! Os dois grandes problemas O campo alterado pela Trigger não é atualizado no DBGrid Se tentarmos inserir um registro pelo DBGrid. perceberemos que o campo PROD_DATACADASTRO não é atualizado na tela.btnAbrirTesteTriggerClick(Sender: TObject).br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 1 – Preparando o formulário principal para fazermos os testes da Trigger Codifique o evento do botão da seguinte forma: procedure TfrmPrincipal.br .Open.http//www.edudelphipage.com. 98 - Active Delphi . Feito isto.cdsTesteTriggerAfterPost(DataSet: TDataSet).http://www. pois o ClientDataSet não encontra o registro.br . WHERE . portanto utilizaremos a terceira opção na qual resolve os dois problemas de uma só vez.Ajustar a propriedade ProviderFlags dos campos atualizados pela Trigger de modo que não sejam utilizados na cláusula where ..activedelphi. porém ambas resolveriam apenas o erro do registro não localizado.Corrigir o primeiro problema. Note que apenas incluímos a chamada ao método Refresh caso não tenha ocorrido erros na atualização.edudelphipage. conseqüentemente ao tentarmos alterar este registro o ClientDataSet tentará usar um SQL de atualização da seguinte forma: UPDATE PRODUTO SET . Após chamarmos o método ApplyUpdates basta executarmos o método Refresh e o ClientDataSet será refletido com os novos valores atualizados pela Trigger e tudo será resolvido! Portanto. pois o campo atualizado pela Trigger não foi refletido no ClientDataSet.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Este é o problema.. AND PROD_DATACADASTRO IS NULL Este registro não será encontrando no banco de dados. não está nulo como o ClientDataSet acha! Por este motivo temos a mensagem de erro.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Para resolvermos estes problemas temos algumas saídas: . fazendo com que o ClientDataSet “enxergue” os valores dos campos atualizados pela Trigger. após incluirmos o registro. Verifique se esta apostila possui uma licença registrada www.. inclusive um outro problema de campos com valores default’s. pois ele está com o campo PROD_DATACADASTRO preenchido.com. mas tudo isso é por falta de um simples Refresh no ClientDataSet. o componente não sabe deste novo valor. Resolvendo estes problemas. podemos testar a aplicação e veremos que o valor do campo atualizado pela Trigger é exibido no DBGrid.. end. no banco de dados o campo PROD_DATACADASTRO está com um determinado valor e no ClientDataSet está nulo.com.edudelphipage. begin with cdsTesteTrigger do begin if ApplyUpdates(0) <> 0 then CancelUpdates else Refresh. ajuste o evento AfterPost do ClientDataSet da seguinte forma: procedure TdmPrincipal.Ajustar a propriedade UpdateMode do Provider de modo que utilize apenas a chave primária na cláusula where . as duas primeiras já vimos como utilizar em capítulos anteriores do primeiro módulo deste curso. A solução Pode não parecer.http//www. Dentre estas soluções.com. end. http://www. o ClientDataSet não saberá dos novos valores atribuídos aos campos com valores defaults. basta executarmos o método Refresh da mesma forma que fizemos anteriormente.com. Conclusão Neste capítulo percebemos que a utilização de Triggers no ambiente Delphi não requer componentes especiais nem programação diferenciada.activedelphi.http//www.99 - Active Delphi .br . Verifique se esta apostila possui uma licença registrada www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.br .com. Figura 4 – Campos PROD_DATAALTERACAO E PROD_DATACADASTRO sendo refletidos no ClientDataSet após inclusão e alteração Por que foi citado: inclusive um outro problema de campos com valores default’s? Quando utilizamos campos com valores defaults definidos no banco de dados o problema que vimos anteriormente acontecerá da mesma forma. pois neste momento o ClientDataSet já sabe o valor do campo após o refresh e montará o SQL de atualização corretamente. o único detalhe é sempre chamarmos o Refresh para que os valores dos campos defaults e atualizados por Triggers possam ser refletidos no ClientDataSet evitando assim esses “problemas”.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Podemos também alterar o registro normalmente.edudelphipage. ou seja. Para solucionar este caso é simples.edudelphipage. conseqüentemente não aparecerá no DBGrid e ao tentarmos alterar o registro a mensagem de erro acusando que o registro não foi encontrado será exibida também pelo mesmo motivo. neste caso poderíamos criar uma View representando parte destes dados e liberaríamos o acesso do usuário somente a esta view e não a tabela inteira de Clientes.edudelphipage.activedelphi.br . ou seja. é apenas uma “visão”. Imagine que temos uma tabela de Clientes onde não gostaríamos que determinados usuários do banco de dados tivessem acesso a todos os dados. etc.100 - Active Delphi . qualquer alteração.br . desde que obedeçam algumas regras: . vamos ver um exemplo deste caso: CREATE VIEW VIEW_EXEMPLO_1 AS SELECT * FROM PRODUTO Analisando a sintaxe.edudelphipage. se uma View é uma tabela virtual onde posso utilizar SELECT * FROM MINHA_VIEW. Imagine aquela situação onde temos um SELECT complexo e em todo momento utilizamos este SELECT na aplicação.com. Neste exemplo a View retornará todos os campos e registros da tabela PRODUTO.com. PROD_DESCRICAO FROM PRODUTO Verifique se esta apostila possui uma licença registrada www. Criando uma View Na criação de uma View é opcional informarmos os campos que serão retornados.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando e definindo Views Views são visões que criamos no banco de dados representando os dados de uma ou mais tabelas através de SELECT’s resultando assim em uma tabela “virtual”.com. Poderíamos utilizar a View da seguinte forma: SELECT * FROM VIEW_EXEMPLO_1. utilizar WHERE.http://www. subquerys. é como se VIEW_EXEMPLO_1 fosse realmente uma tabela! Vejamos agora um caso onde queremos criar uma View que retorne apenas alguns campos da tabela PRODUTO: CREATE VIEW VIEW_EXEMPLO_2 AS SELECT PROD_CODIGO.http//www. Uma outra vantagem interessante é que poderíamos utilizar Views para limitar o acesso a dados confidenciais por usuários do banco de dados. etc.O objetivo principal da utilização de Views é exatamente este! É importante deixar claro que uma View não é uma cópia das tabelas envolvidas no SELECT.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . inclusão ou exclusão efetuada nas tabelas serão refletidas na View. Legal. Já imaginou ter uma tabela “virtual” (a VIEW) representando os dados retornados por este SELECT e depois simplesmente utilizar SELECT * FROM MINHA_VIEW? . poderia então atualizá-la? Views podem ser atualizadas sim.Campos NOT NULL sem valores padrões deverão estar na lista de campos da View . Neste SELECT podemos especificar os campos que gostaríamos de retornar da View.Não pode ser uma View que resulta dados de mais de uma tabela . JOINS. após o CREATE VIEW informamos o nome da View e logo após o AS informamos o resultado da View através de um SELECT.Não pode haver campos agregados. utilizamos para isso uma cláusula WHERE no SELECT: CREATE VIEW VIEW_EXEMPLO_3 AS SELECT PROD_CODIGO. é uma visão das tabelas envolvidas no SELECT.activedelphi. neste caso a atualização é feita da mesma forma que uma tabela: UPDATE VIEW_EXEMPLO_3 SET PROD_DESCRICAO = 'PRODUTO 1 ALTERADO' WHERE PROD_CODIGO = 1 Da mesma forma poderíamos utilizar INSERT e DELETE.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Agora se executarmos SELECT * FROM VIEW_EXEMPLO_2 visualizaremos todos os campos da View e não da tabela PRODUTO. ao executarmos o SELECT na View. Os nomes dos campos retornados por esta View serão os mesmos nomes especificados no SELECT. serão retornados os campos PROD_CODIGO e PROD_DESCRICAO. PROD_TIPO FROM PRODUTO WHERE PROD_TIPO = 'D' Neste exemplo podemos executar SELECT * FROM VIEW_EXEMPLO_3 e serão retornados todos registros da View. neste caso estamos alterando fisicamente a tabela PRODUTO.edudelphipage. a View não é uma cópia de tabelas.com.http://www.http//www. Até poderíamos ser ousados em executar.edudelphipage. teremos como resultado apenas os campos PROD_CODIGO e PROD_DESCRICAO.br . nesta View não seria retornado. no caso todos os produtos cujo campo PROD_TIPO seja igual a D. porém nomeados como CODIGO e DESCRICAO respectivamente. pois ela está limitando os registros com a cláusula WHERE PROD_TIPO = 'D'. CODIGO e não PROD_DESCRICAO. PROD_CODIGO que são os campos físicos da tabela. PROD_DESCRICAO. podemos alterá-los especificando-os na criação da View: CREATE VIEW VIEW_EXEMPLO_2A (CODIGO. Podemos também limitar os registros que serão retornados. para que uma View seja atualizável ela deverá atender algumas regras. portanto. No caso do nosso exemplo VIEW_EXEMPLO_2A onde os campos foram nomeados.br . PROD_DESCRICAO FROM PRODUTO Neste exemplo. a atualização é feita utilizando os nomes dos campos da VIEW e não da tabela física. ou seja. DESCRICAO) AS SELECT PROD_CODIGO. logo podemos executar um SELECT na tabela e veremos o resultado desta atualização. por exemplo: SELECT * FROM VIEW_EXEMPLO_3 WHERE PROD_TIPO = 'L' Apesar de existirem registros na tabela PRODUTO que atendam esta condição.com.101 - Active Delphi . porém. Atualizando a View Como dito no início.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Verifique se esta apostila possui uma licença registrada www. Reforçando mais uma vez.com. exemplo: UPDATE VIEW_EXEMPLO_2A SET DESCRICAO = 'PRODUTO 1 ALTERADO' WHERE CODIGO = 1 Note que utilizamos os campos DESCRICAO. activedelphi. ao tentarmos inserir o produto com o campo PROD_TIPO <> D um erro interno no banco seria gerado anulando a inclusão do registro.com. 'D'). 'PRODUTO 100'. PROD_TIPO FROM PRODUTO WHERE PROD_TIPO = 'D' WITH CHECK OPTION Se tentarmos inserir um registro com o campo PROD_TIPO = D: INSERT INTO VIEW_EXEMPLO_4 (PROD_CODIGO. o registro seria adicionado na tabela PRODUTO. 'L'). onde criamos uma View para retornar os produtos com o campo PROD_TIPO = D. 'PRODUTO 200'. PROD_DESCRICAO. 'PRODUTO 200'.com.edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Desta forma o registro não seria incluso. PROD_DESCRICAO. a mensagem de erro também não seria exibida caso estivéssemos utilizando a constraint. Este registro será incluso na tabela PRODUTO e será visualizado na View. Analisando nosso exemplo anterior.http//www.com. através da View poderíamos incluir um produto com o campo PROD_TIPO <> D.br . Esta constraint é opcional e evita a inclusão de registros na View que não atendam ao “filtro” (WHERE) especificado no SELECT que foi determinado na View. porém não seria visualizado na View justamente devido à cláusula WHERE estar limitando: INSERT INTO VIEW_EXEMPLO_3 (PROD_CODIGO. PROD_TIPO) VALUES (200. além disso. A seguinte mensagem de erro seria exibida: Operation violates CHECK constraint on view or table VIEW_EXEMPLO_4. Agora se tentarmos inserir um registro com o campo PROD_TIPO <> D: INSERT INTO VIEW_EXEMPLO_4 (PROD_CODIGO.br . se tentássemos atualizar ou excluir um registro que não é retornado pela View.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Não permitindo a inclusão de registros na View que não atendam ao “filtro” Na criação de uma View podemos incluir a constraint WITH CHECK OPTION ao final.edudelphipage. Vale lembrar que independente da utilização desta constraint. apesar da limitação feita na cláusula WHERE. Vejamos um exemplo de View utilizando esta constraint: CREATE VIEW VIEW_EXEMPLO_4 AS SELECT PROD_CODIGO.102 - Active Delphi . o registro não seria atualizado nem excluído. PROD_DESCRICAO. PROD_TIPO) VALUES (100. PROD_DESCRICAO.http://www. mesmo existindo na tabela de produtos. 'L'). PROD_TIPO) VALUES (200. Se utilizássemos a constraint WITH CHECK OPTION na criação da View. Excluindo e Alterando uma VIEW A exclusão de uma View é feita utilizando o comando DROP: DROP VIEW_EXEMPLO_1 Verifique se esta apostila possui uma licença registrada www. br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Não temos um ALTER VIEW. Verifique se esta apostila possui uma licença registrada www. Estaremos agora demonstrando sua utilização diretamente no banco de dados através do IBExpert.103 - Active Delphi .com. Conclusão Neste capítulo abordamos a criação de Views assim como suas respectivas vantagens.edudelphipage.br . portanto.activedelphi.br .com.http://www.http//www. para alterarmos uma View temos que excluir e criar novamente.com.edudelphipage. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando e utilizando Views no IBExpert Vimos no capítulo anterior para que serve uma View e como criamos.br .com.edudelphipage.http://www.. Podemos criar as Views executando os scripts vistos anteriormente no editor SQL do IBExpert.http//www.com.. Com o IBExpert aberto e conectado no banco.edudelphipage. abra a árvore do lado esquerdo selecionando o item Views e clique com o botão direito do mouse selecionando o item de menu New View.activedelphi.com. veremos este último caso. será exibida a tela para criamos a View: Figura 2 – Tela para criação da View Verifique se esta apostila possui uma licença registrada www. Além desta opção poderíamos utilizar o menu Database->New View ou o item Views na árvore de opções da conexão.104 - Active Delphi . Estaremos agora utilizando o IBExpert para criamos e executarmos as Views.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .: Figura 1 – Selecionando o item de menu para criação de uma View Ao clicar nesta opção.br . com.edudelphipage.br .com.Clicando no botão compile para compilar a View Em seguida será exibida a tela para efetuarmos um Commit: Verifique se esta apostila possui uma licença registrada www. Para facilitar estaremos colando nosso script nesta tela: Figura 3 – Adicionando nosso código para criação da View Agora é só clicar no botão Compile ou apertar CTRL + F9 para que ela seja compilada: Figura 4 .edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www.activedelphi.105 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados No lado direito indicado pela seta é onde devemos informar o script da nossa View ou substituir os campos _fields_ _table_name_ _conditions_.http//www.br . podemos alterá-la ou excluí-la clicando com o botão direito na respectiva View: Figura 6 .http//www.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.Opções para alterarmos ou excluirmos a View Criando e realizando testes em outras Views Repetiremos os procedimentos de criação para as Views abaixo e iremos realizando os testes para visualizarmos os resultados. Basta clicar no botão Commit e a nossa View estará criada.106 - Active Delphi .br .http://www. Depois de criada.activedelphi.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 5 – Tela para efetuar o Commit na criação da View. Verifique se esta apostila possui uma licença registrada www.br .edudelphipage. Estaremos utilizando como base 5 produtos da tabela de PRODUTO.edudelphipage. retorna todos os campos e todos os registros da tabela PRODUTO. execute a seguinte instrução SQL: SELECT * FROM VIEW_EXEMPLO_1. Figura 8 – Visualizando o resultado da 2.edudelphipage.a View.a View. Caso não tenha criado ainda.edudelphipage. utilize o seguinte código: CREATE VIEW VIEW_EXEMPLO_1 AS SELECT * FROM PRODUTO Para realizar o teste.com.a View – Especificando os campos CREATE VIEW VIEW_EXEMPLO_2 AS SELECT PROD_CODIGO.a View – Modelo mais simples Antes de partir para a criação da 2. Verifique se esta apostila possui uma licença registrada www.http//www. 2.com.activedelphi.br . vamos realizar um teste na 1.br .a View Esta View continua retornando todos os registros.a View Esta View é a mais simples.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados 1.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com. PROD_DESCRICAO FROM PRODUTO Execute a seguinte instrução SQL para o teste: SELECT * FROM VIEW_EXEMPLO_2. Teremos o seguinte resultado: Figura 7 – Visualizando o resultado da 1.107 - Active Delphi .http://www. porém apenas 2 campos: PROD_CODIGO e PROD_DESCRICAO. edudelphipage. PROD_DESCRICAO FROM PRODUTO Execute a seguinte instrução SQL para o teste: SELECT * FROM VIEW_EXEMPLO_2A.com.a View – Limitando os registros CREATE VIEW VIEW_EXEMPLO_3 AS SELECT PROD_CODIGO.br .a View Perceba que esta View também retorna os 2 campos.a View – Nomeando os campos CREATE VIEW VIEW_EXEMPLO_2A (CODIGO. PROD_TIPO FROM PRODUTO WHERE PROD_TIPO = 'D' Utiliza a seguinte instrução SQL para realizar o teste: SELECT * FROM VIEW_EXEMPLO_3 Figura 10 – Visualizando o resultado da 4. Figura 9 – Visualizando o resultado da 3.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados 3.http://www.108 - Active Delphi . Poderíamos aproveitar este momento para realizar o teste de atualização de uma view: UPDATE VIEW_EXEMPLO_3 SET PROD_DESCRICAO = 'PRODUTO 1 ALTERADO' WHERE PROD_CODIGO = 1 Verifique se esta apostila possui uma licença registrada www. neste caso somente produtos cujo campo PROD_TIPO seja igual a ‘D’.http//www. porém nomeados com os nomes indicados na View.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage.activedelphi.br .a View Nesta View já limitamos os registros a serem retornados.com. PROD_DESCRICAO. 4.com. DESCRICAO) AS SELECT PROD_CODIGO. br .109 - Active Delphi . PROD_TIPO) VALUES (200.edudelphipage. podemos verificar a alteração executando um SELECT na View ou na tabela PRODUTO: SELECT * FROM VIEW_EXEMPLO_3 Figura 11 – Visualizando os registros na View após o update SELECT * FROM PRODUTO Figura 12 – Visualizando os registros na tabela de produtos após o update na View Podemos notar que o update na view atualizou diretamente a tabela de produto.com.http://www. 'PRODUTO 200'. 4.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com. PROD_DESCRICAO.http//www.br .edudelphipage. PROD_TIPO FROM PRODUTO WHERE PROD_TIPO = 'D' WITH CHECK OPTION Podemos testar esta view executando a seguinte instrução SQL: INSERT INTO VIEW_EXEMPLO_4 (PROD_CODIGO.activedelphi. Verifique se esta apostila possui uma licença registrada www.com.a View – Impedindo a inserção de registros não autorizados CREATE VIEW VIEW_EXEMPLO_4 AS SELECT PROD_CODIGO. PROD_DESCRICAO.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Após atualizarmos. 'L'). será inserido normalmente: INSERT INTO VIEW_EXEMPLO_4 (PROD_CODIGO.br .edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 13 – Mensagem de erro ao tentar inserir um registro que viola a constraint Note a mensagem de erro sendo exibida.110 - Active Delphi . PROD_DESCRICAO. compensa executarmos o script SQL diretamente.http//www. já que é utilizada da mesma forma que uma tabela. ou seja. onde na query teríamos. Agora se tentarmos inserir um produto com o PROD_TIPO = 'D'. um SELECT * FROM NOME_DA_PROCEDURE.com. PROD_TIPO) VALUES (200. Não demonstraremos a utilização de Views no Delphi.activedelphi. por exemplo. 'D'). pudemos notar que a IDE não nos facilita muito na criação da View.http://www.edudelphipage. Figura 14 – Produto inserido diretamente na View Conclusão Vimos no IBExpert como criamos e utilizamos Views no banco de dados.br . podemos utilizar os componentes da DBExpress normalmente como já vimos anteriormente utilizando o conjunto ClientDataSet/Provider/Query para visualização dos dados. 'PRODUTO 200'.com. logo violamos a constraint que adicionamos na view: WITH CHECK OPTION.com. pois estamos tentando inserir um produto com o campo PROD_TIPO = 'L' e nossa View limita os registros com PROD_TIPO = 'D'. Verifique se esta apostila possui uma licença registrada www. Por exemplo. PED.PED_VALOR. mas infelizmente não é recomendável em casos onde temos muitos registros mestres.PED_NUMERO O resultado seria: Verifique se esta apostila possui uma licença registrada www. etc. para isto utilizaríamos agrupadores nos geradores de relatórios.edudelphipage. o ApplyUpdates é feito apenas no ClientDataSet mestre. PEDITEM.PED_NUMERO. estaremos utilizando o QuickReport para fins didáticos.br .PED_NUMERO ORDER BY PED.edudelphipage. PEDITEM. a atualização é centralizada na mesma transação. Quando utilizamos este modelo. portanto.activedelphi. pois a query detalhe que estará sendo executada com freqüência será preparada antecipadamente pela própria DBExpress ganhando mais performance no servidor. pois para relatórios com muitos registros mestres.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Relatórios Mestre/Detalhe com performance No primeiro módulo deste curso citei as diferenças entre as formas existentes de se trabalhar com o ClientDataSet utilizando mestre/detalhe. mas vamos exemplificar aqui uma tabela com poucos registros para entendermos melhor com seria. Pode parecer um pouco confuso. ou seja. porém vale a pena.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . se formos gerar um relatório contendo 100 pedidos. para cada registro mestre é executado a query detalhe para retornar os registros detalhes.com. e para cada pedido será executada outra query para retornar os itens. Por esta razão sugiro desenvolvermos relatórios mestre/detalhe utilizando outra técnica (joins) um pouco mais trabalhosa.PEDITEM_VALUNIT.http//www.com. onde fazemos o relacionamento entre as querys. teremos 101 querys sendo executadas. teremos uma query sendo executada para extrair os pedidos. Esta técnica pode ser aplicada em qualquer gerador de relatório que permita fazer quebras. Utilizando Joins A utilização de joins resume-se em fazermos um SELECT na tabela DETALHE com JOIN na tabela MESTRE e no gerador de relatórios fazemos uma quebra pela chave primária da tabela MESTRE.PED_NUMERO = PEDITEM. perceberemos a diferença de performance claramente.PEDITEM_QTDE.PEDITEM_DESCRICAO FROM PEDIDO_ITEM PEDITEM INNER JOIN PEDIDO PED ON PED.com. Por esta razão é comum os desenvolvedores acabarem utilizando este mesmo modelo de relacionamento em relatórios.111 - Active Delphi . PEDITEM.http://www. Utilizaríamos o seguinte SQL: SELECT PED. agrupamentos. Concluímos que a forma mais eficaz na grande maioria dos casos é utilizar o modelo NestedDataSet. claro que otimizadas. br .edudelphipage. neste caso.br . As cores foram utilizadas para ficar claro que as quebras do relatório serão feitas desta forma.edudelphipage.http//www. com isso teremos um efeito de mestre/detalhe.http://www. ou seja.com.com.112 - Active Delphi .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 1 – Exemplo dos registros No exemplo acima perceba que as 3 primeiras colunas são referentes aos dados do pedido e as demais colunas são referentes aos dados dos itens. pois sempre que mudar o número. por isso visualizamos seus dados repetidos nas duas primeiras linhas (vermelho) e 3 primeiras colunas. por este motivo utilizamos o ORDER BY no campo PED_NUMERO para garantir que os registros sejam ordenados por este campo. O segredo do funcionamento é a chave que irá fazer a quebra. A performance está no fato de executarmos apenas uma query no banco e não mais N querys de acordo com o número de registros mestre para buscar os registros detalhes.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Verifique se esta apostila possui uma licença registrada www.com. O pedido número 1 tem 2 itens.activedelphi. utilizaremos o número do pedido. Partindo para prática Para que possamos comprovar na prática a diferença. outra quebra no pedido número 2 imprimindo apenas seu único item e por último a quebra no pedido número 3 imprimindo seus 2 itens. será feita uma quebra no pedido número 1 sendo visualizado seus 2 itens. criaremos o relatório utilizando os dois modelos (NestedDataSet e Joins) e ao final será feita uma comparação demonstrando o arquivo de log gerado por ambos os modelos. uma nova quebra será feita dando um efeito de mestre/detalhe. O pedido número 2 (azul) tem apenas um item e o Pedido número 3 (verde) tem 2 itens. activedelphi.113 - Active Delphi .br . Clique no menu File->New->Other..com.pas Adicione na cláusula uses a unit udmprincipal: . Agora insira os seguintes componentes no QuickReport: TSQLQuery Name: qryPedido SQLConnection: dmPrincipal.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando Relatório Mestre/Detalhe utilizando NestedDataSet Abra nosso projeto no Delphi.br .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . PED_DATA..http//www...edudelphipage. Figura 1 – Criando um novo Report Em seguida salve-o como uqrModeloNestedDataSet.SqlConnPrincipal SQL: SELECT PED_NUMERO. PED_VALOR FROM PEDIDO TDataSetProvider Name: dspPedido DataSet: qryPedido Verifique se esta apostila possui uma licença registrada www. selecione o item Report e confirme clicando no botão Ok.edudelphipage. na janela que será exibida...http://www.com. . implementation uses udmPrincipal.com. http//www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . PEDITEM_QTDE. PEDITEM_DESCRICAO.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados TClientDataSet Name: cdsPedido ProviderName: dspPedido TDataSource Name: dtsLink DataSet: qryPedido TSQLQuery Name: qryPedItem DataSource: dtsLink SQLConnection: dmPrincipal.edudelphipage. Verifique se esta apostila possui uma licença registrada www.br .br .com.SqlConnPrincipal SQL: SELECT PED_NUMERO. PEDITEM_VALTOTAL FROM PEDIDO_ITEM WHERE PED_NUMERO = :PED_NUMERO Agora de um duplo clique no cdsPedido para abrir o FieldsEditor.http://www.activedelphi. Figura 2 – Adicionando os campos ao cdsPedido Em seguida será exibida a lista dos campos a serem adicionados.edudelphipage. em seguida clique com o botão direito do mouse e acesse o item de menu Add fields.com.114 - Active Delphi .com. neste momento temos nossos ClientDatsSet's interligados de modo a trabalhar com mestre/detalhe utilizando NestedDataSet.http://www. Figura 4 – Definindo o DataSetField do cdsPedItem Pronto. Selecione o Report e na propriedade Bands ligue a opção HasDetail Verifique se esta apostila possui uma licença registrada www.edudelphipage.115 - Active Delphi .br . este será o nosso NestedDataSet.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 3 – Lista de campos a serem adicionados ao cdsPedido Perceba o campo qryPedidoItem.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage.br .com.http//www.activedelphi. associe-a com o campo cdsPedidoqryPedidoItem. Confirme clicando no botão OK. portanto. Agora vamos ajustar o QuickReport. Agora selecione o componente cdsPedItem e na propriedade DataSetField já temos o NestedDataSet disponível.com. br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com.edudelphipage.edudelphipage.br .http://www.com.activedelphi.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 5 – Ligando a opção HasDetail do QuickReport Adicione o componente QRSubDetail conforme demonstra a figura a seguir: Figura 6 – Adicionando um QRSubDetail ao QuickReport Figura 7 – Subdetail inserido no relatório Selecione o Report e ajuste a propriedade DataSet apontando para cdsPedido.http//www.com.br .116 - Active Delphi . Verifique se esta apostila possui uma licença registrada www. Verifique se esta apostila possui uma licença registrada www. Figura 9 – Ajustando o DataSet da banda SubDetail Agora o que resta é adicionarmos os QRDBText's na banda Detail ligando-os com o dataset cdsPedido e Subdetail ligando-os com o dataset cdsPedItem assim como seus respectivos campos.com. devemos ajustar a propriedade ForceNewPage da banda Detail.com.edudelphipage.activedelphi.http//www. portanto ative esta propriedade.br .edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 8 – Ajustando o DataSet do QuickReport Agora selecione a banda SubDetail e ajuste o DataSet apontando para cdsPedItem.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . O QuickReport deverá ficar da seguinte forma: Figura 10 – Report montando com os QRDBText's Para que cada quebra seja feita em uma página.br .117 - Active Delphi .http://www.com. begin cdsPedido. . abra o cdsPedido através da propriedade Active e faça o mesmo para o cdsPedItem..com.. var PrintReport: Boolean).QuickRepBeforePrint( Sender: TCustomQuickRep.. Em seguida clique com o botão direito do mouse sobre o QuickReport e clique em Preview.br .Open.edudelphipage. Verifique se esta apostila possui uma licença registrada www.com.com.activedelphi. Para verificar se tudo está funcionando corretamente.. Deverá ser visualizado o relatório no modelo mestre/detalhe conforme demonstra a figura a seguir: Figura 12 – Preview do Relatório Agora vamos colocar uma chamada ao relatório na tela principal do projeto. end. implementation uses uqrModeloNestedDataSet.edudelphipage.http://www.http//www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br .118 - Active Delphi . Abra a unit ufrmPrincipal e na cláusula uses adicione a unit uqrModeloNestedDataSet . porém antes vamos aproveitar que estamos com o Report aberto e codificar seu evento BeforePrint da seguinte forma: procedure TqrModeloNestedDataSet.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 11 – Ligando a propriedade ForceNewPage da banda Detail Aproveite este momento para ajustar o name do QuickReport para qrModeloNestedDataSet. Não esqueça de desligar a propriedade Active do componente cdsPedido e cdsPedItem. TButton Caption: Abrir QuickReport 1 Modelo NestedDataSet Name: btnQrNestedDataSet Codifique o evento OnClick da seguinte forma: procedure TfrmPrincipal.br . end. teremos o mesmo resultado do Preview que testamos em tempo de projeto no próprio QuickReport.edudelphipage.activedelphi. end.119 - Active Delphi .PreviewModal.br .http://www. Se rodarmos a aplicação e clicarmos no botão. Fazendo um log das Querys executadas no banco Faremos um log das querys executadas no banco de dados para que ao final possamos concluir com as diferenças entre os dois modelos de relatório. adicione o componente SQLMonitor no datamodule principal ajustando as seguintes propriedades: Verifique se esta apostila possui uma licença registrada www. try qrModeloNestedDataSet. acesse o menu Project->Options e confira se a paleta Forms está como a figura a seguir.Free.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Certifique-se de que este Report não está como Auto-Create na aplicação.btnQrNestedDataSetClick(Sender: TObject).com. finally qrModeloNestedDataSet.edudelphipage. para verificar.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . caso não esteja ajuste-a desta forma: Figura 13 – Ordem de criação dos formulários Agora adicione um botão no formulário principal.Create(Self). portanto.http//www.com. begin qrModeloNestedDataSet := TqrModeloNestedDataSet.com. ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados TSQLMonitor Name: sqlmon SqlConnection: SqlConnPrincipal FileName: log.txt AutoSave: True Active:True Execute a aplicação novamente e clique no botão para abrir o relatório. Depois que o relatório foi gerado abra o arquivo log.txt que foi criado no mesmo diretório do projeto e perceba um conteúdo semelhante ao que temos a seguir onde faço alguns comentários em alguns pontos: INTERBASE - isc_attach_database INTERBASE - isc_dsql_allocate_statement INTERBASE - isc_start_transaction ## Executando a Query mestre SELECT PED_NUMERO, PED_DATA, PED_VALOR FROM PEDIDO INTERBASE INTERBASE INTERBASE INTERBASE INTERBASE INTERBASE - isc_dsql_prepare isc_dsql_describe_bind SQLDialect = 3 isc_dsql_execute isc_dsql_fetch isc_dsql_allocate_statement ## Preparando a query detail SELECT PED_NUMERO, PEDITEM_DESCRICAO, PEDITEM_QTDE, PEDITEM_VALTOTAL FROM PEDIDO_ITEM WHERE PED_NUMERO = ? INTERBASE - isc_dsql_prepare INTERBASE - isc_dsql_describe_bind ## Executando a query detail pela 1.a vez INTERBASE - SQLDialect = 3 INTERBASE - isc_dsql_execute INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_commit_retaining INTERBASE - isc_dsql_free_statement ## Executando a query detail pela 2.a vez INTERBASE - SQLDialect = 3 INTERBASE - isc_dsql_execute INTERBASE - isc_dsql_fetch Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 120 - Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados INTERBASE INTERBASE INTERBASE INTERBASE - isc_dsql_fetch isc_dsql_fetch isc_commit_retaining isc_dsql_free_statement ## Executando a query detail pela 3.a vez INTERBASE - SQLDialect = 3 INTERBASE - isc_dsql_execute INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_commit_retaining INTERBASE - isc_dsql_free_statement ## Executando a query detail pela 4.a vez INTERBASE - SQLDialect = 3 INTERBASE - isc_dsql_execute INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_dsql_fetch INTERBASE - isc_commit_retaining INTERBASE - isc_dsql_free_statement E assim vai indo, se tivéssemos muitos registros o log estaria enorme, pois para cada registro mestre são executados estes blocos que vimos acima, ou seja, é uma query de itens sendo executada para cada pedido. Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 121 - Active Delphi - http//www.activedelphi.com.br ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Criando o Relatório utilizando Joins Com o projeto aberto, insira um novo Report conforme foi explicado no capítulo anterior utilizando o menu File->New->Other Figura 1 – Criando um novo report Salve a unit como uqrModeloJoin.pas, em seguida nomeie o Report para qrModeloJoin. Adicione na cláusula uses a unit udmprincipal: ... implementation uses udmPrincipal; ... Agora adicione os seguintes componentes: TSQLQuery Name: qryPedido SQLConnection: dmPrincipal.SqlConnPrincipal SQL: SELECT PED.PED_NUMERO, PED.PED_VALOR, PEDITEM.PEDITEM_QTDE, PEDITEM.PEDITEM_VALUNIT, PEDITEM.PEDITEM_DESCRICAO FROM PEDIDO_ITEM PEDITEM INNER JOIN PEDIDO PED ON PED.PED_NUMERO = PEDITEM.PED_NUMERO ORDER BY PED.PED_NUMERO TDataSetProvider Name: dspPedido DataSet: qryPedido Verifique se esta apostila possui uma licença registrada www.edudelphipage.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage - http://www.edudelphipage.com.br - 122 - Active Delphi - http//www.activedelphi.com.br br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Agora selecione o Report e na propriedade Bands ative a opção HasDetail.activedelphi. mas é isto mesmo.com. Verifique se esta apostila possui uma licença registrada www. Figura 2 – Abrindo o FieldsEditor e adicionando os campos no cdsPedido Figura 3 – Campos a serem adicionadas ao cdsPedido Perceba que teremos num único ClientDataSet campos da tabela de Pedido e Itens. pode parecer estranho.br .edudelphipage.123 - Active Delphi .http//www.http://www.com.br .com.edudelphipage.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados TClientDataSet Name: cdsPedido ProviderName: dspPedido Em seguida de um duplo clique no cdsPedido para abrir o FieldsEditor e clique com o botão direito acessando o item de menu Add fields. http://www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . mas não é este nosso objetivo.124 - Active Delphi .activedelphi.http//www.com.com. Figura 5 – Ajustando o DataSet do Report Neste momento já teríamos pronto nosso relatório para exibir uma listagem dos registros sem quebras.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 4 – Ativando a opção HasDetail na propriedade Bands do Report Ajuste a propriedade DataSet do Report apontando para cdsPedido.edudelphipage.br . portanto vamos lá! Insira um TQRGroup no Report conforme demonstra a figura a seguir: Verifique se esta apostila possui uma licença registrada www.edudelphipage. precisamos da quebra para simular o mestre/detalhe.com.br . br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . pois este é o componente para realizarmos agrupamento no QuickReport.com.activedelphi. na propriedade Expression desta banda informe o campo PED_NUMERO conforme demonstra a figura a seguir: Verifique se esta apostila possui uma licença registrada www.edudelphipage.125 - Active Delphi . portanto.http://www.br . neste caso estaremos utilizando esta técnica para fazermos as quebras simulando o mestre/detalhe.com.edudelphipage. Agora precisamos definir no QRGroup qual é o campo que utilizaremos como sendo o agrupador.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 6 – Adicionando um TQRGroup no Report O Report ficará da seguinte forma: Figura 7 – Report com o TQRGroup adicionado Adicionamos o TQRGroup.br .com.http//www. edudelphipage. Na banda QRGroup devemos inserir os campo relativos a tabela mestre (tabela de Pedido).com.edudelphipage. neste momento já temos o Report preparado para trabalhar com Mestre/Detalhe.com.activedelphi. já na banda Detail colocamos os campos relativos a tabela detalhe (tabela de Itens do Pedido). defina com True: Figura 9 – Ajustando a propriedade do QRGroup Pronto. portanto.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .126 - Active Delphi .br .br . precisamos apenas inserir os QRDBText's nas respectivas Bandas.http//www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 8 – Ajustando a propriedade Expression do QRGroup Agora precisamos ajustar a propriedade ForceNewPage do Grupo.com.http://www. O report deverá ficar da seguinte forma: Figura 10 – Componentes QRDBText's inseridos no Report Verifique se esta apostila possui uma licença registrada www. end. end. deixe-os da seguinte forma: Verifique se esta apostila possui uma licença registrada www.Open.edudelphipage.127 - Active Delphi . ..http//www. begin qrModeloJoin := TqrModeloJoin.br ..com.activedelphi.Free. var PrintReport: Boolean). begin cdsPedido.com.btnQrJoinClick(Sender: TObject). uqrModeloJoin. try qrModeloJoin.Create(Self). Agora basta ajustarmos nosso formulário principal para fazer chamada a este report..QuickRepBeforePrint(Sender: TCustomQuickRep. codifique o evento da seguinte forma: procedure TqrModeloJoin. Abra a unit ufrmPrincipal e na cláusula uses adicione a unit uqrModeloJoin .br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage ..PreviewModal. portanto.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Vale lembrar que todos componentes QRDBText’s estarão apontando para o mesmo DataSet. O último passo para finalizarmos este relatório é codificarmos o evento BeforePrint para que o ClientDataSet de Pedido seja aberto ao imprimir o relatório. Agora vamos verificar como está a ordem de criação dos formulários e quais estão como AutoCreate. end.br .edudelphipage. finally qrModeloJoin. implementation uses uqrModeloNestedDataSet. Em seguida adicione um botão ajustando as respectivas propriedades: TButton Caption: Abrir QuickReport 1 Modelo Join Name: btnQrJoin Codifique o evento OnClick da seguinte forma: procedure TfrmPrincipal.http://www. no caso o cdsPedido. com.br .edudelphipage.com.edudelphipage.http://www. eles são criados dinamicamente somente quando clicamos nos botões.128 - Active Delphi . Para podermos fazer o teste. Agora vamos rodar a aplicação e clicar no botão para gerar o relatório. primeiro verifique no datamodule principal se o componente SQLConnection está conectado no banco.activedelphi.txt que está na pasta do projeto e foi gerado no capítulo anterior.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 11 – Verificando a ordem e criação automática dos formulários Esta verificação é feita apenas para não deixarmos nossos Report's sendo criados automaticamente ao entrar na aplicação.txt e notaremos a diferença comparando com o log visto no capítulo anterior: Verifique se esta apostila possui uma licença registrada www.com. teremos o seguinte resultado: Figura 12 – Relatório gerado no modelo Join Podemos analisar o arquivo log.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br . se estiver desconecte-o. Em seguida exclua o arquivo log.http//www. PED_NUMERO = PEDITEM.PEDITEM_VALUNIT.isc_dsql_fetch INTERBASE .isc_start_transaction # Aqui está a diferença.129 - Active Delphi .br .http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados INTERBASE .isc_dsql_fetch .isc_dsql_allocate_statement INTERBASE .activedelphi. é interessante pensar em utilizar o modelo Join.PED_NUMERO INTERBASE INTERBASE INTERBASE INTERBASE - isc_dsql_prepare isc_dsql_describe_bind SQLDialect = 3 isc_dsql_execute # Daqui para baixo é apenas fetchs executados para trazer os registros.com.http//www. no caso do QuickReport ele permite que seja utilizado DataSets unidirecionais. portanto. por este motivo não pudemos notar diferenças em performance.com.PED_NUMERO.com.isc_attach_database INTERBASE .PEDITEM_QTDE.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .isc_dsql_fetch INTERBASE .isc_dsql_fetch INTERBASE . Outro aspecto importante que não foi citado é que não necessariamente precisaríamos ter utilizado o ClientDataSet para gerar o relatório. PEDITEM. sugiro manter o modelo tradicional.br . somente em casos onde haja muitos registros mestres.PEDITEM_DESCRICAO FROM PEDIDO_ITEM PEDITEM INNER JOIN PEDIDO PED ON PED. já que com ele podemos facilitar outros trabalhos.isc_dsql_fetch INTERBASE . isso é normal.isc_dsql_fetch INTERBASE .PED_VALOR. PEDITEM. Conclusão de ambos os modelos Simulamos os dois exemplos com poucos registros. além disso. pois pode acontecer de algum deles não permitir a utilização destes DataSets unidirecionais. porém aqui não temos mais aquele bloco responsável por executar a query detalhe para cada pedido INTERBASE . estamos rodando a aplicação com o banco local. mas fique atento com outros geradores de relatório. caso você não necessite de algo específico do ClientDataSet. poderá utilizar diretamente a TSQLQuery. PED. no log anterior vimos estes fetchs também.. em um ambiente de rede perceberíamos mais a diferença. PEDITEM. Caso sejam poucos registros.. Verifique se esta apostila possui uma licença registrada www. De qualquer forma pudemos notar a diferença no próprio log entre um modelo e outro. apenas um select é executado SELECT PED..edudelphipage.edudelphipage. então sugiro que faça testes mais precisos em um ambiente de rede com mais registros para notar a diferença e decidir qual modelo utilizar. progdigy.com. Um deles é o InterXPress da Upscene sendo pago e podendo ser baixado em http://www.progdigy.0.com. Existem dois drivers DBExpress disponíveis na Internet até este momento.com/modules.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Instalando e utilizando driver DBExpress de terceiros O driver DBExpress que estamos utilizando é nativo da Borland específico para Interbase.http://www. Infelizmente esta compatibilidade pode não durar muito.edudelphipage.br . Algumas sub-pastas serão criadas conforme demonstra a figura abaixo: Figura 1 – Estrutura de diretório após a descompactação Entre na pasta DBExpress e note que existem diversos projetos Delphi (DPR): Verifique se esta apostila possui uma licença registrada www.5 do banco de dados.edudelphipage.activedelphi.br . Depois de feito o download do arquivo zip.130 - Active Delphi . por este motivo é interessante começarmos a utilizar drivers da DBExpress específicos para Firebird.php?name=UIB.com/modules. justamente pelo fato de não haver custo! A instalação é um pouco trabalhosa. pois segundo o site. descompacte-o em: C:\CursoClientDataSet2\Diversos.php?name=UIB Resolvi fazer o download do UIB 2. O outro driver é o UIB (Unified Interbase). mas não se preocupe. Estaremos utilizando este último driver citado.http//www.0 poderemos ter algumas incompatibilidades.com.0. não é tão complicado assim. este possui compatibilidade com a versão do Firebird 2. este já é gratuito e pode ser baixado em: http://www. teremos que ajustar o arquivo INI que contém os drivers da DBExpress e compilar o código fonte do projeto que baixaremos do site para gerar a DLL do driver. com a nova versão 2.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Partindo para prática Primeiramente devemos baixar o pacote do site: http://www.upscene.com. porém estamos utilizando com Firebird pelo fato de ainda existir compatibilidade pelo menos até a versão 1. dpr no Delphi.activedelphi.com. Verifique se esta apostila possui uma licença registrada www. clique no menu Project->Options em seguida clique na aba Directories/Conditionals e ajuste o campo SearchPath informando: C:\CursoClientDataSet2\Diversos\UIB2\source Figura 3 – Ajustando o Search path do projeto Neste momento podemos confirmar e compilar o projeto clicando no menu Project->Build dbexpUIBfire15.131 - Active Delphi .br .http://www.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 2 – Projetos disponíveis na pasta DBExpress Agora abra o projeto dbexpUIBfire15. portanto.http//www.edudelphipage. Precisamos ajustar o SearchPath.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .edudelphipage.com.br . podemos conferir na pasta Figura 5 – DLL gerada após a compilação Agora precisamos copiar a DLL para pasta bin do Delphi onde está também a atual dbexpint.dll e outras dlls da DBExpress.http://www.http//www.edudelphipage.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi.132 - Active Delphi .com.br .br .com.edudelphipage. Figura 6 – Copiando a DLL gerada para a pasta bin do Delphi Verifique se esta apostila possui uma licença registrada www. C:\CursoClientDataSet2\Diversos\UIB2\DBExpress.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 4 – Compilando o projeto para gerar a DLL Com isso já temos a DLL gerada. .com.. adicione uma seção chamada [UIB FireBird15] com suas respectivas linhas conforme demonstra o código abaixo: .com. [UIB FireBird15] GetDriverFunc=getSQLDriverINTERBASE LibraryName=dbexpUIBfire15.http//www.activedelphi..br . O arquivo ficará da seguinte forma: Verifique se esta apostila possui uma licença registrada www.Na seção [Installed Drivers] inclua a linha UIB FireBird15 = 1 conforme demonstra o bloco abaixo: [Installed Drivers] . Neste arquivo é que estão armazenados os drivers disponíveis da DBExpress com seus respectivos parâmetros de conexão. O que precisamos fazer é incluir o driver UIB com seus parâmetros.dll BlobSize=-1 CommitRetain=False Database=database.fdb ErrorResourceFile= LocaleCode=0000 Password=masterkey RoleName=RoleName ServerCharSet= SQLDialect=3 Interbase TransIsolation=ReadCommited User_Name=SYSDBA WaitOnLocks=True . Vá até a pasta C:\Arquivos de programas\Arquivos comuns\Borland Shared\DBExpress e abra o arquivo dbxdrivers.edudelphipage.dll VendorLib=fbclient..edudelphipage. siga os passos: .br . UIB FireBird15 = 1 Em seguida.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . portanto.133 - Active Delphi ...ini.http://www.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Feche o Delphi e agora faremos o ajuste no arquivo de drivers da DBExpress. Figura 8 – Driver UIB Firebird 15 adicionado na lista de Drivers da DBExpress Agora basta selecioná-lo e as propriedades GetDriverFunc e LibraryName do componente serão modificadas de acordo com o novo driver. Carregue nosso projeto no Delphi em seguida abra o datamodule principal e selecione o componente SQLConnection.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .activedelphi. Verifique se esta apostila possui uma licença registrada www. Clique na propriedade DriverName e note que foi adicionado o driver UIB Firebird 15 na lista de drivers disponíveis.edudelphipage. agora podemos salvar este arquivo e abrir o Delphi.br .br .134 - Active Delphi .com.edudelphipage.ini modificado com a inclusão do novo driver Pronto.http//www.http://www.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 7 – Arquivo dbxdrivers.com. edudelphipage. vale a pena comparar com os recursos existentes no driver pago para sabermos em que momento seria interessante o investimento em um driver DBExpress.com.http//www. precisamos ajustar novamente os parâmetros de conexão. Para este caso utilizamos o driver gratuito.135 - Active Delphi .http://www.br .com. Conclusão Neste capítulo demonstramos como instalamos e utilizamos um driver de terceiro específico para Firebird com objetivo de evitar incompatibilidades futuras com o banco de dados.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . clique na propriedade Params ajustando o parâmetro DataBase para C:\CursoClientDataSet2\Projeto\exemplo.edudelphipage. porém. portanto. Verifique se esta apostila possui uma licença registrada www.com.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 9 – Propriedades GetDriverFunc e LibraryName sendo modificadas de acordo com o driver Pelo fato de termos mudado de driver. a diferença é que agora ao invés de levarmos junto a nossa aplicação o arquivo dbexpint.fdb e ServerCharSet para WIN1252.dll levaremos o arquivo dbexpUIBfire15. lembrando que em seu cliente esse arquivo deverá estar no mesmo diretório da aplicação ou no System do Windows. Figura 10 – Redefinindo os parâmetros de conexão após a mudança do driver Distribuindo aplicação Com o uso deste novo driver a distribuição da aplicação não será muito diferente do que já vimos com o driver antigo.br .activedelphi.dll. br .http//www.com. o mesmo poderá ter acesso ao banco mesmo não sabendo a nova senha. É importante sabermos que não adianta apenas modificarmos a senha no servidor. Figura 1 – Entrando na pasta bin do Firebird Agora digite: gsec -user SYSDBA -pass masterkey Ao pressionar o ENTER estaremos no prompt do utilitário gsec.136 - Active Delphi . porém é interessante modificarmos para dificultarmos o acesso ao banco por pessoas não autorizadas.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Trocando a senha do usuário SYSDBA Durante todo curso utilizamos a senha padrão do Firebird.com. pois o Firebird armazena as definições de usuários no próprio servidor (tabela security.com. portanto estaremos utilizando-o para modificarmos a senha do servidor. Por esta razão a segurança deve iniciar no próprio ambiente de rede limitando o acesso ao diretório onde está o banco de dados da aplicação e o Firebird.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .br . O Firebird possui um utilitário chamado gsec responsável pela manipulação de usuários no banco.activedelphi. Verifique se esta apostila possui uma licença registrada www. Figura 2 – Entrando no gsec com o usuário SYSDBA Se digitarmos HELP em seguida ENTER.edudelphipage.edudelphipage. pois ele utilizará a senha do SYSDBA deste outro servidor.fdb) e não em nosso banco de dados específico. veremos todos comandos que o gsec disponibiliza. Partindo para prática Vamos então executar o gsec para modificarmos a senha do usuário SYSDBA Entre no prompt de comando e acesse o diretório bin do Firebird. isso significa que se alguém copiar o banco de dados da aplicação e colocar em um outro servidor Firebird.http://www. devemos digitar o seguinte comando: modify SYSDBA –pw 123456 Figura 4 – Definindo a nova senha para o usuário SYSDBA Ao pressionar o ENTER já teremos o usuário SYSDBA modificado com a nova senha 123456.edudelphipage. portanto.com. portanto.edudelphipage.br . Neste caso estaremos modificando a senha do usuário SYSDBA.137 - Active Delphi .com.br . não adiantaria definirmos uma senha como 123456789 a mesma seria considerada como 12345678.activedelphi.http//www.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .http://www.com. Para sair do gsec basta digitar quit Figura 5 – Saindo do gsec Verifique se esta apostila possui uma licença registrada www. Um detalhe importante é que o Firebird considera apenas os 8 primeiros caracteres.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 3 – Comandos do gsec Estaremos utilizando o comando modify para modificar os dados de um determinado usuário. Verifique se esta apostila possui uma licença registrada www. portanto devemos digitar o seguinte comando: modify SYSDBA –pw masterkey Figura 8 – Voltando a senha sysdba Perceba que o gsec alertou de que somente os primeiros 8 bytes são considerados conforme comentamos no início.com.br . Se tentássemos executar nossa aplicação ou abrir a conexão do banco no IBExpert não conseguiríamos também.br .edudelphipage.activedelphi. Para termos a certeza de que a senha foi modificada.138 - Active Delphi . Aqui concluiríamos o assunto. porém vamos voltar a senha anterior: Figura 7 . basta tentarmos acessar o gsec novamente com a senha masterkey: Figura 6 – Tentando acessar o gsec com a senha masterkey Perceba a mensagem de erro dizendo que este usuário e senha não está definido no servidor.Entrando no gsec com a senha nova Note que agora entramos com a nova senha no gsec. O interessante é que podemos acessar o banco entrando apenas com a senha masterke que é até onde completam 8 caracteres.edudelphipage.http//www. Modificaremos a senha para masterkey novamente.com.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage . Em seguida vamos sair do gsec digitando quit para finalizarmos.ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Em seguida pressione ENTER.http://www.com. precisaríamos modificar as senhas onde definimos como masterkey. definições de regras de acesso. O gsec permite também a criação de usuários.activedelphi.br/licenca?key=SM36A-93DI1-OW59G EduDelphiPage .com. deixaremos este assunto para uma próxima oportunidade pelo fato de que o Firebird 2.br .ClientDataSet com DBExpress e Firebird – Módulo II – Explorando o Banco de Dados Figura 9 – Saindo do gsec Conclusão Neste capítulo vimos como modificamos a senha do usuário SYSDBA através do utilitário gsec. O importante é que com este capítulo já conseguimos uma segurança a mais por não utilizarmos a senha padrão do servidor.com.http//www.edudelphipage.0 ficar bastante estável e logo estudar com detalhes estas mudanças e disponibilizar um artigo passando todos procedimentos necessários para criarmos novos usuários e regras de acesso no servidor.com.br .0 teve diversas modificações conceituais e estruturais nesta parte de usuários para garantir maior segurança. mas é importante não esquecermos da segurança no próprio ambiente de rede. Verifique se esta apostila possui uma licença registrada www. entre outros detalhes. portanto.139 - Active Delphi .edudelphipage. meu objetivo é esperar a versão 2.http://www.