首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Native Client 10将TDateTime字段插入SQL2008数据库

使用Native Client 10将TDateTime字段插入SQL2008数据库
EN

Stack Overflow用户
提问于 2012-08-30 01:27:36
回答 1查看 2.9K关注 0票数 4

我们有一个用Delphi2007编写的遗留应用程序,它仍然在使用BDE (是的,它需要切换到ADO,但有超过500K行,这是一项艰巨的工作)。它使用SQL Server ODBC连接连接到SQL SERVER 2008数据库。我正在尝试切换到SQL Server Native Client 10.0,但遇到了一个有趣的问题。在尝试将记录插入到包含日期时间字段的表中时,我们收到以下错误:

代码语言:javascript
复制
Project DateTimeParamTest.exe raised exception class EDBEngineError with message 'General SQL error.
[Microsoft][SQL Server Native Client 10.0]Datetime field overflow. Fractional second precision exceeds the scale specified in
the parameter binding.'.

在做一些研究时,我看到了使用TParameter对象的NumericScale、精度和大小参数的注释。TADOQuery会自动将参数分别设置为3、23和16,并且插入没有问题。如果我将TQuery对象上的参数设置为相同,则会得到与上面相同的错误。

有没有人有这方面的经验,并知道一个简单的变通方法?我为任何想要尝试的人创建了以下示例代码。您只需要更改连接和SQL代码。

DateTimeParamTest_Main.dfm:

代码语言:javascript
复制
object Form10: TForm10
  Left = 0
  Top = 0
  Caption = 'Form10'
  ClientHeight = 111
  ClientWidth = 181
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button2: TButton
    Left = 20
    Top = 16
    Width = 75
    Height = 25
    Caption = 'BDE'
    TabOrder = 0
    OnClick = Button2Click
  end
  object dbPMbde: TDatabase
    AliasName = 'PMTest'
    DatabaseName = 'DB'
    LoginPrompt = False
    SessionName = 'Default'
    Left = 20
    Top = 52
  end
  object qryBDE: TQuery
    DatabaseName = 'DB'
    SQL.Strings = (
      'INSERT INTO TRAN_DETAIL (ID, STARTDATE, ENDDATE)'
      'VALUES (:ID, :STARTDATE, :ENDDATE);')
    Left = 88
    Top = 52
    ParamData = <
      item
        DataType = ftInteger
        Name = 'ID'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Precision = 23
        NumericScale = 3
        Name = 'STARTDATE'
        ParamType = ptInput
        Size = 16
      end
      item
        DataType = ftDateTime
        Precision = 23
        NumericScale = 3
        Name = 'ENDDATE'
        ParamType = ptInput
        Size = 16
      end>
  end
end

DateTimeParamTest_Main.pas:

代码语言:javascript
复制
unit DateTimeParamTest_Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, DBTables;

type
  TForm10 = class(TForm)
    Button2: TButton;
    dbPMbde: TDatabase;
    qryBDE: TQuery;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

procedure TForm10.Button2Click(Sender: TObject);
begin
  dbPMbde.Open;
  with qryBDE do
  begin
    parambyname('ID').Value := 99999999;
    parambyname('StartDate').Value := now;
    parambyname('EndDate').Value := now;
    execsql;
  end;
  dbPMbde.Close;
end;

end.    
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-30 05:52:55

这似乎是一个毫秒数导致数据类型溢出的问题(基于上面的注释)。如果是这样的话,脑海中就会浮现出一个快速解决方案。

将赋值替换为日期列,如下所示:

代码语言:javascript
复制
qryBDE.ParamByName('STARTDATE').AsDateTime := FixBDEDateTime(Now);

其中FixBDEDateTime只是简单地

代码语言:javascript
复制
function FixBDEDateTime(const Value: TDateTime): TDateTime;
var
  Year, Mon, Day, Hr, Min, Sec, MS: Word;
begin
  DecodeDate(Value, Year, Mon, Day);
  DecodeTime(Value, Hr, Min, Sec, MS);
  Result := EncodeDate(Year, Mon, Day) + 
            EncodeTime(Hr, Min, Sec, 0);
end;

编辑:正如@TLama在评论中指出的那样(我没有提到,因为我在开头一句话中遗漏了Delphi 2007,也没有在标签中看到版本),你也可以直接使用:

代码语言:javascript
复制
uses
  DateUtils;
...

qryBDE.ParamByName('STARTDATE').AsDateTime := RecodeMillisecond(Now, 0);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12183391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档