Programação SQL
Programação SQL
Programação SQL
Este material é de efeito didático/suporte e não pode ser reproduzido sem autorização da
MicroSiga.
CopyRight © 2000 Microsiga Software S.A.
Programação SQL com SIGA Advanced / AP5
Índice
1. Introdução ao ambiente Relacional
1.1. Objetivos
1.2. Conceitos Básicos de Banco de Dados
1.3. Conhecendo a estrutura de Armazenamento dos dados
1.3.1. LOG do Banco de dados
1.3.1.1. Controle Transacional
1.3.1.2. Segurança e Backup
1.3.1.3. Construindo Query’s evitando problemas com estouro da Área de
LOG
1.3.2. Área temporária do Banco de Dados
1.4. Normalização de Base de Dados
1.5. MER (Modelo Entidade Relacionamento)
1.6. Diferenças cruciais entre ambientes DBF e SQL
1.6.1. DBF – Trabalha de forma posicional com acesso compartilhado
1.6.2. SQL – Trabalha de forma relacional (Teoria dos conjuntos) e o acesso é de
forma centralizada
2. TopConnect
2.1. Informações gerais
2.2. Controle de tipo de dados ( Tabela TOP_FIELD )
2.3. Opções de Visualizar os Eventos (Mensagens de Erros)
2.4. Sistema de controle de Registros
2.4.1. Portabilidade
2.4.2. Função da coluna R_E_C_N_O_
2.4.2.1. Limite de registros
2.4.2.2. Renumeração da coluna RECNO
2.4.3. Controle dos registros deletados (Coluna D_E_L_E_T_)
2.5. Constraints do Banco de dados que são criados automaticamente
2.5.1. Criação da Estrutura de tabelas
2.5.2. Índices
2.5.3. Defaults
2.5.4. Problemas com conteúdo Nulo
2.6. Manutenção do Banco de dados
2.6.1. Aumentando a performance executando a operação de PACK
2.7. DBFNTX x TopConnect
2.7.1. Índices de produção
2.7.2. Funções em chaves de índices
2.7.3. Índices condicionais
2.7.4. Chaves numéricas compostas
2.7.5. Expressões de filtro com funções e variáveis
2.8. Comandos
2.8.1. APPEND FROM
2.8.2. COPY TO
2.8.3. USE
2.8.4. BEGIN, COMMIT, ROLLBACK TRANSACTION
Programação SQL com SIGA Advanced / AP5
2.9. Funções
2.9.1. TCCANOPEN
2.9.2. TCCONTYPE
2.9.3. TCDELFILE
2.9.4. TCGETDB
2.9.5. TCLINK
2.9.6. TCQUERY
2.9.7. TCQUIT
2.9.8. TCSETCONN
2.9.9. TCSETFIELD
2.9.10. TCSPEXEC
2.9.11. TCSPEXIST
2.9.12. TCSQLERROR
2.9.13. TCSQLEXEC
2.9.14. TCSRVTYPE
2.9.15. TCUNLINK
2.9.16. TCCHKOBJ*
2.9.17. TCEXEERROR*
2.9.18. TCPGMEXE*
2.9.19. TCSYSEXE*
( * )Funções apenas para o TOPConnect rodando em servidores AS/400.
2.10. Performance
2.10.1. Otimizando seu código
2.10.2. Leitura Sequencial
2.10.3. O uso de filtros
2.10.4. Stored Procedures
2.11. Integração com outros aplicativos
2.11.1. Incluindo registros nas tabelas do SigaAdvanced / AP5
2.11.2. Excluindo registros ( Sempre Marcar )
2.11.3. Vantagens e Desvantagens
3.11. UNIONS
3.12. SUB SELECTS
3.13. TRIGGERS
3.14. STORED PROCEDURES
3.15. CURSORES
5. Utilitários importantes
5.1. SDU ( Siga DataBase Utility) / AP5 configurador
5.2. Dbf2Sql ( Conversor de arquivos DBF para SQL)
5.3. Sql2Dbf ( Conversor de arquivos SQL para DBF)
5.4. DEFAULT ( Ferramenta de ajuste do DataBase)
5.5. Instalador de Stored Procedures no Banco de Dados
Este curso tem como objetivo treinar e aperfeiçoar nossos analistas e parceiros quanto à
confecção de programas específicos, em ambiente de trabalho com Base de Dados SQL
desta forma pretendemos aumentar a facilidade de manuseio dos componentes envolvidos
tanto na análise e detecção de erros, e quais possíveis ações para saná-los, antes de
recorrer ao suporte interno. Demonstraremos também como otimizar programas através da
linguagem SQL em seus RDMAKES e futuras implementações para as próximas versões.
Todos os tópicos mencionados poderão servir como base de consulta, para escrita de
programas e resolução de problemas.
Os conceitos básicos dos Bancos de Dados relacionais são bem diferenciados dos
conhecidos DBF´s. Estes conceitos básicos são úteis principalmente para saber
responder eventuais perguntas que nossos clientes poderão efetuar sobre nosso
sistema.
SQL quer dizer : Structured Query Language , que foi desenvolvido inicialmente pela
IBM Corporation.
A primeira diferença entre o ambiente SQL e o DBF é o fato de criarmos uma área no
disco (DATABASE) que o próprio banco se encarregara de administrar, no sentido de
criar tabelas, índices, e todos os objetos envolvidos no sistema. A nomenclatura muda
um pouco: ao invés de CAMPOS temos COLUNAS e ao invés de REGISTROS temos
LINHAS.
Uma Trigger funciona como um gatilho, só que este é disparado não a cada campo
alterado, e sim a cada Inclusão, Alteração ou Exclusão de uma linha da tabela. Os
Triggers também são escritos como as Stored Procedures, ou seja, como um
programa qualquer, que pode efetuar qualquer tipo de validação, atualização em
outras tabelas, etc...
Hoje não utilizamos no Siga Advanced nenhuma Trigger. Em alguns casos específicos
em clientes, as mesmas poderão ser utilizadas.
Programação SQL com SIGA Advanced / AP5
Uma Foreign Key ( Chave Estrangeira ) é uma ligação entre tabelas que são criadas
nas mesmas. São estas que garantem que nunca o Cliente “X” será excluído se o
mesmo tiver movimentos ( Pedidos, Notas , Duplicatas Etc. ), também será garantido
que nunca será incluído um Pedido de Vendas do Cliente “Y”, se o mesmo não existir.
Este tratamento é feito diretamente pelo Banco de Dados, não necessitando qualquer
codificação para isto.
O uso de um Banco de Dados SQL se faz necessário pela segurança dos dados e pela
fácil recuperação dos mesmos, por vários aplicativos como Siga Advanced/AP5
(TopConnect), Crystal Reports (ODBC), SigaEIS (BDE), Excel, etc.
Para empresas que fazem uma grande utilização de banco de dados normalmente
encontramos um profissional chamado DBA (Data Base Administrator), que tem a
função de administrar o banco de dados, quanto há otimização, configuração, backups
e segurança. Sabemos que na prática isto só funciona para empresas grandes,
portanto temos que saber o mínimo possível de cada banco de dados para podermos
identificar problemas e soluções que se adequam melhor à instalação do cliente.
Programação SQL com SIGA Advanced / AP5
Depois que uma transação é concluída com sucesso, não indica que a mesma
estará sendo transferida para a área real dos dados. Este tramite de
transferência é chamado de CheckPoint , este ponto é configuravél de acordo o
SGDB utilizado. Para bancos de dados de maior escala, o processo de check
point só é realizado após o Backup da área de LOG.
tempo. Em clientes com base de dados pequenas, não utilizamos este tipo de
recurso.
Com a pratica vamos perceber que a normalização é muito boa, mas o seu excesso gera
problemas na programação, portanto temos sempre que fazer o máximo de normalização
mas devemos estar consciente de quanto conseguiremos de vantagem com isto.
Existe casos que a desnormalização é uma das melhores soluções, para facilitar o
desenvolvimento da aplicação ou para ganharmos performance.
A primeira forma normal diz que devemos definir a entidade e seus atributos, e destes
atributos devemos definir um atributo chave de relação.
Neste caso criaremos um campo código que define a sua chave principal de
relacionamento, criaremos o Código. Nunca utilize mais de um coluna agregada com
campo chave.(Este tipo de campo gera vários problemas na programação SQL)
A segunda forma normal diz que devemos subdividir os atributos que ocorrem mais de
que uma vez, em uma outra entidade.(Esta entidade deve ter um campo chave,
atendendo a primeira forma normal).
A terceira forma normal diz que devemos eliminar colunas que são concebidas por
calculo de outras colunas de mesma entidade.
8. TopConnect
Alguns comandos e funções avançadas são disponibilizadas para que seu aplicativo
possa usufruir de todos os benefícios da plataforma cliente servidor, que são
apresentados logo em seguida.
Programação SQL com SIGA Advanced / AP5
Em um banco existem vários tipos de dados (CHAR, VARCHAR, FLOAT, NUMBER, etc.)
porem para existir uma unicidade no código do Topconnect alguns dados são
armazenados de forma diferente da definida na tabela SX3, porem a aplicação recebe o
dado da forma como definido.
A1_FILIAL C 2
A1_COD C 6
A1_LOJA C 2
A1_DESC C 1
A1_EMISSAO C 8
A1_VEND1 C 6
...
Ex.: Tabela TOP_FIELD
Alerta! : Se você for utilizar diretamente o Banco de dados você precisa estar ciente que
um campo numérico é armazenado como um tipo float(MSSQL Server),
Number(Oracle), etc. Por exemplo o valor 40,40 no banco pode estar
armazenado como 40,39999999. Quando formos utilizar query’s você deve
utilizar a função TCSETFIELD para resolver esta situação.(Veja função
TCSETFIELD).
Importante também salientar que qualquer modificação efetuada em arquivo
SX3 diretamente, ou seja, sem utilizar o configurador, você pode Ter problemas
com inconsistência de estrutura da tabela do Banco de Dados e TOP_FIELD
contra o dicionário de dados. Para resolver este problema você deverá remover
os dados da Tabela do Banco de dados, eliminar a tabela e deixa-la criar
novamente e depois importar os dados via APPEND(Utilize SDU/CFG-AP5), ou
você pode ajustar o dicionário de dados manualmente conforme estrutura no
Banco de Dados.
Programação SQL com SIGA Advanced / AP5
Na maioria dos problemas este logo de erros é o ponto principal para descobrir o que
esta acontecendo, entre o Topconnect e o Banco de dados. Você só estará recebendo
mensagens se o link entre o Banco de dados e o Topconnect estiver funcionando.
Esta coluna não possui repetição, ela é sempre preenchida com o valor máximo da
coluna R_E_C_N_O_ + 1 nas próximas inserções. Esta operação é feita pelo
TopConnect , se você utiliza outros produtos que fazem inserção na Base de Dados
do Sigaadvanced / AP5 você deve seguir as orientações do Capítulo Integrações
com outros aplicativos.
Alerta! : Quando você utiliza o comando Set Delet on/off, o TopConnect estará
tratando o dado para você, mas se você utiliza query’s para recuperação de dados
você deverá tratar este coluna (Mais informações sobre o tratamento da coluna
D_E_L_E_T_ será apresentado em exemplos de query’s em RDMAKES.
acaso alguma tabela for removida diretamente por um utilitário do Banco de Dados
o TopConnect terá uma informação não coerente, você deve reiniciar o serviço do
Topconnect (Parando / iniciando o Serviço).
8.5.2. Índices
8.5.3. Defaults
São constraints de validação de campos que não são informados, nos comandos
de inserção e alteração, ou seja, se você não possui os defaults criados o Banco
de Dados estará deixando estes campos com valor nulo. Os defaults são criados
no momento da criação das tabelas.
Alerta!: Se você fizer qualquer operação de transferência via Banco de Dados que
não transfira os Defaults, e logo em seguida você utilizar o sistema , estará
correndo risco de inserir nulos na Base de Dados. Se isto acontecer você poderá
Ter problemas com o TopConnect Server, ele poderá travar ou derrubar conexões
com dados indevidos. A solução neste caso é utilizar o utilitário DEFAULT que
esta disponível no site da Microsiga.
Programação SQL com SIGA Advanced / AP5
Os Bancos de dados possuem o conteúdo nulo para todos os tipo de campos, mas
o nosso sistema não os utiliza, se por ventura qualquer tabela tenha algumas
linhas com alguma coluna com o valor nulo, isto pode provocar problemas que
aparentam ser erro de índice, como ex. Você tem a tabela de pedidos que com os
pedidos 000001,000002 e sua tabela por qualquer motivo não tem os contraints de
defaults na coluna filial, agora você faz a inserção do pedido 0000003 o sistema
irá apresentar um Browse ordenado por pedido da seguinte forma:
Filial Pedido
--------- ------------
Null 000003
000001
000002
Neste exemplo você percebe que o pedido 000003 aparece em primeira ordem,
sendo o índice filial+pedido, ou seja, o valor nulo na tabela ASCII(Binary Order)
aparece antes do caracter espaço em branco.
Este problema muitas vezes causa a impressão que o índice esta com
problemas, por que a tela de Browse do Sigaadvanced / AP5 não apresenta a
coluna filial.
Alerta!: Se você tiver este problema, utilize a operação de Pack do utilitário SDU
na tabela que possui registros excluídos , ou utilize o programa fonte PACK para
fazer esta operação em todas as tabelas.
Function OkProc
Close(oDlg5)
Processa( {|| Execute(RunProc) } )
Return
/*
Funcao ³RunProc
Descrição ³Executa o Processamento
*/
Function RunProc
DbSelectArea("SX2")
NrecnoSX2 := SX2->(Recno())
DbGoTop()
ProcRegua(reccount())
While !Eof()
If Select(SX2->X2_CHAVE) > 0
cQuery := 'SELECT MAX(R_E_C_N_O_) RECNO FROM ' + SX2->X2_ARQUIVO
dbUseArea(.T., "TOPCONN", TCGenQry(,,cQuery), 'CONT', .F., .T.)
nCont := 1
While nCont <= CONT->RECNO
cQuery := "DELETE FROM "+SX2->X2_ARQUIVO
cQuery := cQuery + " WHERE D_E_L_E_T_ = '*'"
cQuery := cQuery + " AND R_E_C_N_O_ between "+Str(nCont)+" AND
"+Str(nCont+1024)
nCont := nCont + 1024
TCSQLEXEC(cQuery)
Enddo
DbSelectArea("CONT")
DbCloseArea()
Endif
DbSelectArea("SX2")
dbSkip()
incproc()
Enddo
return
Programação SQL com SIGA Advanced / AP5
Exemplo:
Em um arquivo com a seguinte estrutura:
Para se criar um índice que ordene o arquivo por CAMPO1 + CAMPO2 deverá o
seguinte comando ser utilizado:
Nos gerenciadores de banco de dados não existe a figura dos índices condicionais.
Para se obter resultados semelhantes aos índices condicionais o TOPConnect
agregou nova funcionalidade ao filtro do SigaAdvanced / AP5.
dbSetOrder(0)
O TOPConnect permite o uso da função OrderBy nos filtros o que reproduz o mesmo
efeito de um índice filtrado.
Os SGDB's não suportam índices que contenham expressões ADVPL onde dois
campos numéricos são somados na chave.
Exemplo:
INDEX ON CPOVAL1 + CPOVAL2 TO ARQIND
Uma vez que o TOPConnect utiliza a arquitetura Cliente/Servidor o servidor não tem
como avaliar o conteúdo de uma variável de memória ou o retorno de uma função do
cliente.
Este filtro contem apenas campos e constantes o que permite que sua avaliação seja
feita no servidor e que apenas os registros que obedeçam ao filtro venha para o
cliente.
Agora este:
SET FILTER TO CODIGO > RetornaCodigo()
Pôr exemplo:
SET FILTER TO ESTADO = 'SP' .AND. SALDO > 10000 .AND. CODIGO >
RetornaCodigo()
Nesta expressão somente virão para o cliente os registros onde os campos ESTADO
e SALDO obedeçam ao filtro e então o campo CODIGO será avaliado no cliente.
Programação SQL com SIGA Advanced / AP5
8.8. Comandos
Neste capítulo mencionaremos apenas os comandos da linguagem ADVPL que tem a sua
funcionalidade alterada ou complementada e os novos comandos implementados pelo
TOPConnect via RDD.
#INCLUDE "TOPCONN.CH"
Exemplo
SELECT CLIENTES
//Importa registros de um DBF
APPEND FROM c:\temp\newcli.dbf
Ou
SELECT CLIENTES
//Importa registros da tabela NEWCLI
APPEND FROM NEWCLI VIA "TOPCONN"
8.8.2. COPY TO
8.8.3. USE
USE [<xcTable>
ALIAS < cAlias> Especifica um nome para a Work Area onde a tabela será
aberta
EXCLUSIVE Especifica que apenas este usuário terá acesso a esta tabela.
Todas as outras tentativas de colocar esta mesma tabela em uso falharão.
SHARED Especifica que a tabela será aberta em modo compartilhado.
NEW Abre a tabela <cTable> na próxima Work Area disponível. Se esta clausula
não for especificada, <xcTable> será na Work Area corrente.
READONLY Abre <cTable> apenas para leitura.
VIA "TOPCONN" Este parâmetro indica ao ADVPL que esta Work Area será
gerenciada pelo TOPconnect.
Se nenhum parâmetro for especificado a tabela aberta na Work Area corrente será
fechada.
Exemplo
//Abre a tabela de Clientes em uma nova Work Area
USE clientes SHARED NEW VIA "TOPCONN"
//Adiciona um pedido
SELECT PEDIDOS
APPEND BLANK
SELECT ITEMS
APPEND BLANK
.....
APPEND BLANK
Programação SQL com SIGA Advanced / AP5
.....
COMMIT TRANSACTION
Programação SQL com SIGA Advanced / AP5
8.9. Funções
8.9.1. TCCANOPEN
Exemplo
//Testa a existência da tabela customer
IF !TCCanOpen("CUSTOMER")
dbCreate("CUSTOMER", aStru, "TOPCONN")
ENDIF
USE CUSTOMER SHARED NEW VIA "TOPCONN"
//Testa a existência do índice
IF !TCCanOpen("CUSTOMER","CUSTCOD")
INDEX ON CODIGO TO CUSTCOD
ELSE
SET INDEX TO CUSTCOD
ENDIF
...
8.9.2. TCCONTYPE
TCConType(<cType>)
8.9.3. TCDELFILE
TCDelFile(<cTable>)
8.9.4. TCGETDB
cDataBase := TCGETDB()
8.9.5. TCLINK
nCon := TCLink(<cConectString>,<cServer>)
Exemplo
nCon := TCLink("MSSQL/SIGAADV","TOPSRV")
if nCon < 0 //Conexões com retorno < 0 significam erro
Alert("Falha de conexão com o TOPConnect")
endif
//Protocolo TCP/IP
TCConType("TCPIP")
//Conecta-se ao Oracle – no ambiente TESTES
nCon := TCLink("ORACLE/TESTES",172.16.1.2)
//Protocolo APPC
//Conecta-se ao AS/400 no ambiente PRODUCAO
nCon := TCLink("PRODUCAO","TOP400")
8.9.6. TCQUERY
TCQUERY [<cSQLExpr>
[ALIAS <xcAlias>]
[NEW]
VIA "TOPCONN"
Obs: Ao executar uma Query que retorne um ou mais valores calculados, o nome
dos campos da WorkArea serão COLUMN1, COLUMN2... COLUMNn.
Exemplo
Programação SQL com SIGA Advanced / AP5
8.9.7. TCQUIT
8.9.8. TCSETCONN
Sintaxe
TCSETCONN(<nConn>)
Onde <nConn> é o número da conexão.
Exemplo
// Abre conexão com o ambiente de Produção
nCon1 := TCLink("MSSQL/PRODUCAO")
if nCon1 < 0
Alert("Falha conectando ambiente de Produção")
QUIT
endif
TCSetConn(nCon1)
TCSetConn(nCon2)
8.9.9. TCSETFIELD
Sintaxe
TCSetField(<cAlias>, <cField> ,<cType>, [<Prec.Inteira>,<Prec.Decimal>] )
Exemplo
TCQUERY "SELECT NOME, DATA, MARRIED, VALOR FROM CUSTOMER"
ALIAS QUERY VIA "TOPCONN"
TCSetField("QUERY","DATA","D")
TCSetField("QUERY","VALOR","N",12,2)
8.9.10. TCSPEXEC
Sintaxe
<aRet> := TCSPExec(<cSPName>,[<xParam1>,<xParam2>...<xParamN>])
Exemplo
//Verifica se a Stored Procedure Teste existe no Servidor
If TCSPExist("TESTE")
//Executa a Stored Procedure Teste
aRet := TCSPExec("TESTE","JOSE",1000)
if aRet <> nil
Programação SQL com SIGA Advanced / AP5
8.9.11. TCSPEXIST
Exemplo
If SPExist("CALCCUSTO")
TCSPExec("CALCCUSTO")
Endif
8.9.12. TCSQLERROR
Sintaxe
<cError> := TCSQLError()
8.9.13. TCSQLEXEC
<nRet> := TCSQLExec(<cCommand>)
8.9.14. TCSRVTYPE
<cType> := TCSrvType()
Onde <cType> é o tipo do servidor podendo Ter seu conteúdo igual a "WinNT" ou
"AS/400".
Exemplo
TCLink("MSSQL/TESTE","TOPSRV")
?TCSrvtype()
8.9.15. TCUNLINK
TCUnlink(<nConn>)
8.9.16. TCCHKOBJ*
<nError> := TCChkObj(<cObj>,<cLibrary>,<cType>)
Onde:
<nError> é 0 quando o objeto existe ou o número do erro no AS/400.
<cLibrary> é o nome da biblioteca que deve conter o objeto.
<cType> é o tipo de objeto AS/400. Ex: *FILE, *PGM, etc.
Exemplo
nError := TCChkObj("CALCCUST","PRODUCAO","*PGM")
ESTA FUNÇÃO SE APLICA APENAS PARA O TOPCONNECT AS/400
8.9.17. TCEXEERROR*
Retorna uma string com a mensagem de erro retornada pela execução das
funções TCPGMEXE() e TCSYSEXE().
Sintaxe
<cError> := TCExeError()
8.9.18. TCPGMEXE*
8.9.19. TCSYSEXE*
TCSysExe( cCommand )
8.10. Performance
8.10.1. Otimizando seu código
O código acima fará com que todas as linhas(registros) da tabela venham para o
Client, o que irá gerar um número de Queries no servidor igual ao número de linhas
da tabela e cada uma delas irá recuperar apenas uma linha, subtilizando a
capacidade de processamento do servidor.
O mesmo não ocorre utilizando o TOPConnect, pois o filtro é avaliado pelo próprio
servidor vindo para a estação apenas os registros que respeitem a condição do
filtro.
Para que um filtro tenha uma boa performance é necessário que a expressão do
filtro corresponda a um índice no servidor, caso contrário, para poder avaliar o filtro
o servidor SQL terá que ler linha a linha da tabela.
As desvantagens deste processo, são que você deve estar ciente de todas
atualizações que são feitas na base de dados no sistema, já que o sistema esta
desta forma vulnerável a problemas inesperados.
Você vai perceber que a linguagem SQL é sempre em comandos textos que são
solicitados ao servidor, o mesmo estará compilando a query e logo em seguida se não
houver erro de sintaxe estará executando a query. Esta operação é feita a cada requisição
ao servidor, se vocês perceberão quanto menor o número de solicitações ao servidor
melhor.
Ferramentas de trabalho para os Banco de Dados mais comuns MSSQL Server (isql/w ,
Query Analyzer), Oracle (WorkSheet) e informix (SQL Editor) . Esta ferramentas são
muito similares a editores de texto, ou seja, você deve digitar todo o comando, e o mesmo
é submetido imediatamente ao SGDB e recebe a resposta.
9.2. SELECT
Este comando tem o objetivo único de fazer uma seleção de dados do Banco de Dados,
este comando estará fazendo o mesmo que um programa comum pode fazer , só que
você precisaria escrever várias linhas para conseguir o mesmo resultado, ex. se você
escrever um programa padrão em ADVPL você terá que posicionar o registro , fazer um
laço, reposicionando o próximo registro até o final do arquivo, ou condicionalmente, etc.
Veja agora como fazer em linguagem SQL.
Sintaxe:
<Nome da Coluna> => Informar a(s) coluna(s) da(s) tabela(s) que você deseja
apresentar / manipular em seu aplicativo. Se você informar o símbolo ‘*’ (Asterisco) o
comando estará assumindo todas as colunas da tabela.
<Nome de Retorno> => Será o nome da coluna apresentado para sua aplicação como o
nome original de resultado da query.
Alerta!: Quando você possui mais de uma tabela associada você deve informar um
apelido + ’.’ + <o nome da coluna ou (*)Asterisco>.
SELECT *
FROM SA1990
Função : ROUND
SELECT round(round(C6_QTDVEN,4)*round(C6_PRCVEN,2),2)VALOR
FROM SC6990
Ex. Select com uso de múltiplas tabelas com seleção de todos as colunas
de uma tabela, e alguns de outra tabela
Obs: Para Banco de dados Oracle e Informix utilize pipe ‘|’ no lugar de ‘+’.
Esta clausula é uma das mais importantes do comando SELECT, existe várias operações
que podemos construir a partir dela, que vamos ver no decorrer do curso, neste momento
estaremos utilizando a clausula para informar ao comando SELECT que existe um filtro. O
filtro que estaremos informando é muito parecido com a que utilizamos em uma função
indregua(), em ADVPL.
Sintaxe:
Programação SQL com SIGA Advanced / AP5
<Condição de filtro> - informar uma expressão lógica que estará eliminando as linhas que
estiverem dentro do contexto informado.
Dentro da condição de filtro você deve utilizar o seguintes operadores :
= (igualdade)
> (maior que)
< (menor que)
>= (maior que ou igual a)
<= (menor que ou igual a)
<> (diferente)
!= (diferente) (não é SQL-92 padrão).
!< (Não menor a) (não é SQL-92 padrão).
!> (Não maior a) (não é SQL-92 padrão).
AND Verdadeiro se ambas expressões forem verdadeiras
OR Verdadeiro se qualquer expressão for verdadeira
BETWEEN Verdadeiro se a expressão esta dentro de um
determinado intervalo
EXISTS Verdadeiro se uma subquery contém alguma linha
IN Verdadeiro se o operando é igual a uma das
expressões da lista
NOT Inverte o valor de qualquer outro expressão boleana
LIKE ([ _ ],%) Verdadeiro se a expressão fixa for encontrada.
SELECT *
FROM SE1990
WHERE E1_FILIAL = '01'
AND E1_CLIENTE BETWEEN ' ' AND 'zzzzzz'
AND E1_LOJA BETWEEN ' ' AND 'zz'
AND E1_PREFIXO LIKE 'P%'
AND E1_NUM BETWEEN ' ' AND 'zzzzzz'
AND E1_VENCREA BETWEEN '20000225' AND '20001231'
AND E1_EMISSAO <= '20001231'
AND E1_TIPO IN ('DP ','NF ','AB-','NCC','NCD')
AND NOT E1_EMISSAO = '20000401'
AND D_E_L_E_T_ <> '*'
9.4. INSERT
Este comando insere uma linha em uma tabela ou visão. Este comando é muito
semelhante a uma inserção feita pelo programa do SigaAdvanced/AP5, não existe muitas
vantagem em fazer inserções diretamente pelo comando insert.
Sintaxe:
Você ainda tem a opção de não informar o nome das colunas, ou seja, desconsiderar a
Parte que esta dentro do colchetes. Utilizando desta forma temos a obrigação de informar
o conteúdo de cada coluna na mesma ordem em que as colunas foram criadas na tabela.
Recomendamos sempre informar o nome de cada coluna. Como as nossas tabelas todas
possuem contraints de Default, não precisamos informar todas as colunas somente as que
você necessitar e normalmente são as colunas obrigatórias.
9.5. UPDATE
Este comando pode ser executado para fazer alterações linha por linha ou fazer alteração
de várias linhas através de um condicional em comum a todas as linhas.
Sintaxe:
Lembre-se que o comando update faz controle transacional implícito, ou seja, enquanto o
comando não for executado até o seu final com sucesso, o dado não será confirmado
(Commit), esta operação requisita área de log, portanto se formos fazer um update o qual
o seu filtro seja equivalente a tabela inteira, devemos estar cientes de que existe espaço
suficiente na área de log do Banco de Dados.
UPDATE SA4990
SET A4_NOME = ‘TRANSPORTADORA STAR LTDA’
WHERE R_E_C_N_O_ = 10
Neste exemplo será alterado apenas uma linha que o Recno seja igual 10,
como o recno é chave única da tabela, apenas um registro será alterado.
UPDATE SA4990
SET A4_NOME = 'TRANSPORTADORA STAR LTDA'
WHERE A4_COD = '000001'
AND D_E_L_E_T_ <> '*'
UPDATE SB1990
SET B1_PRV1 = B1_PRV1 + ( (B1_PRV1 + 10) / 100 )
WHERE D_E_L_E_T_ <> '*'
UPDATE SA4990
SET D_E_L_E_T_ = ‘*’
WHERE R_E_C_N_O_ = 10
Alerta: Nunca execute um comando update sem um condicional, desta forma você estará
alterando todos as linhas da tabela e também estará correndo o risco de estourar a área
de log do Banco de Dados. (Utilize ferramentas como SDU ou Configurador)
Programação SQL com SIGA Advanced / AP5
9.6. DELETE
Este comando pode ser executado para fazer exclusão física do registro, o
SigaAdvanced / AP5 não utiliza esta operação, apenas o comando pack o fará. Este
comando trabalha de forma parecida ao update ele possui o mesma opção de filtro.
Sintaxe:
Lembre-se que o comando delete faz controle transacional implícito, ou seja, enquanto o
comando não for executado até o seu final com sucesso, o dado não será confirmado
(Commit), esta operação requisita área de log, portanto se formos fazer um delete o qual o
seu filtro seja equivalente a tabela inteira, devemos estar cientes de que existe espaço
suficiente na área de log do Banco de Dados.
DELETE SA4990
WHERE R_E_C_N_O_ = 10
Neste exemplo será excluído apenas uma linha que o Recno seja igual 10,
como o recno é chave única da tabela, apenas um registro será excluído.
DELETE SA4990
WHERE A4_COD = '000001'
AND D_E_L_E_T_ = '*'
Note: Veja em alguns Bancos de Dados você pode utilizar o comando TRUNCATE
TABLE, que estará fazendo o mesmo que um comando ZAP em ADVPL. Só que esta
operação é extremamente rápida, para conhecedores de Cobol, esta operaçào é
conhecida como OPEN OUTPUT. Atenção depois desta operação não existe mais como
recuperar as linhas da tabela. (Esta operação não utiliza LOG).
Alerta: Nunca execute um comando delete sem um condicional, desta forma você estará
excluindo todos as linhas da tabela e também estará correndo o risco de estourar a área
de log do Banco de Dados.
Programação SQL com SIGA Advanced / AP5
9.7.1. SUM
SELECT SUM(A1_SALDUP)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
9.7.2. COUNT
SELECT COUNT(*)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
SELECT COUNT(A1_FILIAL)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
Neste exemplo estará retornado o total de linhas da tabela o qual as linhas não
estão excluídos, se houver algum linha que a coluna esteja nula não será
somando.
Programação SQL com SIGA Advanced / AP5
9.7.3. AVG
Esta função tem objetivo de retornar a média dentre as linhas selecionadas pela
clausula where ou having.
SELECT SUM(A1_SALDUP)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
9.7.4. MAX
SELECT MAX(R_E_C_N_O_)
FROM SA1990
Este exemplo retornará o maior valor da coluna, o mesmo é muito usado para
se saber qual a próxima seqüência disponível. Nunca despreze as linhas
excluídas, por que este número é sequencial e único na tabela.
9.7.5. MIN
SELECT MIN(C6_EMISSAO)
FROM SC6990
WHERE C6_CLI = ‘ 123456’
AND D_E_L_E_T_ <> ‘*’
Este exemplo retornará o maior valor da coluna, o mesmo é muito usado para
se saber qual a próxima seqüência disponível. Nunca despreze as linhas
excluídas, por que este número é sequencial e único na tabela.
9.7.6. Group By
Esta função tem objetivo de definir quais são as colunas que determinam o
agrupamento.
Ex. Select para obter valor total de pedidos por cliente e data
Esta clausula tem por finalidade filtrar os dados que estão numa condição de
agrupamento. Apesar de ser um clausula de filtro (semelhante à clausula where), ela
só poderá ser usada para as colunas declaradas na condição group by.
Normalmente temos a utilização de vários TES para o mesmo CFO por nossos
clientes e para descobrimos quais são os CFO’s que o cliente utiliza sem
apresentar esta repetição podemos utilizar o exemplo acima.
Ex. Select para obter código das filiais com linhas existentes (válido para
tabela com X2_MODO = ‘E’)
Esta função é idêntica a função SUBSTR usada em ADVPL, e pode ser utilizada em
qualquer ponto do select o qual utilizamos ou informamos uma coluna.
OBS: Para MSSQL Server e Sybase utilize a função SUBSTRING, agora para Oracle e
informix utilize SUBSTR
Este exemplo poderia ser modificado na condição where para o operador LIKE que
teria o mesmo efeito de de forma muito mais rápida.
Recomendamos a não utilização desta função por gerar muitos problemas de
performance.
9.9. ORDER BY
Esta clausula tem por objetivo modificar o resultado do select quanto a order das linhas,
existe duas formas de se ordenar os dados, de forma crescente(ASC) ou decrescente
(DESC). Um detalhe importante para performance do comando é que quando possuímos
um índice que as mesmas colunas de ordenação que desejamos o Banco de Dados irá
utiliza-lo. Agora se não existir o mesmo estará criando uma área temporária para fazer a
ordenação do dado(TempDB).
Sintaxe :
SELECT …
FROM …
ORDER BY <Coluna1> [ASC|DESC],…,<Coluna16> [ASC|DESC]
SELECT A1_NOME
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
ORDER BY A1_NOME DESC
Ex. Select para apresentar os cliente por order de código e loja de forma
crescente.
Note que neste exemplo não é necessário informar a expressão ASC, para
obter o resultado de forma crescente.
Nota : Em alguns casos de query´s você irá perceber que o resultado já estará
apresentando as linhas por uma certa ordenação, isto que dizer que o Banco
de dados utilizou um índice para resolver o problema, mas isto não indica que
sempre o dado será retornado nesta orderm, portanto se você precisar que o
dados retornados estejam ordenados você dever sempre informa o ORDER BY
Para garantir o resultado ordenado.
9.10. JOINS
Esta operação é uma das mais poderosas expressões de um comando select , existe
duas formas de aplicar joins em selects , estaremos apresentado somente uma destas
formas que é a mais simples de escrever, esta forma é a utilizada em nossos programas.
O único problema desta forma que a mesma não é ANSI para todos os bancos de dados,
mas estaremos apresentando as diferenças que você deve fazer para cada um deles.
A função básica de um JOIN é fazer o relacionamento entre duas ou mais tabelas, que
tenham chaves em comum. Estas chaves não são necessariamente índices criados, o
relacionamento pode ser definido no momento da escrita do select.
O relacionamento entre duas tabelas é feito utilizando o símbolo de igualdade entre duas
colunas, sendo uma coluna de cada tabela. Se houver relacionamento de mais de uma
tabela podemos fazer o relacionamento em cascata, ou fazer o relacionamento a partir da
mesma tabela. Lembre-se que sempre o relacionamento é feito de forma binária, ou seja,
só podemos relacionar duas tabelas de cada vez, mas podemos com isto relacionar
quantas tabelas desejarmos. A única limitação deste tipo de relacionamento vai até o
limite suportado pelo Banco de Dados.
Como recomendação devemos sempre tentar relacionar no máximo quatro tabelas, lógico
que existe exceções, mas sempre que houver o relacionamento de muitas tabelas o
banco de dados precisará de mais tempo para conseguir resolver o problema e em alguns
caso não será viável. Existe várias situações que dependem de experiência e teste para
conseguirmos chegar na melhor solução possível.
Sempre que utilizarmos joins devemos sempre informar todas as tabelas que serão
relacionadas na clausula from e todos os seus relacionamentos na clausula where se por
acaso não for feito o relacionamento de uma destas tabelas o banco de dados estará
fazendo um produto cartesiano (CROSS JOIN) entre todas as linhas da tabela que não foi
relacionado com as demais tabelas.Se isto acontecer o servidor poderá ter sérios
problemas de uso excessivo de CPU.
O resultado de um left join inclui todas as linhas da tabela que foi específica a
esquerda da clausula LEFT OUTER , ou seja, independente de existir ou não um
dado relacionado na tabela informada mais a direita da tabela todas as linhas
referentes a tabela da esquerda serão retornadas. Nas linhas que não existe um
linha de relação com a tabela a direita os campos desta tabela serão retornados
com valor nulo.
Nota: Não é possível fazer outer joins subsequentes, ou seja, se você fizer
outer join de uma tabela que logo em seguida tem um relacionamento com
outra tabela.
O resultado de um Right join inclui todas as linhas da tabela que foi específica a
direita da clausula RIGHT OUTER , ou seja, independente de existir ou não um
dado relacionado na tabela informada mais a esquerda da tabela todas as linhas
referentes a tabela da direita serão retornadas. Nas linhas que não existe um
linha de relação com a tabela a direita os campos desta tabela serão retornados
com valor nulo.
Ex. Select para retornar todos os clientes mesmo que não exista pedidos
relacionados
Ex. Select para retornar todos os clientes mesmo que não exista pedidos
relacionados
Programação SQL com SIGA Advanced / AP5
Ex. Select para retornar todos os clientes mesmo que não exista pedidos
relacionados
Nota: Não é possível fazer outer joins subsequentes, ou seja, se você fizer outer
join de uma tabela que logo em seguida tem um relacionamento com outra tabela.
Um full outer join é o resultado de um inner join + right join + left join , desta forma
você terá o resultado com todas as linhas da primeira tabela mais o resultado com
todas as linhas da Segunda tabela e apresentará em mesma linha os itens que
forem possíveis de relacionamento.
Ex. Select para retornar todos os clientes e todos os pedidos mesmo que
não exista pedidos ou clientes relacionados
Nota: Nos demais Bancos de Dados não existem este tipo de join. Mas existem
outras formar de resolver este problema utilizando inner join + left join + right join +
unions , iremos ver a seguir como utilizar o union desta forma teremos a solução
também para os demais bancos de dados, e até mesmo os que tem a opção.
Programação SQL com SIGA Advanced / AP5
Ex. Select para retornar todos os clientes e todos os pedidos mesmo que
não exista pedidos ou clientes relacionados
9.11. UNIONS
9.13. TRIGGERS
9.15. CURSORES