SQL trigger update another table with same prime key - sql

CREATE OR REPLACE TRIGGER TRIGGER_RENEWAL
AFTER UPDATE OF NEXT_RENEW_DATE ON SUBSCRIPTION_CUSTOMER
REFERENCING OLD AS OLD NEW AS NEW
For each row
BEGIN
update Subscription_log
Set next_renew_date = :NEW.next_renew_date, previous_renew_date = :OLD.next_renew_date;
"Where rowid = updated row;"
END;
The table "Subscriptio_log" has a column "Phone_number" and "Email_address" referenced from the "Subscription_Customer" as a FK and PK
The case here is that I'd like to trigger an update on a log table whenever the subscription customer makes an update of their next renewal date.
The problem I'm facing is that I can't figure a way to select only specific rows to update the value of next_renew_date and previous_renew_date.
Is there a way to select the rowID or other ways to update based on the FK "Phone_number" and "Email_address"?

If your PHONE | EMAIL combination uniquely defines a row in your log table and if the same data is accesssible within your database trigger than you could update the unique record in your log. If that is not the case then all the log records having same PHONE | MAIL combination will be updated.
This structure of the log keeps just last two changes made to your customer data (previous and next date columns) making all other history changes definetely lost.
Log table - Sample data
PHONE
EMAIL
PREV_DATE
NEXT_DATE
1915555678
john.doe#domain.com
07-JUL-20
23-FEB-21
1995555001
jane.doe#domain.com
12-APR-19
12-SEP-22
Assuming that column PREV_DATE should be overwritten with value of NEXT_DATE column within same row of log table (if not - you can define the update's SET PREV_DATE command differently) you can try something like below:
Update
subscription_log
Set
PREV_DATE = NEXT_DATE,
NEXT_DATE = your_desired_new_next_date_value
Where
PHONE = subs_customer_trigg_phone_value And
EMAIL = subs_customer_trigg_email_value
Regards...

Related

Error when running trigger - Error Code: 1054 Unknown Column 'action' in field list

When I run the below UPDATE command after I run the trigger, I get the following error
Error Code: 1054 Unknown Column 'action' in field list
Any assistance would be much appreciated.
DELIMITER $$
CREATE TRIGGER Trigger_9
BEFORE UPDATE ON Customers
FOR EACH ROW
BEGIN
INSERT INTO Customers
SET action = 'update',
Email = NEW.Email,
CustomerID = NEW.CustomerID;
END$$
DELIMITER ;
UPDATE Customers
SET Email = 'Update'
WHERE CustomerID = 12345;
SELECT * FROM Customers
It looks like your trigger is being used for auditing changes to the Customer.Email field. You would be better off inserting that info into a different (audit) table, maybe named something like Customer_Audit or something like that.
There are two ways of setting this up:
1) If you want to keep the entire history, then only do INSERTs into your Audit table (no updates, because they destroy history). In that table, make sure the PK is either a (new) auto-number col (not the CustomerID) or a compound PK consisting of CustomerID + a (new) datetime col. I usually recommend autonumber because it is easier and guarantees uniqueness.
-or-
2) If you only want to keep 1 history record per customer, the easy way would be to delete (just 1 customer row) and re-insert into to your Audit table. The hard way would be to use logic like IF Exists(SELECT CustomerID FROM HistoryTable WHERE CustomerID=#####) UPDATE ... ELSE INSERT ...

Inserting column data into an already created table SQL

For example I created a data of transactions and included names, location, and ID. Now I created another column saying date. How would I update each individually and include a date for each?
So this was my table before
and now this is my table after
How do I add information to the transaction date to lets say TransactionID 12?
update MSTransaction
set TransactionDate = ('2015-12-17')
where TransactionID = 12
This is the t-sql syntax
Update TableName set TransactionDate = DateTimeValue
Where TransactionID = 12

Copying dates to a column from another table with criteria

I'm trying to do the following:
One table in the database is called service_state_history, that table has three columns:
service_id - which refers to the id of the service that the service_state is related to. (it's nor foreign key because the relation is done in the JPA code in this case).
state_started column which has DATETIME values, that indicate whenever the state on that row has started.
state column which describes the state of that history entry and has following VARCHAR-values: (STANDBY, IN PROGRESS, DONE)
The other table in the database is called services, that table has two relevant columns:
id BIGINT
done_date DATETIME
Now, what I'm supposed to do is update the done_date column in services from the service_state_history table's column state_started, when the state column's value in the row is DONE and the service_id value in matches id in services.
How does that translate into SQL?
So to get all the records that will be updating the destination table, you will use the results generated from:
SELECT service_id, state_started, state
FROM service_state_history
WHERE state = 'DONE'
To perform the UPDATE you will need to JOIN this result set to the destination table on the identity column and use the state_started in the update. Something like:
UPDATE s
SET s.done_date = ssh.state_started
FROM services s
INNER JOIN service_state_history ssh ON ssh.service_id = s.id
WHERE ssh.state = 'DONE'

CHECK operation for two tables

I have problems using a CHECK constraint. I have two tables
Users Table
userid | register_date
Activity table
id | userid | activity_date
I need to put a constraint that disallows the insertion of an activity_date which is less than a register_date. I could do it with a CHECK constraint if they were in same table. But, how do you do it for two different tables? (also Oracle disallows sub-queries in a check constraint).
Is there any other way to perform this action?
The simplest way is to have a trigger:
create or replace trigger tr_activity
before update or insert of activity_date on activity
for each row
declare
l_register_date users.register_date%type;
begin
select register_date into l_register_date
from users
where id = :new.userid
;
if :new.activity_date < l_register_date then
raise_application_error(-20000, 'Stop attempting the impossible');
end if;
end tr_activity;
/
But, this seems a little strange; I would assume that you're only ever inserting the current date into the activity date, which means that the registration date will always be before the activity date, unless it's been updated prior. I would simply ensure that the activity date is never updated or inserted in your application code and use a default value in the table:
alter table activity modify activity_date default sysdate not null

Update a table and return both the old and new values

Im writing a VB app that is scrubbing some data inside a DB2 database. In a few tables i want to update entire columns. For example an account number column. I am changing all account numbers to start at 1, and increment as I go down the list. Id like to be able to return both the old account number, and the new one so I can generate some kind of report I can reference so I dont lose the original values. Im updating columns as so:
DECLARE #accntnum INT
SET #accntnum = 0
UPDATE accounts
SET #accntnum = accntnum = #accntnum + 1
GO
Is there a way for me to return both the original accntnum and the new one in one table?
DB2 has a really nifty feature where you can select data from a "data change statement". This was tested on DB2 for Linux/Unix/Windows, but I think that it should also work on at least DB2 for z/OS.
For your numbering, you might considering creating a sequence, as well. Then your update would be something like:
CREATE SEQUENCE acct_seq
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO CYCLE
CACHE 24
;
SELECT accntnum AS new_acct, old_acct
FROM FINAL TABLE (
UPDATE accounts INCLUDE(old_acct INT)
SET accntnum = NEXT VALUE FOR acct_seq, old_acct = accntnum
)
ORDER BY old_acct;
The INCLUDE part creates a new column in the resulting table with the name and the data type specified, and then you can set the value in the update statement as you would any other field.
A possible solution is to add an additional column (let's call it oldaccntnum) and assign old values to that column as you do your update.
Then drop it when you no longer need it.
Here's what I'd do:
-- create a new table to track the changes.
- with columns identifying a unique key, old-vale, new-value, timestamp
-- create a trigger on the accounts table
to write the old and new values to the new table.
But, not knowing all the conditions, it may not be worth the trouble.