使用客户端游标将记录添加到日期/时间字段中具有默认值SQL Server表时出错

本文可帮助你解决使用客户端游标将记录添加到日期时间字段中具有默认值SQL Server表时出现的问题。

原始产品版本:SQL Server
原始 KB 编号: 279888

症状

如果使用 ADO 通过客户端记录集将新记录插入具有默认值的不可datetime为空字段的SQL Server表中,如果未为datetime字段提供值,则会收到以下错误消息:

运行时错误“-2147217887 (80040e21) ”:多步骤操作生成错误。 检查每个状态值。

无论是使用用于SQL Server的 OLE DB 提供程序还是将 OLE DB 提供程序用于 ODBC 驱动程序,都会出现此错误。 使用 Microsoft 数据访问组件 (MDAC) 版本 2.5 Service Pack 1 (SP1) 或更低版本时,错误消息可能会有所不同。 服务器端游标不会发生此错误。

原因

当客户端游标引擎尝试将 类型的DBTYPE_DBTIMESTAMPDBTYPE_VARIANT值转换为 时,在客户端游标引擎中发生此错误。

解决方案

有几种方法可以解决此问题:

  • 对记录集使用服务器端游标。
  • 删除为数据库中的 字段指定的默认值。
  • 添加新记录时,始终为字段指定值。

重现行为的步骤

  1. 向SQL Server添加一个表,其中包含不接受 null 且具有默认值的日期/时间字段。 至少包含一个附加字段。 为了本文所述,将创建以下SQL Server 2000 表:

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[DateTest]')
    and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[DateTest]
    GO
    
    CREATE TABLE [dbo].[DateTest] ([DateId] [int] IDENTITY (1, 1) NOT NULL ,
    [TestDate] [datetime] NOT NULL ,
    [Nonsense] [varchar] (16) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
    ) ON [PRIMARY]
    GO
    
    ALTER TABLE [dbo].[DateTest] WITH NOCHECK ADD 
    CONSTRAINT [DF_DateTest_TestDate] DEFAULT ('3/1/2001') FOR [TestDate],
     PRIMARY KEY CLUSTERED 
    ([DateId]
    ) ON [PRIMARY] 
    GO
    
  2. 若要在表中插入行,请运行类似于以下代码的代码。

    注意

    在运行此代码之前,必须将用户 ID =<UID> 和 password =<strong password> 更改为正确的值。 确保 <UID> 具有对数据库执行此操作的适当权限。 此外,请确保不为 datetime 字段提供值。

     Dim cnn As ADODB.Connection
     Dim rst As ADODB.Recordset
    
    Set cnn = New ADODB.Connection
    cnn.Open "Provider=SQLOLEDB;Data Source=(local);" & _
    "Initial Catalog=test;User Id=<UID>;Password=<strong password>;"
    
    Set rst = New ADODB.Recordset
    With rst
    .CursorLocation = adUseClient
    .Open "SELECT * FROM DateTest", cnn, adOpenStatic, adLockOptimistic
    
    .AddNew
    .Fields("Nonsense").Value = "test data"
    .Update
    End With
    
    Debug.Print rst("TestDate").Value
    

    检查字段的 Value 属性 datetime 时,会收到上述错误消息。