2012-02-14 17 views
5

Abbiamo portato il codice a Delphi XE2 e abbiamo bisogno di cambiare i componenti di accesso ai dati da ODBCExpress di terze parti che non è più in commercio, a TSQLQuery di dbExpress. query SQLÈ possibile utilizzare TSQLQuery di dbExpress? come parametri?

Abbiamo parametrizzata come ad esempio:

sSQL := 
    'UPDATE ZTestData SET '+ 
    ' StringField =?, '+ 
    ' IntField = ?, '+ 
    ' DecimalField = ?, '+ 
    ' BooleanField = ?, '+ 
    ' DateTimeField = ?, '+ 
    ' TextField = ? '+ 
    ' WHERE UniqueID = 3'; 

se usiamo il seguente codice:

var 
    qry:TSQLQuery; 
begin 
    qry.Close; 
    qry.SQL.Text := sSQL; 
    ShowMessage(IntToStr(qry.Params.Count)); 
end; 

Esso restituisce 0, quindi non siamo in grado di ottenere le associazioni di lavoro, ma se cambiamo sSQL a:

sSQL := 
    'UPDATE ZTestData SET '+ 
    ' StringField =:Param1, '+ 
    ' IntField = :Param2, '+ 
    ' DecimalField = ?, '+ 
    ' BooleanField = ?, '+ 
    ' DateTimeField = ?, '+ 
    ' TextField = ? '+ 
    ' WHERE UniqueID = 3'; 

Riporta 2.

Sarà una grande seccatura cambiare tutte le query SQL nella nuova sintassi dei parametri. È comunque necessario che TSQLQuery riconosca il? sintassi?

Vedo che DBXCommon.TDBXCommand utilizza il? sintassi:

http://www.andreanolanusse.com/en/parameterized-queries-with-dbexpress-dbx-framework/

Ma vorrebbe dire buttare via il nostro codice che utilizza TSQLQuery. Qual è il modo più rapido/semplice per risolvere questo problema? Qual è la differenza tra TSQLQuery e TDBXCommand comunque, in termini di ciò che è rilevante per me?

risposta

0

Ho finito per scrivere un metodo per convertire i punti interrogativi nella query in: parametri di stile param1. È interessante notare che Delphi ha un metodo DB.TParams.ParseSQL che converte i parametri in punti interrogativi. Questo metodo è fondamentalmente un rovescio di quello.

function THstmt.AddParamsToSQL(const SQL: String): String; 
var 
    LiteralChar: Char; 
    CurPos, StartPos, BeginPos: PChar; 
    ParamCount:Integer; 
begin 
    //Locates the question marks in an SQL statement 
    //and replaces them with parameters. 
    //i.e. the reverse of DB.TParams.ParseSQL 

    //This method is base on DB.TParams.ParseSQL 

    //For example, given the SQL string 
    //SELECT * FROM EMPLOYEES WHERE (ID = ?) AND (NAME = ?) 

    //ParseSQL returns the string 
    //SELECT * FROM EMPLOYEES WHERE (ID = :1) AND (NAME = :2) 

    Result := ''; 

    ParamCount := 0; 
    StartPos := PChar(SQL); 
    BeginPos := StartPos; 
    CurPos := StartPos; 
    while True do 
    begin 
    // Fast forward 
    while True do 
    begin 
     case CurPos^ of 
     #0, '?', '''', '"', '`': 
      Break; 
     end; 
     Inc(CurPos); 
    end; 

    case CurPos^ of 
     #0: // string end 
     Break; 
     '''', '"', '`': // literal 
     begin 
     LiteralChar := CurPos^; 
     Inc(CurPos); 
     // skip literal, escaped literal chars must not be handled because they 
     // end the string and start a new string immediately. 
     while (CurPos^ <> #0) and (CurPos^ <> LiteralChar) do 
      Inc(CurPos); 
     if CurPos^ = #0 then 
      Break; 
     Inc(CurPos); 
     end; 
     '?': //parameter 
     begin 
     Inc(CurPos); 
     Inc(ParamCount); 
     Result := Result + Copy(SQL, StartPos - BeginPos + 1, CurPos - StartPos - 1) + ':' + IntToStr(ParamCount); 
     StartPos := CurPos; 
     end; 
    end; 
    end; 
    Result := Result + Copy(SQL, StartPos - BeginPos + 1, CurPos - StartPos); 
end; 
8

penso che l'approccio più veloce è quello di utilizzare gli helper classe che implementeranno questa funzionalità qualcosa di simile:

type 
    TMyParamsHelper = class Helper for TSQLQuery 
    public 
    function SetupParams(AParamList: array of Variant): Boolean; overload; 
    function SetupParams(ASQL: string; AParamList: array of Variant): Boolean; overload; 
    end; 

// implementation 

function TMyParamsHelper.SetupParams(AParamList: array of Variant): Boolean; 
var 
    Index: Integer; 
begin 
    // here you can process the SQL as text and replace each ? 
    // with :paramINDEX 
    // first occurence of ? will be :param0, second will be :param1, etc. 
    // implement your replace algorithm before the "for loop" 
    for Index := Low(AParamList) to High(AParamList) do 
    ParamByName(Format(':param%d', [Index])).AsVaraint := AParamList[ Index ]; 
    // of course you need to do it in a try...except block and return TRUE|FALSE 
end; 

function TMyParamsHelper.SetupParams(ASQL: string; AParamList: array of Variant): Boolean; 
begin 
    SQL.Text := ASQL; 
    Result := SetupParams(AParamList); 
end; 

Così ora tutto quello che dovete fare è chiamare:

... 
ASQLQueryVariable.SetupParams([2012, 'Hello World', 2.14, 'It WORKS!']); 
// or 
ASQLQueryVariable.SetupParams(
    'UPDATE MyTable SET Year = ?, Title = ?, Cents = ?, Comment = ? WHERE <CLAUSE HERE>', 
    [2012, 'Hello World', 0.02, 'It WORKS!'] 
); 
... 

Nota: I' Sto scrivendo questo in cima alla mia testa, potrebbe avere errori di battitura e potrebbe non essere l'approccio migliore ...

Fammi sapere come funziona per te, ho sempre voluto il "?" al posto di ParamByName ma era troppo pigro per la sua attuazione ...

+0

Vedere la risposta. DB.TParams.ParseSQL è un metodo che converte i parametri in punti interrogativi, se questa è la rotta che si desidera percorrere. Preferisco di gran lunga ParamByName me stesso. – Robo

5

approccio non banale:

  • subsclass TMyQuery da TSQLQuery;
  • nel costruttore di TMyQuery impostare TStringList(SQL).OnChange nel proprio metodo QueryChanged. Vedere TSQLQuery.QueryChanged nell'unità SqlExpr.pas per i dettagli, che cosa sta facendo.
  • qui sarà necessario sostituire la chiamata SetParamsFromSQL con la propria, che analizzerà il testo SQL e creerà l'oggetto parametro per ogni '?' occorrenza.

Altro approccio semplice:

  • creare procedure e che vi ottenere una stringa SQL e la raccolta Parametri;
  • la procedura analizzerà il testo SQL e creerà l'oggetto parametro per ogni '?' occorrenza;
  • impostare TSQLQuery.ParamCheck su False e chiamare il proc dopo aver impostato la proprietà SQL.

Infine, considera l'utilizzo di soluzioni di party 3d, come AnyDAC. Supporta ODBC e '?' marcatori di parametri.

Problemi correlati