DB2/400 - Auto generated timestamp on change (error) - sql

I'm trying to create a table with a timestamp column that autogenerates with 'current timestamp' on each update of the record. I'm on DB2/400 (version V5R3) using ODBC driver.
That's the query:
CREATE TABLE random_table_name (
ID integer not null generated always as identity,
USERS_ID varchar (30),
DETAILS varchar (1000),
TMSTML_CREATE timestamp default current timestamp ,
TMSTMP_UPDATE timestamp not null generated always for each row on update as row change timestamp,
PRIMARY KEY ( ID )
)
I get this error (translated):
ERROR [42000] [IBM][iSeries Access ODBC Driver][DB2 UDB]SQL0104 - Token EACH not valid. Valid tokens: BIT SBCS MIXED.
Without the 'TMSTMP_UPDATE' row the query works. How can i solve this?
EDIT: Ok, i understand that in my DB2 version, the only way is to use triggers, but today AS400 seems to be evil with me.
I'm trying with this:
CREATE TRIGGER random_trigger_name
AFTER UPDATE ON random_table_name
REFERENCING NEW AS NEW_ROW
FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
SET NEW_ROW.TMSTM_UPDATE = CURRENT TIMESTAMP;
END
Error (translated):
ERROR [42000] [IBM][iSeries Access ODBC Driver][DB2 UDB]SQL0312 - Variable TMSTM_UPDATE not defined or not available.
The column TMSTM_UPDATE exist and it's a normal timestamp.
EDIT 2: I've solved the trigger problem by replacing 'after' with 'before'. Now everything works as expected. Thank you all!

There is a standard way to do it in iSeries DB2. It is documented here: IBM Knowledge center - Creating a row change timestamp column
You should change your table definition to:
TMSTMP_UPDATE TIMESTAMP NOT NULL FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP
I am using it in tables in production over V7R2 and it works like a charm :) Hope it will be available for V5R3
EDIT
As Charles mentioned below unfortunately this feature is available since DB2 for i V6R1

Related

Incorrect time value showing in Snowflake table for datatype TIMESTAMP_LTZ

We are specifying all our datetime/timestamp datatypes as TIMESTAMP_LTZ while creating Snowflake tables.
for one of the values in Oracle source '0001-01-01 00:00:00.000001000' we are observing that when this value gets inserted in Snowflake tables this changes to '0000-12-31 23:52:58.000001000' .
There are no issues with other datetime/timestamp values except this.
There is no changes and alter to timezones when the query runs.
Is this some conversion issue due to to timezone or bug at Snowflake side?
This can happen based on the timezone set for your session/user. More details for Timezone parameter can be found here.
https://docs.snowflake.com/en/sql-reference/parameters.html#timezone
Please use below link to get the timezone set for your session/user/account.
https://docs.snowflake.com/en/sql-reference/parameters.html#viewing-the-parameters-and-their-values
show parameters like '%zone%';
alter session set TIMEZONE = 'America/New_York';
CREATE or replace TABLE time_test (timeval TIMESTAMP_LTZ);
INSERT INTO time_test values('0001-01-01 00:00:00.000001000');
select * from time_test;
Output of the select query is 0000-12-31 23:56:02.000.

Updating invalid timestamps in Google BigQuery table

My table has a few invalid timestamps that I think are too precise (maybe beyond microseconds) for BigQuery.
When I tried updating the table with the following query using Standard SQL:
UPDATE mytable
SET event_time = TIMESTAMP(DATETIME(TIMESTAMP_MILLIS(CAST(SUBSTR(SAFE_CAST(UNIX_MILLIS(event_time) AS string),1,13) AS int64))))
WHERE DATE(logtime) BETWEEN "2018-03-21" AND "2018-03-23"
AND event_time IS NOT NULL
I get the invalid timestamp error:
Cannot return an invalid timestamp value of 1521738691071000064 microseconds relative to the Unix epoch. The range of valid timestamp values is [0001-01-1 00:00:00, 9999-12-31 23:59:59.999999]; error in writing field event_time
I think the problem is the SET event_time = part, but I don't know how to get around setting the values in the event_time column without referring to it.
Anyone have any ideas on how to resolve this?
Necessity is the mother of invention. For anyone who has a similar issue, I've figured out a workaround.
Create a new table of the affected rows (include this in the WHERE clause: LENGTH(CAST(UNIX_MILLIS(event_time) as string)) > 13, while transforming the
invalid timestamp into a valid format using TIMESTAMP(DATETIME(TIMESTAMP_MILLIS(CAST(SUBSTR(SAFE_CAST(UNIX_MILLIS(event_time) AS string),1,13) AS int64))))
Delete the affected rows from the original table using the WHERE clause mentioned above.
Insert all rows from the new table back into the original table.
A lot more work, but it should do the trick.

tSQL - convert nvarchar(8) to time only

I am using Microsoft SQL Server Management Studio to manipulate Public transport system database.
I have a table in database named 'dbo.tblStop_times', two columns of which should be of data type time. At the moment, they are both nvarchar and they have data stored in a pattern like this - "07:39:00" (without quotes)
I had same question with date columns as well, but found a solution for that on stackoverflow just few hours back.
Below works fine for conversion of nvarchar column to date column.
ALTER TABLE tblCalendar ALTER COLUMN [start_date] DATE NOT NULL;
I am not sure if what I want is achievable or not, because the above mention conversion works just fine, I assume it might be possible.
What I have atm is - nvarchar(8), what I want it to be is sql time data type, something like hh:mm:ss [and if possible - without trailing nnnnnn - nanoseconds component]
You should be able to do:
ALTER TABLE tblStop_times ALTER COLUMN start_time TIME NOT NULL;
Here is a rextester.
EDIT:
If you don't have valid time values, then you have a problem. You should first look for the values:
select col
from tblStop_times
where try_convert(time, col) is null;
This will show you the values that cannot be converted. If you like, you can NULL them out so the alter will work:
update tblStop_times
set col = NULL
where try_convert(time, col) is null;

Make a constraint for SYSDATE minus a date of birth

I would love to know what I'm doing wrong ,
I would like to add a CHECK constraint in oracle to make sure a user is over 18
So I did
ALTER TABLE User
ADD CONSTRAINT check_age CHECK(TO_CHAR(SYSDATE, 'yyyy/mm/dd')- TO_CHAR(dateOfBirth, 'yyyy/mm/dd')> 18)
But Im receiving error
Cause: An attempt was made to use a date constant or system variable,
such as USER, in a check constraint that was not completely
specified in a CREATE TABLE or ALTER TABLE statement. For
example, a date was specified without the century.
*Action: Completely specify the date constant or system variable.
Setting the event 10149 allows constraints like "a1 > '10-MAY-96'",
which a bug permitted to be created before version 8.
Why it's wrong?
I still don't understand why I can't add it and I would kindly love if someone can explain it to me
Thanks
Starting in Oracle 11g, while you can't directly use sysdate in a constraint, you could get the same effect with a virtual column:
create function over_18 (
p_birth_date in User.dateOfBirth%type
) return varchar2 deterministic is
begin
return case when months_between(sysdate, p_birth_date) /12 > 18 then 'Y' else 'N' end;
end over_18;
/
alter table User add (over_18_ind as (cast(over_18(dateOfBirth) as varchar2(1))));
/
alter table User add constraint check_age check (over_18_ind = 'Y');
/
Based on an article here.
Even if Oracle allowed you to use sysdate in a constraint, your constraint wouldn't work anyway, since the formats you converted your dates to can't be implicitly cast back to numbers to subtract (I supplied an alternate age check).

Postgresql : set timestamp to null

I have searched across SO related questions, but I couldn't find the solution for :
How to set timestamp to NULL during an insert to DB or an update ? (in postgresql).
If I put NULL like pstat.setTimestamp(idx++, null); I get an error which says that the type I put in is integer and that I should cast to Timestamp.
As definition for this table column, I use : ADD COLUMN admin_validation_date timestamp with time zone
Thank you for your help.
pstat.setNull(idx++, Types.TIMESTAMP);
should do it.