Você está na página 1de 32

março 2010

março 2010
índice Editorial Delphi Delphi

04 05 10
Espero que nesse mês todos Manipulando Streams no Delphi Utilizando componentes ABCr no
tenham recebido 2010 Delphi 2010
muitos ovinhos do
coelhinho. Quem
não recebeu seja
um bom menino... Autor: Antonio Spitaleri Autor: Antonio Spitaleri

Banco de Dados Banco de Dados .NET

14 19 24
Indo mais além eplorando as Stored Procedures e Triggers no Novidades do Visual Studio 2010
tabelas de sistema MySQL
Interbase/Firebird

Autor: Djonatas Tenfen


Autor: Felipe Santos Autor: Bruno Alcarás

Dicas Desafio The Club

28
- Dicas Delphi

30
- Cruzada

Legenda
Iniciante
Intermediário
Avançado

março 2010 03
Bem-vindo Av. Profº Celso Ferreira da Silva, 190

Espero que nesse mês todos tenham recebido muitos ovinhos do coelhinho. Jd. Europa - Avaré - SP - CEP 18.707-150
Informações: (14) 3732-1529
Quem não recebeu seja um bom menino ou menina que no próximo ano ele Suporte: (14) 3733-1588

vem.
Internet
Aproveito para convidar nossos leitores a comparecerem ao “Microsoft http://www.theclub.com.br
Cadastro: cadastro@theclub.com.br
TechDay” que será realizado em Blumenau-SP no dia 24/04 e que tem com um Suporte: suporte@theclub.com.br

dos idealizadores nosso colunista Djonatas Tenfen. O The Club tem prazer em Informações: info@theclub.com.br
Skype Cadastro: theclub_cadastro
apoiar essa iniciativa. Tenho certeza que será um grande evento. Saiba mais Skype Suporte: theclub_linha1

acessando: www.mstechday.com theclub_linha2


theclub_linha3

Nessa edição temos artigos pra todos os gostos.

Nosso consultor técnico Antonio Spitaleri Neto trabalha dobrado esse mês e
nos apresenta dois artigos. No primeiro, ”Manipulando Streams no Delphi 2010”,
ele fala sobre um recurso presente no Delphi desde o seu início, os Streams, e www.twitter.com/theclubbr
que apesar de ser pouco utilizado nos dias de hoje, pode ser muito importante
Copyright The Club Megazine 2009
para alguns pontos específicos dos nossos aplicativos. No segundo, ”Utilizando
os Componente ACBr com Impressoras Fiscais no Delphi 2010” ele fala sobre os
Diretor Técnico
componentes Open Source ACBr que são uma verdadeira “mão na roda” para Marcos César Silva
nós desenvolvedores trabalharmos com ECF.
Diagramação e Arte
Iniciando as páginas dedicadas a Banco de Dados dessa edição, Felipe Santos Vitor M. Rodrigues
com seu artigo “Indo mais além, explorando as tabelas de sistema Interbase/
Firebird” nos mostra como trabalhar com as tabelas de sistema do Interbase/ Revisão
Tassiane Fileto
Firebird visando uma melhor manutenção dos nossos Bancos de Dados.

Colunistas
Nosso consultor Jr. Bruno Alcarás neste mês nos trás o artigo “Stored Procedure Antonio Spitaleri Neto
e Triggers no MySQL”, nos dando uma visão geral sobre esses ótimos recursos Bruno Alcarás
Djonatas Tenfen
que são mais conhecidos em Banco de Dados Firebird mas que também tem um Felipe Santos
papel muito importante no desenvolvimento de um Banco MySQL.
Impressão e acabamento:
Djonatas Tenfen no seu artigo “Novidades do Visual Studio 2010” nos apresenta GRIL - Gráfica e Editora
Taquarituba-SP - Tel. (14) 3762-1345
as principais novidades dessa nova versão do Visual Studio que foi oficialmente
lançado no dia 12/04.
Reprodução
A utilização, reprodução, apropriação, armazenamento em banco
de dados, sob qualquer forma ou meio, de textos, fotos e outras
criações intelectuais em cada publicação da revista “The Club

Um grande abraço
Megazine” são terminantemente proibidos sem autorização
escrita dos titulares dos direitos autorais.

Marcos César Silva - Editor Chefe


marcos@theclub.com.br Delphi é marca registrada da Borland International,
as demais marcas citadas são registradas
pelos seus respectivos proprietários.

04 março 2010
Delphi

Manipulando Streams
no Delphi 2010
FileStream
Entre os vários recursos que existem Nesse artigo estarei abordando de forma
Como o próprio nome já sugere, a classe TFileS-
desde versões mais antigas do Delphi e ainda prática o uso dos Streams utilizando a versão tream, descendente de TStream, manipula arquivos
assim são pouco explorados pelos desen- 2010 do Delphi. Porém os exemplos funcio- em disco na forma de Streams. Em geral utilizamos
volvedores especializados na ferramenta, nam em versões anteriores do Delphi com essa forma de Stream para manipular arquivos de
sem dúvida um dos mais destacados são os pouca ou nenhuma modificação. texto, mas a utilização da mesma para outros tipos
de arquivos é perfeitamente possível.
Streams. Streams são objetos que remetem
ao início dos tempos da programação, quando Mãos a obra!
Inicie uma nova aplicação no Delphi e monte
a manipulação de dados era feita byte a byte. o layout da mesma conforme a figura 1:
Com o surgimento de novas tecnologias, a uti-
lização dos Streams ficou restrita a situações
em que os mesmos são imprescindíveis.

No Delphi existe uma classe base TStre-


am e dela descendem as demais classes de
manipulação de Streams: TMemoryStream,
TFileStream, TBlobStream. Essas três classes
que citei são as mais importantes na mani-
pulação de Streams em Delphi. Apesar de
possuírem diferenças entre si, a forma de
trabalhar com cada uma das três classes é
bem semelhante.

Figura 1

março 2010 05
O que faremos a seguir é carregar um arquivo cionado, iremos realizar a carga do mesmo para o
texto para um objeto FileStream e em seguida car- FileStream e exibir o conteúdo do mesmo no objeto Veja a Figura 2.
regar esse Stream no objeto Memo para exibição memo que inserimos na aplicação.
do mesmo.
Segue o código: Stream com imagens
Quando criamos um objeto FileStream no
construtor do mesmo temos de informar além do Embora não seja o mais recomendado, todos
caminho do arquivo o modo de abertura desse os servidores de banco de dados utilizados com
arquivo. FileStream nos possibilita quatro formas procedure TForm1. o Delphi aceitam o armazenamento de dados na
de abertura que são: btnexibirClick(Sender: forma binária através de campos Blob. Esse tipo de
TObject); campo em geral é utilizado para o armazenamento
var de imagens no banco de dados, mas pode ser uti-
Fmcreate- Caso o arquivo não exista, será sFilename:string; lizado para armazenar vídeos, textos entre outros
criado. Caso exista, será zerado e a escrita no oFileStream:TFileStream; dados de forma binária.
mesmo irá sobrescrever seu conteúdo atual; begin
try Para se trabalhar com campos Blob nos com-
Fmopenread- Abre o arquivo apenas ponentes DataSet existentes no Delphi, podemos
para leitura; lançar mão de mais duas classes: TBlobStream,
sFilename:=edtcaminho. para os componentes BDE, e TMemorystream
Fmopenwrite- Abre o arquivo apenas Text; ou a própria classe TStream para demais tipos de
para escrita; DataSets. Com essas classes poderão ser feitos o
oFileStream:=TFileStream. envio e recuperação de dados a partir de campos
Fmopenreadwrite- Abre o arquivo para Create(sFilename,fmOpenRead); Blob. Lembrando que para o Stream independe
leitura e escrita. memstream.Lines. se o campo Blob contém um texto, uma imagem
LoadFromStream(oFileStream); ou outra forma de dado. Sua função é apenas
finally servir de veículo para envio e recuperação dessas
O primeiro passo será a busca do arquivo com informações.
o OpenDialog, que será feita no evento OnClick do FreeAndNil(oFileStream);
botão “Carregar”. end; Vamos a um exemplo prático com Blob em
end; combinação com outros dois objetos para carga
Segue o código: de imagens. No PageControl de nossa aplicação,
adicione uma nova página e coloque como caption
Salve as alterações e teste o aplicativo. Se da mesma “Blobstream”. Em seguida adicione a
procedure TForm1. tudo correu bem, o resultado será semelhante ao página um componente Clientdataset, alterando
btncarregarClick(Sender: mostrado na figura 2: seu nome para CdsBlob. Abra o FieldsEditor do
TObject);
var
sFilename:string;
begin
if(OpenDialog1.Execute)
then

sFilename:=OpenDialog1.
FileName;
edtcaminho.
Text:=sFilename;
end;

Com o caminho do arquivo devidamente sele- Figura 2

março 2010
clientdataset e adicione campo Blob com o nome
de IMAGEM. Isso feito clique com o botão direito
sobre o clientdataset e clique em CreateDataSet.

Nesse exemplo estarei trabalhando com


o clientdataset apenas em memória, mas ele
poderia estar ligado a uma fonte de dados sem
problemas.

Com o clientdataset devidamente criado e


configurado, monte o restante do layout da página
conforme a figura 3.

Figura 3
Os outros dois objetos que estaremos utilizan-
do são: TStream para a recuperação do conteúdo
do Blob após o mesmo ter sido carregado. E TJpe- procedure TForm1.SalvarClick(Sender: TObject);
gImage para armazenar a imagem proveniente do var
campo Blob. sFilename:string;
oFilestream:TFileStream;
oMemorystream:TStream;
Veja a Figura 3.
oImage:TJPEGImage;
begin
Lembrando que o componente OpenDialog try
não precisa ser criado novamente, será utilizado o sFilename:=edtcaminhoimg.Text;
que já havíamos criado na primeira página. oFilestream:=TFileStream.
Create(sFilename,fmOpenRead);
Iremos selecionar o caminho de uma imagem oMemorystream:=TMemoryStream.Create;
para em seguida enviá-lo para o Blobstream. Para oImage:=TJPEGImage.Create;
a seleção do arquivo, no evento OnClick do botão cdsblob.Open;
“Selecionar” faça: cdsblob.Append;
cdsblobIMAGEM.LoadFromStream(oFilestream);
cdsblob.Post;
oMemorystream:=cdsblob.CreateBlobStream(cdsbl
procedure TForm1.
obIMAGEM,bmRead);
SelecionarClick(Sender:
oImage.LoadFromStream(oMemorystream);
TObject);
Image1.Picture.Assign(oImage);
begin
finally
OpenDialog1. FreeAndNil(oFilestream);
Filter:=EmptyStr; FreeAndNil(oMemorystream);
OpenDialog1. FreeAndNil(oImage);
Filter:=’Image Files|*. end;
Listagem 4
jpg’;
if(OpenDialog1.Execute)
then
edtcaminhoimg. seguida salvamos o caminho do arquivo de imagem nada em um FileStream, salvá-la no campo blob
Text:=OpenDialog1. na Edit edtcaminho. e depois recuperá-la com a técnica do blobstream
FileName; combinada com o Jpegimage.
end; Como estamos trabalhando com imagens em
formato Jpeg devemos adicionar na uses da unit a Veja a codificação no evento OnClick do botão
biblioteca Jpeg. “Salvar”:
Alteramos o filtro do OpenDialog para que
apenas aceite imagens com a extensão jpeg e em Iremos agora salvar essa imagem já selecio- Veja a listagem 4.

março 2010 07
Repare que o objeto TJpegImage apenas serve
de container provisório para receber a imagem
proveniente do campo Blob.

Com essa técnica podemos salvar e recuperar


imagens em qualquer DataSet que ofereça suporte
aos campos Blob.

Salve as alterações e teste o aplicativo. Um


exemplo de resultado pode ser visto na figura 4:

Veja a Figura 4.

Figura 4

Trabalhando com buffers

Quando trabalhamos com Streams é impor-


tante termos em mente que o conteúdo do Stream
irá ocupar uma certa quantidade de memória no
computador. Em algumas situações pode ser im-
portante que tenhamos um controle mais preciso
desse espaço e de como ele será manipulado.
Esse maior controle pode ser conseguido com a
técnica de “bufferização”, que consiste em alocar
previamente um espaço de memória onde o buffer
irá trabalhar. Algo semelhante ao que é feio com
ponteiros em linguagens como C++.

Figura 5
Antes de passarmos a prática com buffers, é
importante destacar duas propriedades importan-
tes de um Stream, que são: Size e Position.
Botão “Selecionar Arquivo”:
Size retorna um inteiro com o tamanho ocu-
pado pelo Stream, e Position também retorna um
inteiro com a posição atual do cursor de leitura do procedure TForm1.btnarqselecionarClick(Sender:
Stream. Assim como os datasets, Streams também TObject);
possuem um cursor interno responsável pela leitura begin
dos dados. if(OpenDialog1.Execute)then
edtcaminhoarq.Text:=OpenDialog1.FileName;
Vamos a prática. Adicione uma nova página end;
ao PageControl da aplicação e monte seu layout
conforme a figura 5:
Botão “Copiar”:
Veja a Figura 5.

Nesse exemplo iremos selecionar um arquivo procedure TForm1.btncopiarClick(Sender: TObject);


texto, carregá-lo para um FileStream, em seguida var
copiá-lo para outro FileStream com a técnica da oStreamin,
bufferização e exibir seu conteúdo no Memo. oStreamout:TFileStream;
aBufferstream:array[0..1023]of Byte;

08 março 2010
iByteRead:integer;
sFilename:string;
begin
try
ProgressBar1.Position:=0;
sFilename:=edtcaminhoarq.Text;
oStreamin:=TFileStream.
Create(sFilename,fmOpenRead);
oStreamout:=TFileStream.Create(‘temp.
txt’,fmCreate);
repeat
iByteRead:=oStreamin.
Read(aBufferstream,1024);
oStreamout.Write(abufferstream,iByteRead);
ProgressBar1.StepBy(1);
until(iByteRead=0);
finally
ProgressBar1.Position:=100;
FreeAndNil(oStreamin);
FreeAndNil(oStreamout);
Memo1.Lines.LoadFromFile(‘temp.txt’);
end;
end;

Veja o aplicativo em execução na Figura 6:

Veja a Figura 6.

Conclusão

Streams são um excelente recurso disponibi-


lizado pelo Delphi quando necessitamos utilizar
técnicas avançadas de manipulação de arquivos
em disco sendo carregados em memória.

Espero que tenham gostado e até a próxima!


Figura 6

Sobre o autor
Antonio Spitaleri Neto
Consultor Técnico The Club.

antonio@theclub.com.br

março 2010 09
Utilizando os componentes
ACBr com Impressoras
Fiscais no Delphi 2010
Iniciando a aplicação
No dia-a-dia do desenvolvimento voltado Outro ponto importante a se destacar no
para a área de automação comercial, uma Acbr é o fato de utilizar muitos dos conceitos Criaremos uma aplicação que irá realizar as
grande preocupação dos desenvolvedores da orientação a objetos. Conceitos esses principais operações relacionadas às impressoras
é a comunicação do aplicativo com as cha- muito raramente utilizados quando se trata fiscais, como por exemplo: Leitura X, Redução Z,
madas impressoras fiscais, conhecidas pela de aplicativos e bibliotecas desenvolvidos além é claro das operações de registro de itens
sigla “ECF”. Para quem trabalha nesse ramo em Delphi. O fato de utilizar orientação a em uma venda.
a algum tempo, a solução mais simples e co- objetos tornou o código do ACBr mais legível
mumente utilizada eram as dll’s dos próprios e extensível e ao longo dos últimos anos várias Veja como ficará o layout principal da aplicação
desenvolvedores da ECF utilizada. melhorias tem sido aplicadas ao projeto. na figura 1:

Recorrer a essas dll’s sem dúvida torna o Nesse artigo, estarei mostrando como No alto e a esquerda da tela, temos dois
trabalho de se comunicar com as ECF’s mais podemos utilizar o ACBr para fazermos nosso componentes ComboBox onde no primeiro iremos
tranqüilo, porém apresenta um incoveniente: aplicativo se comunicar com uma impresso- colocar na propriedade Items uma lista com os
E se o modelo e\ou fabricante da ECF for ra fiscal. Para os que não dispõem de uma modelos suportados pelo Acbr. São eles:
trocada pelo cliente? Ou ainda se um cliente impressora fiscal para testes, é importante
novo utilizar um modelo de um fabricante ressaltar que o exemplo funciona com emu-
diferente? Para essas situações, se faz ne- ladores de ECF sem problemas. ecfNenhum, ecfNaoFiscal, ecfBematech,
cessário readaptar o aplicativo para trabalhar ecfSweda, ecfDaruma, ecfSchalter,
com o novo modelo\fabricante de ECF. No artigo não estarei mostrando a insta- ecfMecaf, ecfYanco, ecfDataRegis,
lação dos componentes ACBr no Delphi 2010, ecfUrano, ecfICash, ecfQuattro, ecfFiscNET,
O projeto ACBr vem de encontro a esse já que instruções para instalação acompa- ecfEpson, ecfNCR, ecfSwedaSTX;
problema. Esse conjunto de componentes e nham o componente.
rotinas totalmente Open Source e desenvol-
vido em Delphi, permite que a aplicação que Também não será abordada no artigo No segundo componente ComboBox, coloca-
irá se comunicar com a ECF seja desenvolvida a instalação e configuração de emuladores remos uma lista com os nomes das portas COM
apenas uma vez, e a troca de modelo ou de ECF. disponíveis no computador. No exemplo fiz a lista
fabricante de componente deixa de ser um com as portas COM1 até COM6.
problema.
Logo abaixo dos componentes ComboBox,

10 março 2010
temos uma série de 7 botões que utilizaremos para
efetuar as operações com a ECF. A função de cada
botão pode ser vista nos captions de cada botão.

No lado direito do formulário temos um


componente PageControl com duas páginas. Na
primeira colocamos um componente TMemo,
que será ligado ao componente ACBrEcf através
da propriedade MemoBobina deste último. Na
segunda página, colocamos um componente
TWebbrowser para exibirmos as informações da
bobina do ACBrECF.

Finalmente, na parte inferior do formulário,


pode ser visto o componente ACBrECF que será o Figura 1
responsável pela interação de nosso aplicativo com
a impressora fiscal.

Foi inserido no formulário também um compo- StatusBar1.Panels[0].


nente StatusBar para exibir o staus da impressora “Leitura X”: Text:=’Cupom Aberto’;
fiscal. end;

Com o layout da aplicação pronto, iremos criar procedure TForm1.


btnleituraxClick(Sender:
as rotinas dos botões inseridos no formulário, com “Cancela Cupom”:
TObject);
execeção do botão “Vender Item” que codificare-
begin
mos depois.
ACBrECF1.LeituraX;
procedure TForm1.
end;
Seguem os códigos dos eventos OnClick dos btncancelacupomClick(Sender:
botões: TObject);
begin
“Redução Z”:
“Ativar ECF”: ACBrECF1.CancelaCupom;
StatusBar1.Panels[0].
Text:=’Livre’;
procedure TForm1. end;
procedure TForm1. btnreducaozClick(Sender:
btnativarClick(Sender: TObject);
TObject); begin
begin “Desativar ECF”:
if(MessageDlg(‘Se for
ACBrECF1.Modelo:=TAC emitida a Redução Z, a ECF
BrECFModelo(cmbmodelo. ficará inoperante até o
ItemIndex); procedure TForm1.
dia seguinte.Deseja Contin
ACBrECF1. btndesativarClick(Sender:
uar?’,mtConfirmation,[mbYe
Porta:=cmbporta. TObject);
s,mbNo],0)=mrYes)then
Items[cmbporta.ItemIndex]; begin
ACBrECF1.
ACBrECF1.TimeOut:=3000; if ACBrECF1.Ativo then
ReducaoZ(Now);
ACBrECF1.Ativar; ACBrECF1.Desativar;
end;
Application. if not ACBrECF1.Ativo
ProcessMessages; then
if ACBrECF1.Ativo then begin
begin
“Abrir Cupom”: btndesativar.
btnativar. Enabled:=false;
Enabled:=false; btnativar.
StatusBar1. procedure TForm1. Enabled:=true;
Panels[0].Text:=’ECF btnabrircupomClick(Sender: end;
Ativa’; TObject); end;
end; begin
end; ACBrECF1.AbreCupom;

março 2010 11
Destaca-se nesse código a rotina da Redução
Z. Como se trata de uma operação que irá deixar
a ECF inoperante pelo restante do dia é altamente
recomendável que peçamos uma confirmação ao
usuário antes de efetuar a mesma.

Em seguida faremos a codificação para exibir


os dados da bobina da ECF no WebBrowser. O
componente ACBrECF irá enviar os dados para o
componente Memo apontado em sua propriedade
Figura 2
MemoBobina. O que precisamos fazer é salvar o
conteúdo do Memo em um arquivo .html e em
seguida exibi-lo no WebBrowser.
A função que utilizaremos para registrar a
Segue o código. Ficará no evento OnChange venda do item e a função VendeItem do ACBrECF. Esse código irá chamar o formulário de venda
do componente Memo: Essa função recebe os parâmetros necessários para de itens.
se efetuar uma venda na ECF. Essa função será
utilizada no botão “Vender Item”. Agora, segue a codificação dos eventos OnClick
procedure TForm1. dos botões do formulário de venda de itens:
membobinaChange(Sender: Não poderemos permitir a saída da tela sem
TObject); que a venda seja finalizada. Para isso, no botão
begin Botão “Vender Item” :
“Sair” utilizaremos as funções SubtotalizaCupom
membobina.Lines.
e EfetuaPagamento. Essas funções irão encerrar
SaveToFile(‘bobina.html’);
Application.
a venda e permitir que a ECF fique livre para uma
nova venda. procedure Tfrmvenderitem.
ProcessMessages;
btnvenderitemClick(Sender:
WebBrowser1.Navigate(‘file
Referente ao pagamento, é importante ressal- TObject);
:///’+ExtractFilePath(Appl
begin
ication.ExeName)+’bobina. tar que as formas de pagamento precisam estar
if(Form1.ACBrECF1.
html’); cadastradas na impressora fiscal. Nesse exemplo,
Ativo)and(Form1.ACBrECF1.
end; estarei trabalhando com forma de pagamento em Estado=estVenda)then
dinheiro, representada pelo código 01, constante begin
da maioria das ECF’s. Form1.ACBrECF1.
Repare que com a utilização do componente VendeItem(edtcodigo.
ACBrECF, todas as operações envolvendo a ECF Antes da codificação nesses botões, volte ao Text,edtdescricao.
ficam transparentes ao desenvolvedor. Basta dar formulário principal e no evento OnClick do botão Text,edticms.Text,
um comando através do componente para realizar “Vender Item”, coloque o seguinte código: StrToFloat(edtquantidade.T
a operação. Essa sem dúvida é a grande vantagem ext),StrToFloat(edtvalorun
dessa suíte de componentes. itario.Text),
procedure TForm1.
Teste o aplicativo e salve as alterações. Com Button1Click(Sender: StrToFloat(edtdesconto.
TObject); Text),edtunidade.Text);
isso terminamos a primeira parte de nosso exem-
begin end;
plo. A seguir mostrarei como registrar itens de uma
try end;
venda através do componente ACBrECF.

frmvenderitem:=Tfrmvenderitem.
Create(Self); Botão “Sair”:
Operação de venda de itens
frmvenderitem.
ShowModal;
Adicione um novo formulário a aplicação e finally procedure Tfrmvenderitem.
monte o layout do mesmo conforme mostrado btnsairClick(Sender:
na figura 2: FreeAndNil(frmvenderitem); TObject);
end; var
Veja a Figura 2. end; sValorpagamento:string;
begin

12 março 2010
if(MessageDlg(‘Deseja
finalizar a venda?’,mtConf
irmation,[mbYes,mbNo],0)=m
rYes)then
begin
Form1.ACBrECF1.
SubtotalizaCupom;
sValorpagamento:=In
putBox(‘ACBr’,’Informe o
valor pago’,’’);
Figura 3
Form1.ACBrECF1.Efetu
aPagamento(‘01’,StrToFloat
(sValorpagamento));
Form1.ACBrECF1.
FechaCupom(‘Obrigado Volte
O projeto ACBr, é totalmente open source,
Sempre!’);
podendo ser adquirido nos seguintes links:
Close;
end;
end;

Pagina principal ACBR


http://acbr.sourceforge.net/drupal/
Veja o formulário com valores para teste na
figura 3:
Ferramenta de controle de versão
SVN no Windows (Tortoise):
Veja a Figura 3.
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
drupal/?q=node/37
Após a venda dos itens e o pagamento, a ECF
ficará livre para uma nova venda. Para instalar o componente NFe:
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
Fique atento para os tipos de dados necessá- drupal/?q=node/36
rios nas passagens de parâmetros para as funções,
para evitar erros de conversão. FAQ - ACBrNFe
h t t p : / / a c b r. s o u r c e f o r g e . n e t /
Além da venda de itens e principais leituras, drupal/?q=node/38
como a Leitura X e Redução Z, o ACBr, permite
também o completo gerenciamento da ECF, como
o cadastro de formas de pagamento e a emissão
de relatórios gerenciais. Nesses links também se pode obter maiores
informações sobre os componentes.
Ao se trocar o modelo de ECF, nenhuma
alteração precisará ser feita no código, já que o Abraços e até a próxima.
ACBrECF, envia os comandos de acordo com o
modelo de ECF configurada em sua propriedade
Modelo. Os modelos suportados são descritos no
ínicio desse artigo. Sobre o autor
Antonio Spitaleri Neto
Consultor Técnico The Club.
Conclusão

Na área de automação comercial, o projeto


ACBr sem dúvida é uma grande ajuda quando pre-
cisamos operar com ECF’s, pois sua portabilidade antonio@theclub.com.br
e extensibilidade garante um grande ganho de
desempenho no desenvolvimento.
março 2010 13
INDO MAIS ALÉM
EXPLORANDO AS
TABELAS DE SISTEMA
INTERBASE/FIREBIRD
Olá pessoal, Jurídica). Quando nós criamos essa Constraint impõe para manter a integridade interna.
não especificamos o nome da mesma. Então Então vamos lá:
Tem certos momentos em que quebra- o banco de dados cria um nome aleatório do
mos a cabeça tentando montar fórmulas, que- tipo CHECK$10. Agora precisamos alterar essa
ries, procedures e todo tipo de truques para validação, acrescentando um novo valor. Para
resolver determinadas situações em nossos isso precisamos dropar a constraint e recria-la AS TABELAS DE SISTEMA
bancos de dados. Por exemplo: precisamos novamente. Mas como dropar a constraint se
realizar uma grande atualização em nosso não sabemos o nome da mesma? Outra tarefa Assim como outros objetos internos, as tabelas
banco de dados, mas devido a toda integrida- difícil de cumprir. de sistema são todas aquelas cujo nome se iniciam
de referencial que temos através de triggers, com os caracteres RDB$ ou, no caso do InterBase,
um único Update dispararia centenas, mi- Por isso nesse mês abordaremos um as- também TMP$. Essa nomenclatura é de uso exclu-
lhares de outras ações que, provavelmente, sunto diferente: o uso das tabelas de sistema sivo do banco de dados e não pode ser utilizado
sairiam de nosso controle. Então uma saída em bancos de dados InterBase/Firebird. na criação de novas tabelas pelo usuário. As TMP$
seria a desativação das triggers. Mas como são tabelas temporárias de sistema, utilizadas no
desativar todas as triggers de nosso banco? São tabelas que contém informações recurso de monitoramento do banco de dados. Já
Usando o comando Alter trigger tal_de_tal extremamente úteis e que, se bem utilizadas as RDB$ são as tabelas de sistema responsáveis
inactive? Uma a uma? Pois é, um tanto quanto e manipuladas, podem nos ajudar a ir muito por guardar todo tipo de informação relativa,
complicado, não? mais além na administração e manutenção principalmente, ao metadata do banco de dados,
de nossos bancos. à estrutura do banco.
Ou mesmo essa outra situação: Temos
uma coluna em nossos bancos chamada Na prática podemos realizar todo tipo de Quando criamos um banco de dados, o sis-
Tipo_Cliente que é validada por uma Check comando DML (Data Manipulation Language) tema já cria automaticamente as tabelas RDB$.
Constraint determinando que os valores sobre as tabelas de sistema, respeitando algu- São elas:
possíveis são ‘F’ (Pessoa Física) e ‘J’ (Pessoa mas restrições que o próprio banco de dados
Veja a Tabela.

14 março 2010
Tabela de Sistema Funcionalidade
RDB$CHARACTER_SETS Descreve todos os tipos de Character Sets disponíveis no banco de dados.
RDB$CHECK_CONSTRAINTS Grava informações sobre todas as Constrainst do tipo Check presentes no banco de dados. Também armazena informações
sobre todas as Constraints das colunas marcadas como Not Null.
RDB$COLLATIONS Descreve as regras das Collations permitidas para uso do banco de dados.
RDB$DATABASE Salva informações sobre o banco de dados.
RDB$DEPENDENCIES Armazena todos os tipos de dependência entre os objetos do sistema. Tabelas / Stored Procedures / Triggers, enfim. É
por aqui que o banco de dados valida se uma coluna pode ser alterada / excluída sem afetar outros objetos.
RDB$EXCEPTIONS Descreve todas as exceções de erro geradas e utilizadas pelas Stored Procedures, inclusive as exceções criadas pelo
usuário.
RDB$FIELDS Contém informações sobre as características de cada coluna e domínio do banco de dados. Informações sobre valores
default, not null, campos computados, enfim. Todas as colunas de todas as tabelas são referenciadas nessa tabela.
RDB$FIELD_DIMENSIONS Descreve o tamanho de cada coluna.
RDB$FILES Lista informações sobre todos os arquivos secundários do tipo shadow que estão em uso no banco de dados.
RDB$FILTERS Contém informações sobre filtros de campos do tipo Blob.
RDB$FORMATS Uma tabela interessante. Ela armazena informações sobre o versionamento de alterações realizadas nas tabelas do banco.
Todas as vezes que executamos um comando de Alter/Drop/Create Table essa tabela grava o número dessa alteração. E
isso que permite que uma aplicação possa acessar tabelas alteradas sem a necessidade de ser recompilada. O sistema
permite que sejam feitas até 255 alterações na estrutura de tabelas. Ao atingir esse limite, um backup e um restore do
banco precisa ser feito para zerar esse contador e permitir novas alterações.
RDB$FUNCTION_ARGUMENTS Define atributos de funções utilizadas pelo banco de dados, inclusive as UDFs.
RDB$FUNCTIONS Descreve as UDFs utilizadas pelo banco de dados.
RDB$GENERATORS Contém informações sobre todas as Generators utilizadas pelo banco de dados.
RDB$INDEX_SEGMENTS Uma tabela de sistema muito importante que grava informações sobre todas as colunas que são referenciadas em todos
os índices do banco de dados. Modificar manualmente essa tabela pode causar grandes corrupções!
RDB$INDICES Descreve todos os índices criados no banco de dados. Cada índice dessa tabela deve ser suas respectivas referencias na
tabela RDB$INDEX_SEGMENTS.
RDB$LOG_FILES Essa tabela não é mais utilizada nos bancos de dados InterBase/Firebird, mas permanece listada por legado.
RDB$PAGES Uma tabela bem técnica, que grava informações sobre cada página de dados alocada do banco de dados. Qualquer tipo
de modificação manual nessa tabela irá corromper o mesmo.
RDB$PROCEDURE_PARAMETERS Essa tabela grava informações sobre os parâmetros (input e output) usados em todas as Stored Procedures do banco
de dados.
RDB$PROCEDURES Contém a descrição das Stored Procedures do banco de dados.
RDB$REF_CONSTRAINTS Grava informações sobre as Constraints de Integridade Referencial usadas no banco (Primary e Foreing Keys).
RDB$RELATION_CONSTRAINTS Aqui são listadas as relações entre as Constraints e de Integridade Referencial e as respectivas tabelas relacionadas.
RDB$RELATION_FIELDS Descreve informações complementares sobre as colunas e domínios do banco de dados, bem como as relações entre
as colunas e as tabelas.
RDB$RELATIONS Define algumas características de tabelas e Views.
RDB$ROLES Listas todos os Roles criados no banco, bem como o usuário dono desse Role.
RDB$SECURITY_CLASSES Define as listas de controle de acesso (ACLs) criadas no banco, bem como a relação dessas regras com os objetos do
sistema.
RDB$TRANSACTIONS Grava informações sobre todas as transações multi-banco que estão em uso no sistema.
RDB$TRIGGER_MESSAGES Contém informações sobre todas a mensagens de Triggers, bem como as Triggers relacionadas às mensagens.
RDB$TRIGGERS Descreve todas as Triggers do banco de dados.
RDB$TYPES Lista todos os tipos de dados e apelidos para os Character Sets e Collations usados no banco de dados.
RDB$USER_PRIVILEGES Contém informações sobre o direito de acesso de cada usuário criado no banco de dados. Sempre que usamos os co-
mandos Grant e Revoke, o sistema grava essas referências nessa tabela.
RDB$VIEW_RELATIONS Aqui são listadas as relações entre as Views e suas respectivas tabelas.

março 2010 15
Também pode existir outras tabelas de sistema
de forma distinta entre o InterBase e o Firebird,
conforme a ODS (On Disk Structure) do banco
de dados.

VISUALIZANDO AS TABELAS DE SIS-


TEMA

Para acessar e visualizar as tabelas de sistema


devemos:

1. Usando o utilitário de linha de comando


ISQL, executamos o comando:

Imagem 2
SQL> show system;
RDB$CHARACTER_SETS
RDB$CHECK_CONSTRAINTS uma coluna Char/Varchar. Por exemplo: Precisamos outra tabela principal, por exemplo. Precisamos
RDB$COLLATIONS ampliar a coluna NOME de 30 para 60 caracteres. então rodar comandos do tipo Alter Trigger ... Inac-
RDB$DATABASE Mas como fazer de uma só vez em todas as tabelas tive/Active. Mas como fazer isso de forma prática
RDB$DEPENDENCIES do banco de dados onde essa coluna existe? Mani- quando temos centenas / milhares de Triggers?
RDB$EXCEPTIONS pulando as tabelas de sistema: Executando o comando DML abaixo:
[...]
SQL>
Update UPDATE
rdb$fields RDB$TRIGGERS
2. Usando o utilitário gráfico IBConsole, Set SET
selecionamos no menu: rdb$field_length = 60 rdb$trigger_inactive = 1
Where WHERE
rdb$field_name = (rdb$system_flag = 0 or
(select f.rdb$field_ rdb$system_flag IS NULL)
source AND
from rdb$relation_ rdb$trigger_name NOT LIKE
fields f ‘CHECK%’ AND
where f.rdb$field_name rdb$trigger_name NOT LIKE
= ‘NOME’) ‘RDB$%’

3. Usando o utilitário gráfico IBExpert,


marcamos na propriedade da conexão: Esse comando irá buscar todas as colunas des- Esse comando irá desativar todas as Triggers
critas com o nome “NOME” e aumentar na tabela do banco de dados, com exceção das Triggers de
Veja a imagem 2. que descreve os campos o Length dessa coluna sistema e das Checks Constraints. Para reativar
para 60 caracteres. novamente as mesmas, basta realizar o Update
novamente, ajustando o valor para “0” (Zero).
MANIPULANDO AS TABELAS DE SIS-
TEMA Ativando e Desativando Triggers:
Apagando Checks Constraints sem
Devemos sempre tomar cuidado antes de Quando precisamos realizar uma atualização saber o nome:
assim proceder, mas vamos dar alguns exemplos em massa no banco de dados ou quando temos um
de comandos DML que podemos executar sobre banco de dados vazio que precisa ser populado, po- Como no exemplo que demos na abertura do
as tabelas de sistema. demos nos deparar com um problema: as Triggers. nosso artigo, como podemos apagar todas as Che-
Isso porque, muitas vezes usamos as Triggers para cks Constraints relacionadas à uma determinada
Ampliando o tamanho de um campo Char/ realizar a integridade referencial de nossos bancos. coluna de nosso banco de dados, se não sabemos
Varchar: Ai quando vamos inserir um dado em determinada o nome de nossa Check Constraint? Basta executar
tabela, a Trigger impede por não existir relação com o comando DML abaixo:
Muitas vezes precisei ampliar o tamanho de

16 março 2010
Club Megazine comentamos a respeito do uso das
DELETE UDFs. Segue um exemplo de uso de UDF contra de Tamanhos’
FROM RDB$RELATION_ uma tabela de sistema: WHERE RDB$RELATION_NAME=’
CONSTRAINTS A T02P007LJ’;
Where UPDATE RDB$RELATIONS SET
(Select count(*) from RDB$DESCRIPTION=’Cadastro
Select F_UUID1MACMAC(F_
RDB$CHECK_CONSTRAINTS B, de Cores’
UUID1MAC()) from
RDB$TRIGGERS C WHERE RDB$RELATION_NAME=’
rdb$database;
where T03P007LJ’;
(A.RDB$CONSTRAINT_TYPE = UPDATE RDB$RELATIONS SET
‘CHECK’) and RDB$DESCRIPTION=’Tabelas de
(A.RDB$CONSTRAINT_ Esse comando executado a partir de qual- Preco’
NAME = B.RDB$CONSTRAINT_ quer computador cliente retornará o endereço WHERE RDB$RELATION_NAME=’
NAME) and Mac Address do servidor do banco de dados. Isso T04P009LJ’;
(B.RDB$TRIGGER_NAME = pode ser muito útil por exemplo para se criar uma UPDATE RDB$RELATIONS SET
C.RDB$TRIGGER_NAME) and rotina de validação da aplicação para liberação de RDB$DESCRIPTION=’Imagens de
(C.RDB$TRIGGER_TYPE = licenças de uso. Produtos’
1) and WHERE RDB$RELATION_NAME=’
(A.RDB$RELATION_NAME T05P015LP’;
in Trabalhando com Descrições em
(SELECT Tabelas:
DISTINCT E assim por diante. Quando abrimos o uti-
r.rdb$relation_name litário IBExpert, podemos facilmente identificar
Esse é outro ponto interessante. É muito
FROM rdb$check_
comum encontrar bancos de dados com centenas as tabelas:
constraints C JOIN
de tabelas, mas onde o nome da tabela não iden-
rdb$relation_
constraints R tifica seu real propósito. Por exemplo: ao invés de Veja a Imagem 3.
ON chamar uma tabela de cadastros de produto de
(C.rdb$constraint_name = TABPRODUTOS, o nome da tabela é algo do tipo Ou mesmo podemos executar um comando
R.rdb$constraint_name) T01P007LJ. Então novo desenvolvedor ou mesmo DML para pesquisar uma determinada tabela pela
WHERE um usuário mais experiente acaba ficando perdido sua descrição:
C.rdb$trigger_ ao tentar encontrar uma determinada tabela.
name IN
(SELECT Uma maneira interessante de se tratar esse Select rdb$relation_name,
D.rdb$dependent_name problema é criando uma descrição para as tabelas rdb$description from
FROM rdb$relations
de sistema. Para isso usamos o comando DML:
rdb$dependencies D where rdb$description
WHERE like ‘%rodutos%’;
D.rdb$field_
UPDATE RDB$RELATIONS SET
name = ‘TIPO_CLIENTE’ and
RDB$DESCRIPTION=’Cadastro
de Produtos’
d.rdb$dependent_name like
WHERE RDB$RELATION_NAME=’
‘CHECK%’))
T01P007LJ’;
UPDATE RDB$RELATIONS SET
)) > 0;
RDB$DESCRIPTION=’Cadastro

Esse nosso comando irá apagar todas as Checks


Constraints que validarem a coluna Tipo_Cliente,
em todas as tabelas do banco de dados. Depois,
podemos recriar as mesmas com a nova regra de
validação. Rápido e Seguro.

Resgatando o MAC Address do Servidor Inter-


Base/Firebird:

Recentemente em um artigo nosso aqui na The


Imagem 3

março 2010 17
Retornaria algo como:
Nos vemos no próximo artigo para falar mais
sobre o InterBase e seus recursos. Valeu pessoa
RDB$RELATION_NAME RDB$DESCRIPTION
e Até lá!
T01P007LJ Cadastro de Produtos
T05P015LP Imagens de Produtos
Referência:

CONCLUSÃO as informações estão lá o tempo todo. Cabe a InterBase 2009 Language Reference – cap. 6.
nós desenvolvedores irmos mais além, usar essas http://edn.embarcadero.com
E esses são apenas alguns exemplos. Nova- informações à nosso favor.
mente explorando mais dos recursos de nossos
bancos de dados. Se pesquisarmos mais e estu-
darmos as tabelas de sistema de nossos bancos, Sobre o autor
podemos extrair muito mais. Claro e novamente Felipe Santos
repetindo: tudo com muito cuidado para não der- Felipe Santos é especialista em InterBase. Trabalha com o InterBase desde
2001. atuando como consultor e instrutor do produto em todo Brasil. Especialista em
rubar alguma integridade ou mesmo corromper ambientes críticos. Atua e trabalha com os maiores clientes do InterBase no Brasil.
Participante ativo na comunidade, com diversos artigos publicados. Participante do
nossos bancos. Mas recomendo a todos a leitura grupo de beta testers mundial do produto. Palestrante em eventos como IB Tour, Borcon
Conference, CodeRage Latin América, Delphi Developers Day, Linux Day, entre outros.
complementar do Capitulo 6 do guia Language Atualmente trabalhando na área técnica do InterBase na Presence Tecnologia – agente
Reference do InterBase SMP 2009, que contém oficial especializado do produto no Brasil.

informações completas sobre as tabelas de sistema felipe.santos@presence.com.br


e sobre as tabelas temporárias de sistema. Afinal,

18 março 2010
STORED PROCEDURES
E TRIGGERS NO MYSQL

As Stored Procedures e Triggers são mais • Melhora do desempenho – por se- alteração que prejudique o Banco de Dados;
conhecidas no Firebird, mas também são mui- rem armazenadas e processadas no servidor
to importantes na otimização do desempenho elas enviarão ao usuário somente os resulta- • Distribuição de tarefas – as tarefas
de um Banco de Dados no MySQL, neste arti- dos das consultas diminuindo assim o trafego da criação de uma aplicação podem ser divi-
go mostrarei o que elas são, como funcionam na rede; didas entre um profissional especializado em
no MySQL e farei alguns exemplos. Banco de Dados e um Programador que criará
• Economia de código – é necessária a aplicação.
apenas uma linha de código para se chamar
uma SP já que a instrução SQL está toda en-
STORED PROCEDURES capsulada no corpo da SP, você não terá mais
que escrever várias linhas toda vez que quiser As SP são basicamente classificadas em três
Introduzidas a partir da versão 5.0 do MYSQL uma operação específica em seu banco; tipos:
as Stored Procedures (SP) ou Procedimentos Ar-
mazenados são um conjunto de comando SQL que • Facilidade de manutenção – elas
podem ficar armazenados no servidor e poupar podem ser alteradas sem a necessidade de 1. As que retornam algum valor, como
os usuários da necessidade de enviar extensos se alterar as aplicações que as utilizam e sem a contagem de registros de uma tabela;
comandos SQL ao servidor só sendo necessário importar a linguagem em que foi escrita essa
fazer a chamada a SP. aplicação; 2. As que retornam registros funcionan-
do como um Select , e;
As vantagens do uso das SP’s são muitas, entre • Segurança – os usuários terão acesso
as principais que posso destacar estão: somente as SP’s e não as tabelas, isso diminui 3. As que fazem ações específicas no
a possibilidade de algum usuário fazer alguma banco, como inserções, alterações, atualiza-
ções etc.

março 2010 19
STORED PROCEDURES NO MYSQL comandos procedurais executados automatica-
mente em resposta a algum evento executado no corpo_trigger
A sintaxe geral de uma SP no MySQL é a banco de dados, como por exemplo na inserção de
seguinte: um registro em uma tabela de pessoas, a trigger
automaticamente gerará na tabela de salários um Onde:
campo referente ao salário daquela pessoa.
CREATE PROCEDURE nome_
proc([parâmetro ...]) As triggers são usadas geralmente para: • DEFINER: checa quais os privilégios
[características] que usuário do banco tem para disparar a
BEGIN trigger. Quando a trigger é criada esse campo
• Para manter a integridade entre as é preenchido por padrão com CURRENT_USER
Corpo da SP; ou pode ser preenchida com o usuário(ex:
tabelas: podem ser criados grandes processos
de controle dos relacionamentos entre as ta- ‘bruno’@’localhost’);
END;
belas, principalmente aos usuários de tabelas
MyISAM que não suportam relacionamnetos • nome_trigger: define-se o nome da
via chave estrangeira; trigger, o padrão adotado entre os desenvol-
Onde:
vedores é TRG_nome_trigger;
• Manter a segurança do Banco: as tri-
ggers podem controlar o acesso, atualizações • tempo_trigger: aqui se define quan-
• Nome_proc - aqui se define o nome
e alterações nas tabelas; do a trigger será executada:
da procedure, um padrão muito adotado en-
tre os desenvolvedores é SP_nome_da_pro-
• Melhorar o desempenho do banco: • BEFORE: a trigger será ativada antes
cedure;
imagine um banco com 500.000 registros que do comando que a disparou;

• Parâmetro – os parâmetros utilizados de tempos em tempos requer uma simples


alteração nos registros, atrvés de uma trigger • AFTER: a trigger será ativada depois
em SP no MySQL dividem-se em três:
essas alterações podem ser feitas automati- do comando que a disparou;

1. IN – São os parâmetros de entrada camente através da trigger.;


• evento trigger: o evento que será
que serão trabalhados no corpo da SP e pro-
• Auditoria do Banco de Dados: por executado quando a trigger for disparada:
duzirão algum resultado;
serem executadas automaticamente são
excelentes ferramentas para auditria do BD. • INSERT: um ou mais registros serão
2. OUT – É o parâmetro interno que re-
inseridos em uma tabela;
torna algum resultado para o lado externo;
• UPDATE: um ou mais registros serão
3. INOUT - É o parâmetro que pode
TRIGGERS NO MYSQL. atualizados em uma tabela;
funcionar das duas formas.

A sintaxe geral de uma Trigger no MySQL é • DELETE: um ou mais registros serão


• Características – definem o tipo da
a seguinte: apagados em uma tabela;
procedure, se determinística ou não, questões
de segurança do banco de dados e linguagem
• nome_tabela: tabela onde a trigger
de escrita da SP,não setem a obrigatoriedade
CREATE trabalhará;
de declara – las quand se escrevea SP ;
[DEFINER = { USER |
CURRENT USER}] • corpo_trigger: comandos executados
• Corpo da SP – onde são escritos os
pela trigger.
comandos SQL. TRIGGER nome_trigger
tempo_trigger evento_
trigger

EXEMPLOS
TRIGGERS ON nome_tabela

FOR EACH ROW


Para ilustrar melhor as explicações vamos criar
As triggers (ou gatilhos em português) são

março 2010
alguns exemplos de Triggers e Stored Procedures.
O primeiro passo é criar as tabelas, para este int(11) default NULL, CREATE PROCEDURE SP_ADD_
exemplo vamos criar duas tabelas, uma tabela de PRIMARY KEY (`ID_ USUARIOS (
USUARIO`), IN USUARIO VARCHAR (80),
pessoas e outra de usuários. Abaixo seguem os
KEY `FK_PESSOA_USUARIO` IN SENHA VARCHAR (35),
scripts de criação das tabelas: IN TIPO CHAR(1),
(`FK_PESSOA_USUARIO`),
IN FK_PESSOA INT)
CONSTRAINT `USUARIO_
BEGIN
PESSOA_FK` FOREIGN KEY
PESSOAS (`FK_PESSOA_USUARIO`)
INSERT INTO `usuarios`
(USUARIO_NOME, USUARIO_
REFERENCES `pessoas` (`ID_ SENHA, USUARIO_TIPO,FK_
Essa tabela servira para o cadastro de pessoas, PESSOA`) PESSOA_USUARIO)
como por exemplo clientes e funcionários, essa ) ENGINE=InnoDB DEFAULT VALUES
especificação se dará no campo PESSOA_TIPO que CHARSET=latin1 (USUARIO,SENHA,TIPO,FK_
receberá G para gerente(que terá todos os privilé- PESSOA);
gios), C – para cliente ou F – para funcionário. END;

TRG_CRIP_SENHA
CREATE TABLE `pessoas` (
`ID_PESSOA` INTEGER(11) Agora vamos criar nossa primeira trigger, essa TRG_USUARIOS
NOT NULL AUTO_INCREMENT, trigger se encarregará de criptografar a senha de
`PESSOA_NOME` usuário quando este for inserido, o método de Essa trigger incluirá automaticamente uma
VARCHAR(80) NOT NULL, pessoa cadastrada na tabela de pessoas, desde
criptografia é o MD5 que já é uma função presente
`PESSOA_RG` VARCHAR(15) que seu pessoa tipo na tabela seja F, na tabela de
no banco MySQL, o MD5 é um algoritmo unidire-
DEFAULT NULL, usuários como um usuário do sistema. Por padrão,
cional que criptografa uma string e não permite
`PESSOA_TIPO` CHAR (1)
que essa criptografia seja revertida. Percebam que que será definido na trigger, o nome de desse
DEFAULT NULL,
usamos o operador NEW (NEW. USUARIO_SENHA) usuário será o seu nome em letras minúsculas,
PRIMARY KEY (`ID_
esse operador significa que queremos o dado que a senha será 123456 e o tipo será definido como
PESSOA`)
) ENGINE=InnoDB; acaba de ser inserido, se porventura apagássemos C - Comum.
esse registro poderíamos recuperá – lo através do
operador OLD (OLD. USUARIO_SENHA).
CREATE TRIGGER TRG_
USUARIOS AFTER INSERT ON
USUARIOS
`pessoas`
CREATE TRIGGER TRG_CRIP_
FOR EACH ROW
Essa tabela guardará os dados dos usuários SENHA BEFORE INSERT ON
BEGIN
de um suposto programa, desde que eles sejam `usuarios`
IF (NEW.ID_PESSOA IS NOT
FOR EACH ROW
definidos com F no campo PESSOA_TIPO. O campo NULL) AND (NEW.PESSOA_TIPO
BEGIN
USUARIO_TIPO deve ser marcado com A – Adminis- = ‘G’) THEN
SET NEW.USUARIO_SENHA =
trador ou C- Comum sendo que só o Administrador CALL SP_ADD_
MD5(NEW.USUARIO_SENHA);
tem permissões para inserir registros na tabela USUARIOS(LOWER(NEW.PESSOA_
END;
de pessoas. NOME),’123456’,’A’,NEW.
ID_PESSOA);
ELSE
CREATE TABLE `usuarios` ( IF (NEW.ID_PESSOA IS
SP_ADD_USUARIOS
`ID_USUARIO` int(11) NOT NOT NULL) AND (NEW.PESSOA_
NULL auto_increment, TIPO = ‘F’) THEN
O nosso próximo passo é criar uma Stored CALL SP_ADD_
`USUARIO_NOME`
varchar(80) default NULL,
Procedure que será usada em conjunto com a USUARIOS(LOWER(NEW.PESSOA_
`USUARIO_SENHA` próxima trigger e que quando executada incluirá NOME),’123456’,’C’,NEW.
varchar(35) default NULL, dados na tabela de usuários. ID_PESSOA);
`USUARIO_TIPO` char(1) END IF;
default NULL, END IF;
`FK_PESSOA_USUARIO` END

março 2010 21
TESTES
Imagem 1
Agora vamos efetuar alguns testes nesse
banco para verificar o funcionamento das Triggers
e Stored Procedures. Para efetuar esses testes
estou usando a IDE Gráfica EMS SQL Manager Lite
for MySQL que é gratuita e pode ser encontrada Imagem 2
no seguinte endereço:

Vamos inserir um registro na tabela de PESSO-


AS com o tipo definido com G –GERENTE.

Imagem 3

INSERT INTO `pessoas`


(PESSOA_NOME, PESSOA_RG,
PESSOA_TIPO)
VALUES
(‘BRUNO’,’12.345.678-
Imagem 4
9’,’G’);
um registro, referente ao funcionário DANIEL
(35);
Veja a Imagem 1. Veja a Imagem 4. SELECT USUARIO_TIPO,
USUARIO_SENHA INTO V_TIPO,
No momento da inserção a trigger que insere V_SENHA
Vamos criar agora uma Stored Procedure
um usuário(TRG_USUARIOS) é automaticamente FROM USUARIOS
que controlará a inserção de dados na tabela
executada e gera na tabela de usuários um novo WHERE USUARIO_NOME =
PESSOAS.
USUARIO;
registro com a senha já criptografada (TRG_CRIP_
IF V_TIPO = ‘A’ AND V_
SENHA), e como o PESSOA_TIPO é = G esse usuário
SENHA = MD5(SENHA) THEN
será um administrador. SP_PERMISSOES INSERT INTO `pessoas`
(PESSOA_NOME, PESSOA_RG,
Veja a Imagem 2. Essa procedure quando executada servirá PESSOA_TIPO)
para incluir dados na tabela de pessoas, mas ela VALUES (NOME, RG,
Vamos inserir agora mais dois registros, um controlará quem o fará, só poderão incluir registros TIPO);
funcionário (que também é um usuário do sistema) usuários cadastrados como A – Administrador e ELSE
e um cliente. que tenham digitado o nome e senha de usuário SELECT ‘VOCÊ NÃO TEM
correta, caso o usuário seja C – comum retornará PERMISSÃO PARA EXECUTAR
ESSA TAREFA’ AS AVISO;
uma mensagem avisando que não é possível fazer
INSERT INTO `pessoas` END IF;
essa inserção.
(PESSOA_NOME, PESSOA_RG, END
PESSOA_TIPO)
VALUES
CREATE PROCEDURE SP_
(‘DANIEL’,’87.654.321- Vamos agora testar essa SP:
PERMISSOES (
0’,’F’),
IN USUARIO VARCHAR (80),
(‘FREDERICO’,’87.654.321-
IN SENHA VARCHAR (35),
0’,’C’); CALL SP_PERMISSOES(‘bruno’
IN NOME VARCHAR(80),
,’123456’,’ANTONIO’,’71.82
COMMIT; 5.936.-4’,’C’)
IN RG VARCHAR(15),
IN TIPO CHAR(1))
BEGIN
Veja a Imagem 3. DECLARE V_TIPO CHAR(1);
Percebam que o registro ANTONIO foi inse-
DECLARE V_SENHA VARCHAR rido:
Na tabela de usuários foi gerado apenas mais

22 março 2010
Veja a Imagem 5.

Vamos tentar inserir um registro como um


usuário C – comum:
Imagem 5

CALL SP_PERMISSOES(‘daniel
’,’123456’,’JEREMIAS’,’84.
369.521-7’,’G’)
Imagem 6

Ele retornará uma mensagem de erro:

Veja a Imagem 6. Sobre o autor


Bruno Alcarás
Consultor Técnico The Club.
CONCLUSÃO

Neste artigo procurei demonstrar de forma


simples algumas das operações que podem ser
feitas com Triggers e Stored Procedures no MySQL, bruno@theclub.com.br
mas elas podem ser usadas de muitas outras for-
mas na busca de um melhor desempenho do seu
banco, sempre que possível as utilize.

E isso é tudo pessoal, até outra hora.

março 2010 23
Além dos modelos básicos de programação Visual Studio Ultimate (além das funcionalida-
Olá, Então pessoal como alguns devem WCF, WPF, Windows Form, Silverlight, WebAppli- des da versão Premium):
saber no dia 12/04/2010 foi lançado o Visual cation e a novidade agora é Azure ou seja Cloud
Studio 2010 oficialmente e na edição de hoje Computing, e essa nova versão conta com Unit
eu vou falar sobre algumas novidades dessa Tests, ao contrário da versão Professional do Visual • Debugging histórico com IntelliTra-
versão, nessa edição eu vou focar nas área e Studio 2008. ce
nas novidades que mais gostei área de arqui- • Ferramentas de testes compreensi-
tetura e modelos UML. Visual Studio Premium (além das funcionali- vas
dades da versão Professional): • Ferramentas avançadas de UML
• Ferramentas de descoberta de arqui-
As versões tetura
• Debugging e desenvolvimento de • Test Case e gerenciamento do labo-
Ao contrário de seus antecessores, o Visual aplicações avançado ratório de testes
Studio 2010 conta com SKUs (edições) mais simpli- • Unit Tests com cobertura de código
ficadas, de anteriormente 9 para simplesmente 4 (Code Coverage - mostra quanto por cento
agora: Ultimate, Premium, Professional e a versões do código está sendo testado), prioritização
Express. Irei abordar aqui individualidades de cada de testes, análise, métrica e otimização de
uma das três versões pagas, Ultimate, Premium e código
Professional: • Desenvolvimento e testes unitários
de banco de dados
Visual Studio Professional • Diagramas de arquitetura (apenas
leitura)

24 março 2010
Modelagem UML

Para criar um modelo novo basta clicar em


New Project e escolher a opção Modeling Projects
e escolher o template Modeling Project, depois só
indique o caminho aonde será salvo e pronto você
terá um Projeto de modelos, esse projeto você
pode tranquilamente fazer controle de versão com
o Visual Studio team System ( falarei mais sobre ele
em outro artigo ). Figura 1

Veja a figura 1.

Diagrama de Sequência
Figura 1. Criando um projeto de diagrama
A UML significa muito para arquitetos e ana-
listas de sistema. Parqa criar os modelos basta
clicarmos com o botão direito sobre qualquer mé-
todo de classe que desejemos visualizar o diagrama
de sequência e escolhermos a opção Generate
Sequence Diagram, que em seguida será aberta
uma janela para customização do método, como
profundidade, referências externas, entre outras.
Após o OK, teremos o Diagrama de Sequência do
método, como visto a seguir: Figura 2

Veja a figura 2.

Diagrama de Dependências

Um sistema, por menor que seja, terá algumas


referências (bibliotecas externas) o acompanhan-
do, seja elas do próprio sistema ou de terceiros.
Mas a medida que o projeto vai crescendo, suas
referências também vão aumentando, dificultando
assim a visualização do que cada parte do sistema
necessita.

Com o diagrama de sequência do do Visual


Studio 2010, fica mais fácil fazer e de visualizar
o mesmo melhorando a vida do arquiteto do
Figura 2. Diagrama de sequência
sistema.

Para que geremos um novo diagrama de de-


pendências, basta irmos no menu Architecture -> exemplo: Figura 3 dendo ser expandida até um nível mais profundo e
Generate Dependency Graph e escolher o tipo de com isso os arquitetos, desenvolvedores, analistas
diagrama que será mostrado, por assembly, por Vejaa figura 3. e designers conseguem entender e vizualizar me-
namespace, entre outras opções. Veja aqui um lhor o impacto das alterações a serem realizadas.
Note que cada dependência está contraída, po-
março 2010 25
Diagrama de Componentes

Quando utilizamos componentes de terceiros


em nossos sistemas, várias vezes nos perguntamos
como eles se relacionam com o código desenvolvi-
do pela equipe. Esta pergunta surge principalmente
quando um desenvolvedor novo entra no time que
já tem um projeto em andamento. Como a UML
conta com o diagrama de componentes, a equipe
de desenvolvimento do Visual Studio achou inte-
ressante incorporá-lo ao template de projetos de
modelagem, para que seja de fácil visualização e
modificação para aqueles que estão entrando no
time depois de um tempo de desenvolvimento.

Figura 3. Diagrama de dependências


Este diagrama contém os seguintes objetos na
toolbox: Component, Provided Interface, Required
Interface, Part Assembly, além dos objetos de re-
lacionamento e comentários. Confira como é seu
design no Visual Studio: Figura 4

Veja a imagem 4.

Diagrama de Camadas

Hoje em dia, nos deparamos com diversos


padrões de projeto que dividem o sistema em
camadas. Seja MVC (Model-View-Controller),
MVP (Model-View-Presenter), MVVM (Model-
View-ViewModel) ou N camadas, esta divisão de
camadas está presente no nosso dia a dia, pois
Figura 4. Diagrama de componente
permite uma manutenibilidade boa, além de não
ficarmos focados em apenas um tipo de visão, ou
banco de dados, por exemplo.

Por isso é importante enxergarmos o sistema


como um todo dividido em algumas partes, para
sabermos qual parte faz o quê. Partindo deste
princípio, o diagrama de camadas foi criado, e
agora o Visual Studio conta com um template para
diagramação das mesmas.

Apenas arrastando itens da toolbox, podere-


mos facilmente, por exemplo, criar um diagrama
de camadas MVC, de acordo com a figura a seguir:
Figura 5

Veja a figura 5.
Figura 5. Diagrama de camadas

26 março 2010
Agora que já falamos de UML e diagramas
vou falar um pouco das novas funcionalidades
do editor.

References Highlighting

Agora é possível encontrar onde cada proprie-


dade e outros símbolos definidos em determinada
classe estão sendo usados, através do recurso Refe-
rences Highlighting. Clicando sobre qualquer refe-
rência de determinada propriedade da sua classe,
a IDE vai destacar todas as suas ocorrências. Além
Figura 6. - Propriedade Nome selecionada, mostrando as ocorrências na classe
disto, ainda é possível navegar pelas referências,
com as teclas CTRL + SHIFT + Seta para cima ou CTRL
+ SHIFT + Seta para baixo, levando para a ocorrência
anterior ou superior, respectivamente.

Veja a figura 6.

Call Hierarchy
Figura 7. - Chamadas ao MetodoFilho, e chamadas do MetodoFilho
Quem nunca precisou saber quais métodos
chamam outros métodos enquanto está melho-
rando aquele código imenso? A nova versão do
Visual Studio agora lhe possibilita isto, através do
Conclusão
Call Hierarchy.
Então o que concluimos é que a Microsoft está
trabalhando intensamente em cima das necessi-
Como exemplo, criei um projeto Silverlight,
dades da comunidade e dos Feedback enviados. E
que conta com a MainPage.xaml.cs, uma classe
esses novos diagramas e funcionalidades facilitam
chamada ClassePai e outra chamada ClasseFilha.
a vida dos arquitetos, analistas e desenvolvedores,
Criei alguns métodos para interpretação, o Me-
vale a pena conferir. Mais informações podem ser
todoPai na ClassePai, que chama o MetodoFilho,
obtidas em:
na ClasseFilha. E por sua vez, no construtor da
MainWindow.xaml.cs, o MetodoPai é chamado.
http://www.microsoft.com/visualstudio/
Seria algo parecido como:
en-us/
MainPage.xaml.cs -> MetodoPai -> Metodo-
Filho.

Indo lá no cabeçalho do MetodoFilho, clicamos


Sobre o autor
com o botão direito, indo em View Call Hierarchy, Djonatas Tenfen
Trabalha a quase 7 anos com Delphi, trabalha na empresa Benner
o que nos abrirá a seguinte janela: Sistemas (www.benner.com.br ) na área de tecnologia desenvolvendo fer-
ramentas em Delphi e como hobby e visão de mercado está migrando seus
conhecimentos para a plataforma .NET. Faz parte do grupo .NET Blumenau
Veja a figura 7. http://dotnetblumenau.ning.com/ . Possue certificação 70-536 (Microsoft
.NET Framework 2.0 Application Development Foundation ) .
Twitter: djonatastenfen - blog http://www.djonatastenfen.blogspot.com/

djonatas.tenfen@gmail.com

março 2010 27
Dicas DELPHI Serial,DirLen,Flags,nil,0);
Result := IntToHex(Serial,8);
Except
Limitar número de caracteres digitados em um Memo Result :=’’;
ou RichEdit end;

Mude a propriedade MaxLenght do Memo ou RichEdit para o valor


desejado(neste exemplo usaremos 140), adicione também uma label para Estado da memória do computador
mostrarmos a contagem dos caracteres.

No evento OnChange Adicione um Memo ao Form.

Label1.Caption:= const
IntToStr(length(Memo1.Text)); // cBytesPorMb = 1024 * 1024;
uma label mostrando o número de var
caracteres digitados M: TMemoryStatus;
begin
M.dwLength := SizeOf(M);
GlobalMemoryStatus(M);
No evento KeyUp Memo1.Clear;
with Memo1.Lines do begin
Add(Format(‘Memória em uso:
%d%%’, [M.dwMemoryLoad]));
if length(Memo1.Text) = 140 then
Add(Format(‘Total de memória
// se o tamanho do memo igual a 140
então física: %f MB’, [M.dwTotalPhys /
ShowMessage(‘Somente 140 cBytesPorMb]));
caracteres permitidos’); // mostra Add(Format(‘Memória física
mensagem disponível: %f MB’, [M.dwAvailPhys
/ cBytesPorMb]));
Add(Format(‘Tamanho máximo
do arquivo de paginação: %f
MB’, [M.dwTotalPageFile /
cBytesPorMb]));
Serial HD Add(Format(‘Disponível
no arquivo de paginação: %f
MB’, [M.dwAvailPageFile /
cBytesPorMb]));
Function SerialNum(FDrive: String):
String; Add(Format(‘Total de memória
var virtual: %f MB’, [M.dwTotalVirtual
Serial:DWord; / cBytesPorMb]));
DirLen,Flags: DWord; Add(Format(‘Memória
DLabel : Array[0..11] of Char; virtual disponível: %f MB’,
begin [M.dwAvailVirtual / cBytesPorMb]));
Try end;
GetVolumeInformation(PC end;
har(FDrive+’:’),dLabel,12,@

28 março 2010
março 2010 29
Horizontal Vertical

30 março 2010
março 2010
março 2010

Você também pode gostar