I'm trying to import this trigger into a postgre database but i got an error.
This is my code
Select "comandes.before_insert_detall" AS "05";
DROP TRIGGER IF EXISTS before_insert_detall;
DELIMITER --
CREATE TRIGGER before_insert_detall BEFORE INSERT ON detall
FOR EACH ROW
BEGIN
Declare stock INT;
SET stock = (select existencias from productos where id_fab=NEW.fab AND id_producto = NEW.producto);
IF NEW.cantidad > stock THEN
SET NEW.cantidad = stock;
END IF;
SET NEW.preu = (select precio from productos where id_fab=NEW.fab AND id_producto = NEW.producto);
END;
--
DELIMITER ;
I've already checked the fields name's and are ok. Can anyone help me?
Thanks
Try with SELECT INTO
SELECT INTO stock
existencias
FROM productos
WHERE ....
I found the answer!There's the correct code:
CREATE OR REPLACE FUNCTION F_before_insert_detall() RETURNS TRIGGER AS $F_before_insert_detall$
Declare stock INT;
BEGIN
stock = (select existencias from productos where id_fab=NEW.fab AND id_producto = NEW.producto);
IF NEW.cantidad > stock THEN
NEW.cantidad := stock;
END IF;
NEW.preu := (select precio from productos where id_fab=NEW.fab AND id_producto = NEW.producto);
RETURN NEW;
END;
$F_before_insert_detall$ LANGUAGE plpgsql;
CREATE TRIGGER before_insert_detall BEFORE INSERT ON detall FOR EACH ROW
EXECUTE PROCEDURE F_before_insert_detall();
Thank you so much anyway :)
Related
I'm having trouble when I updated my values with a trigger.
Here is my trigger function
CREATE OR REPLACE FUNCTION insert_check_item()
RETURNS trigger AS
$$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO invoice_item(name, quantity, item_id, total, invoice_id)
SELECT i.name, NEW.quantity, NEW.item_id, NEW.quantity * i.price, NEW.invoice_id
FROM item i
WHERE new.item_id = i.item_id;
ELSEIF TG_OP = 'UPDATE' THEN
UPDATE invoice_item
SET total = NEW.quantity * i.price,
quantity = NEW.quantity
FROM item i
WHERE old.item_id = i.item_id;
END IF;
RETURN NULL;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER insert_total
BEFORE INSERT OR UPDATE
ON invoice_item
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE insert_check_item();
My table invoice_item depends on item to have the name and total amount
I added this other where clause to my update and solved the problem
ELSEIF TG_OP = 'UPDATE' THEN
UPDATE invoice_item
SET total = NEW.quantity * i.price,
quantity = NEW.quantity
FROM item i
WHERE invoice_item.item_id = i.item_id AND invoice_item.invoice_item_id = NEW.invoice_item_id;
You are overcomplicating things. There is no need to replace the original INSERT or UPDATE operation if you just want to change the value of a column.
You can simply assign the needed value to the column in the NEW record.
CREATE OR REPLACE FUNCTION insert_check_item()
RETURNS trigger AS
$$
DECLARE
l_price numeric;
BEGIN
select i.price
into l_price
from item i
where i.item_id = new.item_id;
new.total := new.quantity * l_price;
RETURN new;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER insert_total
BEFORE INSERT OR UPDATE
ON invoice_item
FOR EACH ROW
EXECUTE PROCEDURE insert_check_item();
I am trying to make procedure that count total slab # of from each pallet from prod_result table and insert or update that count to qty column in plt_result table that has same pallet #(plt_no)
I've tried insert, update both but doesn't work.
create or replace PROCEDURE update_qty
is
v_plt_no nvarchar2(20);
v_qty number;
cursor q1 is
select count(slab_no)
into v_qty
from prod_result
where plt_no = v_plt_no;
begin
if v_qty > 0 then
update plt_result
set qty = 'v_qty'
where plt_no = v_plt_no;
end if;
end;
What am I doing wrong here? Help please.
I'm not sure which version you're looking for - is it the one that loops through all PLT_NOs in a table, or the one that should accept PLT_NO as a parameter. Here are both options, see whether any of them helps.
The first one uses cursor FOR loop; it is easier to maintain as Oracle does most of the dirty job for you (opening the cursor, fetching, exiting the loop, closing the cursor).
create or replace procedure update_qty
is
begin
for cur_r in (select plt_no, count(slab_no) v_qty
from prod_result
group by plt_no
)
loop
if cur_r.v_qty > 0 then
update plt_result r set
r.qty = cur_r.v_qty
where r.plt_no = cur_r.plt_no;
end if;
end loop;
end;
The second one accepts PLT_NO as a parameter:
create or replace procedure update_qty
(par_plt_no in prod_result.plt_no%type)
is
v_qty number;
begin
select count(p.slab_no)
into v_qty
from prod_result p
where p.plt_no = par_plt_no;
if v_qty > 0 then
update plt_result r set
r.qty = v_qty
where r.plt_no = par_plt_no;
end if;
end;
Something like the following, where you actually open and fetch from the cursor. You'll have to assign a value to v_plt_no for the cursor to fetch anything.
create or replace PROCEDURE update_qty
is
v_plt_no nvarchar2(20);
v_qty number;
cursor q1 is
select count(slab_no)
into v_qty
from prod_result
where plt_no = v_plt_no;
begin
OPEN q1;
FETCH q1 INTO v_qty;
CLOSE q1;
if v_qty > 0 then
update plt_result
set qty = 'v_qty'
where plt_no = v_plt_no;
end if;
end;
I want to create trigger but I don't know how to do that. Below is the sample:
CREATE OR REPLACE TRIGGER checkDuration
after UPDATE on comm_shipping
FOR EACH ROW
DECLARE
quantity NUMBER;
BEGIN
SELECT * FROM comm_orders c
WHERE C.ORDER_ID = :new.order_id
AND c.quantity = 1;
IF quantity=NULL THEN
RAISE_APPLICATION_ERROR('no more items');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
Try the following ( I suppose your DBMS is Oracle or DB2 because of RAISE_APPLICATION_ERROR ):
CREATE OR REPLACE TRIGGER checkDuration
AFTER UPDATE ON comm_shipping
FOR EACH ROW
DECLARE
quantity NUMBER;
BEGIN
SELECT c.quantity
INTO quantity -- this part is missing
FROM comm_orders c
WHERE c.order_id = :new.order_id;
IF quantity is NULL THEN
RAISE_APPLICATION_ERROR(-20001,'no more items'); -- you need a code
-- between -20000 and -20999
END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;
I am trying to write trigger which will control if a record is already in table or not. If is the record already in table (compare for example by name), so current record set valid='False' and insert new. Is there any way?
This is my idea, but it doesn't work.
create or replace TRIGGER
Check_r
before insert on t$customer
FOR each ROW
declare
v_dup number;
v_com number;
v_id number;
v_id_new number;
begin
v_date:=SYSDATE;
select count(id) INTO v_dup from t$customer where surname=:NEW.surname ;
select count(id) INTO v_com from t$customer where firstname =:NEW.firstname and
address=:NEW.address;
select id into v_id from t$customer where surname=:NEW.surname;
if v_dup > 0 and v_com=0 then
v_id_new:= m$_GET_ID; -- get id
update t$customer set valid = 'False' where id = v_id;
insert into t$customer ( id, surname ,firstname, valid, address ) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
if v_dup = 0 then
v_id_new:= m$_GET_ID; -- get id
insert into t$customer ( id, surname ,firstname, valid , address) values (v_id_new,:NEW.surname ,:NEW.firstname, :NEW.valid, :NEW.address);
end if;
end;
You can use a compound trigger, for example:
CREATE OR REPLACE TRIGGER Check_r
FOR INSERT ON t$customer
COMPOUND TRIGGER
TYPE customerRecordType IS RECORD(
surname t$customer.surname%TYPE,
firstname t$customer.firstname%TYPE,
address t$customer.address%TYPE,
ID nubmer);
TYPE customerTableType IS TABLE OF customerRecordType;
customerTable customerTableType := customerTableType();
n NUMBER;
BEFORE STATEMENT IS
BEGIN
customerTable.DELETE; -- not requried, just for better understanding
END STATEMENT;
BEFORE EACH ROW IS
BEGIN
customerTable.EXTEND;
customerTable(customerTable.LAST).surname := :NEW.surname;
customerTable(customerTable.LAST).firstname := :NEW.firstname;
customerTable(customerTable.LAST).address := :NEW.address;
customerTable(customerTable.LAST).ID := m$_GET_ID;
:NEW.ID := customerTable(customerTable.LAST).ID;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR i IN customerTable.FIRST..customerTable.LAST LOOP
SELECT COUNT(*) INTO n
FROM t$customer
WHERE surname = customerTable(i).surname;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE surname = customerTable(i).surname;
END IF;
SELECT COUNT(*) INTO n
FROM t$customer
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address;
IF n > 1 THEN
UPDATE t$customer
SET valid = 'False'
WHERE firstname = customerTable(i).firstname
AND address = customerTable(i).address
END IF;
END LOOP;
END AFTER STATEMENT;
END;
/
Please note, this solution is ugly and poor in terms of performance!
But it should give you an impression how it works.
In general you should put all this into a PL/SQL Procedure instead of a trigger.
First, this is trigger for insert. you don't need to write insert statement.
Second, you need to update old record. Just update it with your where clause.
CREATE OR REPLACE TRIGGER Check_r
before insert on t$customer
FOR each ROW
BEGIN
UPDATE t$customer set valid = 'False'
WHERE surname = :NEW.surname
AND firstname =:NEW.firstname;
:NEW.id := m$_GET_ID;
END;
create or replace procedure BAS_NUM_UPD is
cursor cur is
select distinct o.oi_b,mpr.pa_ke_i,ltrim(substr(convert_171_to_711(cp.p_t_num),1,7),'0') bs_nbr
from t_obj o, mat_pa_rel mp, cor_pa cp
where o.ob_t = 'something'
and o.oi_b = mp.oi_b
and mp.pa_ke_i = cp.pa_ke_i;
l_ba_num_at_i number(10) := get_attribute_id('Ba timber');
flag1 VARCHAR2(10);
type t1 is table of varchar2(10);
par_k t1;
BEGIN
for x in cur loop
BEGIN
select pa_ke_i into par_k from mat_pa_rel where oi_b=x.oi_b ;
if par_k.count=null then
insert into cs_val (oi_b, at_i, value, flag, ) values (x.oi_b, l_ba_num_at_i, null, 1);
end if;
select flag into flag1 from cs_val where at_i = l_ba_num_at_i and oi_b = x.oi_b
and value = x.bs_nbr;
EXCEPTION
when NO_DATA_FOUND THEN
insert into cs_val (oi_b, at_i, value, flag, )
values (x.oi_b, l_ba_num_at_i, x.bs_nbr, 1);
flag1 :='Nothing';
when OTHERS
then
raise_application_error(-20011,'Unknown Exception in PROCEDURE');
END;
end loop;
end BAS_NUM_UPD;
error:
PLS-00642: local collection types not allowed in SQL statements
You should get it running if you do a bulk collect
select pa_ke_i bulk collect into par_k from mat_pa_rel where oi_b=x.oi_b ;
Then I think the if is not right. I think you need to do
if par_k.count = 0 then
But to be honest you might just make a count
select count(*) into l_cnt from mat_pa_rel where oi_b=x.oi_b;
If l_cnt = 0 then ...
Of course l_cnt has to be defined.
You should create type t1 in the schema and not in the pl/sql block.