Adding a where clause to a SQL Server trigger - sql-server

I'm looking to add a WHERE clause to the trigger shown below and looking for a bit of advice if possible. Currently the trigger works on the basis of any particular items being added to the order and not just specific ones (ideally with a prefix).
CREATE TRIGGER ItalianEmail ON SOPOrderReturn
FOR INSERT, UPDATE
AS
declare #SOPOrderReturnID int;
UPDATE SOPOrderReturn
SET AnalysisCode19 = 'mario#aol.com'
FROM SOPOrderReturn
INNER JOIN INSERTED i ON SOPOrderReturn.SOPOrderReturnID = i.SOPOrderReturnID)
GO
The layout of the tables in SQL Server is the following:
SOPOrderReturn [Header Table] -- Holds Order Information (has primary key SOPOrderReturnID)
SOPOrderReturnLine [Order Line table] -- stores the item data for the order
(has primary key SOPOrderReurnLineID and a foreign key SOPOrderReturnID)
I need the WHERE clause to pick up the StockItem on the SOPOrderReturnLine table if its LIKE 'XXX_%'
I hope I have explained enough of the structure of the tables for you to get an idea of what I would like to achieve?
Any help offered is gratefully appreciated and I thank you for your time.

Try the following. Notice the alias on
CREATE TRIGGER ItalianEmail ON SOPOrderReturn
FOR INSERT, UPDATE
AS
declare #SOPOrderReturnID int;
UPDATE oRet
SET AnalysisCode19 = 'mario#aol.com'
FROM SOPOrderReturn oRet
INNER JOIN INSERTED i ON (oRet.SOPOrderReturnID = i.SOPOrderReturnID)
INNER JOIN SOPOrderReturnLine oRetLine ON (oRetLine.SOPOrderReturnID = i.SOPOrderReturnID)
WHERE oRetLine.StockItem LIKE 'XXX%'
GO

Related

Create Trigger to modify a row to the value on a joined table

I have a tables job_costcodes(id, cost_code_no, dept_id) and cost_codes(code_code_no, dept_id).
I am trying to make it so if job_costcodes.cost_code_no is modified, job_costcodes.dept_id is filled with the appropriate one from the cost_codes table, based on a matching code_code_no.
So referring to the tables below, if the top row in job_costcodes is changed to 10, the dept_id should change to 1212. Or 20 to 1313, etc.
I am not sure exactly how the syntax works... here is what I have so far.
UPDATE: updated code.. i think it works now.
create trigger update_test on dbo.job_costcodes
for update, insert
as
begin
set nocount on
update dbo.job_costcodes
set dept_id = (select CASE WHEN COUNT(1) > 0 THEN MIN(dbo.cost_codes.dept_id) ELSE NULL END as Expr1
FROM inserted INNER JOIN
dbo.cost_codes ON dbo.cost_codes.cost_code_no = inserted.cost_code_no)
from inserted as i
inner join dbo.[job_costcodes] on dbo.[job_costcodes].id = i.id
end
Treating your question as academic, start off by looking up the CREATE TRIGGER command in TSQL to get a solid understanding of the virtual tables inserted and deleted.
Then here is what I would do, in pseudo-cod-ish descriptive terms:
In your trigger, simply UPDATE job_costcodes and set the value of dept_id to the corresponding dept_id in cost_codes by JOINing to cost_codes and inserted in the FROM clause of the UPDATE.
There is no need to verify that the cost_code_no changed when doing this, the result will be the same, but if you feel you must do this, then look at the IF UPDATE() function in TSQL. You can then compare the value of cost_code_no in inserted vs deleted to know if it changed at all.

SQL Change in one table automatically change the other table

I am new to Database and in SQL also. I have two tables t1 and t2. There is a "name" column in t1 and t2 tables. Here t1. name will be given by me, but I want that t2. name automatically change on the basis of t1. id=t2. id please help me by giving SQL query for it. Also tells me "is, stored procedures or triggers required for this?" If yes, then how I will use them? Thanks in advance..... :-)
CREATE TRIGGER [dbo].[trg_Table2]
ON [dbo].[table1] AFTER UPDATE
AS
BEGIN
IF UPDATE (name)
BEGIN
INSERT INTO table2 (name)
SELECT d.name FROM DELETED d
END
END
I provided you an idea. Use it for updating the record. Here 'Deleted' table is the one where the data changed in table1 which can be used to store that previous data into other table that you want. I inserted the data, you update it now.
Sorry, I just saw it, you want the current data then use the 'INSERTED' table just like the 'DELETED'.

Unique entries over to tables in database

I have a problem where I need to check that two columns in each table in a database are unique.
We have the database with barcode entries called uid and rid.
Table 1: T1.uid
And
Table 2: T2.rid
No barcodes in the two table columns must be the same.
How can we ensure that.
If a insertion of a barcode into table T1.uid matches an entry in
T2.rid we want to throw an error.
The tables are cleaned up and is in a consistent state where the entries in
T1.uid and T2.rid are unique over both table columns.
It is not possible to insert NULL values in the tables respective uid and tid column(T1.uid and T2.rid)
It is not possible to create a new table for all barcodes.
Because we don't have full control of the database server.
EDIT 19-02-2015
This solution cannot work for us, because we cannot make a new table
to keep track of the unique names(see table illustration).
We want to have a constraint over two columns in different tables without changing the schema.
Per the illustration we want to make it impossible for john to exist in
T2 because he already exists in table T1. So an error must be "thrown"
when we try to insert John in T2.Name.
The reason is that we have different suppliers that inserts into these tables
in different ways, if we change the schema layout, all suppliers would
need to change their database queries. The total work is just to much,
if we force every suppplier to make changes.
So we need something unobtrusive, that doesnt require the suppliers to change
their code.
A example could be that T1.Name is unique and do not accept NULL values.
If we try insert an existing name, like "Alan", then an exception will occur
because the column has unique values.
But we want to check for uniqueness in T2.Name at the same time.
The new inserted value should be unique over the two tables.
Maybe something like this:
SELECT uid FROM Table1
Where Exists (
SELECT rid FROM Table2
WHERE Table1.uid = rid )
This will show all rows from Table1 where their column uid has an equivalent in column rid of Table2.
The condition before the insertion happens could look like below. #Idis the id you need to insert the data for.
DECLARE #allowed INT;
SELECT #allowed = COUNT(*)
FROM
(
SELECT T1.uid FROM T1 WHERE T1.uid = #Id
UNION ALL
SELECT T2.rid FROM T2 WHERE T2.rid = #id
)
WHERE
#id IS NOT NULL;
IF #allowed = 0
BEGIN
---- insert allowed
SELECT 0;
END
Thanks to all who answered.
I have solved the problem. A trigger is added to the database
everytime an insert or update procedure is executed, we catch it
check that the value(s) to be inserted doens't exist in the columns of the two
tables. if that check is succesfull we exceute the original query.
Otherwise we rollback the query.
http://www.codeproject.com/Articles/25600/Triggers-SQL-Server
Instead Of Triggers

What is the best way to figure out if an UPDATE, DELETE or INSERT occur for a trigger

I want to create a single trigger in MS SQL for INSERT, UPDATE and DELETE but I want to be able to simple extract the data without 3 IF statements
I want to do something like this:
DECLARE #PK int
SELECT #PK = COALESCE(i.PK, d.PK)
FROM inserted i, deleted d
This did not work but would like to know if I can do it in one query.
What are some alternatives?
You can do the switch logic found here: SQL Server Trigger switching Insert,Delete,Update
Or you can create 3 different triggers.
Those are you options.
I ended up using a FULL OUTER JOIN
DECLARE #DataIWanted as varchar(255)
SELECT #DataIWanted = COALESCE(i.TheData,d.TheData)
FROM inserted i
FULL OUTER JOIN deleted d on d.PK=i.PK
The query above will be from the deleted table or the inserted/updated table. With the assumption that TheData is defined as NON NULL in the DB.

is there anyway to cache data that can be used in a SQL server db trigger

i have an orders table that has a userID column
i have a user table that has id, name,
i would like to have a database trigger that shows the insert, update or delete by name.
so i wind up having to do this join between these two tables on every single db trigger. I would think it would be better if i can one query upfront to map users to Ids and then reuse that "lookup " on my triggers . . is this possible?
DECLARE #oldId int
DECLARE #newId int
DECLARE #oldName VARCHAR(100)
DECLARE #newName VARCHAR(100)
SELECT #oldId = (SELECT user_id FROM Deleted)
SELECT #newId = (SELECT user_id FROM Inserted)
SELECT #oldName = (SELECT name FROM users where id = #oldId)
SELECT #newName = (SELECT name FROM users where id = #newId)
INSERT INTO History(id, . . .
Good news, you are already are using a cache! Your SELECT name FROM users WHERE id = #id is going to fetch the name for the buffer pool cached pages. Believe you me, you won't be able to construct a better tuned, higher scale and faster cache than that.
Result caching may make sense in the client, where one can avoid the roundtrip to the database altogether. Or it may be valuable to cache some complex and long running query result. But inside a stored proc/trigger there is absolutely no value in caching a simple index lookup result.
How about you turn on Change Data Capture, and then get rid of all this code?
Edited to add the rest:
Actually, if you're considering the possibility of a scalar function to fetch the username, then don't. That's really bad because of the problems of scalar functions being procedural. You'd be better off with something like:
INSERT dbo.History (id, ...)
SELECT i.id, ...
FROM inserted i
JOIN deleted d ON d.id = i.id
JOIN dbo.users u ON u.user_id = i.user_id;
As user_id is unique, and you have a FK whenever it's used, it shouldn't be a major problem. But yes, you need to repeat this logic in every trigger. If you don't want to repeat the logic, then use Change Data Capture in SQL 2008.

Resources