Fórum Delphi - Problemas na passagem de parâmetros para Stored Procedures #508986
30/01/2015
0
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
Curtir tópico
+ 0Posts
30/01/2015
Marcos Silva
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.
Gostei + 0
02/02/2015
Marcos P
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 ?
Gostei + 0
12/02/2015
Marcos Silva
Gostei + 0
19/02/2015
Marcos P
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 !
Gostei + 0
23/02/2015
Marcos P
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
Gostei + 0
08/04/2015
Marcos P
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;
Gostei + 0
09/04/2015
Thiago Santana
A correção para o seu problema é justamente esse que você postou. :)
Gostei + 0
17/04/2015
Marcos P
Por exemplo...
De...
qrGravaPck.ParamByName('sPack').AsString:= Pack;
*}
Para...
qrGravaPck.ParamByName('sPack').AsMemo:= Pack;
*}
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)