Clipper On Line • Ver Tópico - Chamando procedure SQL

Chamando procedure SQL

Discussão sobre SQL

Moderador: Moderadores

 

Chamando procedure SQL

Mensagempor JoséQuintas » 04 Set 2021 18:51

Tava aqui pensando.... como integrar melhor as stored procedures com o Harbour?

   :ExecuteCmd( "call ze_jptabcategoriaLicencaExclui(" + NumberSQL( nIdCategoria ) + "," + NumberSQL( nIdLicenca ) + ")" )


Depois pensei.... porque não uma função intermediária?

ze_TabCategoriaLicencaExclui( nIdCategoria, nIdLicenca )
...
FUNCTION ze_TabCategoriaLicencaExclui( nIdCategoria, nIdLicenca )
   :ExecuteCmd( "call ze_jptabcategoriaLicencaExclui(" + NumberSQL( nIdCategoria ) + "," + NumberSQL( nIdLicenca ) + ")" )
   RETURN Nil


Mas vai ter muito criar conexão ou algo parecido.

FUNCTION ExecuteSQLProcedure( ... )

   LOCAL cnSQL := ADOClass():New( AppConexao() )
   LOCAL cSQL, aList

   aList := hb_AParams()
   // monta a chamada de SQL e execute
   ...


Não valida o nome da procedure? mas... também não valida o texto do comando SQL, então dá no mesmo
Pode até servir para casos com e sem retorno.

Apesar de parecer quase a mesma coisa, fica melhor para o fonte.

   :ExecuteCmd( "call ze_jptabcategoriaLicencaExclui(" + NumberSQL( nIdCategoria ) + "," + NumberSQL( nIdLicenca ) + ")" )


ExecuteSQLProcedure( "ze_jptabcategoriaLicencaExclui", nIdCategoria, nIdLicenca )


A função de executar procedure faria a conversão dos parâmetros, conforme o tipo.
Fonte mais limpo.

Vou amadurecer essa idéia.
Dá até pra validar o nome das procedures, pra ver se existem mesmo
Um campo array STATIC, assim numa checagem seguinte basta olhar se está no array.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 04 Set 2021 19:34

Nessas horas dá um nó na cabeça.

Seria melhor se o banco de dados tivesse uma API de acesso direto as procedures/functions?
Mas aí o SQL cai por terra.... seria melhor um objeto.

Mas o objeto cai por terra, quando lembramos que as IDEs para o Harbour não validam objetos.

É de ficar doido, mas são possibilidades... é disso que nascem novas opções.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 05 Set 2021 04:42

   cnSQL:ExecuteProcedure( "ze_PedidoCalculo", nIdPedido )

   //WITH OBJECT cnSQL
      //cnSQL:ExecuteCmd( "CALL ze_PedidoCalculo(" + NumberSQL( nIdPedido ) + ")" )
   //ENDWITH


Coloquei na classe ADO e vamos em frente.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 05 Set 2021 07:48

Esta com mais parâmetros;

   cnSQL:ExecuteProcedure( "ze_PedidoProdutoBaixaEstoque", nIdItPed, dData, ;
         nNumNotFis, cDeposito, nSomaTira, LogInfo() )

   WITH OBJECT cnSQL
      :Execute( "CALL ze_PedidoProdutoBaixaEstoque( " + ;
         NumberSQL( nIdItPed ) + ", " + DateSQL( dData ) + ", " + ;
         NumberSQL( nNumNotFis ) + ", " + StringSQL( cDeposito ) + ", " + ;
         NumberSQL( nSomaTira ) + ", " + StringSQL( LogInfo() ) + ")" )
   ENDWITH


Deixei execute, porque no resto está execute, mas pensei em CallProcedure, ou somente :Call
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 05 Set 2021 16:10

Acabei alterando, pra ter os mesmos recursos que já tenho.

METHOD ExecuteCmdProcedure( ... ) CLASS ADOClass

   LOCAL cSQL, aItem, aList := hb_AParams()

   cSQL := "CALL " + aList[ 1 ]
   hb_ADel( aList, 1, .T. )

   cSQL += "("
   FOR EACH aItem IN aList
      cSQL += ValueSQL( aItem )
      cSQL += iif( aItem:__ENumIsLast(), "", "," )
   NEXT
   cSQL += ")"
   ::ExecuteCmd( cSQL )

   RETURN Nil

METHOD ExecuteProcedure( ... ) CLASS ADOClass

   LOCAL cSQL, aItem, aList := hb_AParams()

   cSQL := "CALL " + aList[ 1 ]
   hb_ADel( aList, 1, .T. )

   cSQL += "("
   FOR EACH aItem IN aList
      cSQL += ValueSQL( aItem )
      cSQL += iif( aItem:__ENumIsLast(), "", "," )
   NEXT
   cSQL += ")"
   ::Execute( cSQL )

   RETURN Nil


Hoje tenho Execute() e ExecuteCmd()
Uma considera o recordset principal, e a outra cria um alternativo.
Então fiz igual pra procedure, porque em alguns casos, ela não deve interferir no recordset principal.

Tipo....

WITH OBJECT cnSQL
   :Execute( "comando" )
   DO WHILE ! :Eof()
      :ExecuteCmd( "ddddd" )
      :MoveNext()
   ENDDO
   :CloseRecordset()
END WITH


No caso acima, o :ExecuteCmd() não causa interferência no recordset que já está aberto.
Apesar do nome, ela pode retornar recordset, mas independente do que já está em uso.

Lembrando: eu misturo conexão e recordset, numa única classe, pra facilitar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 05 Set 2021 16:28

stored.png


Parece até que o MySQL ficou integrado ao aplicativo, dispensando conversões.
Mas só parece, continua tudo igual antes.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 05 Set 2021 16:33

O :Execute() da imagem anterior, esqueci de apagar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 08 Set 2021 06:50

Aqui mais interessante.

Fonte anterior Harbour:

      WITH OBJECT cnSQL
         :cSQL := "SELECT * FROM JPITPED WHERE IPPEDIDO = " + NumberSQL( nIdPedidoJuntar )
         :Execute()
         DO WHILE ! :Eof()
            IF ADORecCount( "JPITPED", "IPPEDIDO = " + NumberSQL( nIdPedido ) + " AND IPPRODUTO = " + NumberSQL( :Number( "IPPRODUTO" ) ) ) == 0
               :QueryCreate()
               :QueryAdd( "IPPEDIDO", StrZero( nIdPedido, 6 ) )
               :QueryAdd( "IPPRODUTO", StrZero( :Number( "IPPRODUTO" ), 6 ) )
               :QueryAdd( "IPQTDE", :Number( "IPQTDE" ) )
               :QueryExecuteInsert( "JPITPED" )
            ELSE
               :ExecuteCmd( "UPDATE JPITPED SET IPQTDE = IPQTDE + " + NumberSQL( :Number( "IPQTDE" ) ) + ;
                  " WHERE IPPEDIDO = " + NumberSQL( nIdPedido ) )
            ENDIF
            :MoveNext()
         ENDDO
         :CloseRecordset()
      ENDWITH


fonte atual:

      cnSQL:ExecuteCmdProcedure( "ze_PedidoJuntar", nIdPedido, nIdPedidoJuntar )


procedure:

CREATE PROCEDURE ze_PedidoJuntar( nIdPedido INT(11), nIdPedidoJuntar INT(11) )

BEGIN

DECLARE nIdProduto INT(11);
DECLARE nQtde, nPrePed DECIMAL(16,4);

DECLARE nCursorEOF INT(11) DEFAULT 0;
DECLARE SP_CURSOR CURSOR FOR
   SELECT IPPRODUTO, IPQTDE, IPPREPED
   FROM JPITPED
   WHERE IPPEDIDO = nIdPedidoJuntar;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET nCursorEOF = 1;

OPEN SP_CURSOR;

THIS:WHILE nCursorEOF <> 1 DO
   FETCH SP_CURSOR INTO nIdProduto, nQtde, nPrePed;
   IF nCursorEOF = 1 THEN
      LEAVE THIS;
   END IF;
   IF ( SELECT COUNT(*) FROM JPITPED WHERE IPPEDIDO = nIdPedido AND IPPRODUTO = nIdProduto ) != 0 THEN
      UPDATE JPITPED SET IPQTDE = IPQTDE + nQtde WHERE IPPEDIDO = nIdPedido AND IPPRODUTO = nIdProduto;
   ELSE
      INSERT
      INTO JPITPED ( IPPEDIDO, IPPRODUTO, IPQTDE, IPPREPED )
      VALUES ( nIdPedido, nIdProduto, nQtde, nPrePed );
   END IF;
END WHILE;

CLOSE SP_CURSOR;

END


Coloquei pra gravar o valor, mas vou repensar.
O problema seria permitir um preço não autorizado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Chamando procedure SQL

Mensagempor JoséQuintas » 08 Set 2021 14:56

Mais outro.

Era assim em Harbour:

         WITH OBJECT cnSQL
            :ExecuteCmdProcedure( "ze_PedidoRelaciona", nIdPedido, nIdPedidoRel, ::cOpc )
/*
            IF nIdPedidoRel == 0
               :QueryCreate()
               :QueryAdd( "PDPEDREL", StrZero( 0, 6 ) )
               :QueryAdd( "PDNOTREL", StrZero( 0, 9 ) )
               :QueryExecuteUpdate( "JPPEDIDO", "IDPEDIDO = " + NumberSQL( nIdPedido ) )
            ELSE
               :cSQL := "SELECT JPPEDIDO.*, JPITPED.*, JPNOTFIS.NFNOTFIS" + ;
                  " FROM JPPEDIDO" + ;
                  " LEFT JOIN JPITPED ON JPITPED.IPPEDIDO = JPPEDIDO.IDPEDIDO" + ;
                  " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
                  " WHERE IDPEDIDO = " + NumberSQL( nIdPedidoRel )
               :Execute()
               IF :Eof()
                  :QueryCreate()
                  :QueryAdd( "PDPEDREL", StrZero( 0, 6 ) )
                  :QueryAdd( "PDNOTREL", StrZero( 0, 9 ) )
                  :QueryExecuteUpdate( "JPPEDIDO", "IDPEDIDO = " + NumberSQL( nIdPedido ) )
               ELSE
                  :QueryCreate()
                  :QueryAdd( "PDPEDREL", StrZero( nIdPedidoRel, 6 ) )
                  :QueryAdd( "PDNOTREL", StrZero( ADOField( "NFNOTFIS", "N", "JPNOTFIS", "NFPEDIDO = " + NumberSQL( nIdPedidoRel ) ), 9 ) )
                  :QueryExecuteUpdate( "JPPEDIDO", "IDPEDIDO=" + NumberSQL( nIdPedido ) )
                  IF ::cOpc == "I"
                     :QueryCreate()
                     :QueryAdd( "PDVALSEG", :Number( "PDVALSEG" ) )
                     :QueryAdd( "PDVALOUT", :Number( "PDVALOUT" ) )
                     :QueryAdd( "PDVALEXT", :Number( "PDVALEXT" ) )
                     :QueryAdd( "PDVALFRE", :Number( "PDVALFRE" ) )
                     :QueryAdd( "PDVALDES", :Number( "PDVALDES" ) )
                     :QueryExecuteUpdate( "JPPEDIDO", "IDPEDIDO = " + NumberSQL( nIdPedido ) )
                     DO WHILE ! :Eof()
                        :QueryCreate()
                        :QueryAdd( "IPPEDIDO", StrZero( nIdPedido, 6 ) )
                        FOR EACH cField IN { "IPPRODUTO", "IPTRIBUT" }
                           :QueryAdd( cField, StrZero( :Number( cField ), 6 ) )
                        NEXT
                        FOR EACH cField IN { "IPCFOP", "IPPEDCOM", "IPLEIS", "IPORIGEM", "IPIPIICM", ;
                              "IPIPICST", "IPIPIENQ", "IPICMCST", "IPDIFCAL", "IPPISCST", "IPPISENQ", ;
                              "IPCOFCST", "IPCOFENQ" }
                           :QueryAdd( cField, :String( cField ) )
                        NEXT
                        FOR EACH cField IN { "IPPRECUS", "IPPREPED", "IPQTDE", "IPVALCUS", "IPGARANTIA", ;
                              "IPPRENOT", "IPVALADI", "IPVALFRE", "IPVALSEG", "IPVALOUT", "IPVALEXT", ;
                              "IPVALADU", "IPVALIOF", "IPVALDES", "IPVALPRO", "IPVALNOT", "IPIIBAS", ;
                              "IPIIALI", "IPIIVAL", "IPIPIBAS", "IPIPIALI", "IPIPIVAL", "IPICMBAS", ;
                              "IPICMALI", "IPICMRED", "IPICMVAL", "IPFCPALI", "IPFCPVAL", "IPICSBAS", ;
                              "IPICSALI", "IPICSVAL", "IPSUBIVA", "IPSUBBAS", "IPSUBRED", "IPSUBALI", ;
                              "IPSUBVAL", "IPDIFBAS", "IPDIFALIF", "IPDIFALIU", "IPDIFALII", "IPDIFVALI", ;
                              "IPDIFVALF", "IPPISBAS", "IPPISALI", "IPPISVAL", "IPCOFBAS", "IPCOFALI", ;
                              "IPCOFVAL", "IPISSBAS", "IPISSALI", "IPISSVAL" }
                           :QueryAdd( cField, :Number( cField ) )
                        NEXT
                        :QueryExecuteInsert( "JPITPED" )
                        :MoveNext()
                     ENDDO
                  ENDIF
               ENDIF
               :CloseRecordset()
            ENDIF
            SubPedidoClass():CalculaValores( nIdPedido )
*/
            :ExecuteCmdProcedure( "ze_PedidoCalculo", nIdPedido )
         ENDWITH


Agora fica no servidor, assim em SQL

CREATE PROCEDURE ze_PedidoRelaciona( nIdPedido INT(11), nIdPedidoRel INT(11), cOpcao VARCHAR(5) )

THIS:BEGIN

IF nIdPedidoRel = 0 THEN
   UPDATE
   JPPEDIDO SET
   PDPEDREL = '000000', PDNOTREL = '000000000'
   WHERE IDPEDIDO = nIdPedido;
   LEAVE THIS;
END IF;

IF ( SELECT IDPEDIDO FROM JPPEDIDO WHERE IDPEDIDO = nIdPedidoRel ) = 0 THEN
   UPDATE
   JPPEDIDO SET
   PDPEDREL = '000000', PDNOTREL = '000000000'
   WHERE IDPEDIDO = nIdPedido;
   LEAVE THIS;
END IF;

UPDATE
JPPEDIDO SET
PDPEDREL = LPAD( nIdPedidoRel, 6, '0' ),
PDNOTFIS = LPAD( COALESCE( ( SELECT NFPEDIDO FROM JPNOTFIS WHERE NFPEDIDO = nIdPedidoRel ), 0 ), 9, '0' )
WHERE IDPEDIDO = nIdPedido;

IF cOpcao != "I" THEN
   LEAVE THIS;
END IF;

UPDATE
JPPEDIDO
INNER JOIN JPPEDIDO AS B ON B.IDPEDIDO = nIdPedidoRel
SET
JPPEDIDO.PDVALSEG = COALESCE( B.PDVALSEG, 0 ),
JPPEDIDO.PDVALOUT = COALESCE( B.PDVALOUT, 0 ),
JPPEDIDO.PDVALEXT = COALESCE( B.PDVALEXT, 0 ),
JPPEDIDO.PDVALFRE = COALESCE( B.PDVALFRE, 0 ),
JPPEDIDO.PDVALDES = COALESCE( B.PDVALDES, 0 )
WHERE JPPEDIDO.IDPEDIDO = nIdPedido;

INSERT
INTO JPITPED
( IPPEDIDO, IPPRODUTO, IPTRIBUT,
IPCFOP, IPPEDCOM, IPLEIS, IPORIGEM, IPIPIICM,
IPIPICST, IPIPIENQ, IPICMCST, IPDIFCAL, IPPISCST, IPPISENQ,
IPCOFCST, IPCOFENQ,
IPPRECUS, IPPREPED, IPQTDE, IPVALCUS, IPGARANTIA,
IPPRENOT, IPVALADI, IPVALFRE, IPVALSEG, IPVALOUT, IPVALEXT,
IPVALADU, IPVALIOF, IPVALDES, IPVALPRO, IPVALNOT, IPIIBAS,
IPIIALI, IPIIVAL, IPIPIBAS, IPIPIALI, IPIPIVAL, IPICMBAS,
IPICMALI, IPICMRED, IPICMVAL, IPFCPALI, IPFCPVAL, IPICSBAS,
IPICSALI, IPICSVAL, IPSUBIVA, IPSUBBAS, IPSUBRED, IPSUBALI,
IPSUBVAL, IPDIFBAS, IPDIFALIF, IPDIFALIU, IPDIFALII, IPDIFVALI,
IPDIFVALF, IPPISBAS, IPPISALI, IPPISVAL, IPCOFBAS, IPCOFALI,
IPCOFVAL, IPISSBAS, IPISSALI, IPISSVAL )
SELECT
nIdPedido, IPPRODUTO, IPTRIBUT,
IPCFOP, IPPEDCOM, IPLEIS, IPORIGEM, IPIPIICM,
IPIPICST, IPIPIENQ, IPICMCST, IPDIFCAL, IPPISCST, IPPISENQ,
IPCOFCST, IPCOFENQ,
IPPRECUS, IPPREPED, IPQTDE, IPVALCUS, IPGARANTIA,
IPPRENOT, IPVALADI, IPVALFRE, IPVALSEG, IPVALOUT, IPVALEXT,
IPVALADU, IPVALIOF, IPVALDES, IPVALPRO, IPVALNOT, IPIIBAS,
IPIIALI, IPIIVAL, IPIPIBAS, IPIPIALI, IPIPIVAL, IPICMBAS,
IPICMALI, IPICMRED, IPICMVAL, IPFCPALI, IPFCPVAL, IPICSBAS,
IPICSALI, IPICSVAL, IPSUBIVA, IPSUBBAS, IPSUBRED, IPSUBALI,
IPSUBVAL, IPDIFBAS, IPDIFALIF, IPDIFALIU, IPDIFALII, IPDIFVALI,
IPDIFVALF, IPPISBAS, IPPISALI, IPPISVAL, IPCOFBAS, IPCOFALI,
IPCOFVAL, IPISSBAS, IPISSALI, IPISSVAL
FROM JPITPED
WHERE IPPEDIDO = nIdPedidoRel;

END


Fonte final Harbour:

         WITH OBJECT cnSQL
            :ExecuteCmdProcedure( "ze_PedidoRelaciona", nIdPedido, nIdPedidoRel, ::cOpc )
            :ExecuteCmdProcedure( "ze_PedidoCalculo", nIdPedido )
         ENDWITH
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18160
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes




Retornar para SQL

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 10 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro