Timestamp decrease the hour in insert overwrite - sql

I have been work with Sqoop, hive and Impala.
My Sqoop Job get a field from SQL Server with the format datetime to write in a TABLE1 stored as textfile. The field in TABLE1 have the timestamp format.
After this, I created a HQL script using INSERT OVERWRITE TABLE2 ... SELECT TABLE1.
The field in TABLE2 have the Timestamp format too, but the time increased in 1 hour, I don't know why.
All the tables was created previously. How can I fix this?

The difference might come from different time zones (local time, server time, utc, ...)
However, you can fix the wrong values in the database with
DATEADD(interval, number, date);
Also see: https://www.w3schools.com/sql/func_sqlserver_dateadd.asp for more

Related

SQL : datatype as trunc(sysdate)

I was trying to create a table with a column's data type as trunc(sysdate).
Is that possible?
When I tried it , I got below error
SQL Error: ORA-00902: invalid datatype
I am trying this because I want to make sure data inserted into that column doesn't have timestamp.
Just create a trigger
CREATE TRIGGER schema.trigger_name
BEFORE INSERT OR UPDATE
ON schema.table_name
FOR EACH ROW
new.column_name = trunc(column_name);
No that is not possible.
Trunc() is a function that truncates date to a specific unit of measure.
The DATE datatype stores point-in-time values (dates and times) in a
table. The DATE datatype stores the year (including the century), the
month, the day, the hours, the minutes, and the seconds (after
midnight).

Update Oracle timestamp to current date

I have a TIMESTAMP(6) field in Oracle db. Value of this field is in format
DD/MM/YYYY HH:MM:SS.000000000 PM
How to update this value to the current timestamp?
[a link to a similar question:] update date value in oracle
I followed this link, but following query is taking very long time to execute.
update table_name set start_time = to_char(to_date(start_time, 'yyyy/mm/dd-hh:mi:ss:ff3'), '2012/10/10-19:30:00:00') where column='Q'
A timestamp is a point in time, it has no format. To update such a field to the current timestamp, use SYSTIMESTAMP or CURRENT_TIMESTAMP (respectively the date/time of the server and the date/time of the session):
UPDATE your_table
SET your_column = systimestamp
WHERE ...
If the query takes an abnormal amount of time (much longer than a comparable SELECT with the same WHERE clause), the mostly likely causes are:
The rows that your are updating are locked by another session (doing a SELECT FOR UPDATE NOWAIT on these rows will make sure that you have the lock).
You have triggers that perform additional work,
You're updating a column referenced by a non-indexed foreign key.
Why you don't just
update table_name
set start_date = systimestamp
where column='Q'
If you suspect there are locks on the table, there are some tables to check: dba_locks, v$session, v$session_blockers etc. These are useful when a user blocked something with an accidental update without a commit or rollback, but you should be able to see if can exists blocking locks from the architecture of your application. You should just simulate on paper all the scenarios.

Is it possible to get last update time of the row in sql

Is it possible to get last updated time and date of the row using MYSQL server.
Well there is no inbuild feature exists with MySQL. Though you can get the same effect by adding a timestamp column:
ALTER TABLE NAMEYOURTABLE
ADD COLUMN last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
using above to create timestamp with name last_update column will make it pretty much automatically managed and updated. Now you can select from NAMEYOURTABLE the last updated row based on the timestamp.

Migrating Oracle DATE columns to TIMESTAMP with timezone

Bakground:
I've got a legacy app I'm working on that uses DATE types for most time storage in the database. I'd like to try update some of these tables so that they can utilize time zones since this is causing problems with users in different areas from where the db is(see A below). This is for Oracle 10g.
Quetions:
1) Can I migrate this "in place." That is can I convert like so
DATE_COL = type:DATE => DATE_COL = type:TIMESTAMP
...or will I have to use a different column name?
Keep in mind that data needs to be retained. If this can be done semi-easily in a migration script it will work for my purposes.
2) Will this type of conversion be backwards compatible? We likely have some scripts or reports that will hit this table that we may not know about. We can probably deal with it but I'd like to know what sort of hornet's nest I'm walking into.
3) What pitfalls should I be on the lookout for?
Thanks,
EDIT:
(partly in response to Gary)
I'm fine with a multi-step process.
1) move data to a new Timestamp column (caled TEMP) with some sort of conversion
2) drop old column (we'll call it MY_DATE)
3) create new timestamp column with the old date column name (MY_DATE)
4) move data to the MY_DATE column
5) drop TEMP column
A Gary also wanted clarification on the specific timezone issue. I copied my answer from below to keep it more readable.
Basically the data will be accessed from several different areas. We need to be able to convert to/from the local time zone as needed. We also have triggers that use sysdate further complicating things. timestamp with time zone alleviates a lot of this pain.
Oh and thanks for the answers so far.
You could just run:
ALTER TABLE your_table MODIFY your_date_column TIMESTAMP WITH TIME ZONE;
But I would recommend adding a TIMESTAMP column to the table, using an UPDATE statement to populate, and drop the original date column if you so choose:
ALTER TABLE your_table ADD date_as_timestamp TIMESTAMP WITH TIME ZONE;
UPDATE your_table
SET date_as_timestamp = CAST(date_column AS TIMESTAMP WITH TIME ZONE);
The conversion is backwards compatible - you can switch back & forth as you like.
Simple enough to demonstrate
SQL> create table x (y date);
Table created.
SQL> insert into x select sysdate from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> alter table x modify y timestamp;
Table altered.
SQL> select * from x;
Y
---------------------------------------------------------------------------
03/NOV/09 12:49:03.000000 PM
SQL> alter table x modify y date;
Table altered.
SQL> select * from x;
Y
---------
03/NOV/09
SQL> alter table x modify y timestamp with time zone;
alter table x modify y timestamp with time zone
ERROR at line 1:
ORA-01439: column to be modified must be empty to change datatype
SQL> alter table x modify y timestamp with local time zone;
Table altered.
SQL> alter table x modify y date;
Table altered.
So you can go from date to timestamp (or timestamp with local timezone) and back again, but not for timestamp with time zone (ie where the offset is persisted).
You'd have to add another column, and copy the existing data over (with a default for the appropriate time zone).
"causing problems with users in different areas from where the db is".
Might help to be a bit more specific. Is it sufficient to convert the dates (or timestamps) from the database timezone to the user's timezone when inserted/changed/queried, or do you actually need to persist the fact that the record was created at 3:00pm in a specific timezone.

Sqlite: CURRENT_TIMESTAMP is in GMT, not the timezone of the machine

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