I am not good at T-SQL. How can does following trigger into T-SQL? For each doesn't work in T-SQL.
CREATE OR REPLACE TRIGGER DSS.TRG_DEPO_STOK_IZLEME
BEFORE INSERT OR UPDATE
ON DSS.CR_DEPO_STOK FOR EACH ROW
BEGIN
INSERT INTO CR_DEPO_STOK_IZLEME
(ID_DEPO_STOK_IZLEME
, ID_DEPO_STOK
, MT_MIKTAR_ESKI
, MT_MIKTAR_YENI
, EKLEME_TARIHI
)
VALUES (SEQ_ID_DEPO_STOK_IZLEME.NEXTVAL
, :NEW.ID_DEPO_STOK
, :OLD.MT_MIKTAR
, :NEW.MT_MIKTAR
, SYSDATE
);
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
Probably something like
CREATE TRIGGER DSS.TRG_DEPO_STOK_IZLEME
ON DSS.CR_DEPO_STOK
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO CR_DEPO_STOK_IZLEME
(ID_DEPO_STOK
, MT_MIKTAR_ESKI
, MT_MIKTAR_YENI
, EKLEME_TARIHI
)
SELECT i.ID_DEPO_STOK
, d.MT_MIKTAR
, i.MT_MIKTAR
, GETDATE()
FROM INSERTED i FULL OUTER JOIN DELETED d ON i.pk = d.pk
END;
There are no row triggers in TSQL also sequences will not appear until the next version so I have assumed that ID_DEPO_STOK_IZLEME will be an identity column.
Related
How to write a constraint (table level unique, using GIST and or EXCLUDE ) to perform duplication record validation using the following rule:
Entered from_date and to_date values should not be equal or within the range, and
Employee_id should not be equal, and
After the validation, an error message should be return saying 'Duplicate Entry'.
This is in postgreSQL.
Note: I am new to postgreSQL (worked in MS SQL Server and MySQL).
Thanks in advance.
As stated by #Laurenz Albe, it sounds like impossible to do with a constraint. You can implement either a trigger function or a rule instead :
Trigger function :
CREATE OR REPLACE FUNCTION test_insert_table()
RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS
$$
BEGIN
IF NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range #> daterange(NEW.from_date, NEW.to_date)
)
THEN
RAISE EXCEPTION 'Duplicate Entry' ;
RETURN NULL ;
ELSE
RETURN NEW ;
END IF ;
END ;
$$
CREATE OR REPLACE TRIGGER test_insert_table
BEFORE INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION test_insert_table() ;
Rule :
CREATE OR REPLACE RULE test_insert AS
ON INSERT TO your_table
WHERE NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range #> daterange(NEW.from_date, NEW.to_date)
)
DO INSTEAD NOTHING ;
I am using triggers if any update on my table - 'test'. I have created trigger as mentioned below.
create table log_changes(one integer primary key not null, old_three text, new_three text, old_four text, new_four text, old_five text, new_five text, update_time timestamp DEFAULT Now());
create or replace function log_changes()
returns trigger as
$$
BEGIN
insert into log_changes(one,old_three , new_three , old_four , new_four , old_five , new_five )
values
(one, old.old_three , new.new_three , old.old_four , new.new_four , old.old_five , new.new_five);
return new;
END;
$$ language plpgsql
create trigger update_log_table
after update on test
for each row execute procedure log_changes();
update test
set three = 'aa' and four = 'aa' and five = 'aa'
where one = 1 and two = 'a';
After I am executing update query, I am getting following error
ERROR: invalid input syntax for type boolean: "aa"
LINE 1: update test set three = 'aa' and four = 'aa' and five = 'aa'...
^
SQL state: 22P02
Character: 25
=================================================================
Another Error ::
Trigger Function :
create or replace function log_changes()
returns trigger as
$$
BEGIN
insert into log_changes(one,old_three , new_three , old_four , new_four , old_five , new_five ) values (new.one, old.old_three , new.new_three , old.old_four , new.new_four , old.old_five , new.new_five);
return new;
END;
$$ language plpgsql
After update, error is :
ERROR: record "old" has no field "old_three"
CONTEXT: SQL statement "insert into log_changes(one,old_three , new_three , old_four , new_four , old_five , new_five ) values (new.one, old.old_three , new.new_three , old.old_four , new.new_four , old.old_five , new.new_five)"
PL/pgSQL function log_changes() line 3 at SQL statement
SQL state: 42703
As documented in the manual the assignment expressions in an UPDATE are separated by commas:
update test
set three = 'aa', --<< comma here, no AND
four = 'aa',
five = 'aa'
where one = 1
and two = 'a';
I have an Oracle procedure to add a row to the JOB_HISTORY table and a trigger to call the procedure when data is updated on two columns( job_id, department_id) in the table EMPLOYEES: I´m trying to rewrite them for Sql server 2008, can anyone help me to rewrite both of them please? I might have done it with the procedure but cannot do it with the trigger. any suggestion is welcome?
Procedure:
CREATE OR REPLACE PROCEDURE add_job_history
( p_emp_id job_history.employee_id%type
, p_start_date job_history.start_date%type
, p_end_date job_history.end_date%type
, p_job_id job_history.job_id%type
, p_department_id job_history.department_id%type )
IS BEGIN
INSERT INTO job_history (employee_id, start_date, end_date,job_id,department_id)
VALUES(p_emp_id,p_start_date,p_end_date,p_job_id,p_department_id);
END add_job_history;
Trigger:
CREATE OR REPLACE TRIGGER update_job_history
AFTER UPDATE OF job_id,department_id ON employees
FOR EACH ROW
BEGIN
add_job_history(:old.employee_id, :old.hire_date, sysdate,
:old.job_id,:old.department_id);
END;
This is how I wrote the procedure I´m not sure is doing the same thing as the one above though.
CREATE PROCEDURE add_job_history
(#p_emp_id INTEGER,
#p_start_date DATE,
#p_end_date DATE,
#p_job_id VARCHAR(10),
#p_department_id INTEGER ) AS
BEGIN
INSERT INTO job_history (employee_id, start_date, end_date,
job_id, department_id)
VALUES(#p_emp_id, #p_start_date, #p_end_date, #p_job_id,#p_department_id)
END ;
CREATE TRIGGER update_job_history ON (table_EMPLOYEES)
AFTER UPDATE
AS
BEGIN
if exists(select 1 From inserted as i inner join deleted as d on d.employee_id = i.employee_id where d.job_id != i.job_id or d.department_id != i.department_id)
begin
insert into job_history (employee_id, start_date, end_date,job_id,department_id)
select d.employee_id, d.start_date,d.end_date,d.job_id,d.department_id
from deleted as d
end
END;
thanks for your help #Long
I found The answer even if I still have to test the logic of it and i might change some inserted i. with d.
create trigger update_job_history on employees
after update
as
begin
set nocount on;
insert into job_history (employee_id, start_date, end_date ,job_id,department_id)
select i.employee_id, i.hire_date as start_date , d.hire_date as end_date, d.job_id ,d.department_id
From inserted as i inner join deleted as d on d.employee_id = i.employee_id where d.job_id != i.job_id or d.department_id != i.department_id
end
I have few SELECT statements that are made by joining multiple tables.
Each select is returning single row but from 10 to 20 fields in that row. What is the easiest way to store that data for later use?
I would like to avoid creating 50 variables and writing select into statements, using cursors and loop for single row is not the smartest idea from what i read around.
Is there a good way to do this?
Stupid example so you can get general idea
SELECT t1.field1
, t1.field2
, t1.field3
, t1.field4
, t2.field5
, t2.field6
, t2.field7
, t3.field8
FROM table1 t1
JOIN table2 t2 ON something
JOIN table3 t3 ON something
Sorry for errors in my english and thanks in advance
Create a view from your select statement. Thereafter can reference a record by using a single variable of type <viewname>%ROWTYPE.
Another option would be to wrap the select in an implicit cursor loop:
DECLARE
strvar VARCHAR2(400); -- demo purpose only
BEGIN
-- ...
FOR i IN (
-- ... here goesyour select statement ...
) LOOP
strvar := i.field1 || i.field2; -- ... whatever
END LOOP;
-- ...
END;
-- ...
Still another option is the declaration of a record type and a record variable:
DECLARE
TYPE tRec IS RECORD (
field1 table1.field1%TYPE
, field2 table1.field2%TYPE
, field3 table1.field3%TYPE
, field4 table1.field4%TYPE
, field5 table2.field5%TYPE
, field6 table2.field6%TYPE
, field7 table2.field7%TYPE
, field8 table3.field8%TYPE
)
r tRec;
BEGIN
-- ...
SELECT --...
INTO r
FROM --...
;
-- ...
END;
-- ...
Every time you make a select you will have a cursor - there's no escape from that.
Views and explicit cursors are a way to reuse select statements. Which one is better option depends on the case.
rowtype-attribute is handy way to create records automatically based on tables/views/cursors. I think this is the closest to your requirement what PL/SQL can offer.
create or replace package so51 is
cursor cursor1 is -- an example single row query
select
dual.* -- all table columns included
,'Y' as str
,rownum as num
,sysdate as date_
from dual
;
function get_data return cursor1%rowtype;
end;
/
show errors
create or replace package body so51 is
-- function never changes when cursor1 changes
function get_data return cursor1%rowtype is
v_data cursor1%rowtype;
begin
open cursor1;
fetch cursor1 into v_data;
close cursor1;
return v_data;
end;
end;
/
show errors
declare
v_data constant so51.cursor1%rowtype := so51.get_data;
begin
-- use only the data you need
dbms_output.put_line('v_data.dummy = ' || v_data.dummy);
dbms_output.put_line('v_data.str = ' || v_data.str);
dbms_output.put_line('v_data.num = ' || v_data.num);
dbms_output.put_line('v_data.date_ = ' || v_data.date_);
end;
/
Example run
SQL> #so51.sql
Package created.
No errors.
Package body created.
No errors.
v_data.dummy = X
v_data.str = Y
v_data.num = 1
v_data.date_ = 2015-11-23 09:42:02
PL/SQL procedure successfully completed.
SQL>
This is my first time using triggers in green plum environment. I think I have most of it setup but I am facing some issues when I insert data. Here is my trigger
CREATE TRIGGER insert_trigger
BEFORE INSERT ON leads.abhi_temp
FOR EACH ROW EXECUTE PROCEDURE leads.my_trigger();
Here is the definition of the trigger
CREATE OR REPLACE FUNCTION leads.my_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF ( NEW.date >= DATE '2003-01-01' AND
NEW.date < DATE '2003-12-31' ) THEN
INSERT INTO leads.abhi_temp_y2003 VALUES (NEW.*);
ELSIF ( NEW.date >= DATE '2004-01-01' AND
NEW.date < DATE '2004-12-31' ) THEN
INSERT INTO leads.abhi_temp_y2004 VALUES (NEW.*);
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Now to insert data into my table I use
insert into leads.myData (select column1, column2 from leads.someOtherDara where column1 = '1');
But this gives me an error
ERROR: function cannot execute on segment because it issues a non-SELECT statement (functions.c:133)
I think the error is because I am using nested queries to insert data. Not sure how to fix this. Any recommendation. Thanks in advance for your help
I am aware, There is very limited support for triggers in Greenplum, It does not support DML operations.
May i know how do you achieve this, i mean how the rules can be applied as u said in your previous comments