2012-02-14 15 views
5

Chúng tôi đã chuyển mã sang Delphi XE2 và cần thay đổi các thành phần truy cập dữ liệu của chúng tôi từ ODBCExpress của bên thứ ba vốn không còn hoạt động nữa, thành TSQLQuery của dbExpress.Có thể sử dụng TSQLQuery của dbExpress không? như thông số?

Chúng tôi đã parametrized truy vấn SQL như:

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

nếu chúng ta sử dụng đoạn mã sau:

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

Nó trả về 0, vì vậy chúng tôi không thể để có được những ràng buộc làm việc, nhưng nếu chúng tôi thay đổi sSQL thành:

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

Nó trả về 2.

Sẽ là một rắc rối lớn khi thay đổi tất cả các truy vấn SQL thành cú pháp tham số mới. Có anyway cho TSQLQuery để nhận ra? cú pháp?

Tôi thấy DBXCommon.TDBXCommand sử dụng? Cú pháp:

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

Nhưng nó sẽ có nghĩa ném đi mã của chúng tôi có sử dụng TSQLQuery. Cách nhanh nhất/dễ nhất để giải quyết vấn đề này là gì? Sự khác biệt giữa TSQLQuery và TDBXCommand là gì, về những gì có liên quan đến tôi?

Trả lời

0

Tôi đã kết thúc bằng cách viết một phương thức để chuyển đổi dấu chấm hỏi trong truy vấn thành: tham số kiểu param1. Điều thú vị là Delphi có phương thức DB.TParams.ParseSQL chuyển đổi các tham số thành các dấu hỏi. Phương pháp này về cơ bản là ngược lại.

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

Tôi nghĩ rằng cách tiếp cận nhanh nhất là sử dụng những người giúp đỡ lớp đó sẽ thực hiện chức năng điều này như:

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; 

Vì vậy, bây giờ tất cả bạn phải làm là gọi:

... 
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!'] 
); 
... 

Lưu ý: Tôi m viết điều này ra khỏi đầu của tôi, có thể có lỗi chính tả và có thể không phải là cách tốt nhất ...

Hãy cho tôi biết cách này hoạt động cho bạn, tôi luôn muốn "?" thay cho ParamByName nhưng đã quá lười biếng để thực hiện nó ...

+0

Xem câu trả lời của tôi. DB.TParams.ParseSQL là một phương thức chuyển đổi các tham số thành các dấu hỏi, nếu đó là tuyến đường bạn muốn đi. Tôi thích ParamByName hơn. – Robo

5

cách tiếp cận không tầm thường:

  • subsclass TMyQuery từ TSQLQuery;
  • trong hàm tạo của TMyQuery đặt TStringList(SQL).OnChange vào phương thức QueryChanged của riêng bạn. Xem TSQLQuery.QueryChanged trong đơn vị SqlExpr.pas để biết chi tiết, những gì nó đang làm.
  • ở đó bạn sẽ cần phải thay thế SetParamsFromSQL cuộc gọi của riêng bạn, điều này sẽ phân tích cú pháp văn bản SQL và tạo đối tượng tham số cho mỗi '?' sự xuất hiện.

Nhiều phương pháp đơn giản:

  • tạo thủ tục, mà sẽ nhận được một chuỗi SQL và bộ sưu tập Params;
  • quy trình sẽ phân tích văn bản SQL và tạo đối tượng tham số cho mỗi '?' sự xuất hiện;
  • đặt TSQLQuery.ParamCheck thành False và gọi cho proc sau khi đặt thuộc tính SQL.

Cuối cùng, hãy xem xét sử dụng các giải pháp của bên thứ ba, chẳng hạn như AnyDAC. Nó hỗ trợ ODBC và '?' dấu tham số.

Các vấn đề liên quan