Can I access values from where clauses in SQLite triggers? - sql

I would like to trigger an update to a table based on the where clause of an insert to a different table. For example:
CREATE TRIGGER update_key_table
BEFORE INSERT ON value_table
BEGIN
INSERT OR IGNORE INTO key_table (key_name) VALUES ('new_key_name');
END;
This would update key_table with the value 'new_key_name' when the following query is run:
INSERT INTO value_table (key_id, value)
SELECT key_table.key_id, 'new_value'
FROM key_table
WHERE key_table.key_name = 'new_key_name';
However, I have not been able to find any way to get access to the 'new_key_name' value from the triggering query's WHERE clause.
I understand that I can just run the following two queries in sequence, it would just be inconvenient in this particular application:
INSERT OR IGNORE INTO key_table (key_name) VALUES ('new_key_name');
INSERT INTO value_table (key_id, value)
SELECT key_table.key_id, 'new_value'
FROM key_table
WHERE key_table.key_name = 'new_key_name';

An INSERT trigger can access only the values in the new record to be inserted.
You have to execute the two queries separately.
Alternatively, if you can modify all your applications, you could create a view with all three columns (key_id, value, and key_name), and create an INSTEAD OF trigger that executes both the 'real' INSERTs.

Related

Trigger works based on type of insert SQL Server

I am working in SQL Server Management Studio v18, and I have the following trigger:
CREATE TRIGGER [dbo].[update_surface]
ON [dbo].[my_table]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #surface_m2 REAL
SET #surface_m2 = (SELECT cast(round(CAST(Dimension1*Dimension2 as decimal)/ cast(1000000 as decimal),3,3) as decimal(10,3)) AS surface FROM my_table WHERE Surface_m2 IS NULL)
UPDATE dbo.my_table SET Surface_m2 = #surface_m2
END
I have two columns in my_table, which are Dimesion1 and Dimension2. I want that the trigger multiplies them, and set the result to other column in the same table, which is Surface_m2, whenever this column is null. The trigger does his function, but based on the type of insert I do:
If I insert a row in my_table by the graphic environment the trigger works as I wish. With each new row, Surface_m2 has his own result.
But if I insert by INSERT INTO my_table VALUES ().... (query) the trigger updates Surface_m2 column of all previous rows with the result of each new insert.
Why is the trigger working like that? Is there any other simple way to do what I am trying to do?
Thanks.
Insert trigger gives you actual values that are inserted in a special table called... "inserted".
So what you need to do is join this table against your main table and perform the logic needed, no variables required.
Something like this untested code
create trigger...
begin
UPDATE t
SET Surface_m2 = cast(round(CAST(t.Dimension1*t.Dimension2 as decimal)
/ cast(1000000 as decimal),3,3) as decimal(10,3))
from dbo.my_table t
inner join inserted i
ON i.ID = t.ID
WHERE t.Surface_m2 IS NULL
end
This begs the question though, why can't you just insert the Surface_m2 value yourself. Or even better, change Surface_m2 to be a computed column if it's always depends on Dimension1 and Dimension2

How to write a trigger to get before and after values in a single table

I have two tables transcriptTable and trancript_log.
I need to get before and after values in trancriptTable_log (OldValue,New,Value) when any update accrue on transcriptTable.
I have a trigger for before and after update but only one trigger at a time is executed.
Create trancriptTable_log table with required columns
create trigger below (one trigger is enough)
CREATE TRIGGER INSERTEDAndDELETEDTableExample
ON transcriptTable
FOR UPDATE
AS
BEGIN
--to get the old value (insert statement may vary depend on your need and table)
insert into trancriptTable_log (column_1) SELECT <your_column_name> FROM DELETED
--to get the new value
insert into trancriptTable_log values (column_2) SELECT <your_column_name> FROM INSERTED
END

ORACLE TRIGGER INSERT INTO ... (SELECT * ...)

Trigger with Insert into (select * ...)
I'm trying it.
INSERT INTO T_ USERS SELECT * FROM USERS WHERE ID = :new.ID;
not working...
this work.
INSERT INTO T_USERS(ID) VALUES(:new.ID);
Trigger
create or replace trigger "TRI_USER"
AFTER
insert on "USER"
for each row
begin
INSERT INTO T_USER SELECT * FROM USER WHERE ID = :new.ID;
end;​
this work.
INSERT INTO T_USERS(ID) VALUES(:new.ID);
So if it fits to you then try this:
INSERT INTO T_USER(ID) SELECT ID FROM USER WHERE ID = :new.ID;
If you want to select one or more rows from another table, you have to use this syntax:
insert into <table>(<col1>,<col2>,...,<coln>)
select <col1>,<col2>,...,<coln>
from ...;
Perhaps you could post the actual error you are experiencing?
Also, I suggest that you rethink your approach. Triggers that contain DML introduce all sorts of issues. Keep in mind that Oracle Database may need to restart a trigger, and could therefore execute your DML multiple times for a particular row.
Instead, put all your related DML statements together in a PL/SQL procedure and invoke that.
Its not about your trigger but because of INSERT statement
here insert statement works as below
INSERT INTO <TABLE>(COL1,COL2,COL3) VALUES (VAL1,VAL2,VAL3); --> If trying to populate value 1 by one.
INSERT INTO <TABLE>(COL1,COL2,COL3) --> If trying to insert mult vales at a time
SELECT VAL1,VAL2,VAL3 FROM <TABLE2>;
The number of values should match with number of columsn mentioned.
Hope this helps you to understand

How to Use FIRE_TRIGGERS in insert sql statement

I am trying to copy data from table "tb_A" to itself (with different primary key).
When "tb_A" table is insert new record, I have written a trigger to populate another table "tb_B" with one record.
I ran the following statement.
INSERT INTO [tb_A]
([NAME])
select top (20)[NAME] from [tb_A]
I was expected 20 new records in "tb_B". But I didn't.
Anyway I saw FIRE_TRIGGERS is using during bulk insert to overcome this issue.
is there is a any way to use it on inset statements too ? Please provide me example.
Gayan
Trigger code (copied from Gayan's comment to gbn's answer):
CREATE TRIGGER UpdatetbB ON [dbo].[tb_A] FOR INSERT
AS
DECLARE #AID as int
SELECT #AID = [ID] FROM inserted
INSERT INTO [tb_B]([IDA]) VALUES (#AID)
The reason your trigger did not work properly is because it is poorly designed. Triggers fire once for each insert even if you are inserting a million records. You havea trigger that makes the assumption it will owrk one record at a time. Anytime you set a value form inserted or deleted to a scalar variable the trigger is wrong and needs to be rewritten. Try something like this instead.
CREATE TRIGGER UpdatetbB ON [dbo].[tb_A] FOR INSERT
AS
INSERT INTO [tb_B]([IDA])
SELECT [ID] FROM inserted
FIRE_TRIGGERS is only for BULK INSERT (and bcp), not "standard" INSERT
I'd expect your trigger to look something like
CREATE TRIGGER TRG_tbA_I ON tb_A FOR INSERT
AS
SET NOCOUNT ON
INSERT tb_B (col1, col2, ...)
SELECT col1, col2, ... FROM INSERTED
GO
You use the special INSERTED table to get the list of new rows in tb_A, then INSERT from this into tb_B. This works for more than one row
If you add the trigger code then we can explain what went wrong.
Edit: your trigger will only read a single row (any row, no particular order) from INSERTED. It isn't set based like my rough example.

sql server trigger

I have a table structure like this:
create table status_master
(
Name varchar(40)
status varchar(10)
)
I need to create trigger for status column if the status column value updated value
FAIL then the trigger invoke one insert commant like:
insert into temp value('s',s's')
Could you please any one give me tha idea to solve this?
Not sure what you really want to achieve - but in SQL Server, you have two types of triggers:
AFTER triggers that fire after INSERT, UPDATE, DELETE
INSTEAD OF triggers which can catch the operation (INSERT, UPDATE, DELETE) and do something instead
SQL Server does not have the BEFORE INSERT/UPDATE/DELETE triggers that other RDBMS have.
You can have any number of AFTER triggers, but only one INSTEAD OF trigger for each operation (INSERT, UPDATE, DELETE).
The more common case is the AFTER trigger, something like:
CREATE TRIGGER trgCheckInsertedValues
ON status_master
AFTER INSERT
AS
BEGIN
INSERT INTO dbo.temp(field1, field2, field3)
SELECT i.Name, i.Status
FROM inserted i
WHERE i.Status = 'FAIL'
END
Here, I am inspecting the "inserted" pseudo-table which contains all rows inserted into your table, and for each row that contains "status = FAIL", you'd be inserting some fields into a "temp" table.
Again - not sure what you really want in detail - but this would be the rough outline how to do it in SQL Server T-SQL code.
Marc
Trigger in SQL, is used to trigger a query when any action perform in the particular table like insert,delete,update
http://allinworld99.blogspot.com/2015/04/triggers-in-sql.html
What you're looking for is an INSTEAD OF INSERT, UPDATE trigger. Within your trigger you attempt the insert or update yourself inside a try-catch. If it errors out then you insert those values into your other table (assuming it's a logging table of some sort).
Assuming what you mean is, should the status's new value be FAIL, then what about this:
triggers reference the new record row as 'inserted' and the old one as 'deleted'
CREATE TRIGGER trgCheckInsertedValues ON status_master AFTER INSERT AS
BEGIN
if inserted.status = 'FAIL'
INSERT INTO dbo.temp(field1, field2, field3)
SELECT i.Name, i.Status, 'anything' FROM inserted i