尝试将datetime
值12/30/1899传递给SQL Server,失败,显示无效的日期格式-但仅适用于本机客户端驱动程序,并且仅在DataTypeCompatiblity模式下。
[当尝试针对SQL Server在ADO中使用参数化查询时:
SELECT ?
我将datetime
值参数化为adDBTimeStamp
:
//Language agnostic, vaguely C#-like pseudo-code
void TestIt()
{
DateTime dt = new DateTime("3/15/2020");
VARIANT v = DateTimeToVariant(dt);
Command cmd = new Command();
cmd.CommandText = "SELECT ? AS SomeDate";
cmd.Parameters.Append(cmd.CreateParameter("", adDBTimeStamp, adParamInput, 0, v);
Connection cn = GetConnection();
cmd.Set_ActiveConnection(cn);
cmd.Execute(out recordsAffected, EmptyParam, adExecuteNoRecords);
}
并且当日期为3/15/2020
时效果很好。
您创建一个VARIANT
,其VARIANT
为7(VType
),并且该值是8字节浮点值:
VType
如果我在一个特定的日期时间执行相同的测试代码,它将失败:
VT_DATE
ADO OLEDB提供程序引发异常(即,甚至在到达SQL Server之前,它:]
VT_DATE
调试此问题时,我意识到并不是所有的SQL Server OLEDB提供程序都发生这种情况。 Microsoft通常为SQL Server提供4个OLE DB提供程序:
VARIANT
Int32 vt = 7; //VT_DATE
Double date = 0;
:用于SQL Server的Microsoft OLE DB提供程序(自Windows 2000开始与Windows一起提供)]void TestIt()
{
DateTime dt = new DateTime("12/30/1899");
VARIANT v = DateTimeToVariant(dt);
Command cmd = new Command();
cmd.CommandText = "SELECT ? AS SomeDate";
cmd.Parameters.Append(cmd.CreateParameter("", adDBTimeStamp, adParamInput, 0, v);
Connection cn = GetConnection();
cmd.Set_ActiveConnection(cn);
cmd.Execute(out recordsAffected, EmptyParam, adExecuteNoRecords);
}
:SQL Server本机客户端(SQL Server 2005附带)Invalid date format
:SQL Server Native Client 11.0(SQL Server 2008附带)SQLOLEDB
:SQL Server Native Client 12.0(SQL Server 2012附带)SQLNCLI
:用于SQL Server的Microsoft OLE DB驱动程序(SQL Server 2016附带)[当与一些其他提供商一起尝试时,它does在某些情况下可以正常工作:
SQLNCLI10
:作品SQLNCLI11
(无DataTypeCompatibility):有效MSOLEDBSQL
(启用了DataTypeCompatiility的情况:失败)是。 ActiveX数据对象(ADO)是不友好的COM OLEDB API的友好COM包装器,无法理解新的SQLOLEDB
,SQLNCLI11
,SQLNCLI11
,date
,time
数据类型。创建了新的OLEDB数据类型常量以表示这些新类型。因此,任何现有的OLEDB应用程序都无法理解新的常量。
为此,一个新的xml
datetime2
您可以将其添加到连接字符串中:
“ Provider = SQLNCLI11;数据源=螺丝刀;用户ID = hatguy;密码= hunter2; DataTypeCompatibility = 80;”
这指示OLEDB驱动程序仅返回首次创建OLEDB时存在的OLEDB数据类型:
datetimeoffset
何时:
DataTypeCompatibility=80
| SQL Server data type | SQLOLEDB | SQLNCLI | SQLNCLI |
| | | | w/DataTypeCompatibility=80 |
|----------------------|-----------------|--------------------------------|-----------------------------------|
| Xml | adLongVarWChar | 141 (DBTYPE_XML) | adLongVarChar |
| datetime | adDBTimeStamp | adDBTimeStamp | adDBTimeStamp |
| datetime2 | adVarWChar | adDBTimeStamp | adVarWChar |
| datetimeoffset | adVarWChar | 146 (DBTYPE_DBTIMESTAMPOFFSET) | adVarWChar |
| date | adVarWChar | adDBDate | adVarWChar |
| time | adVarWChar | 145 (DBTYPE_DBTIME2) | adVarWChar |
| UDT | | 132 (DBTYPE_UDT) | adVarBinary (documented,untested) |
| varchar(max) | adLongVarChar | adLongVarChar | adLongVarChar |
| nvarchar(max) | adLongVarWChar | adLongVarWChar | adLongVarWChar |
| varbinary(max) | adLongVarBinary | adLongVarBinary | adLongVarBinary |
| timestamp | adBinary | adBinary | adBinary |
开启尝试使用日期'12 / 30 / 1899`并没有天生的错误:
datetime
正常工作12/30/1899
启用的本机驱动程序中它只是失败,>显然,这是Microsoft OLE DB驱动程序中的错误。但是,微软绝对不会,ever
我可以检测到这个特殊的日期时间,并且可以尝试在数据访问层中解决此错误。
DataTypeCompatilibty
结构的值,SELECT CAST('18991230' AS datetime)
DataTypeCompatibility
下有效VARIANT
xx驱动程序下12/30/1899 12:00:00 AM
驱动程序下SQOLEDB
中当OLE DB驱动程序does费心去做我所说的事情时,我们可以分析生成的RPC:
SQOLEDB
SQLNCLI
SQLNCLI11
MSOLEDBSQL
CMRE(Delphi)
DataTypeCompatibilityMode
虽然这不是Delphi特有的问题;我正在使用Delphi。因此它被标记为Delphi。如果您抱怨
exec sp_executesql N'SELECT @P1 AS SomeDate',N'@P1 datetime','1899-12-30 00:00:00'
Note
:这不是ADO.net,而是ADO。它不是托管的.NET Framework类库,它是本机Win32 COM OLE DB API。
简短版本尝试将日期时间值12/30/1899传递给SQL Server,但由于日期格式无效而失败-但仅适用于本机客户端驱动程序,并且仅适用于DataTypeCompatiblity模式。长版...
BrakNicku回答了。