I'm trying to change data before an insert/update happens, the following will describe what I'm trying to accomplish, I just don't know how.
CREATE TRIGGER [my trigger]
ON [dbo].[my table]
INSTEAD OF INSERT, UPDATE
AS
BEGIN;
IF( **value of column [x] = "a"** )
**change value of column [y] to "b"**
**continue insert or update**
END;
I know that the pseudo table inserted is available, but I don't know how to handle the different triggers (being either an insert or an update).
How should I continue?
Make your trigger AFTER INSERT/UPDATE instead of INSTEAD OF, so you just need to update the value afterwards and don't need to redo the original insert or update operation.
CREATE TRIGGER [my trigger] ON [dbo].[my table]
AFTER INSERT, UPDATE
AS
BEGIN
IF UPDATE(Columnx)
BEGIN
UPDATE T SET
ColumnY = 'New Value'
FROM
[dbo].[my table] AS T
INNER JOIN inserted AS I ON T.KeyColumn = I.KeyColumn
WHERE
I.ColumnX = 'Value To Check'
END
END
Related
I have to check when a table is inserted to/updated to see if a column value exists for the same HotelID and different RoomNo in the same table. I'm thinking that an INSTEAD OF trigger on the table would be a good option, but I read that it's a bad idea to update/insert the table the trigger executes on inside the trigger and you should create the trigger on a view instead (which raises more questions for me)
Is it ok to create a trigger like this? Is there a better option?
CREATE TRIGGER dbo.tgr_tblInterfaceRoomMappingUpsert
ON dbo.tblInterfaceRoomMapping
INSTEAD OF INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #txtRoomNo nvarchar(20)
SELECT #txtRoomNo = Sonifi_RoomNo
FROM dbo.tblInterfaceRoomMapping r
INNER JOIN INSERTED i
ON r.iHotelID = i.iHotelID
AND r.Sonifi_RoomNo = i.Sonifi_RoomNo
AND r.txtRoomNo <> i.txtRoomNo
IF #txtRoomNo IS NULL
BEGIN
-- Insert/update the record
END
ELSE
BEGIN
-- Raise error
END
END
GO
So it sounds like you only want 1 row per combo of HotelID and Sonifi_RoomNo.
CREATE UNIQUE INDEX UQ_dbo_tblInterfaceRoomMapping
ON dbo.tblInterfaceRoomMapping(HotelID,Sonifi_RoomNo)
Now if you try and put a second row with the same values, it will bark at you.
It's (usually) not okay to create a trigger like that.
Your trigger assumes a single row update or insert will only ever occur - is that guaranteed?
What will be the value of #txtRoomNo if multiple rows are inserted or updated in the same batch?
Eg, if an update is performed against the table resulting in 1 row with correct data and 1 row with incorrect data, how do you think your trigger would cope in that situation? Remember triggers fire once per insert/update, not per row.
Depending on your requirments you could keep the instead of trigger concept, however I would suggest a separate trigger for inserts and for updates.
In each you can then insert / update and include a where not exists clause to only allow valid inserts / updates, ignoring inserting or updating anything invalid.
I would avoid raising an error in the trigger, if you need to handle bad data you could also insert into some logging table with the reverse where exists logic and then handle separately.
Ultimately though, it would be best for the application to check if the roomNo is already used.
I have a requirement where in I want to write a trigger in sybase when any action insert, update and delete will occur on particular table.
Syntax I know but my problem is I want to perform different action each time based on action insert , update and delete.
How can I put this condition in trigger?
like
if insert
-- perform insert specific action
if update
-- perform update specific action
if delete
-- perform delete specific action
I am assuming that this question is about SAP/Sybase Adaptive Server Enterprise (ASE). You have not stated that explicitly.
You can differentiate the behavior based on the counts of the inserted and deleted tables.
For example you can write something like this:
create trigger titles_trg on titles for insert, update, delete as
declare #inserted_cnt int, #deleted_cnt int
select #inserted_cnt = count(*) from inserted
select #deleted_cnt = count(*) from deleted
--insert command
if #inserted_cnt > 0 and #deleted_cnt = 0
begin
...
end
else
--delete command
if #inserted_cnt = 0 and #deleted_cnt > 0
begin
...
end
--update command
else
begin
...
end
go
I'm having some problem to create a new trigger before insert a new row.
It should act before insert to stop an insert of a new row that has a value that is already referenced from another row in the same table.
I tried to use this trigger but it is not compatible with mariaDB, in fact it gives me asyntax error on referencing.
CREATE TRIGGER BadgeAlreadyUsed
BEFORE INSERT ON User
REFERENCING NEW AS N
FOR EACH ROW
WHEN (EXISTS ( SELECT IDBadge FROM User WHERE N.IDBadge = User.IDBadge ))
SIGNAL SQLSTATE '70002' ('Badge already used!!');
How i can do the same thing with the new syntax?
thanks.
Each database (DB2, MariaDB, etc) has hundreds of differences. Don't assume anything!
This might be closer:
CREATE TRIGGER BadgeAlreadyUsed
BEFORE INSERT ON User
FOR EACH ROW
BEGIN
IF (EXISTS ( SELECT IDBadge FROM User
WHERE NEW.IDBadge = User.IDBadge ))
THEN
SIGNAL SQLSTATE '70002'
SET MESSAGE_TEXT = 'Badge already used!!';
END IF;
END;
Notice there there are at least 3 syntax changes (WHEN, NEW, SET).
I've created the following table:
CREATE TABLE updates
(
"table" text,
last_update timestamp without time zone
)
I want to update it whenever any table is updated, the problem is I don't know how, could someone please help me turn this pseudocode into a trigger?
this = current table on whitch operation is performed
ON ALTER,INSERT,DELETE {
IF (SELECT COUNT(*) FROM updates where table = this) = 1
THEN
UPDATE updates SET last_update = timeofday()::timestamp WHERE `table`=this
ELSE
INSERT INTO updates VALUES (this,timeofday()::timestamp);
}
You need a trigger function that is called whenever one of your tables is "updated", assuming that you mean that an INSERT, UPDATE, or DELETE is successfully executed. That trigger function would look like this:
CREATE FUNCTION log_update() RETURNS trigger AS $$
BEGIN
UPDATE updates SET last_update = now() WHERE "table" = TG_TABLE_NAME;
IF NOT FOUND THEN
INSERT INTO updates VALUES (TG_TABLE_NAME, now());
END IF;
IF (TG_OP = 'DELETE') THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END; $$ LANGUAGE PLPGSQL;
Every table that has to be logged this way needs to have a trigger associated with it like this:
CREATE TRIGGER ZZZ_mytable_log_updates
AFTER INSERT OR UPDATE OR DELETE ON mytable
FOR EACH ROW EXECUTE PROCEDURE log_update();
A few comments:
Trigger functions are created with PL/PgSQL; see chapter 40 in the documentation. Trigger functions come with some automatic parameters such as TG_TABLE_NAME.
Don't use reserved words ("table" in your case) as column names. Actually, in this case you are better off using the oid of the table, with the associated TG_RELID automatic parameter. It takes up less storage, it is faster, and it avoids confusion between tables with the same name in different schemas of your database. You can use the pg_tables system catalog table to look up the table name from the oid.
You must return the proper value depending on the operation, or the operation may fail. INSERT and UPDATE operations need to have NEW returned; DELETE needs to have OLD returned.
The name of the trigger starts with "ZZZ" to make sure that it fires after any other triggers on the same table have succeeded (they are fired in alphabetical order). If a prior trigger fails, this trigger function will not be called, which is the proper behaviour because the insert, update or delete will not take place either.
How can I apply a trigger on my sqlite database using objective-c.
I want to apply trigger to check if a table has performed an insert operation.
Run a CREATE TRIGGER statement on it. You'll need to find some way to check the trigger fires, so if you e.g. make the trigger insert rows into another table, you can regularly check the table to see if it has new rows.
If you have a table named CSAppointment, the you can write:
ALTER TABLE "CSAppointment" ADD COLUMN "tableUid" INTEGER;
CREATE TRIGGER log_insert AFTER INSERT ON CSAppointment
BEGIN
INSERT INTO CSRowChanges(tableUId, rowUid, deleteFlag ) VALUES (NEW.tableUid, NEW.uid, 0 );
END;
CREATE TRIGGER log_update AFTER UPDATE ON CSAppointment
BEGIN
INSERT INTO CSRowChanges(tableUId, rowUid, deleteFlag) VALUES (NEW.tableUid, NEW.uid, 0) ;
END;
CREATE TRIGGER log_delete AFTER DELETE ON CSAppointment
BEGIN
INSERT INTO CSRowChanges(tableUId, rowUid, deleteFlag) VALUES (OLD.tableUid, OLD.uid, 1 ) ;
END;
This way you are adding triggers for insert, update and delete operations.
More information on here.