Model View Controller: SQL Básico
Model View Controller: SQL Básico
SQL nível básico (Joins, Funções de Agregação e Subquerys), TcQuery e Embedded SQL.
1
SQL Básico
Sumário
1. SQL..........................................................................................................................3
1.1. Select................................................................................................................3
1.2. Clausula WHERE.............................................................................................4
1.3. Funções de agregação...................................................................................6
1.3.1. SUM...........................................................................................................6
1.3.2. COUNT......................................................................................................6
1.3.3. AVG...........................................................................................................7
1.3.4. MAX...........................................................................................................7
1.3.5. MIN.............................................................................................................7
1.3.6. GROUP BY................................................................................................7
1.3.7. HAVING.....................................................................................................8
1.3.8. DISTINCT..................................................................................................8
1.4. Função de String ( SUBSTRING/SUBSTR )..................................................9
1.5. ORDER BY.......................................................................................................9
1.6. Joins...............................................................................................................10
1.6.1. INNER JOIN............................................................................................10
1.6.2. LEFT JOIN ou LEFT OUTER JOIN........................................................11
1.6.3. RIGHT JOIN or RIGHT OUTER JOIN.....................................................13
1.6.4. FULL JOIN or FULL OUTER JOIN.........................................................14
1.6.5. CROSS JOIN...........................................................................................15
1.7. Unions............................................................................................................15
1.7.1. UNION.....................................................................................................16
1.7.2. UNION ALL.............................................................................................16
1.8. SUB SELECTS...............................................................................................16
2. TCQuery................................................................................................................17
3. Embedded SQL.....................................................................................................19
2
SQL Básico
1. SQL
1.1. Select
Sintaxe:
<Nome da Coluna> => Informar o nome(s) da(s) coluna(s) da(s) tabela(s) que você
deseja apresentar/manipular em seu aplicativo. Se você informar o símbolo ‘*’
(Asterisco) o comando assumirá 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.
SELECT *
FROM SA1990
3
SQL Básico
Sintaxe: ROUND(Coluna,Precisão)
SELECT
round(round(C6_QTDVEN,4)*round(C6_PRCVEN,2),2)VALOR
FROM SC6990
Neste caso percebemos que na frente de cada nome de coluna existe um outro
nome referenciando a respectiva tabela que chamamos de apelido. Este nome
será utilizado como referência na resposta da query.
Obs: Para Banco de dados Oracle e Informix utilize dois pipes ‘|’ no lugar de
‘+’.
1.2. Clausula WHERE
Esta clausula é uma das mais importantes do comando SELECT, pois é a partir dela
que filtramos os dados da query. O filtro que estaremos informando é muito parecido
com a que utilizamos em uma função indregua(), em ADVPL.
Sintaxe:
SELECT [<apelido>.] <Nome da Coluna> [<Nome de Retorno>], n....
FROM <Nome da Tabela> [<apelido>], n ...
WHERE <Condição de filtro>
<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ê pode utilizar os seguintes operadores:
4
SQL Básico
= Igualdade
> Maior que
< Menor que
>= Maior que ou igual a
<= Menor que ou igual a
<> Diferente
!= Diferente
!< Não menor a
!> Não maior a
AND Verdadeiro se ambas expressões forem verdadeiras
OR Verdadeiro se qualquer expressão for verdadeira
BETWEEN Verdadeiro se a expressão está 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 outra 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_ <> '*'
5
SQL Básico
O objetivo principal das funções de agregação é criar colunas de acumuladores de um
determinado agrupamento definido pela cláusula group by. Se esta cláusula não for
informada o retorno será sempre uma linha.
1.3.1. SUM
SELECT SUM(A1_SALDUP)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
1.3.2. COUNT
Esta função totaliza o número de linhas na tabela, utlizando filtro para tal. Se
for informado o nome de uma coluna, a função contará apenas as linhas que
não estiverem com seu conteúdo nulo..
SELECT COUNT(*)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
SELECT COUNT(A1_FILIAL)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
6
SQL Básico
1.3.3. AVG
SELECT AVG(A1_SALDUP)
FROM SA1990
WHERE D_E_L_E_T_ <> ‘*’
1.3.4. MAX
SELECT MAX(R_E_C_N_O_)
FROM SA1990
1.3.5. MIN
SELECT MIN(C6_EMISSAO)
FROM SC6990
WHERE C6_CLI = ‘ 123456’
AND D_E_L_E_T_ <> ‘*’
1.3.6. GROUP BY
Ex. Select para obter valor total de pedidos por cliente e data
7
SQL Básico
WHERE D_E_L_E_T_ <> ‘*’
GROUP BY C6_CLI, C6_LOJA, C6_EMISSAO
1.3.7. HAVING
Esta cláusula tem por finalidade filtrar os dados que estão numa condição de
agrupamento. Apesar de ser uma cláusula de filtro (semelhante à cláusula
where), ela é dependente da cláusula group by.
1.3.8. DISTINCT
Ex. Select para obter código das filiais com linhas existentes (válido
para tabela com X2_MODO = ‘E’)
8
SQL Básico
Esta função é idêntica a função SUBSTR usada em ADVPL, e pode ser utilizada em
qualquer ponto do select onde informamos uma coluna.
1.5. ORDER BY
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
9
SQL Básico
Note que neste exemplo não é necessário informar a expressão ASC, para
obter o resultado de forma crescente.
Esta operação é uma das mais poderosas expressões de um comando select, pois
com ela podemos relacionar tabelas obtendo informações cruzadas. Este comando
pode ser escrito de duas formas, porém alguns bancos suportam apenas uma delas.
Estaremos apresentado esta forma e comentaremos suas diferenças.
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.
10
SQL Básico
FROM SC5990 SC5, SA1990 SA1, SA3990 SA3
WHERE SC5.C5_FILIAL = '01'
AND SA1.A1_FILIAL = ' '
AND SA3.A3_FILIAL = ‘01’
AND SC5.C5_CLIENTE = SA1.A1_COD <= Define o rel.SC5-
>SA1
AND SC5.C5_LOJACLI = SA1.A1_LOJA <= Define o rel.SC5-
>SA1
AND SA1.A1_VEND = SA3.A3_COD <= Define o rel.SA1-
>SA3
AND SC5.D_E_L_E_T_ <> '*'
AND SA1.D_E_L_E_T_ <> '*'
11
SQL Básico
AND SA1.D_E_L_E_T_ <> '*'
12
SQL Básico
AND SA1.D_E_L_E_T_ <> '*'
13
SQL Básico
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.
Exemplo para o Banco MSSQL Server e Sybase
14
SQL Básico
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.
15
SQL Básico
Ex. Select para retornar todos os clientes da empresa 01 e da empresa
02 desconsiderando duplicidades
1.7.1. UNION
Sub-Selects é utilizado na clausula where onde pode ser utilizado para fazer relação
de verificação de um determinado dado da tabela original com várias linhas de uma
outra tabela sem obrigatoriamente ser parte integrante de um join.
16
SQL Básico
AND SC6.C6_NUM =
SC5.C5_NUM
AND SC6.C6_PRODUTO = ‘X’
AND SC6.D_E_L_E_T_ <> ‘*’ )
AND SC5.D_E_L_E_T_ <> '*'
AND SA1.D_E_L_E_T_ <> '*'
2. TCQuery
17
SQL Básico
Parâmetros:
Observações
A Work Area criada com o comando TCQUERY é READ-ONLY, portanto não é
permitido o uso de APPEND's ou REPLACE's.
Exemplo:
//Abre a tabela de Clientes em uma nova WorkArea
cQuery := "SELECT a.codigo, b.nome FROM CLIENTES a, CLIDATA b "
cQuery += "WHERE a.CODIGO = b.CODIGO ORDER BY CODIGO,NOME "
TCQUERY cQuery ALIAS CLIENTES NEW VIA "TOPCONN"
dbGoTop()
While !Eof()
ALERT(CODIGO+"|"+NOME)
dbSkip()
end
cQuery := 'SELECT SUM(VALOR),SUM(SALDO) FROM CUSTOMER'
TCQUERY cQuery NEW VIA "TOPCONN"
ALERT(CValToChar(COLUMN1)+"|"+CValToChar(COLUMN2))
// COLUMN1 - Somatoria dos valores
// COLUMN2 - Somatoria dos saldos
18
SQL Básico
3. Embedded SQL
O objetivo do Embedded SQL é facilitar a escrita e leitura de queries. Para isso, foi
definida uma sintaxe para que se possa escrever a query diretamente no código
AdvPL, sem a necessidade de ficar concatenando pedaços de string para compor a
string final.
Disponibilidade do recurso
Este recurso está disponível nos produtos Microsiga Protheus 10 e 11.
A utilização do Embedded SQL divide-se em:
Compilação de código-fonte.
Execução de código-fonte.
Para compilar um código-fonte com o código escrito no formato Embedded, deve-se
utilizar o produto Microsiga Protheus, com build igual ou superior a 7.00.050721P, em
um ambiente com repositório para TOTVS | DBAccess (RPODB=TOP). A utilização
deste recurso, também depende da atualização da LIB.
Exemplo básico - Código-fonte atual
cQuery : 'SELECT SE2.E2_PREFIXO,SE2.E2_NUM '
cQuery += 'FROM '+RetSqlTable('SE2')+' SE2,'+RetSqlTable('QEK')+'
QEK '
cQuery += 'WHERE SE2.E2_FILIAL= '+xfilial('SE2')+' AND '
cQuery += 'SE2.E2_PREFIXO<> ''+cPrefixo+'' AND '
cQuery += 'SE2.D_E_L_E_T_ = ' ' '
cQuery += 'ORDER BY '+RetSqlOrder('SE2')
dbUseArea(.T.,'TOPCONN',TcGenQry(,,cQuery),'E2TEMP',.T.,.T.)
TCSetField('E2TEMP','E2_EMISSAO','D',8,0)
%noparser%
SELECT SE2.E2_PREFIXO,SE2.E2_NUM
FROM %table:SE2% SE2,%table:QEK% QEK
WHERE SE2.E2_FILIAL= %xfilial:SE2% AND
SE2.E2_PREFIXO<> %exp:cPrefixo% AND
SE2.%notDel%
ORDER BY %Order:SE2%
EndSql
19
SQL Básico
Qualquer instrução colocada entre BeginSQL ... EndSQL, que não seja uma
expressão %...%, será inserida na query que será enviada para o banco de
dados, de forma literal.
Variáveis, expressões e funções aparecem iniciando com %exp:%.
Em column deve-se especificar campos da query que são do tipo de dado
data, lógico ou numérico (DATE, LOGIC, NUMBER). Esta linha é trocada por
chamadas à função TCSetField().
%noparser% indica que a query não deve passar pela função ChangeQuery()
antes de ser enviada ao banco de dados. Caso não especificado, o padrão é a
string da query ser passada automaticamente pela função ChangeQuery().
%table:% é substituída por RetSqlName().
%notDel% é substituída por D_E_L_E_T_=' '.
%Order:% é substituída por SqlOrder (->(IndexKey())).
1º Opção:
%Order: % traduzido para SqlOrder(->(IndexKey()))
2º Opção:
%Order: , % traduzido para SqlOrder(->(IndexKey()))
3º Opção:
%Order: , % traduzido para SqlOrder(->(DBNickIndexKey()))
Limitação
Não é permitido incluir funções no meio do código embedded. Se precisar, o valor
deve ser guardado em uma variável antes do início do BeginSQL.
Exemplo
tam_cp := GetE2ValorSize()
BeginSql
alias 'E2TEMP'
column E2_EMISSAO as Date,
E2_VALOR as Numeric(tam_cp,2)
. . .
EndSql
Erros de compilação
20
SQL Básico
Caso seja utilizado algum argumento inválido para especificar as colunas ou erros de
sintaxe nas expressões que serão transformadas para montagem da query, a
compilação do código-fonte é interrompida com a ocorrência Syntax Error, informando
a linha em que a primeira ocorrência foi encontrada.
Erros de execução
Query Argument Error: Alias [XXX] already in suse.
Caso a instrução BeginSQL especifique um alias que já esteja aberto (em uso), a
aplicação é abortada com ocorrência de erro fatal, informando em XXX o alias
utilizado.
Type Mismach on +
Esta ocorrência, se reproduzida, informará na pilha de chamadas o número da linha do
código-fonte correspondente à instrução EndSQL. Essa ocorrência ocorre caso
alguma função intermediária do engine do Embedded SQL, excluíndo-se as funções
especificadas na query com a sintaxe %exp:...%, retornar um conteúdo não caractere
que será acrescentado na query. Esta ocorrência é mais dificil de localizar, sendo útil
nestes casos a análise do arquivo temporário gerado pelo TOTVS | Development
Studio, no momento da compilação.
21
SQL Básico
%noparser%
SELECT SE2.E2_PREFIXO,
SE2.E2_NUM,
SE2.E2_FORNECE,
SE2.E2_LOJA,
SE2.E2_VALOR,
SE2.D_E_L_E_T_ DEL1,
QEK.D_E_L_E_T_ DEL2 ,
QEK.QEK_SKLDOC,
SE2.R_E_C_N_O_ SE2RECNO
FROM
%table:SE2% SE2,%table:qeK% QEK
WHERE
SE2.E2_FILIAL= %xfilial:SE2% AND
qek.%notDel% and
SE2.E2_PREFIXO<> %exp:cPrefixo% AND
SE2.E2_NUM<> %exp:(cAlias)->M0_CODIGO% AND
SE2.E2_NUM<>45 AND
SE2.E2_FORNECE=%exp:Space(Len(SE2->E2_FORNECE))% AND
SE2.E2_EMISSAO<>%exp:MV_PAR06% AND
SE2.E2_LOJA<>%exp:MV_PAR05% AND
SE2.E2_VALOR<>%exp:MV_PAR04% AND
qek.QEK_SKLDOC<>%exp:MV_PAR03% And
SE2.%notDel%
ORDER BY %Order:SE2,1%
EndSql
22
SQL Básico
__execSql('E2TEMP',' SELECT SE2.E2_PREFIXO,SE2.E2_NUM,
SE2.E2_FORNECE, SE2.E2_LOJA,SE2.E2_VALOR, SE2.D_E_L_E_T_ DEL1,
QEK.D_E_L_E_T_
DEL2 , QEK.QEK_SKLDOC, SE2.R_E_C_N_O_ SE2RECNO FROM
'+RetSqlName('SE2')+' SE2, '+RetSqlName('QEK')+' QEK WHERE
SE2.E2_FILIAL= '' +xFilial
('SE2')+'' AND qek.D_E_L_E_T_= ' ' and SE2.E2_PREFIXO<>
'+___SQLGetValue(CPREFIXO)+' AND SE2.E2_NUM<>
'+___SQLGetValue((CALIAS)
->M0_CODIGO)+' AND SE2.E2_NUM<>45 AND SE2.E2_FORNECE=
'+___SQLGetValue(SPACE(LEN(SE2->E2_FORNECE)))+' AND SE2.E2_EMISSAO<>
'+___SQLGetValue(MV_PAR06)+' AND SE2.E2_LOJA<>
'+___SQLGetValue(MV_PAR05)+' AND SE2.E2_VALOR<>
'+___SQLGetValue(MV_PAR04)+' AND
qek.QEK_SKLDOC<> '+___SQLGetValue(MV_PAR03)+' And SE2.D_E_L_E_T_= '
' ORDER BY '+
SqlOrder(SE2->(IndexKey(1))),{{'E2_EMISSAO','D',8,0},
{'E2_VALOR','N',tam_cp,2},{'QEK_SKLDOC','L',1,0}},.T.)
23