I want to store date in milliseconds, but also I want to see the formatted representation of it.
In order to not waste the drive space it makes sense to use a virtual generated column for this.
I wrote it:
DROP TABLE IF EXISTS example;
CREATE TABLE IF NOT EXISTS example (
time INTEGER,
formatted_time GENERATED ALWAYS AS (strftime('%Y.%m.%d %H:%m', time/1000, 'unixepoch')) VIRTUAL
);
INSERT INTO example (time) VALUES (1605960000000);
INSERT INTO example (time) VALUES (1615413202000);
It works, but I can't set the second modifier of strftime(format,timestring,modifier,modifier...) to get the local time. (It returns UTC time by default.)
When I use:
formatted_time GENERATED ALWAYS AS (strftime('%Y.%m.%d %H:%m', time/1000, 'unixepoch', 'localtime')) VIRTUAL
It throws Result: non-deterministic use of strftime() in a generated column when I insert a data.
While it works as expected:
select strftime('%Y.%m.%d %H:%m', 1615413202000/1000, 'unixepoch', 'localtime');
How to create a virtual column with formatted local time?
It's not possible.
Based on this answers:
Creating generate column based on today's date in SQLite
Computed column 'Month' in table cannot be persisted because the column is non-deterministic
SQLite requires to the value of a generated column would be the same on any machine in any time zone (be deterministic). Even for a virtual generated column.
In my case for time value 1615413202000 the formatted_time would be different for the same table opened in different time zones, so the the table would be "non-deterministic".
As a workaround it possible to create a view:
CREATE VIEW example_view AS
SELECT time, strftime('%Y.%m.%d %H:%m', time/1000, 'unixepoch', 'localtime') as formatted_time_local
FROM example;
(based on Shawn's answer)
I'd like to force Oracle sysdate function to return different values for separate statements, just like it does in Postgres. I've done some digging over the documentation, net and SO itself but couldn't find an answer to address this.
Documentation seems to be pretty poor for this one: see for yourself
I'm using Oracle 11g with SQL Developer 18.3
Please read on the MVCE below.
After executing this:
create table t(a timestamp);
insert into t values (sysdate);
insert into t values (sysdate);
insert into t values (sysdate);
select * from t;
I get:
A
---------------------------
18/12/25 04:25:59,000000000
18/12/25 04:25:59,000000000
18/12/25 04:25:59,000000000
I would want to get (changed by hand):
A
---------------------------
18/12/25 04:25:59,1234
18/12/25 04:25:59,7281
18/12/25 04:26:00,1928
Real issue is presented within different CALL statements to procedures, but the above sample seems to replicate the issue for me.
UPDATE
One thing I found to be helpful is to put pauses between statements, but this really isn't what I'm looking for:
set pause on;
create table t(a timestamp);
insert into t values (sysdate);
pause
insert into t values (sysdate);
pause
insert into t values (sysdate);
As noted in the documentation, the sysdate function returns a date, which only has precision down to seconds - it does not support fractional seconds. So, multiple calls within the same second will always get the same value, and you can't force it to do anything else.
You're putting that date value into a timestamp column, which is causes an implicit conversion from one data type to the other, but that conversion can't set/create a new fractional seconds value - it keeps the implicit fractional seconds from the date, which is of course always zero.
As well as sysdate, Oracle has a systimestamp function, which returns a timestamp with time zone value - and that does have fractional seconds. The precision is limited by the platform you're running on. If you use that to populate your plain timestamp column then an implicit conversion still occurs, but you essentially just throw away the time zone information.
Oracle also supports current_date and current_timestamp, which are very similar - except they return the date/time in the current session time zone, rather than in the server time zone as the sys* versions do.
I found that current_timestamp does the job:
drop table t;
create table t(a timestamp);
insert into t values (current_timestamp);
insert into t values (current_timestamp);
insert into t values (current_timestamp);
select * from t;
Outputs:
A
---------------------------
18/12/25 04:48:54,134000000
18/12/25 04:48:54,142000000
18/12/25 04:48:54,149000000
I have a sqlite (v3) table with this column definition:
"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP
The server that this database lives on is in the CST time zone. When I insert into my table without including the timestamp column, sqlite automatically populates that field with the current timestamp in GMT, not CST.
Is there a way to modify my insert statement to force the stored timestamp to be in CST? On the other hand, it is probably better to store it in GMT (in case the database gets moved to a different timezone, for example), so is there a way I can modify my select SQL to convert the stored timestamp to CST when I extract it from the table?
I found on the sqlite documentation (https://www.sqlite.org/lang_datefunc.html) this text:
Compute the date and time given a unix
timestamp 1092941466, and compensate
for your local timezone.
SELECT datetime(1092941466, 'unixepoch', 'localtime');
That didn't look like it fit my needs, so I tried changing the "datetime" function around a bit, and wound up with this:
select datetime(timestamp, 'localtime')
That seems to work - is that the correct way to convert for your timezone, or is there a better way to do this?
simply use local time as the default:
CREATE TABLE whatever(
....
timestamp DATE DEFAULT (datetime('now','localtime')),
...
);
You should, as a rule, leave timestamps in the database in GMT, and only convert them to/from local time on input/output, when you can convert them to the user's (not server's) local timestamp.
It would be nice if you could do the following:
SELECT DATETIME(col, 'PDT')
...to output the timestamp for a user on Pacific Daylight Time. Unfortunately, that doesn't work. According to this SQLite tutorial, however (scroll down to "Other Date and Time Commands"), you can ask for the time, and then apply an offset (in hours) at the same time. So, if you do know the user's timezone offset, you're good.
Doesn't deal with daylight saving rules, though...
In the (admitted rare) case that a local datatime is wanted (I, for example, store local time in one of my database since all I care is what time in the day is was and I don't keep track of where I was in term of time zones...), you can define the column as
"timestamp" TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M','now', 'localtime'))
The %Y-%m-%dT%H:%M part is of course optional; it is just how I like my time to be stored. [Also, if my impression is correct, there is no "DATETIME" datatype in sqlite, so it does not really matter whether TEXT or DATETIME is used as data type in column declaration.]
When having a column defined with "NOT NULL DEFAULT CURRENT_TIMESTAMP," inserted records will always get set with UTC/GMT time.
Here's what I did to avoid having to include the time in my INSERT/UPDATE statements:
--Create a table having a CURRENT_TIMESTAMP:
CREATE TABLE FOOBAR (
RECORD_NO INTEGER NOT NULL,
TO_STORE INTEGER,
UPC CHAR(30),
QTY DECIMAL(15,4),
EID CHAR(16),
RECORD_TIME NOT NULL DEFAULT CURRENT_TIMESTAMP)
--Create before update and after insert triggers:
CREATE TRIGGER UPDATE_FOOBAR BEFORE UPDATE ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
CREATE TRIGGER INSERT_FOOBAR AFTER INSERT ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
Test to see if it works...
--INSERT a couple records into the table:
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (0, 1, 'xyz1', 31, '777')
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (1, 1, 'xyz2', 32, '777')
--UPDATE one of the records:
UPDATE foobar SET price = 29 WHERE upc = 'xyz2'
--Check the results:
SELECT * FROM foobar
Hope that helps.
SELECT datetime(CURRENT_TIMESTAMP, 'localtime')
SELECT datetime('now', 'localtime');
Time ( 'now', 'localtime' ) and Date ( 'now', 'localtime' ) works.
You can also just convert the time column to a timestamp by using strftime():
SELECT strftime('%s', timestamp) as timestamp FROM ... ;
Gives you:
1454521888
'timestamp' table column can be a text field even, using the current_timestamp as DEFAULT.
Without strftime:
SELECT timestamp FROM ... ;
Gives you:
2016-02-03 17:51:28
I think this might help.
SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');
The current time, in your machine's timezone:
select time(time(), 'localtime');
As per http://www.sqlite.org/lang_datefunc.html
I am working on a SQLite Database which contains a column which stores value in format yyyy-MM-dd HH:mm:ss. Now I need to create a filter to select rows with filter as this datetime column.
Query:
Select * from tbl_locations where datetime >= '2013-09-11 00:00:00' and datetime <='2013-09-13 00:00:00'
Above query is returning null set despite containing values in this slot(which I verified using select statement without filter.)
Any suggestion how can i get the required data set?
Perhaps this excerpt from the SQLite documentation will help you:
1.2 Date and Time Datatype
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:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions.
The date and time functions that you can use in your SQL to build your query are documented at http://www.sqlite.org/lang_datefunc.html
Ok, I tested this out in MySQL but hopefully it will work. I had a table that used timestamps, and changed the column to be of type text. Then I tried the following SQL query and got the same results that I normally would (besides trailing decimals)
SELECT timestamp(stock_quote_timestamp)
FROM stock.stock_quote
WHERE stock_quote_timestamp < timestamp('2013-10-07 11:05:30')##high_date
AND stock_quote_timestamp > timestamp('2013-10-03 14:09:03');##low_date;
So basically, just convert your text statements to timestamps so that they compare correctly. Oh, and you'll also need to state what else you're SELECTing, or you could do a compound select statement: SELECT *, timestamp(stock_quote_timestamp)...
I have a strange issue where upon selecting information from a SQLite database, ans ordering based upon date, the results returned are invalid.
My SQL statement is as such:
Select pk from usersDates order by datetime(usersDate, 'localtime') ASC
I have dates stored in the database which range as far as 2111. However the order the data is returned in indicates that dates from 2036 happen after the ones from 2111.
The column 'usersDate is actually a double (time interval since 1970 / unix time) - hence the reason for the cast.
Does anyone know what would cause this?
You should re-read the date and time syntax. The 'localtime' modifier expects an UTC time on its left.
Use SELECT pk FROM usersDates ORDER BY datetime(usersDate, 'unixepoch', 'localtime') ASC.