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

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;

Related

How to prevent delete query in SQL

I have created a database through Entity Framework Code First Approach and My application is ready and running live . The problem is that I did not turned "False" on Cascade Delete at the time of creating database.
Now if I delete any record from one table that is referenced with another table through foreign so all the record containing foreign key of deleted row is deleted from another table .
Practically demonstration :
Let say I have a Table called Passenger:
ID Name CategoryID
1 ABC 1
CategoryID here is a foreign key
Here is the category Table
ID Name
1 Gold
Let say I run my query on category table
delete from Category where ID = 1
Now all the record from my Passenger Table is deleted . I want to restrict it. Is it Possible through SQL now ?
I suppose
This is what you are looking for :
alter TRIGGER customers_del_prevent
ON dbo.customers
INSTEAD OF DELETE
AS
BEGIN
insert into dbo.log
values ('DELETE')
RAISERROR ('Deletions not allowed from this table (source = instead of)', 16, 1)
END
Hope this helps you. :)

Interbase SQL trigger

Interbase, Sql, trigger. Can't really understand how to write a trigger of this kind: I have several tables. Each one has a document type, status and an unique number. One table in which i wish to create a trigger is a table that holds a file i post, a status of posting, a doctype corresponding to a table and a unique number linking to a record in the corresponding table. I want to change document status in the corresponding table based on the unique number to a certain status depending on the post result (status) that i change after posting. How can I do it?
Trigger T1 will be executed after update on TABLE1.
Trigger checks if TABLE1.StatusOfPosting changed to some value and depending on result updates TABLE2.DocumentStatus.
Depending on bussienes logic, maybe you will need and BEFORE DELETE trigger.
CREATE TRIGGER T1 FOR TABLE1 AFTER UPDATE POSITION 0
AS
BEGIN
IF (NEW.StatusOfPosting <> OLD.StatusOfPosting and NEW.StatusOfPosting=1) THEN
UPDATE TABLE2
SET TABLE2.DocumentStatus=1
WHERE TABLE2.UniqueNumber = TABLE1.UniqueNumber;
END

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'

How could I know the update that occurred in foreign column have done because of cascading or by user?

Let me say that I have 3 tables ( _items, _invoiceHeader ,_invoiceDetails)
I built an update trigger on _invoiceDetails , so I can update _balance column in _items table if I update _itemCode. But the problem is if I update the _itemCode column in _items table the trigger on _invoiceDetails table runs immediatly because of cascade rule on _itemCode columns in _items and _invoiceDetails tables.
So how can I know that the update that happened on _invoiceDetails table have done because of cascade or because of the update on the same table _invoiceDetails .
I put this code inside update trigger on _invoiceDetails table:
if(UPDATE(itemCode)) // I need a condition here to prevent the implementation if the update happened because of cascade rule.
BEGIN
UPDATE items
SET balance=balance+d.quantity
FROM items
INNER JOIN DELETED d
ON items.accountsItemCode=d.accountsItemCode
UPDATE items
SET balance=balance-i.quantity
FROM items
INNER JOIN INSERTED i
ON items.itemCode=i.itemCode
END
Try using Trigger_NestLevel to determine if your other triggers are active.
One of our table design standards is to include meta columns on tables where we want to track changes. We have stuff like UPDATE ID/UPDATE TIMESTAMP or at other times DATA SOURCE.
Generally we pass the corp id of the user calling the procedure and insert that into the table while batch/triggers/any non user action is inserted with some service account name.
Applying such a pattern here would resolve your problem.

Doing UPSERT when row is referenced by a FK

Let's say that I have a table of items, and for each item, there can be additional information stored for it, which goes into a second table. The additional information is referenced by a FK in the first table, which can be NULL (if the item doesn't have additional info).
TABLE item (
...
item_addtl_info_id INTEGER
)
CONSTRAINT fk_item_addtl_info FOREIGN KEY (item_addtl_info)
REFERENCES addtl_info (addtl_info_id)
TABLE addtl_info (
addtl_info_id INTEGER NOT NULL
GENERATED BY DEFAULT
AS IDENTITY (
INCREMENT BY 1
NO CACHE
),
addtl_info_text VARCHAR(100)
...
CONSTRAINT pk_addtl_info PRIMARY KEY (addtl_info_id)
)
What is the "best practice" to update an item's additional info (in IBM DB2 SQL, preferably)?
It should be an UPSERT operation, meaning that if additional info does not yet exist then a new record is created in the second table, but if it does, then it is only updated, and the FK in the first table does not change.
So imperatively, this is the logic:
UPSERT(item, item_info):
CASE WHEN item.item_addtl_info_id IS NULL THEN
INSERT INTO addtl_info (item_info)
UPDATE item.item_addtl_info_id (addtl_info.addtl_info_id)
^^^^^^^^^^^^^
ELSE
UPDATE addtl_info (item_info)
END
My main problem is how to get the newly inserted addtl_info row's id (underlined above). In a stored proc I can request the id from a sequence and store it in a variable, but maybe there is a more straightforward way. Isn't it something that comes up all the time when programming databases?
I mean, I'm really not interested in what the id of the addtl_info record is as long as it remains unique and is referenced properly. So using sequences seems a bit of an overkill to me in this case.
As a matter of fact, this UPSERT operation should be part of the SQL language as a standard operation (maybe it is, and I just don't know about it?)...
The syntax I was looking for is:
SELECT * FROM NEW TABLE ( INSERT INTO phone_book VALUES ( 'Peter Doe','555-2323' ) )
from Wikipedia (http://en.wikipedia.org/wiki/Insert_%28SQL%29)
This is how to refer to the record that was just inserted in the table.
My colleague called this construct an "in-place trigger", which what it really is...
Here is the first version that I put together as a compound SQL statement:
begin atomic
declare addtl_id integer;
set addtl_id = (select item_addtl_info_id from item where item.item_id = XXX);
if addtl_id is null
then
set addtl_id = (select addtl_info_id from new table
(insert into addtl_info
(addtl_info_text)
values ('My brand new additional info')
)
);
update item set item.item_addtl_info_id = addtl_id
where item.item_id = XXX;
else
update addtl_info set addtl_info_text = 'My updated additional info'
where addtl_info.addtl_info_id = addtl_id;
end if;
end
XXX being equal to the item id to be updated - this code can now be easily inserted into a sproc, and XXX can be converted to an input parameter.
I also tried using MERGE INTO, but I couldn't figure out a syntax for updating a table different from what was specified as the target.