Clickhouse datetime comparison not working as expected - database

I am trying to compare the datetime, in clickhouse. But it's seems it's working in some wired way.
I have a column in my table which I want to compare with (now(),'UTC').
If the value of datetime in that column is less then the (now(),'UTC') Time than I wanna select data from that record.
I have created the table like
create table my_table (`mytime` DateTime, `data' [type]) ENGINE= engine
I want the queue like
Select data from my_table where mytime < toDateTime(now(), 'UTC')
Even if mytime > toDateTime(now(), 'UTC') it always considers mytime < toDateTime(now(), 'UTC')

It seems to me that something may up with the way you inserted data or your ClickHouse version has a bug.
The following example shows how to do what you are attempting in a way that works on my 19.15.4.10 server as expected to select only the earlier row. Note the select sleep() to ensure now() invocations are different.
drop table if exists my_table;
create table my_table (mytime DateTime, data String) engine = Memory;
insert into my_table values(now(), 'a');
select sleep(1);
insert into my_table values(toDateTime('2020-01-01 00:00:00', 'UTC'), 'b');
select * from my_table where mytime < now();
select * from my_table where mytime < toDateTime(now(), 'UTC');
On my server it does not matter whether you select now() or convert it. I also tried the way you originally defined the table and that works too. Hence the thought that something is up with your data.

The reason behind this issue was in clickhouse, it takes DateTime and DateTime('UTC') as different objects, therefore the comparison between them does not work as expected. Since I wanted to make the comparison with (now(),'UTC'), I have to change the type of
mytime as DateTime ('UTC').
I have to change the table as
create table my_table (`mytime` DateTime ('UTC'), `data' [type]) ENGINE= engine

Related

SQL server GetDate in trigger called sequentially has the same value

I have a trigger on a table for insert, delete, update that on the first line gets the current date with GetDate() method.
The trigger will compare the deleted and inserted table to determine what field has been changed and stores in another table the id, datetime and the field changed. This combination must be unique
A stored procedure does an insert and an update sequentially on the table. Sometimes I get a violation of primary key and I suspect that the GetDate() returns the same value.
How can I make the GetDate() return different values in the trigger.
EDIT
Here is the code of the trigger
CREATE TRIGGER dbo.TR
ON table
FOR DELETE, INSERT, UPDATE
AS
BEGIN
SET NoCount ON
DECLARE #dt Datetime
SELECT #dt = GetDate()
insert tableLog (id, date, field, old, new)
select I.id, #dt, 'field', D.field, I.field
from INSERTED I LEFT JOIN DELETED D ON I.id=D.id
where IsNull(I.field, -1) <> IsNull(D.field, -1)
END
and the code of the calls
...
insert into table ( anotherfield)
values (#anotherfield)
if ##rowcount=1 SET #ID=##Identity
...
update table
set field = #field
where Id = #ID
...
Sometimes the GetDate() between the 2 calls (insert and update) takes 7 milliseconds and sometimes it has the same value.
That's not exactly full solution but try using SYSDATETIME instead and of course make sure that target table can store up datetime2 up to microseconds.
Note that you can't force different datetime regardless of precision (unless you will start counting up to ticks) as stuff can just happen at the same time wihthin given precision.
If stretching up to microseconds won't solve the issue on practical level, I think you will have to either redesign this logging schema (perhaps add identity column on top of what you have) or add some dirty trick - like make this insert in try catch block and add like microsecond (nanosecond?) in a loop until you insert successfully. Definitely not s.t. I would recommend.
Look at this answer: SQL Server: intrigued by GETDATE()
If you are inserting multiple ROWS, they will all use the same value of GetDate(), so you can try wrapping it in a UDF to get unique values. But as I said, this is just a guess unless you post the code of your trigger so we can see what you are actually doing?
It sounds like you're trying to create an audit trail - but now you want to forge some of the entries?
I'd suggest instead adding a rowversion column to the table and including that in your uniqueness criteria - either instead of or as well as the datetime value that is being recorded.
In this way, even if two rows are inserted with identical date/time data, you can still tell the actual insertion order.

Automatic adding current time in SQL Server 2012

I have table with a column of datatype time(4).
When I'm inserting values into the table I need to auto insert just the current time with milliseconds (without date) into that column. I have tried with time stamp, date time... but without any success.
If you want to get the current time in SQL Server 2012, just use the CAST operator to achieve this:
SELECT
CAST(SYSDATETIME() AS TIME(4))
This will get the current date & time, and cast this to just the time, as you need it.
To achieve automatic entry of time values when a new row is added, you can use the above expression in a default constraint. For example:
DECLARE #T AS table
(
SomeValue integer NOT NULL,
TheTime time(4) NOT NULL
DEFAULT CAST(SYSDATETIME() AS time(4))
);
INSERT #T (SomeValue)
VALUES (1);
SELECT
SomeValue,
TheTime
FROM #T;
As far as I understand, this is what you may be looking for:
SELECT GETDATE() 'Today',
CONVERT(TIME(4),GETDATE()) 'time_only'
You could use the above conversion in your insert statement as following:
INSERT INTO TABLEA (
column1
,column2
,record_insert_time
)
VALUES (
value1
,value2
,CONVERT(TIME(4), GETDATE())
);

T-SQL Select where Subselect or Default

I have a SELECT that retrieves ROWS comparing a DATETIME field to the highest available value of another TABLE.
The Two Tables have the following structure
DeletedRecords
- Id (Guid)
- RecordId (Guid)
- TableName (varchar)
- DeletionDate (datetime)
And Another table which keep track of synchronizations using the following structure
SynchronizationLog
- Id (Guid)
- SynchronizationDate (datetime)
In order to get all the RECORDS that have been deleted since the last synchronization, I run the following SELECT:
SELECT
[Id],[RecordId],[TableName],[DeletionDate]
FROM
[DeletedRecords]
WHERE
[TableName] = '[dbo].[Person]'
AND [DeletionDate] >
(SELECT TOP 1 [SynchronizationDate]
FROM [dbo].[SynchronizationLog]
ORDER BY [SynchronizationDate] DESC)
The problem occurs if I do not have synchronizations available yet, the T-SQL SELECT does not return any row while it should returns all the rows cause there are no synchronization records available.
Is there a T-SQL function like COALESCE that I can use with DateTime?
Your subquery should look like something like this:
SELECT COALESCE(MAX([SynchronizationDate]), '0001-01-01')
FROM [dbo].[SynchronizationLog]
It says: Get the last date, but if there is no record (or all values are NULL), then use the '0001-01-01' date as start date.
NOTE '0001-01-01' is for DATETIME2, if you are using the old DATETIME data type, it should be '1753-01-01'.
Also please note (from https://msdn.microsoft.com/en-us/library/ms187819(v=sql.100).aspx)
Use the time, date, datetime2 and datetimeoffset data types for new work. These types align with the SQL Standard. They are more portable. time, datetime2 and datetimeoffset provide more seconds precision. datetimeoffset provides time zone support for globally deployed applications.
EDIT
An alternative solution is to use NOT EXISTS (you have to test it if its performance is better or not):
SELECT
[Id],[RecordId],[TableName],[DeletionDate]
FROM
[DeletedRecords] DR
WHERE
[TableName] = '[dbo].[Person]'
AND NOT EXISTS (
SELECT 1
FROM [dbo].[SynchronizationLog] SL
WHERE DR.[DeletionDate] <= SL.[SynchronizationDate]
)

how to match datetime column by passing date only in SQL Server

I have a Table, where there is a datetime Column, I want to match this column by passing only date & datetime column is heaving date & time both (i.e 25/06/2013 4:54:12 PM).
It's usually best in this situation to leave the column alone and do some manipulation on your parameter. So if you're passing a #SearchDate parameter, I'd do:
SELECT abc from mytable
where
datetimecolumn >= #SearchDate and
datetimecolumn < DATEADD(day,1,#SearchDate)
I believe that, if you're running on SQL Server 2008 or later, and use the following:
SELECT abc from mytable
where
CAST(datetimecolumn as date) = #SearchDate
That an index on datetimecolumn can be used. Whereas I'm certain that an index is usable given my first query. You should, in general, be wary of calling functions on columns - such actions can often cripple performance by forcing a full table scan.
And unlike you're accepted answer, I would always seek to avoid treating dates as strings - as soon as you do, you're inviting all kinds of issues around formatting.
datetime format in t-sql is a little tricky, first of all you need to be aware of date time (i.e 25/06/2013 4:54:12 PM) is greater than 25/06/2013 , so you need to use > and < operators, for ![enter image description here][1]example orderdate > '20130625' AND orderdate < '20130626' , sql server considers 'YYYYMMDD' as global datetime format and it is language independent. take a look at the attachement...
try -:
DECLARE #givenDate DATE;
DECLARE #t AS TABLE (
fld_DateTime DATETIME
)
SET #givenDate = '2013-04-24'
INSERT INTO #t ( fld_DateTime )
VALUES ('2013-04-23 14:37:59.580')
, ('2013-04-23 14:59:02.403')
, ('2013-04-23 15:15:36.890')
, ('2013-04-24 08:57:45.800')
, ('2013-04-24 10:44:56.663')
, ('2013-04-24 13:18:20.760')
, ('2013-04-25 09:38:55.503')
, ('2013-06-28 09:20:11.007')
, ('2013-06-28 12:37:04.973')
, ('2013-06-28 12:38:50.130')
, ('2013-07-03 15:27:36.167')
SELECT fld_DateTime
FROM #t
WHERE fld_DateTime >= #givenDate AND fld_DateTime < DATEADD(DAY, 1, #givenDate)
You can use CAST and CONVERT functions for converting date
http://msdn.microsoft.com/en-us/library/ms187928(v=sql.105).aspx
For example
select *
from datetimetable
where convert(char(10), datetimecolumn, 103) = '25/12/2013'
BUT remember, that this code is for testing purposes only.
I recommend you to play with different parameters of CONVERT function
in order to better understand it (and to play with different sizes of the first parameter)
please, view solutions in the other answers on your question to find out the best one for your environment

Question About DateCreated and DateModified Columns - SQL Server

CREATE TABLE Customer
(
customerID int identity (500,20) CONSTRAINT
.
.
dateCreated datetime DEFAULT GetDate() NOT NULL,
dateModified datetime DEFAULT GetDate() NOT NULL
);
When i insert a record, dateCreated and dateModified gets set to default date/time. When i update/modify the record, dateModified and dateCreated remains as is? What should i do?
Obviously, i need to dateCreated value to remain as was inserted the first time and dateModified keeps changing when a change/modification occurs in the record fields.
In other words, can you please write a sample quick trigger? I don't know much yet...
You might want to look at creting an update trigger to update this value for you
Have a look at something like
CREATE TABLE Vals(
ID INT,
Val VARCHAR(10),
DateCreated DATETIME DEFAULT GetDate(),
DateUpdated DATETIME DEFAULT GetDate()
)
GO
CREATE TRIGGER Upd ON Vals
AFTER UPDATE
AS
UPDATE Vals
SET DateUpdated = GetDate()
FROM Vals INNER JOIN
inserted ON Vals.ID = inserted.ID
Go
INSERT INTO Vals (ID, Val) SELECT 1, 'A'
SELECT *
FROM Vals
GO
UPDATE Vals SET Val = 'B'
SELECT *
FROM Vals
GO
DROP TABLE Vals
GO
UPDATE
Customer
SET
... = NewValue,
dateModified = DEFAULT
WHERE
...
I'd use this rather than dateModified = GETDATE() so GETDATE() is only used once (say you want to change to GETUTCDATE() in future)
Or a trigger if you have multiple update paths...?
When i insert a record, dateCreated
and dateModified gets set to default
date/time. When i update/modify the
record, dateModified and dateCreated
remains as is? What should i do?
A Column default is only used when INSERTing and not by an UPDATE. The default will be used by the INSERT command if you do not supply the column or issue the DEFAULT keyword in the INSERT.
INSERT INTO Customer (col1, col2)
VALUES (..,..) ---get default for dateCreated & dateModified
INSERT INTO Customer (col1, col2,dateCreated)
VALUES (..,..,DEFAULT) ---get default for dateCreated & dateModified
INSERT INTO Customer (col1, col2,dateCreated,dateModified)
VALUES (..,..,DEFAULT,DEFAULT) ---get default for dateCreated & dateModified
INSERT INTO Customer (col1, col2,dateCreated,dateModified)
VALUES (..,..,'1/1/2010',DEFAULT) ---only get default for dateModified
INSERT INTO Customer (col1, col2,dateCreated,)
VALUES (..,..,'1/1/2010') ---only get default for dateModified
INSERT INTO Customer (col1, col2,dateCreated,dateModified)
VALUES (..,..,'1/1/2010','1/2/2010') ---no defaults for dateCreated & dateModifie
I like using a local variable set that the top of the procedure:
DECLARE #RunDate datetime
SET #RunDate=GETDATE()
I then use that within the procedure, so all changes (even on multiple tables) have the exact same date to the millisecond. I also prefer the dateModified column to allow nulls and not have a default, when it is inserted, it has been created not modified, I'll set the dateModified when it is actually modified.
then use:
UPDATE Customer
SET importantColumn=
,dateModified = #RunDate
WHERE ...
UPDATE CustomerPrice
SET importantColumn=
,dateModified = #RunDate
WHERE ...
#astander is right, you should just use an update trigger if you want this automated. My update triggers are slightly different (I use the 'inserted' virtual table). Here's one that should fit your schema (rename however you see fit):
CREATE TRIGGER [CustomerDateModifiedTrigger] ON [dbo].[Customer]
FOR UPDATE
AS
UPDATE Customer
SET dateModified = GETDATE()
FROM Customer c
INNER JOIN inserted i ON c.customerID = i.customerID
#Kronass, you don't have any idea about what uou are saying!
timestamp is the synonym for the rowversion data type and is subject to the behavior of data type synonyms. In DDL statements, use rowversion instead of timestamp wherever possible. For more information, see Data Type Synonyms (Transact-SQL).
The Transact-SQL timestamp data type is different from the timestamp data type defined in the ISO standard.
The timestamp syntax is deprecated. This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
rowversion (Transact-SQL) Is a data type that exposes automatically generated, unique binary numbers within a database. rowversion is generally used as a mechanism for version-stamping table rows. The storage size is 8 bytes. The rowversion data type is just an incrementing number and does not preserve a date or a time. To record a date or time, use a datetime2 data type.
1) Be sure to create the index for the primary key. (I just uncovered a mistake of this type recently.)
2) You can use one INSERT/UPDATE trigger instead of separate triggers at the price of a tiny loss of efficiency. If insert.DateCreated is null, then update Vals.DateCreated, otherwise update Vals.DateModified.
There is a datatype in SQL Server Called timestamp. which keep track of the row version for each time you modify the row.
Or if you want you can use a trigger and change the ModifiedDate Column.

Resources