SQL Trigger not pulling associated data - triggers

I think I am so close on getting this trigger to work, but not yet. A SalesOrderLine (SOL) contains a Note field with a value. Upon creating a PurchaseOrderLine (POL) which is linked as described below, I desire the SOL.Note to be copied to the POL.Note The SOL and the POL are not directly linked, but rather they are linked via sub-tables (SOLD & POLD).
What I have so far is as follows:
Alter Trigger trInsertPOLNotes
on PurchaseOrderLine
After Insert
AS
BEGIN
SET NOCOUNT ON;
Update PurchaseOrderLine
set Notes = SOL.Notes
from PurchaseOrderLine POL INNER JOIN
PurchaseOrderLineDetail POLD ON POL.LineId = POLD.LineId INNER JOIN
SalesOrderLineDetail SOLD ON POLD.SalesDetailId = SOLD.DetailId INNER JOIN
SalesOrderLine SOL on SOL.LineId = SOLD.LineId
END
Yes it kind of works, but the POL.Note is being populated with Note from a random SOL, not the
specific Note from the linked Sales Order Line. Any help would be appreciated.

Related

Postgres - Pull results from multiple tables based on declared variable

I am new to Postgres. I have 7 tables that have a common field (AcctID). I would like to pull results from each of the tables (without joining) based on the AcctID that I set (e.g. AcctID = '2352').
DO $$
Declare
AcctID := '2352';
BEGIN
Select * from pbx.users where acct = AcctID;
Select * from pbx.transactions where acct = AcctID;
Select * from pbx.logs where acct = AcctID;
....
END;
$$;
I get error message that query has no destination. Any recommendation is greatly appreciated.
The error message is essentially telling you: "okay, so you want to pull these results, but then what?"
It is unclear to me why a join is inadequate for you, it would make things so much easier.
For this purpose, you can create a stored procedure, using a composite out parameter, such as the one proposed as an answer to this question: Composite Array Type as OUTPUT parameter in PostgreSQL
Yet, instead of that I really recommend the use of joins, such as
Select *
from pbx.users
join pbx.transactions on pbx.users.acct = '2352' and pbx.users.acct = pbx.transactions.acct
join pbx.logs on pbx.transactions.acct = pbx.logs.acct;

conditional statement in DB2 without a procedure

I need to execute statements conditionally in DB2. I searched for DB2 documentation and though if..then..elseif will serves the purpose. But can't i use if without a procedure.?
My DB2 verion is 9.7.6.
My requirement is I have a table say Group(name,gp_id). And I have another table Group_attr(gp_id,value,elem_id). We can ignore ant the elem_id for the requirement now.
-> I need to check the Group if it have a specific name.
-> If it has then nothing to be done.
-> If it doesn't have I need to add it to the Group. Then I need to insert corresponding rows in the Group_attr. Assume the value and elem_id are static.
You can use an anonymous block for PL/SQL or a compound statement for SQL PL code.
BEGIN ATOMIC
FOR ROW AS
SELECT PK, C1, DISCRETIZE(C1) AS D FROM SOURCE
DO
IF ROW.D IS NULL THEN
INSERT INTO EXCEPT VALUES(ROW.PK, ROW.C1);
ELSE
INSERT INTO TARGET VALUES(ROW.PK, ROW.D);
END IF;
END FOR;
END
Compound statements :
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0004240.html
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.sqlpl.doc/doc/c0053781.html
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0004239.html
Anonymous block :
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.plsql.doc/doc/c0053848.html
http://www.ibm.com/developerworks/data/library/techarticle/dm-0908anonymousblocks/
Many ot this features come since version 9.7
I got a solution for the conditional insert. For the scenario that I mentioned, the solution can be like this.
Insert into Group(name) select 'Name1' from sysibm.sysdummy1 where (select count(*) from Group where name='Name1')=0
Insert into Group_attr(gp_id,value,elem_id) select g.gp_id,'value1','elem1' Group g,group_attr ga where ga.gp_id=g.gp_id and (select count(*) from Group_attr Ga1 where Ga.gp_id=g.gp_id)=0
-- In my case Group_attr will contain some data for sure if the group has exists already

Update Trigger better approach

I have a Trigger i am developing and want it to basically handle Updates in the sense of the Update statement, not so worried about Delete or Insert statements at the moment.
The end result is that i have two status fields active & inactive, which are bit & datetime respectively. The active field is used to invalidate a record, manually for the time, and i want to make sure that the inactive field contains a value of active change.
Ideally, i would like to check to see if active=0 and place a datetime stamp, using now(), in the field for the record. Long-term im sure i will want to validate that the inactive field doesnt have a datetime stamp already, but for now overriding it fine. As well, would like to have it check if active=1 and clear out the inactive field if any value exists.
The inactive field is nullable so there wont be a conflict.
Trigger Definition, as of now:
CREATE TRIGGER dbo.TRG_tblRegistration_Inactive
ON dbo.tblRegistration
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF update(active) BEGIN
update r
set inactive=now()
from tblRegistration r
join inserted i on r.id = i.id
where i.active = 0
END
END
I have a pretty good understanding of the inserted & deleted trigger tables.
Question:
Is there a better logic pattern within the trigger that will get me the ultimate desired goal?
Any considerations to be had if they submit a inactive value with the active=0, or active=1?
Current Form of the Trigger:
ALTER TRIGGER dbo.TRG_tblRegistration_Inactive
ON dbo.tblRegistration
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF update(active) BEGIN
update r
set inactive=getdate()
from tblRegistration r
join inserted i on r.id = i.id
where i.active = 0
update r
set inactive=NULL
from tblRegistration r
join inserted i on r.id = i.id
where i.active=1
END
END
It works and does as expected but want to make sure that first there isnt a better way of doing this (at the database side or in the trigger).
I think that it'd be better to change active to a (persisted) computed column, with this definition:
CASE WHEN inactive IS NULL THEN 0 ELSE 1 END
Then you don't need any triggers at all, and you can just set inactive = GETDATE() to accomplish the purpose.
Nonetheless, the way that your trigger is currently written (in both versions), the inactive column is going to be updated to the current date even if I run a query like this:
UPDATE tblRegistration
SET active = 0
WHERE active = 0
If you only want the date to be updated if the field changes from 1 to 0, then your update statement in the trigger would need to be:
UPDATE tblRegistration
SET inactive = GETDATE()
FROM inserted i
INNER JOIN deleted d ON i.id = d.id
WHERE tblRegistration.id = i.id AND i.active = 0 AND d.active = 1

What's wrong with my Update Trigger for an Sql Server 2012 FileTable

I have a table, 'game.FileAttachments' which has a stream_id column that links to the stream_id column of a File table, 'game.Attachments'. I created an Update trigger on the File table, to update the stream_id on the linked table; reason being, when a file in the File table is modified, the stream_id changes. Here's my trigger; help please!
CREATE TRIGGER game.tr_Update_Attachments
ON game.Attachments
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF ( UPDATE(stream_id) )
BEGIN
UPDATE game.FileAttachments
SET stream_id = i.stream_id
FROM inserted i
WHERE game.FileAttachments.stream_id IN
(
SELECT d.stream_id
FROM deleted d INNER JOIN
game.FileAttachments f ON f.stream_id = d.stream_id
)
END
END
also tried this:
IF ( UPDATE(stream_id) )
BEGIN
UPDATE game.FileAttachments
SET stream_id = i.stream_id
FROM inserted i INNER JOIN
deleted d ON 1 = 1 INNER JOIN
game.FileAttachments f ON f.stream_id = d.stream_id
END
But that also does not work.
Ok, I created a Delete trigger to test a theory; the FileTable record associated with the file I am modifying is NOT updated, but is instead deleted, and a totally new record created. Well, turns out, for an Ms Word doc, this is true. But, created a plain text file, and I can update as many times as I want, and the stream_id never changes. So, Microsoft Word, the application, it seems, clones the original document, giving it a temp name, then, when a user chooses to save it, the original is simply deleted, and the clone renamed the same as the original. That BYTES !
I think your trigger definition needs to have this:
CREATE TRIGGER game.tr_Update_Attachments
ON game.Attachments
AFTER UPDATE, DELETE
as you refer to:
SELECT d.stream_id
FROM deleted d INNER JOIN
game.FileAttachments f ON f.stream_id = d.stream_id
in your where clause...either that or you incorrectly refer to this table and need to capture the "deleted" attachments into a temp table?

trigger compilation error(insert)

this is my code:
create or replace trigger th
after insert on stock
for each row
declare
sqty number;
rl number;
isb number;
rq number;
begin
set sqty=(select stockqty from inserted);
set rl=(select reorderlevel from inserted);
set isb=(select isbn from inserted);
set rq=(select reorderquantity from inserted);
go
if sqty> rl then
delete from stock where isb=isbn;
insert into stock values(isb,sqty,rl,rq);
end if;
end;
questions:
1.if a after insert trigger is used it means all this happens after inserting right?what if i want to not insert a particular data what do i do?i mean like if weight<15 dont insert like that.
2.if i have inserted multiple data how to retrieve them?does a trigger get called for each of the insert?(if its an insert trigger).
3.this is giving me a compilation error,i just am not able to find the mistake,even using a cursor is giving me an error.
create or replace trigger t1
after insert on stock for each row
declare
cursor cl is select isbn,stockqty,reorderlevel,reorderquantity from stock where isbn>0;
begin
for c2 in c1 loop
if c2.stockqty>c2.reorderlevel then
delete from stock where isbn=c2.isbn;
insert into stock values(c2.isbn,c2.reorderquantity,c2.reorderlevel,c2.reorderquantity);
end if;
end loop;
end;
Btw i am using sql developer,weidly many of my trigger are not executing,but they are executing in oracle 8i.
I can't figure out what you are trying to do, but your syntax is all wrong (where did you get it from? SQL Server?). See documentation for the correct syntax.
You wrote:
set sqty=(select stockqty from inserted);
I suspect you want to do this:
sqty := :new.stockqty;
Ditto the next 3 lines.
Then you have:
go
which is nonsense. Just remove it.
Then you have:
if sqty> rl then
delete from stock where isb=isbn;
insert into stock values(isb,sqty,rl,rq);
end if;
Which appears to mean that if the inserted row's stockqty exceeds its reorderlevel then delete it and then insert it right back in again. This makes no sense, and cannot be done using a FOR EACH ROW trigger as you will get the "table is mutating" error.
Please explain what you are trying to achieve and then we can help see if it can be achieved.
Answers:
1. You can use a Check Constraint for that
2. I don't understand what you mean:
if you want to find duplicated records then you can group by all fields and use
having count(*) >0
but why use a trigger ?
or maybe you mean that you want the values within the trigger ? if so, use
:new and :old