【问题标题】:How to compare Firebird TimeStamp and Delphi DateTime?如何比较 Firebird TimeStamp 和 Delphi DateTime?
【发布时间】:2010-11-11 05:10:42
【问题描述】:

由于 Firebird/Interbase 中的 TimeStamp 数据类型不是 DateTime (*),因此我有以下脚本永远不会检索任何数据

我应该如何解决它?德克萨斯州。

 with DMApp.qryValidPeriod_ do
  begin
    Close;
    SQL.Clear;
    SQL.Add('select P.* from PERIOD P, FISCAL_YR F');    
    SQL.Add('where');
    SQL.Add('P.FISCAL_YR_ID = F.FISCAL_YR_ID and');     
    SQL.Add('F.ENTITY_DB_ID = :PRIMARY_DB_ID and');     
    SQL.Add('F.FISCAL_YR_ID = :CURR_FY_ID and');        
    SQL.Add(':pTranDate BETWEEN P.BEG_PERIOD and P.END_PERIOD');

    ParamByName('pTranDate').AsDateTime :=  sBATCH_DATE; 

// BEG_PERIOD和END_PERIOD为TimeStamp数据类型如'2010-11-09 12:00' // 参数返回数据类型如'2010-11-09'


(*) 时间戳是 Firebird/Interbase/SQL Server 中可用的列数据类型...有助于确保数据完整性。每次插入或更新包含时间戳列的行时,时间戳都会自动更新。时间戳列中的值不是日期时间数据,而是 binary(8) varbinary(8) 数据。时间戳数据类型与系统时间无关,它只是一个单调递增的计数器,其值在数据库中始终是唯一的(使其基本上是唯一的随机数。)

【问题讨论】:

  • 此示例中的时间戳是您自己的自定义数据类型吗?因为我们经常使用标准的 TIMESTAMP 数据类型,并且与查询参数相比,它工作得很好。
  • 不,不是。它是火鸟 2.5。如上所示,脚本从不返回任何数据 - (因为参数 pTranDate 的值只有在调试器中看到的日期格式)
  • 该代码应该可以正常工作。查询没有返回结果的原因可能有所不同。检查您的其他参数。
  • 示例:Delphi 将 '2010-11-09' 作为 pTranDate 参数的值。使用此值,脚本不返回任何数据。如果我用“2010-11-09 00:00”字面替换这个参数值,那么脚本会返回数据。
  • '2010-11-09'是字符串值,怎么给参数设置?

标签: sql delphi firebird


【解决方案1】:

您是不是误解了 Firebird 中的 TIMESTAMP 数据类型?在 SQL92 中,TIMESTAMP 是保存日期和时间值的标准数据类型。它不会自动更新,返回 TIMESTAMP 值的函数与数据库时间有关。

AFAIK,Firebird TIMESTAMP 实现遵循 SQL 92 规则 (http://www.firebirdsql.org/index.php?op=guide&id=ib6_newfeatures#datetime),它应该与 Delphi .AsDateTime 参数完美配合。

正如您所描述的,它是 SQL Server TIMESTAMP - 永远不应与日期和时间进行比较,“SQL Server 时间戳数据类型与时间或日期无关”http://msdn.microsoft.com/en-us/library/ms191240(SQL.90).aspx

【讨论】:

  • 抱歉 - 是的,我在描述 SQL Server TIMESTAMP。我上面的脚本仅在参数 pTranDate 为 'Date''Time' 格式(即 2010-11-09 00:00)时才返回数据。因为它是我只得到日期(2010-11-09)
  • 对不起,伙计们-我在 Firebird 和 SQL Server 之间混淆了(因为我的应用程序是多服务器)。现在,在您的帮助下,我把事情做好了,Delphi DateTime 可以正常使用 Firebird TimeStamp 数据类型。
【解决方案2】:

通常,我将它用作字符串参数,因为时间部分。 想法是设置独立格式,例如'11-NOV-2010 12:32:25'

例如,你可以试试

ParamByName('pTranDate').AsString :=  FormatSQLDateTime(sBATCH_DATE);

你应该在哪里拥有类似于这些的功能

function FormatSQLDate(date: TDate) : string;
const months : array[1..12] of string[3] =
('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');
 var d, y : integer;
     m : string[3];
begin
   d := DayOf(date);
   y := YearOf(date);
   m := months[MonthOf(date)];
   Result := Format('%d-%s-%d', [d, m, y]);
end;


function FormatSQLDateTime(date : TDateTime) : String;
var
  d : String;
  h, m, s : Integer;
begin
  d := SQLDate(date);
  h := HourOf(date);
  m := MinuteOf(date);
  s := SecondOf(date);
  Result := d + Format(' %d:%d:%d', [h, m, s]);
end;

请注意,您还可以使用 sql extract 在服务器端解决问题

extract(day from timestamp_field)

http://www.firebirdsql.org/refdocs/langrefupd20-extract.html

【讨论】:

  • 通常最好以数字格式保存日期,让驱动程序/客户端/数据库处理其余部分。它也稍微快一些,因为引擎不需要解析和转换字符串。 Firebird 的问题较少,因为它理解一组固定的字符串文字,但在其他数据库中,“标准”日期文字格式可能会根据操作系统区域设置、数据库设置以及客户端区域设置和设置而改变。恕我直言,避免使用字符串是一个很好的做法。
  • 感谢这个功能和参考 Sofija - 它会在我的应用程序的其他部分有所帮助。现在我使用 Firebird TimeStamp 和 Delphi DateTime 把事情做好了。
【解决方案3】:

下面是一个用 Delphi 编写的 UDF。它获取日期的三个部分并以 Firebird 格式返回日期值。也许这将帮助您了解如何在 Delphi 和 FB 之间转换日期。

type
  PIBDateTime = ^TIBDateTime;
  TIBDateTime = record
    Days,                           // Date: Days since 17 November 1858
    MSec10 : Integer;               // Time: Millisecond * 10 since midnigth
  end;

const                               // Date translation constants
  MSecsPerDay10 = MSecsPerDay * 10; // Milliseconds per day * 10
  IBDateDelta = 15018;              // Days between Delphi and InterBase dates

// ==============================================
//  declare external function ...
//    smallint, smallint, smallint, date
//  returns
//    date
//  ...
// ==============================================

function g_d_encodedate(var Year, Month, Day: SmallInt;
  var IBDateTime: TIBDateTime): PIBDateTime; cdecl; export;
var
  DateTime: TDateTime;
  DelphiDays : Integer;
begin
  DateTime := EncodeDate(Year, Month, Day);
  DelphiDays := Trunc(DateTime);
  with IBDateTime do begin
    Days := DelphiDays + IBDateDelta;
    MSec10 := Trunc((DateTime - DelphiDays) * MSecsPerDay10);
  end;
  Result := @IBDateTime;
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    相关资源
    最近更新 更多