为什么使用 date/time 值的 TADOTable 中的 Locate() 不起作用

Why Locate() in TADOTable with date/time value is not working

我正在开发一个用于记录用户 activity 的小型子系统。该系统使用 MS SQL Server 作为数据库,Delphi7 和 ADO 构建界面。

我遇到的问题是无法找到具有特定 datetime 值的记录。

下面是问题的示例再现:

1.数据库:MS SQL Server 2005 Express Edition。

-- Table creation
CREATE TABLE [tlog] (
    [USERN] [numeric](10, 0) NULL,
    [USERDATE] [datetime] NULL,
    [LOGTEXT] [varchar](250) COLLATE Cyrillic_General_CS_AS NULL
);

-- Insert date/time value
INSERT INTO [tlog] (USERN, USERDATE, LOGTEXT)
VALUES (1, CURRENT_TIMESTAMP, 'Record current activity')
-- Insert date only value
INSERT INTO [tlog] (USERN, USERDATE, LOGTEXT)
VALUES (1, '20180202', 'Record current activity')

-- Table's content
-------------------------------------------------------------
| USERN |       USERDATE          |          LOGTEXT        |
-------------------------------------------------------------
| 1     | 26/10/2015 17:13:36.597 | Record current activity |
-------------------------------------------------------------
| 1     | 02/02/2018 00:00:00.000 | Record current activity |
-------------------------------------------------------------

2。示例代码: Delphi 7和ADO

procedure TfrmMain.btnLocateClick(Sender: TObject);
var
   d: TDateTime;
   tblLog: TADOTable;
begin
   // 
   ThousandSeparator         := ' ';
   DecimalSeparator          := '.';
   DateSeparator             := '/';
   ShortDateFormat           := 'dd/mm/yyyy';
   LongDateFormat            := 'dd/mm/yyyy';
   TimeSeparator             := ':';
   ShortTimeFormat           := 'hh:mm';
   LongTimeFormat            := 'hh:mm';
   TwoDigitYearCenturyWindow := 50;
   ListSeparator             := ';';
   
   //
   tblLog := TADOTable.Create(Application);
   try
   
      //
      tblLog.ConnectionString :=
         'Provider=SQLOLEDB.1;'+
         'Password=xxxx;'+
         'Persist Security Info=True;'+
         'User ID=xxxxxxxx;'+
         'Initial Catalog=xxxxxxxxx;'+
         'Data Source=127.0.0.1\xxxxxxx,1066';
      tblLog.TableName := '[tlog]';
      tblLog.Open;
      
      // First try - locate with exact value. NOT WORKING.
      d := StrToDateTime('26/10/2015 17:13:36.597');
      if tblLog.Locate('USERDATE', d, []) then
         ShowMessage('Exact value, no Locate options: Located')
      else
         ShowMessage('Exact value, no Locate options: Not located');
      if tblLog.Locate('USERDATE', d, [loPartialKey]) then
         ShowMessage('Exact value, with Locate options: Located')
      else
         ShowMessage('Exact value, with Locate options: Not located');
      
      // Second try - locate with value that matches format settings. NOT WORKING.
      d := StrToDateTime('26/10/2015 17:13');
      if tblLog.Locate('USERDATE', d, []) then
         ShowMessage('Hours and minutes, no Locate options: Located')
      else
         ShowMessage('Hours and minutes, no Locate options: Not located');
      if tblLog.Locate('USERDATE', d, [loPartialKey]) then
         ShowMessage('Hours and minutes, with Locate options: Located')
      else
         ShowMessage('Hours and minutes, with Locate options: Not located');
      
      // Locate with date only value. WORKING.
      d := StrToDateTime('02/02/2018');
      if tblLog.Locate('USERDATE', d, []) then
         ShowMessage('Located')
      else
         ShowMessage('Not located');

   finally
      //
      tblLog.Close;
      tblLog.Free;
   end;   
end;

3。预期结果: 找到记录。

4.实际结果: TADOTable.Locate() returns false.

我做错了什么以及如何将 datetime 值传递给 TADOTable.Locate() 方法?

提前致谢!

您使用了 Locate almost correctly. Almost, because the loPartialKey 搜索 TDateTime 值时包含的选项毫无意义。在这种情况下,您需要搜索确切的日期时间值。问题出在你的测试中。

您的第一次测试的日期时间值有误。它的毫秒部分在您的转换中被忽略,因此您实际上是在尝试定位日期时间 26/10/2015 17:13:36 这不在您的 table.

在第二种情况下,您试图找到日期时间 26/10/2015 17:13,这不在您的 table.[=12 中=]

我建议使用例如EncodeDateTime function for building date time rather than that string conversion and removing those extra calls with loPartialKey 选项。

使用类型字符串定位或查找格式为 yyyy-mm-dd 的日期

示例:

在定位中:

if tblLog.Locate('USERDATE', '2015-10-26', []) then ...

其中:

select * from tbllog where userdate = '2015-10-26'