GARANTIR DESCONTO

Fórum Delphi - Problemas na passagem de parâmetros para Stored Procedures #508986

30/01/2015

0

Olá !

Estou trabalhando na migração de um sistema D5 para D2010, onde o código nativo é todo baseado no BDE, com Sql Server 2000.

Já fiz os ajustes para compilação, mas estou tendo problemas de execução... mais precisamente na passagem de parâmetros para as Stored Procedures.

O problema é bastante simples de entender... tenho, por exemplo, uma procedure ( chamada OpenLogon ) que registra o login do usuário no sistema.

São três parâmetros :

> @Logon = Código de Logon do usuário ( Char 5 )
> @Terminal = Nome do terminal de rede ( Char 25 )
> @SYS = Flag do tipo de sistema ( Boolean )

Quando executo pelo código nativo, via BDE ( componente TStoredProc ), os dois primeiros parâmetros são passados ERRADAMENTE para o Sql Server CONCATENADOS : exec dbo.sp_OpenLogon @Logon = 'logonterminal', @Terminal = NULL, @SYS = 0

Acarretando a falha no login !

Substituindo o componente por DBExpress ( componente TSQLStoredProc ), os dois primeiros parâmetros são passados CORRETAMENTE para o Sql Server SEPARADOS : exec [sp_openLogon] 'logon', 'terminal', 0

O login funciona normalmente !

Alguém já passou por isso ou tem uma ideia do que está acontecendo ?

O sistema é muito extenso e não tenho como migrar imediatamente tudo para DBExpress... preciso, primeiro, fazê-lo funcionar no Delphi2010 + BDE !

Qualquer ajuda é bem-vinda...

Obrigado,
Marcos P

Marcos P

Responder

Posts

30/01/2015

Marcos Silva

Olá,
Eu uso os componentes da palheta ADO, no caso o ADOStoredProc e nunca tive problemas.

Aqui um exemplo de uso:

  with StoredAuxiliar do
    begin
      Close;
      ProcedureName:= 'Nome da Procedure;1';
      Parameters.Refresh;
      Parameters.ParamByName('@Parametro').Value := X;
      Parameters.ParamByName('@Parametro').Value := X;
      Parameters.ParamByName('@Parametro').Value := X;
    try
      Prepared;
    	ExecProc;
      result := True;
    except
      result := False;
    end;
   end;


Não estou insinuando para trocar de componente é apenas para exemplificar, caso tenha alguma dúvida estou as ordens.
Responder

Gostei + 0

02/02/2015

Marcos P

Mssilva,

Obrigado por sua resposta !

Meu problema, contudo, é pontual no componente ( TStoredProc ) do BDE.

Tanto o ADO, como o DBExpress funcionam normalmente se adaptados no sistema.

Meu problema é que são centenas de units e não consigo fazer essa migração de imediato.

Você entendeu o erro que reportei ?

Já ficou algo do gênero ?
Responder

Gostei + 0

12/02/2015

Marcos Silva

Muito genérica sua pergunta, poderia pontuar cada problema?
Responder

Gostei + 0

19/02/2015

Marcos P

Mssilva,

Obrigado pela resposta e desculpe minha demora...

O trecho de código Delphi, abaixo :

      stOpenLogon.Close;

      stOpenLogon.ParamByName('@Logon').AsString := trim(qrUsuariosLogon.Value);
      stOpenLogon.ParamByName('@Terminal').AsString := getNameComputer;
      stOpenLogon.ParamByName('@SYS').asboolean := false;

      if(not stOpenLogon.Prepared) then
      stOpenLogon.Prepare;

      stOpenLogon.ExecProc;


Aplicado sobre a procedure Sql Server abaixo :
CREATE PROCEDURE sp_OpenLogon(@Logon char(5), 
@Terminal char(10), 
@SYS bit) AS
:


Implica em um erro de execução na SP, pois o Delphi passa a seguinte instrução ao Sql Server :
exec dbo.sp_OpenLogon @Logon = 'logonterminal', @Terminal = NULL, @SYS = 0


Observe que os dois parametros tipo CHAR, foram CONCATENADOS por algo fora do meu controle !

Além disso, estou obtendo problemas generalizados com a passagem de parâmetros :

> Tipos CHAR : onde estão sendo inseridos caracteres estranhos nas strings passada ao banco de dados.
> Tipos DATETIME : onde ocorre sobreposição nos formatos de data suportados pelo banco de dados ( mesmo com declaração explícita do formato no lado do Delphi )
> Tipos INT : quando não inicializados / declarados, são passados com valores absurdos ao banco de dados

Lembrando :

1. Delphi 2010 + Sql Server 2000
2. Os problemas são sempre nas conexões via BDE
3. Substituindo a conexão BDE por outra ( DbExpress ou ADO ), os parâmetros são passados normalmente.

Espero que, agora, tenha ficado um pouco mais detalhado.

Obrigado pela ajuda !
Responder

Gostei + 0

23/02/2015

Marcos P

Descobri o que ocorre com os problemas generalizados na passagem da parâmetros no código migrado ( D5 >>> D2010 ) !

Por exemplo, na construção abaixo :

   stRelatorio.Close;

   for i := 1 to stRelatorio.ParamCount - 1 do
     stRelatorio.Params[i].Clear;

     if not ckBanco.Checked then
       stRelatorio.ParamByName('@Banco').asstring := dblcBanco.KeyValue
     else stRelatorio.ParamByName('@Banco').asstring := '';
     *}


Quando o campo relacionado ao parâmetro é informado ( dblcBanco.KeyValue ), o delphi passa corretamente o parâmetro para o Sql Server.

Contudo, quando o campo não é informado, o "else" iguala o parâmetro à vazio.

No D5, isso funcional normalmente... sendo o parâmetro passado como um string vazia.

No D2010, isso não funciona... pois é inserido um ( ou mais ) caracter de controle no parâmetro.

A correção vem, pela eliminação do "else"... ou seja, fazendo : ParamByName.Clear ( que é o padrão inicial ), existe a garantia que o parâmetro será sempre passado como NULL, quando não informado.


   stRelatorio.Close;

   for i := 1 to stRelatorio.ParamCount - 1 do
     stRelatorio.Params[i].Clear;

     if not ckBanco.Checked then
       stRelatorio.ParamByName('@Banco').asstring := dblcBanco.KeyValue;
     *}


Basta, então, revisar o tratamento de NULL nos parâmetros da procedure e o problema está solucionado.

A causa disso o D2010, não tenho a menor ideia qual seja... mas, pelo menos, temos uma solução de contorno possível.

A questão inicial desse post, contudo, permanece sem resposta : porque no código abaixo os parâmetros "char" são passado concatenados quando enviados banco de dados ?

DELPHI
stOpenLogon.Close;
 
stOpenLogon.ParamByName('@Logon').AsString := trim(qrUsuariosLogon.Value);
stOpenLogon.ParamByName('@Terminal').AsString := getNameComputer;
stOpenLogon.ParamByName('@SYS').asboolean := false;
 
if(not stOpenLogon.Prepared) then
stOpenLogon.Prepare;
 
stOpenLogon.ExecProc;


SQL SERVER
exec dbo.sp_OpenLogon @Logon = 'logonterminal', @Terminal = NULL, @SYS = 0
Responder

Gostei + 0

08/04/2015

Marcos P

Depois de um longo período, segue a solução do problema... espero que seja útil no futuro !

A causa : Parâmetros passados como AsString para stored procedures, são indevidamente concatenados.

Solução : Trocar AsString...

stOpenLogon.ParamByName('@Logon').AsString := trim(qrUsuariosLogon.Value);
stOpenLogon.ParamByName('@Terminal').AsString := getNameComputer;


por "AsAnsiString"

stOpenLogon.ParamByName('@Logon').AsAnsiString := trim(qrUsuariosLogon.Value);
stOpenLogon.ParamByName('@Terminal').AsAnsiString := getNameComputer;
Responder

Gostei + 0

09/04/2015

Thiago Santana

Marcos, só vi teu tópico agora, mas esses problemas ocorrem pelo fato do Delphi 5 ter uma codificação de caracteres diferente do Delphi 2010.
A correção para o seu problema é justamente esse que você postou. :)
Responder

Gostei + 0

17/04/2015

Marcos P

Caso seja necessário passar parâmetros ao banco com tamanho superior a 255 caracteres, que é o tamanho máximo do AnsiString, converter o parâmetro para Memo.

Por exemplo...

De...
      qrGravaPck.ParamByName('sPack').AsString:= Pack;
    *}

Para...
      qrGravaPck.ParamByName('sPack').AsMemo:= Pack;
    *}
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar