Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用新的SQL Server本机客户端将datetime迁移到datetime2_C++_Sql Server_Oledb_Datetime2_Sql Server Native Client - Fatal编程技术网

C++ 如何使用新的SQL Server本机客户端将datetime迁移到datetime2

C++ 如何使用新的SQL Server本机客户端将datetime迁移到datetime2,c++,sql-server,oledb,datetime2,sql-server-native-client,C++,Sql Server,Oledb,Datetime2,Sql Server Native Client,我们目前正在将数据库从datetime迁移到datetime2,包括SQL Server本机客户端v11(SQL Server 2012)。数据库更新很容易完成,但问题出现在我们想要使用的新SQLServer原生客户端11上 一般来说,我们有OLEDB消费者,他们为CRUD操作准备了“COLUMN_ENTRY*”访问器。对于datetime2列,成员的类型为DBTIMESTAMP。使用SQLNCLI提供程序,DBTIMESTAMP的分数部分被自动截断为支持的值。使用SQLNCLI11插入的分数太

我们目前正在将数据库从
datetime
迁移到
datetime2
,包括SQL Server本机客户端v11(SQL Server 2012)。数据库更新很容易完成,但问题出现在我们想要使用的新SQLServer原生客户端11上

一般来说,我们有OLEDB消费者,他们为CRUD操作准备了“COLUMN_ENTRY*”访问器。对于
datetime2
列,成员的类型为
DBTIMESTAMP
。使用
SQLNCLI
提供程序,
DBTIMESTAMP
的分数部分被自动截断为支持的值。使用
SQLNCLI11
插入的分数太精确会导致此错误:

DB\u E\u错误导致多步OLE DB操作生成错误。检查每个OLE DB状态值(如果可用)。没有完成任何工作。

根据,如果在字段中插入太多数据,则返回此错误。由此,我假设DBDATETIME成员的小数部分过于精确,无法插入。根据,新的本机客户端版本(10和11)不会截断,但会出现错误。以我们想要实现的简化示例为例:

类CMyTableStruct
{
公众:
CMyTableStruct();
长口盖;
DBTIMESTAMP m_dtLogTime;
};
类CMyTableStruct_InsertAccessor:公共CMyTableStruct
{
公众:
开始参数映射(CMyTableStruct\u InsertAccessor)
列输入(1,m\u dtLogTime)
结束参数映射()
};
在代码的某些部分,我将时间戳初始化为2015-08-10 07:47:49.986149999,插入失败。如果我将分数重置为0,则插入有效;0以外的任何值都将失败。我尝试使用
COLUMN\u ENTRY\u PS
提供具有各种值的日期时间精度和比例,但插入总是失败

我们如何强制本机客户端简单地接受该值并截断它?很明显,我们无法手动将所有值截断为支持的DB精度。我找不到任何关于如何在新的本机客户端上使用datetime2的适当文档。我们是否缺少正确处理datetime2的任何转换或设置

这是测试设置:

  • Windows 7 64位
  • SQL Server本机客户端11(SQLNCLI11)
  • SQL Server 2012
  • DBPROP_INIT_LCID=2055
  • DBPROP_INIT_PROMPT=4
  • DBPROP_INIT_DATASOURCE=localhost
  • DBPROP_AUTH_INTEGRATED=SSPI
使用
SQLNCLI
提供程序,同样的代码也可以工作

[编辑#1]:我使用
AtlTraceErrorRecords
转储了更多错误信息,这确认了与链接的Microsoft Connect报告中相同的错误:

行#:0来源:“Microsoft SQL Server本机客户端11.0”说明:“提供的时间值的小数部分溢出了相应SQL Server参数或列的比例。请增加DBPARAMBINDINFO或列比例中的bScale以更正此错误。”帮助文件:“(null)”帮助上下文:0 GUID:{0C733A63-2A1C-11CE-ADE5-00AA0044773D}


[编辑#2]:从我的进一步研究来看,这似乎是新的本机客户端已定义和接受的行为。请参阅以供参考。但是,如果没有任何文档说明如何正确使用datetime2,Microsoft无法认真对待此更改。他们真的要求开发人员自己在将DBTIMESTAMP插入数据库之前对其进行取整吗?在某些情况下,由于某些浮点精度错误,舍入甚至不起作用。以上面的时间戳为例,您将看到典型的.9999精度错误。任何人都应该如何使这种奇怪的行为起作用?有了这些错误消息,您甚至无法在不使用SQL语句的情况下将当前时间戳保存到数据库中
now()
的操作,因为您通常会在这些溢出中运行。

我做了一些测试,并完全重写了我的答案

我将SQL Server 2008与本机客户端10一起使用。它已经支持
datetime2(7)
,因此我的测试是适用的

datetime

我有一个具有表值参数的存储过程。该参数表的一列具有
datetime
类型。我以前没有使用非零分秒,但现在尝试了。我花了一段时间才弄清楚需要什么

为了在
DBTIMESTAMP.fraction
字段中使用非零值,我必须配置列描述和参数描述:将
DBCOLUMNDESC.bScale
设置为3,将
DBBINDING.bScale
设置为3。这两个
bPrecision
都保留为0。这帮助我意识到我必须设置
DBCOLUMNDESC.bScale也是

SQL Server本机客户端OLE DB提供程序检查DBCOLUMDESC bScale成员确定小数秒精度

一旦
Scale
设置为3,我就可以将
DBTIMESTAMP.fraction
的值设置为
555000000
,并将其作为
.557
成功插入数据库,即服务器将该值进一步四舍五入到毫秒的1/3(日期时间的精度)
类型).但是,当我试图将
DBTIMESTAMP.fraction
的值设置为
552100000
时,我得到了与您得到的相同的错误。因此,服务器希望程序员自己对值进行四舍五入

// truncate fractions to 100 nanoseconds precision
dt.fraction /= 100;
dt.fraction *= 100;
截断分数的一种简单方法如下:

DBTIMESTAMP dt;
// set to any value from 0 to 999,999,999 (billionth of a second)
dt.fraction = 555123456; 

// truncate fractions to milliseconds before inserting into the database
dt.fraction /= 1000000;
dt.fraction *= 1000000;
日期时间2(7)

我将表值参数中的列的类型更改为
datetime2(7)
,并进行了更多的测试

我将
Scale
设置为7,可以成功地将值
555123400
插入数据库
DBTIMESTAMP.fraction
,但当我尝试插入值
555123478
时,我得到了相同的错误。因此,对于
datetime2(7)
服务器也期望使用pro