Db2: Create a Column that stores the timestamp a value in the same row is set - triggers

I have a Boolean column in my database called: IS_SUBMITTED that is by default set to False.
What I would like to do is to have another column in the database called TIME_SUBMITTED that is set to Null by default, but when IS_SUBMITTED is set to True, TIME_SUBMITTED is updated with the current timestamp.
Is this possible to implement? I image it may involve the use of a trigger but I'm quite new to Db2 and I can't quite seem to get it working properly.
Cheers

A BEFORE UPDATE trigger is what you need...
The simple solution assumes that IS_SUBMITTED is only ever changed one time from FALSE to TRUE.
create or replace trigger MYTRIGGER
before update of IS_SUBMITTED on MYTABLE
referencing
new row as n
set n.time_submited = current_timestamp
;
If IS_SUBMITTED can be changed backed to false, you'd need to decide how to handle that. And use a compound BEGIN/END statement in the trigger with the additional logic. I'll leave that as an exercise.
Lastly note, when asking Db2 questions on SO, it's a good idea to include your platform (LUW, z\OS, IBM i) and version.

Related

postgres condition trigger missing from clause

I'm trying to create a trigger on my table such that it only runs if the 'prepaid' column is true for rows where I've modified the value of the 'points_per_month' column. I tried this:
CREATE TRIGGER "fix_usage_trigger"
AFTER UPDATE OF "points_per_month"
ON "public"."clients"
FOR EACH ROW WHEN (ROW.prepaid)
EXECUTE PROCEDURE "fix_prepaid_client_available_usage"();
psql is telling me this:
ERROR: missing FROM-clause entry for table "row"
LINE 1: ...r_month" ON "public"."clients" FOR EACH ROW WHEN (ROW.prepai...
Clearly I have no FROM clause there, but I'm not sure why I'd need one, nor where to put it.
That should be when (new.prepaid), per David's comment. You can access old and new in the when clause (as in the row before and after the update) much like table aliases. The error message is PG complaining that row is not a known table.
Two additional notes:
it might need to be when (old.prepaid or new.prepaid) if you want to manage billing plan switches -- or another two separate triggers. Conversely, when (old.prepaid and new.prepaid) if you do not, and someone might run database queries that might inadvertently fire the trigger and create undesirable state (add a unit test or two).
the function's name suggest something might be wrong further up in your code flow. You might want to fix that instead, by setting the available usage properly to begin with. Doing so might be more efficient, too.

How to send Postgres procedure entire record from trigger

I am new to Postgres (9.0.5) and have written very few functions/triggers in general. I would like to set up a trigger on my widgets table such that every time a widget is inserted, updated or deleted, the entire record is passed to a stored procedure as an argument. The procedure can then inspect the record for various changes and decide what action to take. Here's my best attempt so far, though I know I'm way off course:
CREATE OR REPLACE TRIGGER tg_widgets
ON TABLE widgets
AFTER EVERY INSERT, UPDATED, DELETE
DO run_widget_handler
CREATE OR REPLACE PROCEDURE run_widget_handler AS
# Definitition here
# If the widget's name was changed, do X
# Else if the widget's wow_factor was changed, do Y
# Else, do Z
I'm not worried about how to implement the definition of run_widget_handler, just looking for help and writing the trigger and passing the widget to the proc. Thanks in advance.
You don't need to "pass" the row to the trigger function (btw: there is no "procedure" in PostgreSQL, only functions).
If the function is declared as "returns trigger", you can automatically access the complete row as "new" or "old".
More details in the manual: http://www.postgresql.org/docs/current/static/plpgsql-trigger.html

Trigger procedure for getting modified column names

I've been looking for a way to get the names of any modified columns during an INSERT inside a trigger function. I can get the table modified using the trigger procedure TG_TABLE_NAME, is there anything similar for modified columns?
No, there is no equivalent to TG_TABLE_NAME for column names. You need to compare the old and new records in an UPDATE trigger.
For INSERT triggers the idea of "modified" column names doesn't even make any sense. Do you mean columns that are not at their default values?
Anyway, you need to examine the NEW and (where it applies) OLD records. This can be tricky to do dynamically. The hstore extension is often the most useful tool, as it allows you to do comparisons between and iterations over columns of unknown rowsets.

How does one call a function from a postgresql rule that has access to NEW and OLD?

I'm new to postgresql (and therefore rules) and I've looked around, but can't really find an example calling a 'global' function.
I am using a normalized database where rows will be flagged as deleted rather than deleted. However, I would like to retain the DELETE FROM... functionality for the end user, by using an instead of delete rule to update the table's deleted_time column. Each table should, therefore, be able to use a common function, but I am not sure how this would be called in this context, or how it would have access to NEW and OLD?
CREATE OR REPLACE RULE rule_tablename_delete AS ON DELETE
TO tablename DO INSTEAD (
/// call function here to update the table's delete_time column
);
Is this even the correct approach? (I note that INSTEAD OF triggers are restricted to views only)
Just use an UPDATE statement:
create rule rule_tablename_delete as
on delete to tablename
do instead
update tablename
set delete_time = current_timestamp
where id = old.id
and delete_time is null;
Assuming that the id column is the primary key of that table.
Some more examples are in the manual: http://www.postgresql.org/docs/9.1/static/rules-update.html

How to pick a default value to the column in the trigger?

We implement some triggers which perform some operations with insert data before committing them to the database and when some conditions fail the trigger should pick up the default value for corresponding column.
How to perform it inside the trigger?
Thank you.
PS. we work with PostgreSQL, but implementations with other DBMS may give a hint.
NEW.colname = DEFAULT will do the trick.