A better way of passing parameters to a TADOStoredProc (Delphi)

16,494

Solution 1

This doesn't cause a memory leak. stored_procedure will clean up its parameters. You can confirm this with FastMM by adding the following to your .dpr:

  ReportMemoryLeaksOnShutdown := True;

First, I'd get rid of the "with" statement. It can lead to more problems and less readable code.

I'd create a helper method that accepts a stored procedure, a parameter name and a parameter value, which will make your code more manageable.

AddParam(stored_procedure, '@SSN', edtSSN.text);
AddParam(stored_procedure, '@FirstName', edtFirstName.Text);
AddParam(stored_procedure, '@LastName', edtLastName.Text);
AddParam(stored_procedure, '@UserRID', GetRIDFromCombo(cbUser));

Solution 2

There's an accepted answer :-), but I want to point you to simpler and easier way to define and use the parameters with one line :

stored_procedure.Parameters.CreateParameter('SSN',ftString,pdInput,30,edtSSN.text);

It's simple and flexible, because you can define the input and output parameters with same line.

and from Delphi help:

function CreateParameter(const Name: WideString; DataType: TDataType;
    Direction: TParameterDirection; Size: Integer; 
    Value: OleVariant): TParameter;

Solution 3

ADO will create the parameters for you, you just need to call Refresh on the parameters object:

 SP.Connection := SqlConnection; // must be done before setting procedure name
 sp.ProcedureName := 'MyStoredProc';
 sp.Parameters.Refresh; // This will create the parameters for you as defined in SQL Server
 sp.Parameters.ParamByName('@SSN'').Value  := SSN; // params now exist

etc

If any parameters are output you will need to set them explicitly:

   sp.Parameters.ParamByName('@ReturnValue').Direction := pdInputOutput;
Share:
16,494
Earlz
Author by

Earlz

Hello there! My name's Jordan Earls, but most people online know me as "earlz". I'm the lead developer and a co-founder of the Qtum project which brings the Ethereum Virtual Machine (ie, the thing that makes Solidity contracts function) to a UTXO based blockchain similar to Bitcoin. I've been programming since I was 13 and am completely self-taught. Low-level code like assembly and pointer arithmetic is the fun stuff for me. I also make music when I have time even though it's usually awful. Most of my personal projects are open source and BSD licensed. The majority of them are at bitbucket with the rest of them being listed on github Also, you can follow me on the twitters @earlzdotnet

Updated on July 27, 2022

Comments

  • Earlz
    Earlz almost 2 years

    I am needing to convert a large amount of SQL queries into stored procedures. I have some code that updates about 20 or 30 values at one time in one Delphi procedure. I can handle creating a stored procedures to do such a thing. The problem is my way to pass parameters to stored procedures is very bulky like this:

        with stored_procedure do......
        Param := Parameters.AddParameter;
        Param.Name := '@SSN';
        Param.Value := edtSSN.text;
    
        Param := Parameters.AddParameter;
        Param.Name := '@FirstName';
        Param.Value := edtFirstName.Text;
    
        Param := Parameters.AddParameter;
        Param.Name := '@LastName';
        Param.Value := edtLastName.Text;
    
        Param := Parameters.AddParameter;
        Param.Name := '@UserRID';
        Param.Value:= GetRIDFromCombo(cbUser);
    

    I also am not sure if that causes a memory leak(is it necessary to free such TParameter objects?)

    Anyone have a better way of handling a large amount of parameters? (I can not use a new library. I must use ADO, and the SQL I use is MSSQL) (also, I'm NOT using ADO.net)

  • yellahd
    yellahd almost 15 years
    I didn't know that existed. Thanks for sharing!
  • benwills
    benwills almost 15 years
    Thanks Bruce & Rob, That's the beauty of SO, I have learned many things for Delphier here, and trying to share what I know with others :-)
  • Earlz
    Earlz almost 15 years
    That is quite handy, though I still prefer the first way as it is simpler for a large amount of only input parameters
  • DiGi
    DiGi almost 14 years
    This is nice but it is working only if procedure is in connection's default database. There is a bug in ADO that destroy parameters if you use DifferentDatabase.Owner.ProcedureName
  • Tony
    Tony over 12 years
    I have also found that .Refresh does not always work, even within the same database.owner. I have not found any pattern to when it works and when it doesn't, but when it doesn't I get and error like "Parameter '@SearchText' not found." when I use .ParamByName. That same call works 99.9% of the time. Adding params manually seems to bypass the problem.
  • Kiril Hadjiev
    Kiril Hadjiev over 5 years
    Thank you very much. I was having troubles with parameters of type TDate and TDateTime, because sp.parameters.refresh creates parameters with dataType of WideString instead of TDate.