鉴于以下组件
DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'
Run Code Online (Sandbox Code Playgroud)
将它们结合起来以产生DATETIME2(7)
具有价值的结果的最佳方法是'2013-10-13 23:59:59.9999999'
什么?
有些东西不工作,如下表所示。
SELECT @D + @T
Run Code Online (Sandbox Code Playgroud)
操作数数据类型日期对加法运算符无效。
SELECT CAST(@D AS DATETIME2(7)) + @T
Run Code Online (Sandbox Code Playgroud)
操作数数据类型 datetime2 对加法运算符无效。
SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)
Run Code Online (Sandbox Code Playgroud)
datediff 函数导致溢出。分隔两个日期/时间实例的日期部分数量太大。尝试将 datediff 与不太精确的日期部分一起使用。
* 可以在 Azure SQL 数据库和 SQL Server 2016 中避免溢出,使用DATEDIFF_BIG
.
SELECT CAST(@D AS DATETIME) + @T
Run Code Online (Sandbox Code Playgroud)
数据类型 datetime 和 time 在 add 运算符中不兼容。
SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)
Run Code Online (Sandbox Code Playgroud)
返回结果但失去精度
2013-10-13 23:59:59.997
存储大小
小于 3 的精度为 6 个
字节。精度 3 和 4 为 7 个
字节。所有其他精度需要 8 个字节。
datetime2(0)
、datetime2(1)
、的大小datetime2(2)
使用相同的存储量(6 字节)。
我是否正确地说,我可能会datetime2(2)
在没有任何额外尺寸成本的情况下使用并获得精度的好处?
请注意:
datetime2(0)
在 where 子句中使用或通过索引查找时,cpu 效率会更高吗?
这是一个庞大的表,因此最小的优化将产生很大的不同。
我知道隐式类型转换不是一个好习惯。但当较低的值突然变得较高时,这确实是意想不到的行为。
declare @LastSelectedDate DATETIME = '2021-11-09 13:52:29.187'
declare @LastSelectedDate_1 DATETIME2(7) = '2021-11-09 13:52:29.1866667'
SELECT IIF(@LastSelectedDate_1 > CAST(@LastSelectedDate AS DATETIME2), 1, 0)
SELECT IIF(@LastSelectedDate_1 > @LastSelectedDate, 1, 0)
Run Code Online (Sandbox Code Playgroud)
这是一个错误还是我遗漏了什么?我正在使用 SQL Server 2016。
我们正在开发一个多数据库应用程序(读取和写入多个数据库)。数据库上的数据模型是相同的。
我们在 MSSQL 的 datetime2(6) 列中插入一个时间戳(12 个小数位)值,但是 MSSQL 对该值进行舍入,使其与忽略额外小数位的其他数据库不同。
例子:
DECLARE @t TABLE(x DATETIME2(6))
INSERT @t SELECT '2017-03-28 14:00:59.4106489'
SELECT x FROM @t
Run Code Online (Sandbox Code Playgroud)
结果:2017-03-28 14:00:59.41064 9 预期:2017-03-28 14:00:59.41064 8
DB2 通过丢弃第 7 个小数位来提供预期结果。
我们怎样才能让MSSQL不舍入datetime2值?
编辑
该应用程序将具有 12 个小数位的 java.sql.Timestamp 对象写入 DB2 和 MSSQL。在 DB2 中,该列是 TIMESTAMP(6),在 MSSQL 中是 DATETIME2(6)。DB2 从 12 位小数位截断为 6 位。MSSQL 向下舍入为 6 位。
因此,我们的数据团队寻求帮助以解决他们遇到的问题。我最终将其追踪到了一些真正超出范围的数据 (1/1/0001) 和他们使用的 DATEDIFF 函数。虽然我已经解决了他们的问题,但实际上我并不知道 0 在他们使用时会变成什么。
我最初认为它更接近整数溢出而不是真正的转换错误,但事实并非如此。我在带有 DATEDIFF_BIG 和相同错误的 SQL 2016 框中尝试了它。我有一个样本供你们在下面一起玩,以及哪些有效,哪些无效。
/** Setup The Sample */
DECLARE @TestValue DATETIME2(7)
SET @TestValue = '0001-01-01 10:30:00.0000000'
/** Conversion Error
Msg 242, Level 16, State 3, Line 10
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.
*/
SELECT DATEDIFF(MINUTE, 0, @TestValue)
--Also does not work, same error.
SELECT DATEDIFF_BIG(MINUTE, 0, @TestValue)
/** Works */
SELECT DATEDIFF(MINUTE, '1/1/1900', @TestValue)
/** Works */
SELECT …
Run Code Online (Sandbox Code Playgroud) 我有一个 SQL-Server 数据库,其中包含按 datetime2(2) 列分区的大型表。某些(旧)文件组标记为 READ_ONLY。
我定期使用 READ_WRITE_FILEGROUPS 选项进行备份。我可以成功地从读写分区恢复数据。
但是,我无法读取恢复的数据,出现以下错误:
表“dbo.myorders”的索引“pk_myorderid”的一个分区(分区 ID 72057594043105280)驻留在文件组(“YEAR2021”)上,该文件组因脱机、正在恢复或失效而无法访问。这可能会限制查询结果。
如果我将数据类型更改为 DATETIME 或 datetime2(7),则不会发生错误(当然,如果我从恢复的范围请求数据)
除了这个问题之外,其他一切都工作正常。
我创建了一个测试脚本来说明问题。该脚本创建一个测试数据库、填充表、备份和恢复数据库。
如果在此脚本中将 datetime2(7) 更改为 datetime2(2) ,则恢复后数据将变得无法访问。
测试脚本:
USE MASTER
-- Reset environment
IF DB_ID('PartialDatabase') IS NOT NULL
BEGIN
EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'PartialDatabase'
ALTER DATABASE PartialDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE PartialDatabase
END
GO
IF DB_ID('PartialDatabase_Recovery') IS NOT NULL
BEGIN
EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'PartialDatabase_Recovery'
ALTER DATABASE PartialDatabase_Recovery SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE PartialDatabase_Recovery
END
GO
-- Create …
Run Code Online (Sandbox Code Playgroud) 我有这个查询给我一个错误
将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。
询问:
select
COUNT(*)
from
dbo.patient
INNER JOIN
dbo.study on dbo.patient.pk = dbo.study.patient_fk
and dbo.study.study_datetime IS NOT NULL
and dbo.patient.pat_birthdate IS NOT NULL
and dbo.study.study_datetime <= DATEADD(D, -2192, GETDATE())
and dbo.patient.pat_birthdate <= DATEADD(D, -7670, GETDATE());
Run Code Online (Sandbox Code Playgroud)
我读到这可能有助于转换为“DATETIME2”,但我无法弄清楚如何正确转换列“s.study_datetime”,因为该列很可能有一些错误的值作为条目。
下面的代码有问题。
错误:
Msg 206, Level 16, State 2, Procedure usp_TRAC_PSE_Step_12_Resource_Request_OBJECT-Production-Part1, Line 93
Operand type clash: int is incompatible with datetime2
Run Code Online (Sandbox Code Playgroud)
代码:
insert into [dbo].[pse__Resource_Request__c_LOAD]
(OwnerId, pse__End_Date__c, pse__Milestone__c, pse__Percent_Allocated__c, pse__Planned_Bill_Rate__c,
pse__Practice__c, pse__Project__c, pse__Region__c, pse__SOW_Hours__c, pse__Request_Priority__c,
pse__Resource_Request_Name__c, pse__Resource_Role__c, pse__Start_Date__c, pse__Status__c,
Partner_Requested__c, OA_Migration_ID__c, CurrencyIsoCode, Percent_Onsite__c)
select (select [OwnerId] from [dbo].[pse__Proj__c_LOAD] where [OA_Migration_ID__c] = p.id) 'OwnerId'
, case when case when p.custom_35 is null then ISNULL(b.startdate, '01/01/1900 23:59:59.999') + 180 else p.custom_35 end < ISNULL(b.startdate, '01/01/1900 23:59:59.999') then ISNULL(b.startdate, '01/01/1900 23:59:59.999') + 180 else …
Run Code Online (Sandbox Code Playgroud) datetime2 ×8
sql-server ×6
datetime ×2
datatypes ×1
date ×1
partitioning ×1
restore ×1
time ×1