Teradata Trigger Syntax (referencing similar rows for conditional insert) - sql

I have a TeraData table that looks something like this:
Name;Year;Amount
1. Bob;2018;20
2. Bob;2022;14
3. Joe;2019;40
4. Ben;2017;12
The PK is Name and Year. I have a trigger in place that prevents a user from editing a row's Year to a lesser number. i.e. changing row 3 from 2019 to 2018.
That trigger is below:
Replace TRIGGER xyz.Month_Update
AFTER UPDATE OF Month ON xyz.table
REFERENCING OLD ROW as OldRow NEW ROW as NewRow
FOR EACH ROW
WHEN NewRow.Year < OldRow.Year
abort;
Now I would like to do something similar for insert.
I would like to prevent a user from inserting a new row into the table
if..
There already exists a row for the same person in the table and
That row(s) has a greater year than the one the user is attempting to enter
i.e. User can't enter Joe;2017;19 but user can enter Joe;2020;19
There are a few obvious problems with the trigger below but it shows the general idea:
Replace TRIGGER xyz.Month_Update
AFTER INSERT ON xyz.table
REFERENCING NEW ROW as NewRow
FOR EACH ROW
WHEN NewRow.Year < (select max(year) from xyz.table as t1 where t1.name = NewRow.name group by t1.name)
abort;
I'm new to triggers in general and teradata documentation appears porous.. any suggestions are greatly appreciated.

I don't know exactly if a Correlated Subquery like this is allowed in a Trigger (and how to write it correctly), but you can use Macros or Stored Procedures in a Trigger:
REPLACE MACRO xyz.Month_Insert_macro(yr INT, name VARCHAR(50)) AS
( ABORT 'Greater year already exists for that name'
WHERE :yr <
( SELECT Max(yr) FROM xyz.table
WHERE name= :name
);
);
Replace TRIGGER xyz.Month_Insert
-- it's better to abort BEFORE the Insert than AFTER (same for your Update Trigger)
BEFORE INSERT ON xyz.table
REFERENCING NEW ROW as NewRow
FOR EACH ROW
EXEC xyz.Month_Insert_macro(NewRow.yr, NewRow.name);

Related

Trigger is not inserting value into correct record

I'm trying to write a trigger that get a QuoteNumber from table 1 and insert it into table 2 where ShippingIdentity matches the records in both tables. The problem is the QuoteNumber is being inserted into it's own row(record) Can anyone please let me know why? Thanks.
ALTER TRIGGER InsertQuoteNumber
ON AccountInfo
FOR INSERT
AS
BEGIN
INSERT INTO ShippingInfo (QuoteNumber)
SELECT a.QuoteNumber
FROM AccountInfo a
inner join inserted i on a.ShippingIdentity = i.ShippingIdentity
END
You use the word "insert" in your description, but I think what you mean is "update". That is, you want to modify an existing row in ShippingInfo to reflect the new quote number.
The problem in your code is as simple as your choice of words. You are using an INSERT command, which inserts a new row. If you want to update an existing row, use an UPDATE.

Concat specific string to every inserted row

This is an hypothetical case..
I'm trying to find a good approach to make sure that every value inserted in an specific column col1 of my table mytable has a specific string http:// at the begining of the value.
Example:
I want to insert myprofile into mytable so (after my check condition..) the final value would be http://myprofile
I guess that a good approach could be using a trigger on insert but I didn't find anything concrete yet..
Any ideas?
Thank you.
You can try something like this as a starting point - this is for SQL Server (don't know MySQL well enough to provide that trigger code for you):
-- create the trigger, give it a meaningful name
CREATE TRIGGER PrependHttpPrefix
ON dbo.YourTableName -- it's on a specific table
AFTER INSERT, UPDATE -- it's for a specific operation, or several
AS
BEGIN
-- the newly inserted rows are stored in the "Inserted" pseudo table.
-- It has the exact same structure as your table that this trigger is
-- attached to.
-- SQL Server works in such a way that if the INSERT affected multiple
-- rows, the trigger is called *once* and "Inserted" contains those
-- multiple rows - you need to work with "Inserted" as a multi-row data set
--
-- You need to join the "Inserted" rows to your table (based on the
-- primary key for the table); for those rows newly inserted that
-- **do not** start with "http://" in "YourColumn", you need to set
-- that column value to the fixed text "http:/" plus whatever has been inserted
UPDATE tbl
SET YourColumn = 'http://' + i.YourColumn
FROM dbo.YourTableName tbl
INNER JOIN Inserted i ON tbl.PKColumn = i.PKColumn
WHERE LEFT(i.YourColumn, 7) <> 'http://'
END

Creating Oracle Trigger to copy/INSERT single record on UPDATE into new table?

I am attempting to setup a Trigger in my Oracle Database that fires every time a record is UPDATE'd in Table1. When the trigger executes (after?), I want to copy/insert the :old record values for all fields in the record which was updated into a HistoryTable. The only difference between the 2 tables is the inclusion of a [Table1_ID] field to reference all history records for that particular Table1.[ID]:
[Table1] - [ID][col1][col2][col3][etc.]
[HistoryTable] - [ID][Table1_ID][col1][col2][col3][etc.]
Does anyone know how to set this up? I've attempt to script it as shown below with no luck thus far, and haven't figured out how to specify the action exactly within the TOAD gui. I've already got a Sequence/Trigger pair in place so that the [ID] field for HistoryTable is auto-incremented each time a new record is inserted.
CREATE OR REPLACE TRIGGER SCHEMA1.ITEM_UPDATED_TRG
AFTER UPDATE ON TABLE1
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO SCHEMA1.HISTORYTABLE (Table1_ID, col1, col2, col3, etc.)
VALUES (:OLD.ID, :OLD.col1, :OLD.col2, :OLD.col3, :OLD.etc);
END;
ShOW ERRORS;
Output window comes up with Warning: compiled but with compilation errors - No errors....?

Trigger - After insert and delete example

I have a requirement as a trigger should get fired when any row is inserted or deleted from table FAB which contains num as unique value. and depending upon that num value, another table should be update.
e.g.
FAB table
num code trs
10 A2393 80
20 B3445 780
Reel table
reelnr num use flag
340345 10 500 1
when num 10 from FAB table gets deleted(or any new num gets inserted), the trigger should get fired and should check the reel table which contains that num value and give the reelnr.
How to proceed with this?
you can Use Inserted & Deleted Table in SQL
These two tables are special kind of table that are only available inside the scope of the triggers.
If you tries to use these tables outside the scope of Triggers then you will get Error.
Inserted : These table is use to get track of any new records that are insert in the table.
Suppose there are Six rows are inserted in your table then these table will consist of all the six rows that are inserted.
Deleted : These table is used to track all the Deleted record from your tables.
Last delete rows will be tracked by these table.
For Insert :
CREATE TRIGGER TR_AUDIT_Insert
ON Reel_table
FOR INSERT
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
INSERTED
END
For Delete :
CREATE TRIGGER TR_AUDIT_Delete
ON Product
FOR DELETED
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
DELETED
END
Note :
I don't know from where these three reelnr, use flag values you are getting
So, Please modify this as per your need.
This is the format of the Triggers that normally we use.
You also can do this by using single trigger also
I dont know what is your exact requirement
If you want to achieve by only single Trigger then you can refer this link :
Refer

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.