Copying dates to a column from another table with criteria - sql

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'

Related

SQL trigger update another table with same prime key

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...

Postgres - Move the records from one table to another based on condition

I have two tables with millions of rows in postgres. I wanted to move records from one table to another.
Table name - event
List of columns:
"id"
"url"
"parent_id"
"created"
"created_by"
"last_modified"
"last_modified_by"
"tags"
"type"
"sub_type"
"category"
"name"
"preference"
Table name - preference
List of columns:
"id" - If the entity_type is event, id column in the event table goes here
"entity_type" // event or slot.
"preference"
"created"
"created_by"
"last_modified"
"last_modified_by"
"parent_entity_id"
And these tables are already populated with millions of data. And I have added a new column named preference in the event table, which does not have any data.
Now, I wanted to move the
preference table preference column data to the event table preference column.
Condition:
Migrating the data from the preference column (In preference table) to the preference column (In event table) only when the entity_type is an event. And the insert should
happen with the corresponding row in the event table.
I tried this query, but this seems to be incorrect. And Postgres throws a syntax error.
insert into <schema_name>.event a (preference) where a.id = '<eventId goes here>' (select preference from <schema_name>.preference where entity_id = '<eventId goes here>'
and entity_type = 'event')
You should use update instead of insert, because the table is already populated with data.
update event e
set preference = (select preference from preference p where p.entity_id = e.id and entity_type = 'event')

Can anyone tell me why my table field reference not work with this trigger query?

I have a problem formatting an update trigger for my sqlite project.
The project has 2 tables. One table is called Equipment and has 3 fields:
- UnitID
- Last_PMI
- Preset_Hrs
The other table is called ESPModules and it has 3 fields as well:
- UnitID (FK)
- ESPModuleID
- Install_Date
I have set up an update trigger on the ESPModules table that triggers every time I change the UnitID field in the ESPModules table. The UnitID field has a one-to-one relationship with the Equipment table. (Both tables allow only one unique UnitID)
My trigger actually fires but I do not know how to reference the UnitID field in my ESPModules table. Below is what I have so far and this code does update the Equipment record when it fires:
UPDATE Equipment
SET Last_PMI = date('now'),
Preset_Hrs = 0
WHERE UnitID = "BT-109F"
UPDATE Equipment
SET Last_PMI = date('now'),
Preset_Hrs = 0
WHERE UnitID = ESPModules.UnitID;
But the problem is I need to reference my ESPModules.UnitID field as above: (In other words, as an example, when I type in an existing UnitID like "BT-109F", it does fire but does not work when I try to reference the field I am updating and saving. It throws this error: “ An error occurred while committing the data: no such column: ESPModules.UnitID
I am new to sql language and would love some help in formatting this update query correctly.
Thanks
Clan
This is explained in the SQLite create trigger documentation:
the trigger actions may access elements of the row being inserted, deleted or updated using references of the form "NEW.column-name" and "OLD.column-name", where column-name is the name of a column from the table that the trigger is associated with.
So, consider:
UPDATE Equipment
SET Last_PMI = date('now'),
Preset_Hrs = 0
WHERE UnitID = NEW.UnitID;

Insert strategy for tables with one-to-one relationships in Teradata

In our data model, which is derived from the Teradata industry models, we observe a common pattern, where the superclass and subclass relationships in the logical data model are transformed into one-to-one relationships between the parent and the child table.
I know you can roll-up or roll-down the attributes to end up with a single table but we are not using this option overall. At the end what we have is a model like this:
Where City Id references a Geographical Area Id.
I am struggling with a good strategy to load the records in these tables.
Option 1: I could select the max(Geographical Area Id) and calculate the next Ids for a batch insert and reuse them for the City Table.
Option 2: I could use an Identity column in the Geographical Area Table and retrieve it after I insert every record in order to use it for the City table.
Any other options?
I need to assess the solution in terms of performance, reliability and maintenance.
Any comment will be appreciated.
Kind regards,
Paul
When you say "load the records into these tables", are you talking about a one-time data migration or a function that creates records for new Geographical Area/City?
If you are looking for a surrogate key and are OK with gaps in your ID values, then use an IDENTITY column and specify the NO CYCLE clause, so it doesn't repeat any numbers. Then just pass NULL for the value and let TD handle it.
If you do need sequential IDs, then you can just maintain a separate "NextId" table and use that to generate ID values. This is the most flexible way and would make it easier for you to manage your BATCH operations. It requires more code/maintenance on your part, but is more efficient than doing a MAX() + 1 on your data table to get your next ID value. Here's the basic idea:
BEGIN TRANSACTION
Get the "next" ID from a lookup table
Use that value to generate new ID values for your next record(s)
Create your new records
Update the "next" ID value in the lookup table and increment it by the # rows newly inserted (you can capture this by storing the value in the ACTIVITY_COUNT value variable directly after executing your INSERT/MERGE statement)
Make sure to LOCK the lookup table at the beginning of your transaction so it can't be modified until your transaction completes
END TRANSACTION
Here is an example from Postgres, that you can adapt to TD:
CREATE TABLE NextId (
IDType VARCHAR(50) NOT NULL,
NextValue INTEGER NOT NULL,
PRIMARY KEY (IDType)
);
INSERT INTO Users(UserId, UserType)
SELECT
COALESCE(
src.UserId, -- Use UserId if provided (i.e. update existing user)
ROW_NUMBER() OVER(ORDER BY CASE WHEN src.UserId IS NULL THEN 0 ELSE 1 END ASC) +
(id.NextValue - 1) -- Use newly generated UserId (i.e. create new user)
)
AS UserIdFinal,
src.UserType
FROM (
-- Bulk Upsert (get source rows from JSON parameter)
SELECT src.FirstName, src.UserId, src.UserType
FROM JSONB_TO_RECORDSET(pUserDataJSON->'users') AS src(FirstName VARCHAR(100), UserId INTEGER, UserType CHAR(1))
) src
CROSS JOIN (
-- Get next ID value to use
SELECT NextValue
FROM NextId
WHERE IdType = 'User'
FOR UPDATE -- Use "Update" row-lock so it is not read by any other queries also using "Update" row-lock
) id
ON CONFLICT(UserId) DO UPDATE SET
UserType = EXCLUDED.UserType;
-- Increment UserId value
UPDATE NextId
SET NextValue = NextValue + COALESCE(NewUserCount,0)
WHERE IdType = 'User'
;
Just change the locking statement to Teradata syntax (LOCK TABLE NextId FOR WRITE) and add an ACTIVITY_COUNT variable after your INSERT/MERGE to capture the # rows affected. This assumes you're doing all this inside a stored procedure.
Let me know how it goes...

Oracle: selfcopying data from Oracle tables

Application has different versions. Each version has it's own set of values in each table. I need to provide functionality to copy data from one version to another. Problem :
By inserting data I am trying to insert Ids which has already been in use in this table. So, I need to change ids of components which I want to insert but I must save relationship between those components. How cat I do that?
Create a master table which has a surrogate key as your primary key. A numeric value of type NUMBER(9) works well. You can create a sequence and trigger to automatically insert this.
The rest of the table is the column of your current table plus a column to indicate which version the row is for.
For simplicity you may wish to create views on top of the table along the lines of
select * from master_table where version_id = ####;
To copy the data from one version to another this will work:
Insert into master_table seq_master_table.nextval, new version_id,.....
from master_table
where version_id = ####;