Error: Error al utilizar cursores de cliente para agregar registro a la tabla de SQL Server que tiene un valor predeterminado en el campo de fecha y hora


Síntomas


Si utiliza ADO para insertar un nuevo registro a través de un conjunto de registros de cliente en una tabla de SQL Server que tiene un campo datetime que no aceptan valores NULL con un valor predeterminado, recibirá el siguiente mensaje de error si no se proporciona un valor para el campo de fecha y hora:
Error de tiempo de ejecución '-2147217887 (80040e21)': errores de operación generado de varios pasos. Comprobar cada valor de estado.
Este error se produce si utiliza el proveedor OLE DB para SQL Server o el proveedor OLE DB para controladores ODBC. El mensaje de error puede variar cuando se utiliza Microsoft Data Access Components (MDAC) versión 2.5 Service Pack 1 (SP1) o anterior. Este error no se produce con un cursor del lado del servidor.

Causa


Este error se produce en Client Cursor Engine cuando intenta convertir el valor del tipo DBTYPE_DBTIMESTAMP en DBTYPE_VARIANT.

Solución


Hay varias formas de evitar este problema:
  • Utilice un cursor de servidor para el conjunto de registros.
  • Quitar el valor predeterminado que se especifica para el campo en la base de datos.
  • Siempre debe especificar un valor para el campo cuando se agrega un nuevo registro.

Estado


Microsoft ha confirmado que se trata de un error en los productos de Microsoft que se enumeran al principio de este artículo.

Más información


Pasos para reproducir el comportamiento

  1. Agregar una tabla de SQL Server que contiene un campo datetime que no acepta valores NULL y que tiene un valor predeterminado. Incluir al menos un campo adicional. En aras de este artículo, se crea en la siguiente tabla de 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. Para insertar una fila en la tabla, ejecutar código similar al código siguiente.

    Nota: Debe cambiar User ID = < UID > y la contraseña = < contraseña segura > a los valores correctos antes de ejecutar este código. Asegúrese de que < UID > tiene los permisos apropiados para realizar esta operación en la base de datos. Además, asegúrese de que no proporciona un valor para el campo de fecha y hora.
        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
    Recibirá el mensaje de error mencionado al examinar la propiedad Value del campo datetime.