Postagem em destaque
- Gerar link
- Outros aplicativos
BlackTDN :: Tips & Tricks ~ ADVPL : Embedded SQL - Facilitador de queries
Segundo o TDN “Embedded SQL - Facilitador de queries” tem por objetivo “facilitar a escrita e leitura de queries” e, de fato, a leitura de um código em Embeddes SQL é muito melhor do que a concatenação de strings. Observe um exemplo simples para o MSSQL:
Query String |
1: #include "protheus.ch" 2: #include "tbiconn.ch" 3: #include "topconn.ch" 4: 5: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p> 6: 7: USER PROCEDURE NotSqlEmb() 8: 9: Local cQuery 10: 11: Local cCRLF := CRLF 12: Local cAlias 13: 14: RpcSetType(3) 15: PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01" 16: 17: cAlias := GetNextAlias() 18: 19: cQuery := "SELECT" + cCRLF 20: cQuery += " TOP 10 SA1.*" + cCRLF 21: cQuery += "FROM 22: cQuery += " " + RetSqlName("SA1") + " SA1 " + cCRLF 23: cQuery += "WHERE" + cCRLF 24: cQuery += " SA1.D_E_L_E_T_ = ' '" + cCRLF 25: 26: TCQUERY ( cQuery ) ALIAS ( cAlias ) NEW 27: 28: (cAlias)->( dbCloseArea() ) 29: 30: RESET ENVIRONMENT 31: 32: Return( NIL ) |
Embedded SQL |
1: #include "protheus.ch" 2: #include "tbiconn.ch" 3: 4: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p> 5: 6: USER PROCEDURE SqlEmb() 7: 8: Local cAlias 9: 10: RpcSetType(3) 11: PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01" 12: 13: cAlias := GetNextAlias() 14: 15: BEGINSQL ALIAS cAlias 16: %noParser% 17: SELECT 18: TOP 10 SA1.* 19: FROM 20: %table:SA1% SA1 21: WHERE 22: SA1.%notDel% 23: ENDSQL 24: 25: (cAlias)->( dbCloseArea() ) 26: 27: RESET ENVIRONMENT 28: 29: Return |
Mas nem tudo são “flores” e Embedded SQL, às vezes, dificulta ao invés de facilitar.
Um dos problemas conhecidos com Embedded SQL é o processo de depuração do código. Não conseguimos obter a “Query” antes de sua execução. Ao contrário da “Query String”: que nos permite obter o conteúdo integral da “Query” antes de sua execução. Permitindo-nos testá-la. Os exemplos abaixo, onde forçamos o erro, demonstram claramente isso:
Query String : Depuração |
1: #include "protheus.ch" 2: #include "tbiconn.ch" 3: #include "topconn.ch" 4: 5: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p> 6: 7: USER PROCEDURE NotSqlEmb() 8: 9: Local cQuery 10: 11: Local cCRLF := CRLF 12: Local cAlias 13: 14: RpcSetType(3) 15: PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01" 16: 17: cAlias := GetNextAlias() 18: 19: cQuery := "SELECT" + cCRLF 20: cQuery += " TOP 10 A1.*" + cCRLF 21: cQuery += "FROM 22: cQuery += " " + RetSqlName("SA1") + " SA1 " + cCRLF 23: cQuery += "WHERE" + cCRLF 24: cQuery += " SA1.D_E_L_E_T_ = ' '" + cCRLF 25: 26: TCQUERY ( cQuery ) ALIAS ( cAlias ) NEW 27: 28: (cAlias)->( dbCloseArea() ) 29: 30: RESET ENVIRONMENT 31: 32: Return( NIL ) |
A linha 20 contém um erro e, durante o processo de depuração basta inserirmos um “Break Point” na linha 26 para obtermos o conteúdo integral da “Query”.
Já para Embedded SQL isso não é possível. Uma vez que, logo após a montagem da “Query String” ENDSQL “força” a sua execução gerando uma exceção e finalizando o processo.
Tentativa de Depuração em código Embedded SQL. |
Para solucionar esse problema podemos usar o “Tratamento de Exceção” (que não resolve o fato da “Query String” sempre ser executada) mas nos permite obter o seu conteúdo logo após a execução.
Momento PowerShell: Uma coisa interessante no PowerShell é a cláusa WhatIf que nos permite testar a sintaxe de um comando.
Seria interessante não só para facilitar a depuração mas para personalizar a escrita. Vamos imaginar que utilizaremos o retorno da consulta para criar uma tabela temporária e, sobre essa tabela totalizar valores usando uma outra consulta. Usando Embedded SQL isso não é possível uma vez que a “Query” sempre será executada e teremos que executa-la novamente, e novamente … Um desperdício. |
[]s
иαldσ dj
- Gerar link
- Outros aplicativos
Comentários
Postagens mais visitadas
BlackTDN :: RLeg ~ Desvendando a Função ParamBox
- Gerar link
- Outros aplicativos
Protheus :: Chamando Funções do Menu Diretamente e sem a Necessidade de Login
- Gerar link
- Outros aplicativos
Fala Dj Naldo! Parabéns pelo blog! Sempre com conteúdo muito interessante.
ResponderExcluirSobre a depuração de Embedded SQL, pode-se colocar um ponto de parada logo após a instrução EndSql e utilizar a função GetLastQuery()
Ela retorna um array com a estrutura:
[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 .T., não foi utilizada ChangeQuery() na String original.
[5] nTimeSpend - Tempo, em segundos, utilizado para a abertura do Cursor.
Abraços!
Rafael, boa noite.
ResponderExcluirDesculpe falar, mas sua ideia só funciona se não houver erro na SQL. Fiz aqui de todo jeito, e a única forma foi usando a string mesmo. O sistema dá erro na linha endsql, o que impossibilita o retorno das variáveis pois a instrução não foi finalizada ainda.
Naldo, gostaria de saber como eu posso implementar meu proprio embedded SQL parassando a query para uma classe que tenho que gera os dados da consulta em um objeto.
ResponderExcluirGostaria de saber como eu posso obter o codigo que ficaria entre o beginSQLTESTE ate o EndSQLTeste e executar ao fim e retornar o objeto com os dados que eu quero resultar!