Você está na página 1de 3

Embedded SQL - Facilitador de queries

Embedded SQL - Facilitador de queries


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.

Abrangência

ERP 10 e 11

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_E
MISSAO','D',8,0)

Exemplo básico - Utilizando Embedded SQL


BeginSql alias 'E2TEMP' column E2_EMISSAO as Date %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

Características operacionais - Sintaxe


O bloco de código onde será escrito o comando SELECT, deve sempre ser iniciado com BeginSQL Alias e finalizado com EndSQL.
Partes do código-fonte que devem ser substituídos aparecem entre os sinais de % (porcentagem). Essas expressões possuem
tratamentos especiais em momento de execução.
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())).
Há 3 opções para o %Order:

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
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.

EndSQL (Error C2001 Syntax error:)


Caso a ocorrência de compilação aponte diretamente para a linha do código-fonte, em que está escrita a instrução EndSQL, verifique se existe
algum espaço em branco ou tabulação, a partir do início da linha, antes da instrução EndSQL. A versão atual deste ambiente não suporta esta
declaração, exigindo que a instrução EndSQL seja alinhada à esquerda do código-fonte, sem espaço ou tabulações.

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.

Query Argument Error: Invalid Value Type [X]


Caso alguma expressão informada na query, através da tag %exp:...%, retorne um valor do tipo diferente de C (Caracter), D (Data), N
(Numérico) ou L (Lógico), a aplicação é abortada com ocorrência de erro, em que o tipo do argumento inesperado é apresentando em
[X].

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.

Help NOFUNCW - Função __EXECSQL


Caso um código-fonte Embedded SQL seja executado em um repositório que não tenha sido atualizado ou que não seja um repositório
para o ambiente TOTVS | DBAccess (RPODB=TOP), a aplicação exibirá essa ocorrência, indicando que a função interna de execução
da query não está presente no ambiente. Verifique se a LIB está atualizada e se o RPO, em uso, pertence a um ambiente TOTVS
| DBAccess.

Característica operacionais - Depuração


Dada a montagem da query, não é possível depurar o bloco do código/codeblock compreendido entre as intruções BeginSQL e EndSQL, não
sendo considerados pontos de parada de depuração (BreakPoints), caso colocados neste intervalo do código. A colocação de pontos de parada
deve ser realizada antes ou depois desse bloco.

Função auxiliar - GetLastQuery()


Após a abertura do cursor, no alias especificado, a função GetLastQuery() retorna um array, com 5 elementos, onde estão disponíveis as
seguintes informações sobre a query executada.

[1] cAlias - Alias usado para abrir o cursor.


[2] cQuery - Query executada.
[3] aCampos - Array de campos com critério de conversão especificados.
[4] lNoParser - Caso verdadeiro (.T.), não foi utilizada a função ChangeQuery() na string original.
[5] nTimeSpend - Tempo, em segundos, utilizado para abertura do cursor.

Exemplo mais completo


AdvPL
BeginSql alias 'E2TEMP' column E2_EMISSAO as Date, E2_VALOR as Numeric(tam_cp,2) column QEK_SKLDOC As Logical %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

Código-fonte gerado pelo pré-compilador (PPO)


__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.)

Você também pode gostar