'加法' SQL中的日期字段 - 任何想法?

时间:2016-01-05 00:45:49

标签: sql sql-server datetime integrity

我创建的应用程序本质上是两个数据库之间的完整性检查 - 一个是MSSQL,另一个是旧的提供程序Btrieve。作为要求的一部分,需要比较每个表的所有列以确保数据匹配。目前,我们循环遍历每个表,获取两个DB中表的基本计数,然后深入研究列。对于数字字段,我们执行简单的SUM,对于文本字段,我们总结每行的列长度。如果这两个数据库中的匹配项匹配,则表明数据已正确迁移,这是一个很好的指标。

这一切都很好,但我需要为datetime字段开发类似的东西。显然,我们无法真正理解这些领域,所以我想知道是否有人对最佳方法有所了解。我想的可能是某个日期以来的秒数,但数字会很大。

还有其他想法吗?谢谢!

5 个答案:

答案 0 :(得分:0)

在数字字段行的SQL中使用“Except”,您可以比较两个表中的日期计数。对于Old源,您可以使用excel或在本机数据库中生成select语句,并将其带到SQL Server。出于演示目的,我使用了两个表并显示了以下示例。

IF  EXISTS (SELECT * FROM sys.objects
           WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[DateCompareOld]') AND
           TYPE IN (N'U'))
DROP TABLE [dbo].[DateCompareOld]
GO

CREATE TABLE dbo.DateCompareOld 
(
AsOf DATETIME 
)

INSERT INTO DateCompareOld
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' 


IF  EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[DateCompareNew]') AND TYPE IN (N'U'))
DROP TABLE [dbo].[DateCompareNew]
GO

CREATE TABLE dbo.DateCompareNew 
(
AsOf DATETIME 
)

INSERT INTO DateCompareNew
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' 

SELECT AsOf,COUNT(*) AsOfCount
FROM DateCompareOld
GROUP BY AsOf 
Except  
SELECT AsOf,COUNT(*) AsOfCount
FROM DateCompareNew
GROUP BY AsOf 

答案 1 :(得分:0)

除非数据库中行使用的日期范围极端(如天文星的出生和死亡日期),否则将日期转换为整数应该同样有效。这可以通过多种方式完成,并且稍微特定于数据库,但将2016-01-04转换为20,160,104将会正常工作。

即使SQL Server允许ORD(date_field)类表达式获取内部表示。但这也可以通过便携式,系统无关的方式完成,如

 datediff(day, 'January 1, 1901', date_field)

如果跟踪天数就足够了,或者

 datediff(second, 'January 1, 1901', date_field)

如果需要跟踪秒数。

答案 2 :(得分:0)

对我来说最直接的答案是将日期或日期时间字段转换为具有相同格式的整数。只要您的格式使用前导零,YYYYMMDD或YYYYMMDDHHmmss就可以正常工作。在SQL Server中,您可以执行以下操作:

SELECT SUM(CAST(REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),DateTimeColumn,120),' ',''),':',''),'-','') AS BIGINT)) .....

或者,如果您使用时间,可以将它们转换为给定日期('1970-01-01')的天数或给定日期('1970-01-01 00:00:00')的秒数。

SELECT SUM(DATEDIFF(DAY,'19700101',DateColumn)) ....

我对Btrieve不太熟悉,不知道格式化日期可以使用哪些函数。

答案 3 :(得分:0)

也许它没有多大帮助,也许是:

declare @d1 datetime; set @d1 = '2016-01-05 12:09'
declare @d2 datetime; set @d2 = '1970-04-05 07:09'
declare @d3 datetime; set @d3 = '1999-12-12 23:05'
declare @d4 datetime; set @d4 = '1999-12-12 23:06'

declare @i1 bigint
declare @i2 bigint
declare @i3 bigint
declare @i4 bigint

select @i1 = convert( bigint, convert( timestamp, @d1 ) ) 
select @i2 = convert( bigint, convert( timestamp, @d2 ) )
select @i3 = convert( bigint, convert( timestamp, @d3 ) )
select @i4 = convert( bigint, convert( timestamp, @d4 ) )

select @i1
select @i2
select @i3
select @i4

select @i1 ^ @i2 ^ @i3 ^ @i4

答案 4 :(得分:-1)

我认为你可以在SQL Server端做这样的事情来找到列的中心("平均值")值。然后在Btrieve端使用该值,以避免在我猜测您受到更多约束的情况下出现溢出问题。

-- January 1, 2000 value pulled out of the air as a stab in the dark
select
    dataadd(
        second,
        avg(cast(datediff(datediff(second, '20000101', <data>) as bigint)),
        '20000101'
    ) /* find the center */

如果您不得不求助于Btrieve的浮点类型或将扫描划分为更小的范围以避免中间总和过大,我不会感到惊讶。并且您可能希望使用游标并随机化行的顺序,这样您就不会按照导致溢出的排序顺序命中它们。在这一点上,我只是猜测,因为我还没有看到任何数据,而且我对Btrieve的了解是如此古老而且极少。

我也有一种感觉,这种努力的一部分都是为了满足非技术利益相关者的一些不安。我确信你可以提出更好的校验和和哈希,但是这个总结概念是他们能够掌握的概念,并且可以让他们放心,而不是更容易快速实施。