PDA

View Full Version : Inserir parâmetros SQL



Renato.Antonacci
6-Apr-2022, 06:39 AM
Bom dia.

Estou com um problema neste trecho abaixo que estou batalhando desde segunda feira, mas não consigo entender o motivo do erro. Estou tentando implementar o uso de query's parametrizadas, porém o código abaixo, hora funciona, hora não funciona aleatoriamente, e não consigo identificar o motivo. Já fiz tudo que é imaginável nessa rotina abaixo e ela não funciona. Já descartei as possibilidades de erro de comunicação com o banco, erro nos dados, espaços, tamanho de campo, etc, etc, etc

Inclusive o código original do programa, que mostro no final desta mensagem funciona perfeitamente. Esta faltando alguma coisa que não consigo identificar, ou algum "pulo do gato" que não conheço.

Gostaria de saber se tem algum erro no código abaixo, e se tem alguma forma de exibir a query completa que foi enviada ao banco para poder depurar onde esta acontecendo o erro.

Qualquer dica será muito bem vinda.





Procedure ManterDados_PTC_Company String sTipoManutencao String sIDConexaoSQL tDados_PTC_Company vtDados_PTC_Company
Handle hoSQL hdbc hstmt
String sLinhaSQL sAux
Integer iCNPJ iRazao iEndereco iNumero iCompl iCEP iCidade iUF iFone iEmail iCodSys

//sTipoManutencao (I)= Inclusão (A)= Alteração
If (sTipoManutencao="I") Begin
Move "INSERT INTO ptc.PTC_Company" to sLinhaSQL
Move (sLinhaSQL*"(CNPJ, RazaoSocial, Endereco, Numero, Complemento, CEP, Cidade, UF, Fone, eMail, CodigoSistemaTogni)") to sLinhaSQL
Move (sLinhaSQL*"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);") to sLinhaSQL

//Posição dos coringas
Move 1 to iCNPJ
Move 2 to iRazao
Move 3 to iEndereco
Move 4 to iNumero
Move 5 to iCompl
Move 6 to iCEP
Move 7 to iCidade
Move 8 to iUF
Move 9 to iFone
Move 10 to iEmail
Move 11 to iCodSys
End
If (sTipoManutencao="A") Begin
Move "UPDATE ptc.PTC_Company" to sLinhaSQL
Move (sLinhaSQL*"Set RazaoSocial=?, Endereco=?, Numero=?, Complemento=?, CEP=?, Cidade=?, UF=?, Fone=?, eMail=?, CodigoSistemaTogni=?") to sLinhaSQL
Move (sLinhaSQL*"WHERE CNPJ=?;") to sLinhaSQL


//Posição dos coringas
Move 1 to iRazao
Move 2 to iEndereco
Move 3 to iNumero
Move 4 to iCompl
Move 5 to iCEP
Move 6 to iCidade
Move 7 to iUF
Move 8 to iFone
Move 9 to iEmail
Move 10 to iCodSys
Move 11 to iCNPJ
End

//*** Conectar ao Servidor de dados
Get Create U_cSQLHandleManager to hoSQL
Send SQLSetConnect of hoSQL "MSSQLDRV" ("DFCONNID="-Uppercase(sIDConexaoSQL))
Get SQLConnect of hoSQL "" "" to hdbc
If (hdbc<>0) Begin
Get SQLOpen of hdbc to hstmt
If (hstmt<>0) Begin


Send SqlSetParameter of hstmt iCNPJ (NFeRemoveSeparadores(vtDados_PTC_Company.sCNPJ))
Send SqlSetParameter of hstmt iRazao (trim(vtDados_PTC_Company.sRazaoSocial))
Send SqlSetParameter of hstmt iEndereco (trim(vtDados_PTC_Company.sEndereco))
Send SqlSetParameter of hstmt iNumero vtDados_PTC_Company.iNumero typeNumber
Send SqlSetParameter of hstmt iCompl (trim(vtDados_PTC_Company.sComplemento))
Send SqlSetParameter of hstmt iCEP (NFeRemoveSeparadores(vtDados_PTC_Company.sCEP))
Send SqlSetParameter of hstmt iCidade (trim(vtDados_PTC_Company.sCidade))
Send SqlSetParameter of hstmt iUF (trim(vtDados_PTC_Company.sUF))
Send SqlSetParameter of hstmt iFone (trim(vtDados_PTC_Company.sFone))
Send SqlSetParameter of hstmt iEmail (trim(vtDados_PTC_Company.seMail))
Send SqlSetParameter of hstmt iCodSys vtDados_PTC_Company.iCodigoSistemaTogni typeNumber


Send SQLExecDirect of hstmt sLinhaSQL
Send SQLClose of hStmt


End
Send SQLDisconnect of hDbc
End
Send Destroy_Object of hoSQL
End_Procedure




Abaixo o mesmo código sem a inserção dos valores via "SQLSetParameter" que esta funcionando, ou seja, com os mesmos dados:




If (SizeOfArray(sRetornoSelect)>0) Begin
//Já cadastrado, efetuar atualização
Move ("UPDATE ptc.PTC_Company SET RazaoSocial='"-TCOMPANY.Nome-"',Endereco='"-TCOMPANY.Endereco-"',Numero='"-TCOMPANY.NUMERO-"',Complemento='"-TCOMPANY.COMPL-"',CEP='"-NFeRemoveSeparadores(TCOMPANY.CEP)-"',Cidade='"-TCOMPANY.Cidade-"',UF='"-TCOMPANY.UF-"',Fone='"-TCOMPANY.FONE-"',eMail='"-TCOMPANY.EMAIL-"',CodigoSistemaTogni="-String(TCOMPANY.Codigo)-" WHERE CNPJ='"-NFeRemoveSeparadores(TCOMPANY.CNPJ)-"';") to sComandoSQL
Send ExecutaComandoSQL sComandoSQL sIDConexaoWEB
End
Else Begin
//Não cadastrou ainda, efetuar o cadastro
Move ("INSERT INTO ptc.PTC_Company (CNPJ,RazaoSocial,Endereco,Numero,Complemento,CEP, Cidade,UF,Fone,eMail,CodigoSistemaTogni) VALUES('"-NFeRemoveSeparadores(TCOMPANY.CNPJ)-"','"-TCOMPANY.Nome-"','"-TCOMPANY.Endereco-"','"-TCOMPANY.NUMERO-"','"-TCOMPANY.COMPL-"','"-NFeRemoveSeparadores(TCOMPANY.CEP)-"','"-TCOMPANY.Cidade-"','"-TCOMPANY.UF-"','"-NFeRemoveSeparadores(TCOMPANY.FONE)-"','"-TCOMPANY.EMAIL-"','"-String(TCOMPANY.Codigo)-"');") to sComandoSQL
Send ExecutaComandoSQL sComandoSQL sIDConexaoWEB
End

Samuel Pizarro
6-Apr-2022, 11:26 AM
qual o erro que vc recebe qdo falha ?

o erro eh sempre o mesmo, ou erros diferentes ?

Samuel Pizarro
6-Apr-2022, 11:39 AM
so olhando assim , e sem saber quai erro exatamente voce esta recebendo..

diria que deve ser campos "nulos" ou vazios nessas variaveis que esta setando os parametros.

talvez tenha que fazer algo do tipo...



Send SqlSetParameter of hstmt iFone If(trim(vtDados_PTC_Company.sFone) <> '' , trim(vtDados_PTC_Company.sFone), '' )

e assim por diante.. se for esse o caso claro..

so expeculaçao por enquanto..

Renato.Antonacci
6-Apr-2022, 11:46 AM
Então Samuel. Esse é o problema. Não apresenta nenhuma mensagem de erro. O erro deve estar acontecendo internamente ao aplicar os parâmetros na query. O SQLFetch apresenta 0 como resultado, e até li no help que ações de Insert,Update e Delete não geram mesmo retorno. Então, fiquei a deriva, sem como conseguir saber onde acontece o meu erro. Até por isso pensei em procurar uma forma de obter a query completa, já com os parâmetros inseridos e poder testa-la diretamente no Microsoft SQL Server Management Studio, mas já li em outro tópico que isso não é possível de ser feito também. Vou inserir aqui a tela do meu studio, parando para debugar na linha do SQLFetch. Observe as variáveis, instruções. Me parecem todas corretas, e devem esta mesmo, pois ao aplicar a instrução diretamente, sem ser através do SqlSetParameter, as informações são gravadas com sucesso.

[]s15333

Renato.Antonacci
6-Apr-2022, 11:53 AM
Entendi, é uma hipótese. Irei tentar como vc sugeriu. O problema esta obscuro, porque não tenho nenhum erro de retorno.

Já posto o resultado deste teste.

Samuel Pizarro
6-Apr-2022, 12:00 PM
se vc nao ta recebendo erro, tem algo errado.

vc esta executando isso numa BP, com display_error desligado ?

se um insert e update falha, vc obrigatoriamente tem que receber erro.. nao existe isso de nao receber erro..

se isso eh verdade, eh um bug, e vc deve reportar o caso...

-------
Sobre capturar a query final , isso realmente nao eh possivel, pois vc esta executando uma query parametriza..
no banco vc so vai ver que a query foi executada.. mas com o "?" marcadores no lugar dos valores.

No db2 ate tem como capturar os valores.. submetidos pela aplicacao. mas nao eh padrao , e precisa ligar um tipo de um trace/audit pra conseguir capturar isso. No MS-SQL deve ter algo equivalente, mas nao vai ser algo trivial de se fazer.
-----

O SQLFetch apresenta 0 como resultado
Fetch ? seu codigo nao tinha Fetch.. nao faz sentido executar Fetch pra uma operacao de Insert/Update.
Se vc quer pegar o numero de rows inseridas ou atualizadas, eh outro jeito de fazer.. no MSSQL vc precisa ligar um atributo no statement pra retornar isso como uma mensagem.
no forum tem varios perguntando sobre isso.. e tem exemplos la.

Samuel Pizarro
6-Apr-2022, 12:04 PM
hehehe...

ja descobri seu erro:

vc ta executando SQLExecDirect.. ao inves de Prepare/Exec
Pra queries parametrizadas, vc deve 1ro preparar o statement, (que eh a complicacao da query no banco) . SQLPrepare
depois vc seta os parametros. SqkSetParameter ...
e so depois executa.. SQLExecute e nao SQLExecDirect

segue esse exemplo ai.
Parameterized Queries (dataaccess.com) (https://docs.dataaccess.com/dataflexhelp/mergedProjects/DevelopmentGuide/Parameterized_Queries.htm)

como vc ta submetendo um execdirect, ele nao ta mandando os valores dos parametros ainda.. ele so mandou a query com os "?" , e o banco so compiolou sua query.. por isso vc nao recebe erro.
na verdade nao tem erro mesmo do lado do banco.

Samuel Pizarro
6-Apr-2022, 12:19 PM
PQP..

agora que vi que nessa pagina, o segundo exemplo ta fazendo exatamente o que vc fez.. entao vc deve ter copiado dai..

isso ta errado.. Nunva vi DirectExecution com query parametrizada.. a nao ser que o deiver da DAW tenha implementado uma gambiarra internamente.. o que nao acredito.
Pra mim, esse exemplo ta furado.

Renato.Antonacci
6-Apr-2022, 12:27 PM
Bingo, por isso um olhar de fora sempre é bom. Acha aquilo que não conseguimos enxergar (rsrs).

É dentro de uma BussinesProcess e o DisplayErrorState estava False. Agora tenho uma mensagem de erro:




C:\Sistema\Adm\Programs\ProjetoTeste.exe
Erro genérico. 22001 (0)--[Microsoft][ODBC Driver 17 for SQL Server]Truncamento Ó direita dos dados da cadeia de caracteres Connection handle = 1229, Statement handle = 1230


Erro: 12289
Fonte do erro = MSSQLDRV.ESQL.SQLExecDirect


MSG_SQLEXECDIRECT (6585) - oObject (1230) - at address 27190
MSG_MANTERDADOS_PTC_COMPANY (12399) - oClientArea (640) - at address 101431
MSG_MANTERDADOS_PTC_COMPANY (12399) - oEnviarCotacaoPreco_BP (704) - in native code
GET_FCARREGARDADOSPORTAL (12416) - oEnviarCotacaoPreco_BP (704) - at address 101928
MSG_ONPROCESS (6170) - oEnviarCotacaoPreco_BP (704) - at address 101604
MSG_DOPROCESS (6171) - oEnviarCotacaoPreco_BP (704) - at address 23774
MSG_ENVIARCOTACAOSELECIONADOS (12441) - oPrincipal_CJGrid (819) - at address 103015
MSG_ONCLICK (4659) - oOk_BT (814) - at address 102510
MSG_COMMAND (648) - oOk_BT (814) - in native code
[start] - at address 103808




Com relação ao Fetch, realmente no código não tem, porque eu já tinha lido no Help que não temos retorno para esse caso. Então eu coloquei agora nestas ultimas conversas na tentativa de obter algum retorno do problema, mas logicamente não obtive nenhum resultado.

Agora tenho que investigar o que é esse erro, que não conheço. Você conhece este erro?

Com relação ao trecho abaixo:



Se vc quer pegar o numero de rows inseridas ou atualizadas, eh outro jeito de fazer.. no MSSQL vc precisa ligar um atributo no statement pra retornar isso como uma mensagem.
no forum tem varios perguntando sobre isso.. e tem exemplos la.


Vou pesquisar sobre no Fórum, vai ser muito útil nessa tarefa que estou executando agora.

Obrigado por enquanto.

Samuel Pizarro
6-Apr-2022, 12:28 PM
cacetada...

parece que estou enganado.. apeasar de nunca ter usado isso desse jeito. sempre vi queries parametrizadas, sendo executadas com Prepare+Execute e nao com execDirect.

Mas fui atras da documentacao tanto do db2 quanto do MSSQL, e ambos suportam parametros no execDirect.
SQLExecDirect() - Execute a statement directly - IBM Documentation (https://www.ibm.com/docs/en/db2-for-zos/11?topic=functions-sqlexecdirect-execute-statement-directly)

The SQL statement string can contain parameter markers. A parameter marker is represented by a question mark (?) character, and it is used to indicate a position in the statement where an application-supplied value is to be substituted when SQLExecDirect() is called.

SQLExecDirect Function - ODBC API Reference | Microsoft Docs (https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlexecdirect-function?view=sql-server-ver15)

The application can include one or more parameter markers in the SQL statement. To include a parameter marker, the application embeds a question mark (?) into the SQL statement at the appropriate position. For information about parameters, see Statement Parameters.

bom..
pode ser que o driver da daw esteja bugado ai.. e nao esteja te retonrando o erro..

eu tentaria mudar pra Prepare/Execute , que eh o mais classico pra queries parametrizadas.

E se vc mudar, e passar a funcionar sempre. ou comecár a retornar erro.. vc comprava que o driver da daw ta bugado..

Renato.Antonacci
6-Apr-2022, 12:35 PM
PQP..

agora que vi que nessa pagina, o segundo exemplo ta fazendo exatamente o que vc fez.. entao vc deve ter copiado dai..

isso ta errado.. Nunva vi DirectExecution com query parametrizada.. a nao ser que o deiver da DAW tenha implementado uma gambiarra internamente.. o que nao acredito.
Pra mim, esse exemplo ta furado.


Sim, eu peguei o código do exemplo do Help. Irei usar as duas formas de execução. Com o arquivo de empresas (PTC_Company) que é executado apenas uma vez, então irei usar como no segundo exemplo do Help (SQLExecDirect). Já no caso das Cotações de preço, serão centenas em uma única execução, eu irei usar a primeira forma do exemplo, que otimiza o processamento.

Obrigado pela ajuda

Renato.Antonacci
6-Apr-2022, 01:41 PM
Resolvido!!!!!

Depois das dicas do Samuel, consegui corrigir o problema. Estava com dois problemas diferentes:

1- Estava em uma BussinessProcesss com a opção DisplayErrorState como False, que estava ocultando a mensagem de erro:

2- Depois que mostrou a mensagem de erro, consegui verificar que a minha versão do Driver de comunicação com o SQL estava desatualizado. Atualizei e acabaram os problemas

Obrigado pela ajuda.

Samuel Pizarro
6-Apr-2022, 03:04 PM
Sobre o erro:

Algum dos valores eh maior q a definição do campo. Nao cabe

Provavelmente, um dos campos string.

Samuel Pizarro
6-Apr-2022, 03:05 PM
Interessante...

Abcs