Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Other SQL Server 2008 Topics
 Milliseconds off on only some insertions

Author  Topic 

bmahf
Starting Member

14 Posts

Posted - 2012-04-09 : 18:35:28
Hi all,

I have a new one. I have seen the milliseconds problems that SQL Server has, and have fixed them up to this point by moving to using datetime2 for greater precision. I am running on SQL Server 2008 R2, and I have a procedure that first inserts into one table, and then inserts into another related table. The second table holds zero to many records associated with one record in the first. Both tables have an EffectiveDate time stamp that I need in order to do some queries. Please don't ask why, since this was a very strong decision on the part of the client.

Anyway, I need to be able to pick up records from the second table by equating the EffectiveDate columns in both tables. My algorithm for insertion goes as follows. When I insert into table1 (the master table you might call it), I first declare a datetime2 variable, and set it to GetDate(). I then use that variable to insert the EffectiveDate in both tables.

Now there is a concept of history, so I modify what is in the first table, after first putting the original data into a new table in a related history table. Then I set the Modified date in that table and the EffectiveDate in the secondary table, instead of both EffectiveDate fields.

My problem is that, although when I insert, both the EffectiveDate fields match with each other, when I do a Modify (using update), even though I am doing the same thing of setting a variable with GetDate() and then using that variable to modify the master table and insert into the secondary table, every so often, call it every 10th to 20th modify, the ModifyDate column of the master table is off by 3 to 7 milliseconds, while the EffectiveDate column of the secondary table is always perfectly good.

I am not at all sure what could be happening. Both all three date fields, the EffectiveDate and ModifyDate in the master table, and the EffectiveDate in the secondary table, are set as datetime2. No difference between them, but the first and third of these are always correct compared to a printout of the variable I use, and the second of these is sometimes off by 3 - 7 milliseconds.

Any idea of how I could approach fixing this issue?
Thanks...

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2012-04-09 : 19:53:53
This sounds like a bug. What build number of SQL Server 2008 R2 are you using (@@VERSION)?

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2012-04-10 : 03:26:23
GETDATE() returns a datetime value, which rounds off some milliseconds.



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2012-04-10 : 07:34:01
I hope I don't come across the wrong way, but to me this sounds more like a bug in your code than anything else.

You might try using SYSDATETIME instead of GETDATE to populate your variable witha higher precision timestamp to see if the round-off caused by GETDATE is causing the problem.
Go to Top of Page

bmahf
Starting Member

14 Posts

Posted - 2012-04-10 : 10:03:17
I would love it if this were found to be a bug in my code. That would be easily fixable. The code I am using to plug this data in is as follows (names changed to protect the innocent), where @pTableID is a parameter declared as bigint, and @pTypeList is a second parameter defined as a user-defined table type with one column called StringEntry of type varchar(max). The first bit of code works, but the second doesn't always work. The EffectiveDate column in what I'm calling MyTable1 and the EffectiveDate column in MyTable2 are both always correct. The ModifyDate column in MyTable1 is not always correct. This makes no sense to me. By the way, you can see where I have commented out six different selects to show the value of @tEffectiveDate three times after it is set. They are always the same. I was just wondering if possibly the value might be set at usage time rather than at setting time, but that seems not the case:


=============== Code snippet 1 ========================

DECLARE @tTypes TABLE (TableID bigint, Type int, EffectiveDate datetime2);
DECLARE @tEffectiveDate datetime2
SET @tEffectiveDate = GetDate()

-- select 1, @tEffectiveDate

INSERT [MyTable1] ([TableID], [Data1], [Data2], [Data3], [Data4], [EffectiveDate])
VALUES (@pTableID, @pData1, @pData2, @pData3, @pData4, @tEffectiveDate);

-- select 2, @tEffectiveDate

INSERT @tTypes ([Type])
(SELECT StringEntry AS Type FROM @pTypeList)

UPDATE @tTypes
SET [TableID] = @pTableID,
[EffectiveDate] = @tEffectiveDate

INSERT [MyTable2] ([Table1ID], [Type], [EffectiveDate])
(SELECT [TableID], [Type], [EffectiveDate] FROM @tTypes)

-- select 3, @tEffectiveDate

=============== End Code snippet 1 ====================

=============== Code snippet 2 ========================

DECLARE @tTypes TABLE (TableID bigint, Type int, EffectiveDate datetime2);
DECLARE @tEffectiveDate datetime2
SET @tEffectiveDate = GetDate()

-- select 4, @tEffectiveDate

UPDATE [MyTable1]
SET [Data1] = @pData1,
[Data2] = @pData2,
[Data3] = @pData3,
[Data4] = @pData4,
[ModifyDate] = @tEffectiveDate
WHERE [TableID] = @pTableID

-- select 5, @tEffectiveDate

INSERT @tTypes ([Type])
(SELECT StringEntry AS Type FROM @pTypeList)

UPDATE @tTypes
SET [TableID] = @pTableID,
[EffectiveDate] = @tEffectiveDate

INSERT [MyTable2] ([Table1ID], [Type], [EffectiveDate])
(SELECT [TableID] as Table1ID, [Type], [EffectiveDate] FROM @tTypes)

-- select 6, @tEffectiveDate

=============== End Code snippet 2 ====================

=============== Table definitions ====================

CREATE TABLE [dbo].[MyTable1](
[TableID] [bigint] NOT NULL,
[Data1] [varchar](128) NULL,
[Data2] [int] NOT NULL,
[Data3] [bigint] NULL,
[Data4] [bigint] NULL,
[EffectiveDate] [datetime2(7)] NOT NULL,
[Modifydate] [datetime2(7)] NULL,
CONSTRAINT [PK__target__72F2C0F0214BF109] PRIMARY KEY CLUSTERED
(
[TableID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)

CREATE TABLE [dbo].[MyTable2](
[Table2ID] [int] IDENTITY(1,1) NOT NULL,
[Table1ID] [bigint] NOT NULL,
[Type] [int] NOT NULL,
[EffectiveDate] [datetime2(7)] NOT NULL,
CONSTRAINT [PK__device__2FAC98AB3CF40B7E] PRIMARY KEY CLUSTERED
(
[DeviceID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)

ALTER TABLE [dbo].[MyTable2] WITH CHECK ADD CONSTRAINT [MyTable1_MyTable2_FK1] FOREIGN KEY (
[Table1ID]
)
REFERENCES [dbo].[MyTable1] (
[TableID]
)

=============== End Table definitions ====================

After seeing the comments on my posting, I changed this so that I used SYSDATETIME instead of GETDATE as suggested. That really shows the problem more clearly. I ran my tests, and what I saw every time was that the ModifyDate column in MyTable1 was always being rounded to three decimal places of precision, whereas the EffectiveDate columns in both tables were giving me data to all seven places. The following is the output of one run:


TableID Data1 Data2 Data3 Data4 EffectiveDate Modifydate
1 2 2 2 2 2012-04-10 09:37:58.0403046 2012-04-10 09:37:58.0570000

Table2ID Type Table1ID EffectiveDate
205 1 1 2012-04-10 09:37:58.0403046
206 2 1 2012-04-10 09:37:58.0403046
207 3 1 2012-04-10 09:37:58.0403046
208 4 1 2012-04-10 09:37:58.0403046
209 5 1 2012-04-10 09:37:58.0403046
210 6 1 2012-04-10 09:37:58.0403046
211 1 1 2012-04-10 09:37:58.0563062
212 2 1 2012-04-10 09:37:58.0563062
213 3 1 2012-04-10 09:37:58.0563062
214 4 1 2012-04-10 09:37:58.0563062
215 5 1 2012-04-10 09:37:58.0563062
216 6 1 2012-04-10 09:37:58.0563062


My question now is, why would two fields with the same definition be acting differently, where one is rounding and the other isn't. The only difference I can see is that both actions on EffectiveDate columns are inserts, whereas the one action on ModifyDate is an update. This really shouldn't be the reason why these are acting differently.

Any further ideas on this would be highly appreciated. I'm really quite at a loss with this one.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2012-04-10 : 12:20:39
quote:
Originally posted by SwePeso

GETDATE() returns a datetime value, which rounds off some milliseconds.




The OP is storing the value in a variable and then using that, so the rounding off would have occurred already. Or am I misunderstanding?

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2012-04-10 : 12:36:27
[code]DECLARE @tEffectiveDate datetime2(7)[/code]



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2012-04-10 : 12:40:26
Do you have a trigger on the table?



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2012-04-10 : 12:43:38
quote:
Originally posted by bmahf

one column called StringEntry of type varchar(max).
Do the Modified date come through the VARCHAR parameter?
If so, you are victim of datetime-to-varchar conversion which defaults to datetime.



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

bmahf
Starting Member

14 Posts

Posted - 2012-04-10 : 14:37:15
And SwePeso wins the prize!!!! Thanks. I looked at everything, but didn't even give the trigger a thought. That's because the GetDate() (now SysDateTime()) was being done at the modification time, so I guess in the back on my mind I thought the trigger would just be doing the right thing. But the trigger was using datetime instead of datetime2 to copy EffectiveDate from Inserted to the history table, and was actually doing a completely separate GetDate() to set ModifyDate, instead of pulling it from Inserted.

Thanks again. It's working spankingly now...
B
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2012-04-10 : 14:40:35
Way to go, Peter!

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2012-04-11 : 03:23:59
Thank you both.



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page
   

- Advertisement -