How to create timestamp column with default value 'now'? - sql

How to create a table with a timestamp column that defaults to DATETIME('now')?
Like this:
CREATE TABLE test (
id INTEGER PRIMARY KEY AUTOINCREMENT,
t TIMESTAMP DEFAULT DATETIME('now')
);
This gives an error.

As of version 3.1.0 you can use CURRENT_TIMESTAMP with the DEFAULT clause:
If the default value of a column is CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP, then the value used in the new row is a text representation of the current UTC date and/or time. For CURRENT_TIME, the format of the value is "HH:MM:SS". For CURRENT_DATE, "YYYY-MM-DD". The format for CURRENT_TIMESTAMP is "YYYY-MM-DD HH:MM:SS".
CREATE TABLE test (
id INTEGER PRIMARY KEY AUTOINCREMENT,
t TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

according to dr. hipp in a recent list post:
CREATE TABLE whatever(
....
timestamp DATE DEFAULT (datetime('now','localtime')),
...
);

It's just a syntax error, you need parentheses: (DATETIME('now'))
The documentation for the DEFAULT clause says:
If the default value of a column is an expression in parentheses, then the expression is evaluated once for each row inserted and the results used in the new row.
If you look at the syntax diagram you'll also notice the parentheses around 'expr'.

This is a full example based on the other answers and comments to the question. In the example the timestamp (created_at-column) is saved as unix epoch UTC timezone and converted to local timezone only when necessary.
Using unix epoch saves storage space - 4 bytes integer vs. 24 bytes string when stored as ISO8601 string, see datatypes. If 4 bytes is not enough that can be increased to 6 or 8 bytes.
Saving timestamp on UTC timezone makes it convenient to show a reasonable value on multiple timezones.
SQLite version is 3.8.6 that ships with Ubuntu LTS 14.04.
$ sqlite3 so.db
SQLite version 3.8.6 2014-08-15 11:46:33
Enter ".help" for usage hints.
sqlite> .headers on
create table if not exists example (
id integer primary key autoincrement
,data text not null unique
,created_at integer(4) not null default (strftime('%s','now'))
);
insert into example(data) values
('foo')
,('bar')
;
select
id
,data
,created_at as epoch
,datetime(created_at, 'unixepoch') as utc
,datetime(created_at, 'unixepoch', 'localtime') as localtime
from example
order by id
;
id|data|epoch |utc |localtime
1 |foo |1412097842|2014-09-30 17:24:02|2014-09-30 20:24:02
2 |bar |1412097842|2014-09-30 17:24:02|2014-09-30 20:24:02
Localtime is correct as I'm located at UTC+2 DST at the moment of the query.

It may be better to use REAL type, to save storage space.
Quote from 1.2 section of Datatypes In SQLite Version 3
SQLite does not have a storage class set aside for storing dates
and/or times. Instead, the built-in Date And Time Functions of SQLite
are capable of storing dates and times as TEXT, REAL, or INTEGER
values
CREATE TABLE test (
id INTEGER PRIMARY KEY AUTOINCREMENT,
t REAL DEFAULT (datetime('now', 'localtime'))
);
see column-constraint .
And insert a row without providing any value.
INSERT INTO "test" DEFAULT VALUES;

It is syntax error because you did not write parenthesis
if you write
Select datetime('now')
then it will give you utc time but if you this write it query then you must add parenthesis before this
so (datetime('now')) for UTC Time.
for local time same
Select datetime('now','localtime')
for query
(datetime('now','localtime'))

If you want millisecond precision, try this:
CREATE TABLE my_table (
timestamp DATETIME DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
);
This will save the timestamp as text, though.

This alternative example stores the local time as Integer to save the 20 bytes. The work is done in the field default, Update-trigger, and View.
strftime must use '%s' (single-quotes) because "%s" (double-quotes) threw a 'Not Constant' error on me.
Create Table Demo (
idDemo Integer Not Null Primary Key AutoIncrement
,DemoValue Text Not Null Unique
,DatTimIns Integer(4) Not Null Default (strftime('%s', DateTime('Now', 'localtime'))) -- get Now/UTC, convert to local, convert to string/Unix Time, store as Integer(4)
,DatTimUpd Integer(4) Null
);
Create Trigger trgDemoUpd After Update On Demo Begin
Update Demo Set
DatTimUpd = strftime('%s', DateTime('Now', 'localtime')) -- same as DatTimIns
Where idDemo = new.idDemo;
End;
Create View If Not Exists vewDemo As Select -- convert Unix-Times to DateTimes so not every single query needs to do so
idDemo
,DemoValue
,DateTime(DatTimIns, 'unixepoch') As DatTimIns -- convert Integer(4) (treating it as Unix-Time)
,DateTime(DatTimUpd, 'unixepoch') As DatTimUpd -- to YYYY-MM-DD HH:MM:SS
From Demo;
Insert Into Demo (DemoValue) Values ('One'); -- activate the field Default
-- WAIT a few seconds --
Insert Into Demo (DemoValue) Values ('Two'); -- same thing but with
Insert Into Demo (DemoValue) Values ('Thr'); -- later time values
Update Demo Set DemoValue = DemoValue || ' Upd' Where idDemo = 1; -- activate the Update-trigger
Select * From Demo; -- display raw audit values
idDemo DemoValue DatTimIns DatTimUpd
------ --------- ---------- ----------
1 One Upd 1560024902 1560024944
2 Two 1560024944
3 Thr 1560024944
Select * From vewDemo; -- display automatic audit values
idDemo DemoValue DatTimIns DatTimUpd
------ --------- ------------------- -------------------
1 One Upd 2019-06-08 20:15:02 2019-06-08 20:15:44
2 Two 2019-06-08 20:15:44
3 Thr 2019-06-08 20:15:44

Related

I cant do a select by one of its parameters even if it exists in the database. Encoding issues? PostgreSQL

I have a postgresql database snapshot with the following structure
id (integer / autoincrement)
address (varchar)
balance (integer)
datetime (date)
CREATE TABLE public.snapshots
(
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
address character varying COLLATE pg_catalog."default",
balance bigint,
datetime date,
CONSTRAINT snapshots_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE public.snapshots
OWNER to postgres;
But it has some weird issues, for example I have this data
Some example of data is:
12531 "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 34567733 "2020-09-01"
12532 "0x8cfb1D4269f0daa003CDEa567aC8f76c0647764a" 34547733 "2020-09-01"
12533 "0xdAC17F958D2ee523a2206206994597C13D831ec7" 34512333 "2020-09-01"
12534 "0x94d863173EE77439E4292284fF13fAD54b3BA182" 34511133 "2020-09-01"
12535 "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 34555733 "2020-09-01"
12536 "0x9287130ba603359E9621ae89c4164613BF239Fa2" 34327733 "2020-09-01"
Well the problem is now that I do this select
SELECT * FROM snapshots where address = '0x9287130ba603359E9621ae89c4164613BF239Fa2'
0 returns
But if i do
SELECT id, address, balance, datetime
FROM public.snapshots where datetime = '2020-09-01' and balance = 34327733;
It does return the result
What is going on? It works with some addresses, but doesn't with others
The issue was related with tolowercase lol, I was doing the select in my script with uppercase
There are different collate and encoding in SQL ( lc_collate default) which are set during
database creation.
Now you have to find out what is default value.
what's the default collate? Use SHOW to discover that.
SHOW lc_collate;
Now set
SET CLIENT_ENCODING TO 'UTF8';
or
SET CLIENT_ENCODING TO 'LATIN9';
or whatever is you server encoding
https://www.postgresql.org/docs/9.5/multibyte.html
Then write query it will match the data.
SELECT * FROM snapshots where address = '0x9287130ba603359E9621ae89c4164613BF239Fa2'

How to insert the default time correctly? [duplicate]

How do you set a default value for a MySQL Datetime column?
In SQL Server it's getdate(). What is the equivalant for MySQL? I'm using MySQL 5.x if that is a factor.
IMPORTANT EDIT:
It is now possible to achieve this with DATETIME fields since MySQL 5.6.5, take a look at the other post below...
Previous versions can't do that with DATETIME...
But you can do it with TIMESTAMP:
mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)
mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str | varchar(32) | YES | | NULL | |
| ts | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)
mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+------+---------------------+
| str | ts |
+------+---------------------+
| demo | 2008-10-03 22:59:52 |
+------+---------------------+
1 row in set (0.00 sec)
mysql>
CAVEAT: IF you define a column with CURRENT_TIMESTAMP ON as default, you will need to ALWAYS specify a value for this column or the value will automatically reset itself to "now()" on update. This means that if you do not want the value to change, your UPDATE statement must contain "[your column name] = [your column name]" (or some other value) or the value will become "now()". Weird, but true. I am using 5.5.56-MariaDB
In version 5.6.5, it is possible to set a default value on a datetime column, and even make a column that will update when the row is updated. The type definition:
CREATE TABLE foo (
`creation_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)
Reference:
http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html
MySQL (before version 5.6.5) does not allow functions to be used for default DateTime values. TIMESTAMP is not suitable due to its odd behavior and is not recommended for use as input data. (See MySQL Data Type Defaults.)
That said, you can accomplish this by creating a Trigger.
I have a table with a DateCreated field of type DateTime. I created a trigger on that table "Before Insert" and "SET NEW.DateCreated=NOW()" and it works great.
For me the trigger approach has worked the best, but I found a snag with the approach. Consider the basic trigger to set a date field to the current time on insert:
CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
FOR EACH ROW SET NEW.dateAdded = NOW();
This is usually great, but say you want to set the field manually via INSERT statement, like so:
INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');
What happens is that the trigger immediately overwrites your provided value for the field, and so the only way to set a non-current time is a follow up UPDATE statement--yuck! To override this behavior when a value is provided, try this slightly modified trigger with the IFNULL operator:
CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());
This gives the best of both worlds: you can provide a value for your date column and it will take, and otherwise it'll default to the current time. It's still ghetto relative to something clean like DEFAULT GETDATE() in the table definition, but we're getting closer!
I was able to solve this using this alter statement on my table that had two datetime fields.
ALTER TABLE `test_table`
CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
This works as you would expect the now() function to work. Inserting nulls or ignoring the created_dt and updated_dt fields results in a perfect timestamp value in both fields. Any update to the row changes the updated_dt. If you insert records via the MySQL query browser you needed one more step, a trigger to handle the created_dt with a new timestamp.
CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
FOR EACH ROW SET NEW.created_dt = NOW();
The trigger can be whatever you want I just like the naming convention [trig]_[my_table_name]_[insert]
You can use triggers to do this type of stuff.
CREATE TABLE `MyTable` (
`MyTable_ID` int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData` varchar(10) NOT NULL ,
`CreationDate` datetime NULL ,
`UpdateDate` datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;
CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
-- Set the creation date
SET new.CreationDate = now();
-- Set the udpate date
Set new.UpdateDate = now();
END;
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
-- Set the udpate date
Set new.UpdateDate = now();
END;
For all those who lost heart trying to set a default DATETIME value in MySQL, I know exactly how you feel/felt. So here is is:
ALTER TABLE `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0
Carefully observe that I haven't added single quotes/double quotes around the 0
I'm literally jumping after solving this one :D
If you have already created the table then you can use
To change default value to current date time
ALTER TABLE <TABLE_NAME>
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
To change default value to '2015-05-11 13:01:01'
ALTER TABLE <TABLE_NAME>
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';
MySQL 5.6 has fixed this problem.
ALTER TABLE mytable CHANGE mydate datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP'
this is indeed terrible news.here is a long pending bug/feature request for this. that discussion also talks about the limitations of timestamp data type.
I am seriously wondering what is the issue with getting this thing implemented.
You can use now() to set the value of a datetime column, but keep in mind that you can't use that as a default value.
I'm running MySql Server 5.7.11 and this sentence:
ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
is not working. But the following:
ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'
just works.
As a sidenote, it is mentioned in the mysql docs:
The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'.
even if they also say:
Invalid DATE, DATETIME, or TIMESTAMP values are converted to the “zero” value of the appropriate type ('0000-00-00' or '0000-00-00 00:00:00').
For all who use the TIMESTAMP column as a solution i want to second the following limitation from the manual:
http://dev.mysql.com/doc/refman/5.0/en/datetime.html
"The TIMESTAMP data type has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC. It has varying properties, depending on the MySQL version and the SQL mode the server is running in. These properties are described later in this section. "
So this will obviously break your software in about 28 years.
I believe the only solution on the database side is to use triggers like mentioned in other answers.
While defining multi-line triggers one has to change the delimiter as semicolon will be taken by MySQL compiler as end of trigger and generate error.
e.g.
DELIMITER //
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
-- Set the udpate date
Set new.UpdateDate = now();
END//
DELIMITER ;
Working fine with MySQL 8.x
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
`dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `mobile_UNIQUE` (`mobile`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Here is how to do it on MySQL 5.1:
ALTER TABLE `table_name` CHANGE `column_name` `column_name`
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
I have no clue why you have to enter the column name twice.
While you can't do this with DATETIME in the default definition, you can simply incorporate a select statement in your insert statement like this:
INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))
Note the lack of quotes around the table.
For MySQL 5.5
If you are trying to set default value as NOW(), I don't think MySQL supports that. In MySQL, you cannot use a function or an expression as the default value for any type of column, except for the TIMESTAMP data type column, for which you can specify the CURRENT_TIMESTAMP as the default.
I think it simple in mysql since mysql the inbuilt function called now() which gives current time(time of that insert).
So your query should look like similarly
CREATE TABLE defaultforTime(
`creation_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`modification_time` DATETIME default now()
);
Thank you.
If you set ON UPDATE CURRENT_TIMESTAMP it will take current time when row data update in table.
CREATE TABLE bar(
`create_time` TIMESTAMP CURRENT_TIMESTAMP,
`update_time` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
CREATE TABLE `testtable` (
`id` INT(10) NULL DEFAULT NULL,
`colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)
In the above query to create 'testtable', i used '1999-12-12 12:12:12' as default value for DATETIME column colname
Use the following code
DELIMITER $$
CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
BEGIN
SET new.datefield = NOW();
END $$
DELIMITER ;
If you are trying to set default value as NOW(),MySQL supports that you have to change the type of that column TIMESTAMP instead of DATETIME. TIMESTAMP have current date and time as default..i think it will resolved your problem..
Take for instance If I had a table named 'site' with a created_at and an update_at column that were both DATETIME and need the default value of now, I could execute the following sql to achieve this.
ALTER TABLE `site` CHANGE `created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `site` CHANGE `created_at` `created_at` DATETIME NULL DEFAULT NULL;
ALTER TABLE `site` CHANGE `updated_at` `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `site` CHANGE `updated_at` `updated_at` DATETIME NULL DEFAULT NULL;
The sequence of statements is important because a table can not have two columns of type TIMESTAMP with default values of CUREENT TIMESTAMP
This is my trigger example:
/************ ROLE ************/
drop table if exists `role`;
create table `role` (
`id_role` bigint(20) unsigned not null auto_increment,
`date_created` datetime,
`date_deleted` datetime,
`name` varchar(35) not null,
`description` text,
primary key (`id_role`)
) comment='';
drop trigger if exists `role_date_created`;
create trigger `role_date_created` before insert
on `role`
for each row
set new.`date_created` = now();
You can resolve the default timestamp. First consider which character set you are using for example if u taken utf8 this character set support all languages and if u taken laten1 this character set support only for English. Next setp if you are working under any project you should know client time zone and select you are client zone. This step are mandatory.

Create table in SAS using DB2 timestamp

We've recently gotten the accelerator (IDAA) working on our DB2, which I mainly access using SAS.
This requires us, due to network issues, to create tables first, before inserting rows.
My problem is creating a table with the correct timestamp format, I can create the table using a select statement, but this is very slow, but here I can see the format in SAS is DATETIME30.6
But if I try something like:
RSUBMIT prod_acc;
Proc delete data=user.table1; run; %PUT &sqlxrc &sqlxmsg;
proc sql inobs=MAX stimer feedback noerrorstop;
connect to db2(ssid=server);
create table user.table1
(
date datetime30.6
,reference char(16)
,transact char(20)
,alias char(60)
,amount decimal(15,2)
,currency char(3)
);
%PUT &sqlxrc &sqlxmsg;
quit;
run;
Which gives the following in the log
(
15 date datetime30.6
-----------
1 22
200
WARNING 1-322: Assuming the symbol DATE was misspelled as datetime30.
ERROR 22-322: Syntax error, expecting one of the following: a quoted string,
an integer constant, ), ',', CHECK, DISTINCT, FORMAT, INFORMAT, LABEL, LEN,
LENGTH, NOT, PRIMARY, REFERENCES, TRANSCODE, UNIQUE, ^, ~.
ERROR 200-322: The symbol is not recognized and will be ignored.
And if I look in DB2, the column has the type timestmp which SAS don't recognize as a type.
(
31 date timestmp
--------
22
76
ERROR 22-322: Syntax error, expecting one of the following: CHAR, CHARACTER, DATE, DEC,
DECIMAL, DOUBLE, FLOAT, INT, INTEGER, NUM, NUMERIC, REAL, SMALLINT, VARCHAR.
ERROR 76-322: Syntax error, statement will be ignored.
Tried googling and found a lot of different versions of answers, but nothing I can see is relevant to this, the closest was something about manually creating the format, but I can't figure out how to do that.
Any ideas?
It is probably more natural in SAS to define a table's structure using a DATA step rather than PROC SQL.
data userdb.table1;
stop;
length date 8 reference $16 transact $20 alias $60 amount 8 currency $3 ;
format date datetime30.6 amount 15.2 ;
run;
If your libref is pointing to a database then you should be able to use DBTYPE= dataset option to tell SAS what data types to use for your fields in the external database. At least it works for Teradata. These dataset options should work inside PROC SQL also.
proc delete data=userdb.table1; run;
data userdb.table1
(dbtype=
( date='timestamp'
reference='varchar(16)'
transact='varchar(20)'
alias='varchar(60)'
amount='decimal(15,2)'
currency='char(3)'
)
);
stop;
length date 8 reference $16 transact $20 alias $60 amount 8 currency $3 ;
format date datetime30.6 amount 15.2 ;
run;
Can't you just:
create table user.table1
(
"date" TIMESTAMP(6)
,reference char(16)
,transact char(20)
,alias char(60)
,amount decimal(15,2)
,currency char(3)
);
? Remember, in DB2, date is a reserved word, and then it's always safe to put that into double quotes. Alternatively, use a non-reserved word for the column name, like dt or so.
These two lines are incongruous:
connect to db2(ssid=server);
create table user.table1
The first creates a connection for a pass-through query, while the latter creates the table using the libname engine. In this case your first statement is irrelevant as it's not used; you should remove it (unless you use it later and just left it in by mistake in your example).
Since you used the libname syntax, you must follow SAS syntax rather than DB2. There is no specification for datetime type in the create table statement, specifically under the column-definition documentation page. Instead you have this list to choose from:
CHARACTER | VARCHAR <(width)> indicates a character column with a column width of width. The default column width is eight characters.
INTEGER | SMALLINT indicates an integer column.
DECIMAL | NUMERIC | FLOAT <(width<, ndec>)> indicates a floating-point column with a column width of width and ndec decimal
places.
REAL | DOUBLE PRECISION indicates a floating-point column.
DATE indicates a date column.
The way I find best to specify datetime (meaning, most likely to work as you expect) is not to use date but numeric, and then use the format argument to define it as datetime.
proc sql;
create table table1
( date num format=datetime30.6
,reference char(16)
,transact char(20)
,alias char(60)
,amount decimal(15,2)
,currency char(3)
);
quit;
However, I would suggest your best choice is to use passthrough to create the table, so you can use DB2 syntax - since you're creating a table there, not in SAS itself.

Tsql: datediff not working with DEFAULT getdate()

I got a table with date type column and default set to: getdate()
But when I try to do datediff() on two separated raws, it always gives me 0 or some constant value. How to assign default value of date and perform datediff() that will work?
Example code, that reproduce my problem
CREATE TABLE Test
(
id INT PRIMARY KEY NOT NULL IDENTITY,
date DATE DEFAULT getdate() NOT NULL,
user VARCHAR(100)
);
CREATE UNIQUE INDEX Test_id_uindex ON Test (id);
Call the below raws with 1 sec delay in between or more
INSERT INTO Test(user) VALUES ('Cool1')
INSERT INTO Test(user) VALUES ('Cool2')
Now look below over the strange outputs of the next queries:
SELECT getdate() as date
Output:
date
2016-12-22 10:42:40
SELECT * from Test
Output:
id date user
1 2016-12-22 Cool
2 2016-12-22 Cool1
And the last one:
SELECT
a.id,
datediff(MILLISECOND, a.date, b.date)
FROM Test a
JOIN Test b ON a.id = b.id + 1
Output:
id difTime
2 0
Your code is fine. You are confusing the date data type with datetime or datetime2. Change your table definition to use a type that stores the time along with the date:
CREATE TABLE Test (
id INT PRIMARY KEY NOT NULL IDENTITY,
date DATETIME DEFAULT getdate() NOT NULL,
user VARCHAR(100)
);
This is a natural place for confusion because GETDATE() returns a value with a time component. However, DATE doesn't support the time component.
You can also use CURRENT_TIMESTAMP, whose name is a bit more evocative of the fact that it returns the time.

Alter character field to date

I've a legacy postgres db that has date columns cast as character(50) fields (don't ask). I'd like to alter the table and columns to contain actual dates. Because this worked:
select distinct to_date(date_begin, 'YYYY DD MM') from dates;
I naively thought this might work:
alter table dates alter column date_begin type character
using to_date(date_begin, 'YYYY DD MM');
But it does not. Any clues for the clueless?
This just works as intended by the OP. What we have here is a simple thinko/typo.
Read more in the manual about ALTER TABLE.
Demo:
-- DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
CREATE TABLE x.tbl(date_begin character(50));
INSERT INTO x.tbl VALUES ('2011-11-11 11:11'), (NULL), (''), ('1977');
-- NULL and empty string work too
-- even just YYYY works: '1977' .. is converted to '1977-01-01' automatically
-- empty string produce a possibly surprising result: '0001-01-01 BC'
ALTER TABLE x.tbl ALTER COLUMN date_begin TYPE date USING to_date(date_begin, 'YYYY DD MM');
SELECT * FROM x.tbl;
Hint: You wrote type character instead of type date.
It will take three stages:
1) Alter the table to add the date column.
2) Run an update query which converts each string date into the date field
3) Alter the table to remove the text date column.