Trigger compilation error - sql

I need some help in creating a trigger.
create or replace trigger trigger_one
before insert on Funtom_timesheet
for each row
Declare
V_id number;
V_hours number;
Begin
Select max(timesheet_ID)+1 into v_id from Funtom_timesheet
:new.timesheet_ID :=v_id;
select grade_hours into V_hours
from funtom_grade join funtom_employee
on emp_grade = grade_id
where empid = :new.timesheet_emp;
if V_hours >:new.timesheet_hours
else
:new.timesheet_overtime :=
:new.timesheet_hours-V_hours
:new.timesheet_hours:= V_hours;
END IF;
END;
/
please tell me which part of my code is wrong so I could work on it,
Thanks

You have many syntax errors - missing ; and then. There can't be if only with else part and without expression on it.
CREATE OR REPLACE TRIGGER TRIGGER_ONE
BEFORE INSERT ON FUNTOM_TIMESHEET
FOR EACH ROW
DECLARE
V_ID NUMBER;
V_HOURS NUMBER;
BEGIN
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
SELECT GRADE_HOURS
INTO V_HOURS
FROM FUNTOM_GRADE
JOIN FUNTOM_EMPLOYEE
ON EMP_GRADE = GRADE_ID
WHERE EMPID = :NEW.TIMESHEET_EMP;
IF V_HOURS > :NEW.TIMESHEET_HOURS THEN
NULL;
ELSE
:NEW.TIMESHEET_OVERTIME := :NEW.TIMESHEET_HOURS - V_HOURS;
:NEW.TIMESHEET_HOURS := V_HOURS;
END IF;
END;
/
Also better use SEQUENCES instead of:
SELECT MAX(TIMESHEET_ID) + 1 INTO V_ID FROM FUNTOM_TIMESHEET;
:NEW.TIMESHEET_ID := V_ID;
When selecting form the same table as inserting, you can get MUTATING trigger error (http://www.dba-oracle.com/t_avoiding_mutating_table_error.htm)

Related

Update trigger not updating timestamp(update operation) in column

Trigger not working while updating the table column with trigger enabled on table...
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_U
BEFORE Update
on FINLSTATASSETDESIGNATION FOR EACH ROW
DECLARE
v_AtDateTime TIMESTAMP(3);
v_LogOperation NUMBER(3,0);
v_UserName VARCHAR2(255);
v_AppName VARCHAR2(255);
SWV_error NUMBER(10,0) DEFAULT 0;
BEGIN
begin
select USERNAME INTO v_UserName FROM v$session WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
end;
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;
SELECT distinct TO_CHAR(SYSTIMESTAMP,'DD-MON-YY hh24:mi:SS.FF AM') INTO v_AtDateTime FROM dual;
if UPDATING('FinlStatAssetDesignation') then
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
/*
ROLLBACK */
return;
end if;
if not UPDATING('UpdDate') then
SWV_error := 0;
begin
UPDATE FinlStatAssetDesignation a SET(UpdDate) =(SELECT distinct v_AtDateTime FROM dual where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation)
WHERE ROWID IN(SELECT a.ROWID FROM FinlStatAssetDesignation a where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation);
EXCEPTION
WHEN OTHERS THEN
SWV_error := SQLCODE;
end;
if SWV_error <> 0 then
/*
ROLLBACK */
return;
end if;
end if;
END;
QL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 anything 0
01-JAN-17 08.00.00.000000 AM
SQL> update finlstatassetdesignation set finlstatassetdesignationdesc ='nothing';
1 row updated.
SQL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 nothing 0
01-JAN-17 08.00.00.000000 AM
SQL> desc finlstatassetdesignation;
Name Null? Type
----------------------------------------- -------- ----------------------------
FINLSTATASSETDESIGNATION NOT NULL CHAR(10 CHAR)
FINLSTATASSETDESIGNATIONDESC NOT NULL VARCHAR2(50 CHAR)
UPDOPERATION NOT NULL NUMBER(10)
UPDDATE NOT NULL TIMESTAMP(6)
Trying to update column FINLSTATASSETDESIGNATIONDESC gets succeded however doesnt update the timestamp in column UPDDATE
Please help....in fixing this trigger...
Trigger not working while updating the table column with trigger enabled on table...
Usually it is a bad idea to write strings (i.e. TO_CHAR(SYSTIMESTAMP,'DD-MM-YY hh24:mi:SS.FF AM') INTO v_AtDateTime) when you actually want to write timestamps.
There are several weak points in your code, according to my understanding you can write it simpler:
CREATE OR REPLACE TRIGGER TR_FinlStatAssetDesignation_U
BEFORE UPDATE
ON FINLSTATASSETDESIGNATION FOR EACH ROW
BEGIN
IF UPDATING('FinlStatAssetDesignation') THEN
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
-- Rather strange if a column has the same name as the table
END IF;
IF NOT UPDATING('UpdDate') THEN
:NEW.UpdDate := SYSTIMESTAMP;
END IF;
END;
Everything else in your code is redundant, resp. junk.
In case you need the username somewhere, just write USER instead of
select USERNAME INTO v_UserName
FROM v$session
WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
For application use NVL(SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME'), 'Unknown') instead of
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;

I want to create trigger but I dont know how to do that. Below is the sample

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;

How do I enter the data in this table in the insert?

I am new in pl / sql , I want to enter this data in the insert someone help me please?
I do not know how to enter this data in the insert without making a join
I can not find the way to enter the data in the insert
these SELECT PORCENTAJE
FROM RANGO_SUBIDA_COMISION;
VARIABLE B_ANIO NUMBER;
EXECUTE :B_ANIO := 042018;
DECLARE
V_EMPLEADO_ID EMPLEADOS.EMPLEADO_ID%TYPE;
V_NOMBRE EMPLEADOS.NOMBRE%TYPE;
V_APELLIDO EMPLEADOS.APELLIDO%TYPE;
V_VALOR_COMISION COMISIONES.VALOR_COMISION%TYPE;
V_SUELDO EMPLEADOS.SUELDO%TYPE;
BEGIN
FOR R IN
(
SELECT DISTINCT E.EMPLEADO_ID , E.NOMBRE , E.APELLIDO , C.VALOR_COMISION , E.SUELDO
FROM EMPLEADOS E JOIN COMISIONES C
ON (C.EMPLEADO_ID = E.EMPLEADO_ID)
)
LOOP
V_EMPLEADO_ID := R.EMPLEADO_ID;
V_NOMBRE := R.NOMBRE;
V_APELLIDO := R.APELLIDO;
V_VALOR_COMISION := R.VALOR_COMISION;
V_SUELDO := R.SUELDO;
INSERT INTO INFORME_SUBIDA_COMISION
VALUES ( :B_ANIO ,V_EMPLEADO_ID , V_NOMBRE , V_APELLIDO , V_VALOR_COMISION , V_SUELDO );
END LOOP;
END;
I'm not quite sure what your question is. But I don't understand why you are using a cursor for this. Why not just execute a query like this?
INSERT INTO INFORME_SUBIDA_COMISION (ANIO, EMPLEADO_ID, NOMBRE, APELLIDO, VALOR_COMISION, SUELDO)
SELECT DISTINCT :B_ANIO, E.EMPLEADO_ID, E.NOMBRE, E.APELLIDO,
C.VALOR_COMISION, E.SUELDO
FROM EMPLEADOS E JOIN COMISIONES C
ON C.EMPLEADO_ID = E.EMPLEADO_ID;
Note: I'm guessing what the column names are in INFORME_SUBIDA_COMISION, but you should explicitly list them.
you can use this insert in Bulk Mode if you have huge data to insert
SET SERVEROUTPUT ON
/*use this script to insert data in bulk mode.*/
DECLARE
TYPE array IS
TABLE OF informe_subida_comision%rowtype;
v_data array;
dml_errors EXCEPTION;
PRAGMA exception_init ( dml_errors,-24381 );
CURSOR l_cur IS
SELECT DISTINCT
e.empleado_id,
e.nombre,
e.apellido,
c.valor_comision,
e.sueldo
FROM
empleados e
JOIN comisiones c ON (
c.empleado_id = e.empleado_id
);
v_error_count NUMBER;
v_err VARCHAR2(500);
v_err_indx NUMBER;
BEGIN
OPEN l_cur;
LOOP
BEGIN
FETCH l_cur BULK COLLECT INTO v_data LIMIT 1000;
FORALL i IN 1..v_data.count SAVE EXCEPTIONS
--insert data into the table
INSERT INTO informe_subida_comision VALUES v_data ( i );
-- log any dml errors
EXCEPTION
WHEN dml_errors THEN
v_error_count := SQL%bulk_exceptions.count;
FOR i IN 1..v_error_count LOOP
v_err_indx := SQL%bulk_exceptions(i).error_index;
v_err := sqlerrm(-SQL%bulk_exceptions(i).error_code);
dbms_output.put_line(v_data(v_err_indx).empleado_id
|| ''
|| v_err);
END LOOP;
END;
COMMIT;
EXIT WHEN l_cur%notfound;
END LOOP;
CLOSE l_cur;
END;

Oracle Procedure - How to insert every combination of records into a table?

I have an Oracle procedure I am working on that needs to insert every combination of Customers and Products into a specific table based on the CustomerIDs passed into the parameter.
Inputs:
Customers parameter (p_customers - comma separated):
IE: (1,2,3,4)
Order parameter (p_order - single value)
Output table that I must write to:
CustomerID, ProductID
I am hoping the following query will get me a list of the products that need be inserted:
select ProductID from orders where order_id = p_order_id
What is the most efficient way to write the insert statement?
Thank you!
Based on your "pseudo" code, try something like this. I ripped off parts of this from http://www.oratechinfo.co.uk/delimited_lists_to_collections.html
Assuming these structures:
CREATE TABLE orders (
orderId VARCHAR2(100) primary key
, customerId VARCHAR2(100)
, productId VARCHAR2(100)
);
CREATE TABLE output_table (customerId VARCHAR2(100), productId VARCHAR2(100));
Code:
CREATE TYPE varchar_table IS TABLE OF VARCHAR2(100);
/
CREATE OR REPLACE FUNCTION csv_convert(p_list IN VARCHAR2)
RETURN varchar_table
AS
l_string VARCHAR2(32767) := p_list || ',';
l_comma_index PLS_INTEGER;
l_index PLS_INTEGER := 1;
l_tab varchar_table := varchar_table();
BEGIN
LOOP
l_comma_index := INSTR(l_string, ',', l_index);
EXIT WHEN l_comma_index = 0;
l_tab.EXTEND;
l_tab(l_tab.COUNT) := SUBSTR(l_string, l_index, l_comma_index - l_index);
l_index := l_comma_index + 1;
END LOOP;
RETURN l_tab;
END csv_convert;
/
A simple unit test of the newly created csv_convert function:
SELECT * FROM TABLE(csv_convert('1,2,3,4'));
COLUMN_VALUE
------------
1
2
3
4
Now the stored proc that makes use of the csv_convert function:
CREATE OR REPLACE PROCEDURE cust_products_process (p_customers IN VARCHAR2)
IS
BEGIN
INSERT INTO output_table (customerId, productId)
SELECT customerId, productId
FROM orders o
JOIN TABLE(csv_convert(p_customers)) c
ON (o.customerId = c.column_value);
END;
/

Bind variable error in SQL trigger

Here is my trigger.Following error.
45 /
SP2-0552: Bind variable "OLD" not declared.
I am unable to find the error .I have tried several times but failed.I have declared every variable but the error is showing.Someone please help me .
drop trigger DELETE_Single_food
CREATE OR REPLACE TRIGGER DELETE_Single_food
BEFORE DELETE ON SingleFoodOrder
FOR EACH ROW
declare
f_price number;
old_bill number;
f_quantity number;
p_bill number;
foodID number;
orderID number;
order_date Date;
s_date Date;
f_date Date;
f_dis number;
a number;
b number;
c number;
BEGIN
IF :old.H_delivery_ID is not NULL then
foodID := :old.Fooditem_ID;
orderID := :old.H_delivery_ID;
f_quantity := :old.Quantity;
select bill into old_bill from HomeDelivery where H_delivery_ID =orderID ;
select price into f_price from Food_Item where Fooditem_ID = foodID;
select discount_percentage into f_dis from Food_Item where Fooditem_ID = foodID;
select start_date into s_date from Food_Item where Fooditem_ID = foodID;
select deadline into f_date from Food_Item where Fooditem_ID = foodID;
select H_delivery_request into order_date from HomeDelivery where H_delivery_ID =orderID;
if f_dis is not NULL then
if (order_date >= s_date and order_date<=f_date) then
a := f_dis/100;
b := f_price*a ;
c := f_price-b;
p_bill := old_bill-( c*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
else
p_bill := old_bill-(f_price*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
end if;
else
p_bill := old_bill-(f_price*f_quantity);
update HomeDelivery set bill = p_bill where H_delivery_ID = orderID;
end if;
END;
/
The problem is not in your variables declarations. I think you're not closing your main IF statement:
IF :old.H_delivery_ID is not NULL then
I don't see the END IF for that one. Add END IF; before the END;
If this does not work, you will need to do some debugging. Try just to leave only that statement in the begin block.
CREATE OR REPLACE TRIGGER DELETE_Single_food
BEFORE DELETE ON SingleFoodOrder
FOR EACH ROW
BEGIN
IF :old.H_delivery_ID is not NULL then
null;
END IF;
END;
/
See if that compiles. Then add the rest of the code to see where it breaks.
Hope this helps!