Академический Документы
Профессиональный Документы
Культура Документы
bjetivo
Abordar o desenvolvimento de queries utilizando o framework Protheus.
Descrio
R_E_C_N_O_
D_E_L_E_T_
R_E_C_D_E_L_
Status do
documento
Concludo
Data
25/03/2015
Verso
1.0
Verso
anterior
1.0
Autores
Srgio Lus de
Alcntara
Silveira
Tabela TOP_FIELD
A tabela Top Field utilizada para converso automtica dos tipos de dados diferentes de
caractere para os tipos correspondentes na linguagem ADVPL, quando utilizamos modo de acesso
ISAM. Ela tambm armazena a quantidade de inteiros e casas decimais dos campos numricos.
A Top Field alimentada automaticamente durante a criao de uma tabela pelo DBAccess e
tambm atualizada quando as propriedades dos campos so alteradas usando comandos e
funes padres do ADVPL.
Dessa forma, quando um campo criado ou mantido pelo configurador, atualizao de verso ou
update, a top field corretamente alimentada.
Por outro lado, se a tabela manipulada diretamente no banco, pode ocorrer divergncia entre a
Top Field e a tabela fsica. Isso vai causar mau funcionamento do sistema.
A tabela Top Field s faz a converso automtica de tipo no modelo ISAM. Quando trabalhamos
com result sets de querys, devemos utilizar a funo TcSetField() para converter manualmente os
tipos de dados.
A linguagem SQL
Definio:
Structured Query Language, ou Linguagem de Consulta Estruturada ou SQL, uma
linguagem de pesquisa declarativa para banco de dados relacional (base de dados
relacional). Muitas das caractersticas originais do SQL foram inspiradas na lgebra
relacional.
O principal objetivo do SQL o de providenciar um mtodo de acesso s bases de dados
de forma interativa atravs de consultas (queries) base de dados.
A linguagem SQL baseia-se na lgica de conjuntos ao invs da lgica procedural
(varredura).
Vantagens do SQL:
uma linguagem universal de acesso a dados, e apesar das variaes, roda em uma
enorme quantidade de plataformas.
Concentra-se nos resultados desejados, deixando ao banco de dados a misso de escolher
a melhor estratgia para consulta dos dados.
Reduz o trafego de rede pois muitos dados so avaliados no servidor do banco de dados,
sem que obrigatoriamente sejam enviados aplicao, como no ISAM.
Desvantagens:
A lgica de conjuntos no natural para muitas pessoas, o que exige certo tempo de
adaptao.
Queries grandes e complexas podem ser tornar muito abstratas, dificultando o
entendimento.
Devido ao desconhecimento dos fundamentos da linguagem, pode-se fazer uma query
esperando uma resposta e receber algo totalmente diferente, e o pior, sem saber disso.
Queries no Protheus
Existem duas formas de executar queries no Protheus:
Comando / funo
Descrio
TcGenQry( )
dbUseArea()
GetNextAlias()
ChangeQuery()
TcSetField()
SqlOrder()
xFilial( )
RetSqlName()
DTOS()
dbGoTop()
dbSkip()
Eof()
dbCloseArea()
TcGetDb()
BeginSql
EndSql
Desenvolvendo Queries
Nos primeiros momentos do DBAccess, um tipo de query foi bastante utilizado pois necessitava de
poucas mudanas na aplicao original. a chamada query de recno.
Apesar de menos eficiente, esse modelo ainda til quando necessrio posicionar a tabela real
para alterar dados ou excluir.
Esta query retorna um campo R_E_C_N_O_ para que na varredura seja efetuado um dbgoto() no
registro real.
Ao contrrio do que se poderia supor, esta abordagem mais rpida que simplesmente varrer a
tabela ISAM, mesmo indexada, pelas seguintes razes:
Efetuar um dbkip() no record set muito mais rpido que o dbskip() na tabela real.
O dbGoto() na tabela real muito eficiente, pois o R_E_C_N_O_ a chave primria de
todas as tabelas e seu ndice diferenciado e muito rpido.
A query consegue eficientemente desprezar as linhas deletadas logicamente, ao passo
que o dbskip() na tabela fsica ter de desprezar sequencialmente os excludos. Existem
casos reais na TOTVS de um nico dbskip() levar 20 minutos por ter encontrado 1 milho
de registros excludos no incio da tabela.
Exemplo de query de recno
Esta query posiciona registros pois chamar uma funo que depende do registro posicionado.
O primeiro campo retornado o R_E_C_N_O_ que recebe o apelido SC9RECNO.
Exemplo
lQuery
:= .T.
cAliasSC9 := GetNextAlias()
Efetue o filtro para remover linhas excludas. Compare D_E_L_E_T_= pois mais rpido que
fazer D_E_L_E_T_<>*
Coloque o maior nmero possvel de condies de filtro na query. Quanto mais restritivo for o
filtro, menos registros vo ser includos no record set e menos trafgo ocorrer na rede local
Efetue o disparo da query e criao de seu record set atravs do uso conjunto de dbUseArea() e
TcGenQry(). Nessa chamada utilizaremos:
TOPCONN -> Nome da RDD do DBAccess
cQuery -> String que contm a query (statement) propriamente dito.
cAliasAB9 -> Alias do record set definido por GetNextAlias()
Caso existam campos com tipo diferente de caractere na lista de retorno, deve-se utilizar
TcSetField() para converter para um tipo vlido no ADVPL. Nesse caso, converteremos o campo
AB9_DTFIM para o tipo data do ADVPL.
Quando for necessrio converter uma grande quantidade de campos de uma tabela, pode-se usar
a estrutura da mesma usando a funo dbStruct() e efetuar uma varredura.
Utilizar o record set conforme desejado. Nesse caso, ser efetuada varredura por While.Utilizar
dbSkip() para varrer e Eof() para testar o fim do record set.
O SQL bastante eficiente para tratar este tipo de consulta, que chamamos de JOIN.
O tipo mais comum de JOIN chamado de INNER JOIN. Neste modelo, devem existir dados tanto
na primeira tabela (esquerda) quanto na segunda (direita) para que alguma linha seja
recuperada.
O INNER JOIN pode ser escrito tanto no estilo antigo, em que os campos de uma tabela
simplesmente so comparados com os campos de outra tabela, ou no estilo novo (ANSI) onde o
relacionamento explicitado.
Abaixo listamos um exemplo de INNER JOIN usando o estilo antigo. As tabelas AB9
(atendimentos) e AAG (tipos de ocorrncias) so relacionadas atravs dos campo AB9_CODPRB
e AAG_CODPRB (cdigo de ocorrncia). O que se deseja trazer, junto dos dados do
atendimento, o tipo da ocorrncia (AAG_TIPPRB) que existe apenas em AAG.
cAlias := GetNextAlias()
cQuery :=
cQuery += "SELECT
AB9_DTINI,AB9_HRINI,AB9_DTFIM,AB9_HRFIM,AAG_TIPPRB FROM
"
cQuery += RetSqlName( "AB9" ) + " AB9," + RetSqlName(
"AAG" ) + " AAG WHERE "
cQuery += "AB9_NUMOS='" + AB7->AB7_NUMOS + AB7->AB7_ITEM
+ "' AND "
cQuery += "AB9_CODPRB=AAG_CODPRB AND "
cQuery += "AB9_FILIAL='" + xFilial("AB9") + "' AND "
cQuery += "AAG_FILIAL='" + xFilial("AAG") + "' AND "
cQuery += "AB9.D_E_L_E_T_= ' AND "
cQuery += "AAG.D_E_L_E_T_= '"
cQuery := ChangeQuery( cQuery )
DbUseArea( .T., "TOPCONN", TcGenQry( ,, cQuery ),
cAlias, .F., .T. )
Funes de agregao
As funes de agregao do SQL permitem que um conjunto de linhas sejam agregadas em uma
nica linha.
As funes de agregao podem otimizar a performance do sistema pois reduzem o nmero de
linhas retornadas diminuindo o trfego de rede.
Principais funes de agregao:
COUNT() Contagem de registros
SUM() Soma dos valores de uma expresso
MAX() Mximo valor de uma expresso
MIN() - Mnimo valor de uma expresso
Ao informar uma funo de agregao em um SELECT, no se pode trazer outros campos na
seleo a menos que faam parte de uma clusula GROUP BY. Isso ocorre porque a funo de
agregao resultado de vrios registros e no faz sentido trazer apenas um deles.
Esta query exemplo retorna a quantidade total de itens liberados de um pedido de vendas (que
ainda no foram faturados), considerando todas as sequencias de liberao existentes (SC9).
cAliasSC9 := GetNextAlias()
cQuery := "SELECT SUM(C9_QTDLIB) C9_QTDLIB "
cQuery += "FROM "+RetSqlName("SC9")+" SC9 "
cQuery += "WHERE SC9.C9_FILIAL='"+xFilial("SC9")+"' AND
"
cQuery += "SC9.C9_PEDIDO='" +(cCurSorSC6)->C6_NUM+"' AND
"
cQuery += "SC9.C9_ITEM='"
+(cCurSorSC6)->C6_ITEM+"'
AND "
cQuery +=
"SC9.C9_NFISCAL='"+Space(Len(SC9->C9_NFISCAL))+"' AND
cQuery += "SC9.D_E_L_E_T_=' ' "
cQuery := ChangeQuery(cQuery)
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cAliasSC9,.T.
,.T.)
nQtdLib := (cAliasSC9)->C9_QTDLIB
dbCloseArea()
dbSelectArea("SC9")