Tôi tình cờ gặp vấn đề này ngày hôm qua khi tôi bận viết một số bài kiểm tra đơn vị bằng cách sử dụng SQLLite. Môi trường của tôi là Windows7/Delphi XE.Sử dụng tham số datetime với ADO (ODBC) mất phần thời gian
Sử dụng TADOQuery cùng với thông số TDateTime dẫn đến mất phần thời gian.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ADODb, DateUtils, DB;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var DbConn : TADOConnection;
Qry : TADOQuery;
DT : TDateTime;
begin
DBConn := TADOConnection.Create(nil);
DBConn.ConnectionString := 'Provider=MSDASQL.1;Extended Properties="DRIVER=SQLite3 ODBC Driver;Database=:memory:;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"';
// DBConn.ConnectionString := 'Provider=MSDASQL.1;Persist Security Info=True;User ID=%0:s;Password=%1:s;Extended Properties="DRIVER={MySQL ODBC 5.1 Driver};SERVER=localhost;PORT=3306;DATABASE=test;USER=root;PASSWORD=rrr;OPTION=1048579"';
Qry := TADOQuery.Create(nil);
Qry.Connection := DbConn;
try
DBConn.Connected := True;
Qry.SQL.Text := 'CREATE TABLE test(d datetime)';
Qry.ExecSQL;
Qry.ParamCheck := True;
Qry.SQL.Text := 'INSERT INTO test (d) VALUES (:d)';
//Qry.Parameters.ParseSQL(Qry.SQL.Text, True); // not needed
TryEncodeDateTime(1999, 12, 12, 10, 59, 12, 0, DT);
Qry.Parameters.ParamByName('d').Value := DT;
Qry.Parameters.ParamByName('d').DataType := ftDateTime;
Qry.ExecSQL;
Qry.SQL.Text := 'SELECT d FROM test';
Qry.Open;
ShowMessage(FormatDateTime('MM/DD/YYYY HH:NN:SS', Qry.FieldByName('d').AsDateTime));
finally
FreeAndNil(Qry);
FreeAndNil(DbConn);
end;
end;
Điều thú vị là, khi tôi nhận xét dòng Qry.Parameters.ParseSQL(Qry.SQL.Text, True);
Nó sẽ hoạt động tốt. Tôi cần phần ParseSQL vì tôi đang xây dựng một ORM mini nên cần phải biết các tham số nào phải được ánh xạ. Một số quan sát:
- Thực hiện cùng một thử nghiệm với MySQL5 cho thấy cùng một vấn đề (bất kể phần ParseSQL).
- Mã này hoạt động với SQL Server và trình điều khiển OLEDB.
Tôi đã tìm kiếm trên net và tìm thấy một số liên kết thú vị:
http://tracker.firebirdsql.org/browse/ODBC-27
http://embarcadero.newsgroups.archived.at/public.delphi.database.ado/201107/1107112007.html
http://bugs.mysql.com/bug.php?id=15681
Các liên kết đầu tiên cho thấy 'sửa chữa' ADODB.pas, cái gì tôi làm không muốn làm. Đọc liên kết cuối cùng, có vẻ như ADO ánh xạ giá trị ngày giờ cho đến nay.
trả lời tôi không muốn nghe: sử dụng một thư viện/phần (như dbExpress, Zeoslib, ...)
Tôi không chắc chắn điều gì sẽ là cách tiếp cận hợp lý nhất để giải quyết vấn đề này.
Vì Linas và Marjan Venema đề xuất tôi có thể bỏ qua phần ParseSQL. Vì vậy, mã hoạt động ngay bây giờ với SQLlite IF Tôi bỏ qua dòng Qry.Parameters.ParamByName('d').DataType := ftDateTime;
.
Nhưng MySQL từ chối tiết kiệm thời gian. Tôi có thấy một vấn đề tương thích giữa ADO và ODBC của MySQL ở đây không?
Tôi muốn đặt datatype _before_ đặt giá trị, nhưng không chắc chắn sẽ tạo ra bất kỳ sự khác biệt nào. Tại sao xây dựng một ORM mini cần ParseSQL? Tôi đã xây dựng một số loại ORM libs và không bao giờ cần nó? IIRC Qry.SQL.Prepare cũng nên điền tập hợp tham số. –
Tôi cần biết những thông số nào tôi có trong Truy vấn của tôi và các giá trị sẽ được ánh xạ từ một đối tượng bằng rtti. bạn có nghĩa là Qry.Prepared: = true; ? không có sự khác biệt. – whosrdaddy
@whosrdaddy Không cần phải tự mình gọi ParseSQL. Nó được gọi tự động khi các thay đổi SQL.Text (ParamCheck phải là True). – Linas