ORACLE avg,max,min salary TRIGGER - oracle

so i'm trying to create a trigger, but always have an error that says
Trigger LOG_SALARY compiled
LINE/COL ERROR
--------- ------------------------------------------------------------- 2/2 PL/SQL: SQL Statement ignored 3/9 PL/SQL: ORA-00934: group
function is not allowed here Errors: check compiler log
Error(2,2):PL/SQL: SQL Statement ignored
Error(3,9):PL/SQL:ORA-00934:group function is not allowed here
this is my code
'''alter table department add AVG_SALARY number(10);
alter table department add MAX_SALARY number(10);
alter table department add MIN_SALARY number(10);
insert into department (AVG_SALARY, MAX_SALARY, MIN_SALARY) values (AVG(salary), MAX(salary) ,MIN(salary));
create or replace TRIGGER log_salary
after update of salary on employee
for each row
begin
insert into DEPARTMENT(AVG_SALARY, MAX_SALARY, MIN_SALARY)
values(AVG(SALARY),MAX(SALARY),MIN(SALARY));
end;
update department
set salary = salary + 100.0
where SSN =888665555;
select * from DEPARTMENT;'''
could you tell me what is wrong with my code?
thankyou in advance!

You are inserting new rows into the department table. I think you want to update them. The logic looks like this:
create or replace TRIGGER log_salary
after update of salary on employee
for each row
begin
update department
set (AVG_SALARY, MAX_SALARY, MIN_SALARY) =
(select AVG(SALARY), MAX(SALARY), MIN(SALARY)
from employee
where e.department_id = :new.department_id
end;
This however will probably generate a mutating table error. Addressing that is really difficult. For instance, consider this:
emp_id dept_id salary
1 1 10
2 1 10
3 1 5
If you change emp_id's salary to 20, then the max is 20. But if you change the salary to 5, then the max remains 10.
I would suggest that you just use a view to calculate the values on-the-fly.

Related

Error unique constraint and during execution of trigger oracle

I have form in which user add information of new born baby with his/her head family name. When add information into table then getting following errors
ORA-00001: unique constraint (PK) violated
ORA-06512: at trigger_name, line 21
ORA-04088: error during execution of trigger
Trigger:
CREATE OR REPLACE TRIGGER "DB_NAME"."TRG_NBB"
AFTER INSERT ON baby
FOR EACH ROW
WHEN (new.status = 'A') DECLARE
v_1 tab_1.col_1%type;
v_2 tab_2.col_2%type;
v_3 tab_2.col_3%type;
v_4 tab_2.col_4%type;
v_5 tab_2.col_5%type;
v_6 date;
newmofid number;
BEGIN
select max(nvl(col_2,0))+1 into newmofid from tab_2;
SELECT distinct col_1,col_2,to_char(col,'DD-MM-YYYY') INTO v_1,v_2,v_6
from table
where tcid = :new.tcid;
SELECT col_4,col_5,col_3 into v_4,v_5,v_3
from tab_2
where col_1 = v_1
and col_2 = v_2;
INSERT INTO tab_2 (all_columns)
VALUES(variable_names);
DBMS_OUTPUT.PUT_LINE('New Born Baby successfully added to member table');
END trg_nbb;
/
ALTER TRIGGER "DB_NAME"."TRG_NBB" ENABLE;
When I execute this sql query It's take 4 to 5 seconds and increment in values very quickly
select max(nvl(col_2,0))+1 into newmofid from tab_2;
Result:
6030819791
Again execute takes 3 to 4 seconds
Result:
6030819798
How to solve this problem?
Thanks
I suspect it is MAX + 1 that causes problems:
select max(nvl(col_2,0))+1 into newmofid from tab_2;
Such a principle is in most cases wrong and will fails, especially in a multi-user environment where two (or more) users at the same time fetch the same MAX + 1 value, do some processing, and - at the time of insert - one of them succeeds (because it is the first), but the rest of them fail because such a value already exists in the table.
I suggest you switch to a sequence, e.g.
create sequence seq_baby;
and then, in your form, do
select seq_baby.nextval into newmofid from dual;

How should I use an object type in an insert DML statement?

I have created two TYPE objects to try out OOP processing in PL/SQL.
I tried to use my type o_customers in my INSERT statement, but I could not do it.
There is a Customers table. It has same columns as o_customers.
create or replace type o_customers as object (
id number,
name varchar2(40),
age number,
address o_addressC,
salary number
);
create or replace type o_addressC as object (
mahalle varchar(30),
apartman varchar(15),
ilce varchar(15),
apt_no number
);
declare
adres o_addressC;
musteri o_customers;
begin
adres := o_addressC('selami ali mah','çınar apt',' üsküdar',19);
musteri:= o_customers(10,'UĞUR SİNAN SAĞIROĞLU',26,adres,1000);
insert into customers values (musteri);
end;
" There is a customers table. it has same columns with o_customers"
In OOP it is not enough for objects to have the same structure to be compatible in a programming context: they must be the same type, or related to each other through inheritance.
So you need to create the table using that type:
SQL> create table customers of o_customers
2 /
Table created.
SQL> desc customers
Name Null? Type
---------------------- -------- -------------
ID NUMBER
NAME VARCHAR2(40)
AGE NUMBER
ADDRESS O_ADDRESSC
SALARY NUMBER
SQL>
Now your insert statement will work:
SQL> declare
2 adres o_addressC;
3 musteri o_customers;
4 begin
5 adres := o_addressC('selami ali mah','cınar apt','uskudar',19);
6 musteri:= o_customers(10,'UĞUR SİNAN SAĞIROĞLU',26,adres,1000);
7 insert into customers values(musteri);
8 end;
9 /
PL/SQL procedure successfully completed.
SQL> select * from customers;
ID NAME AGE
---------- ---------------------------------------- ----------
ADDRESS(MAHALLE, APARTMAN, ILCE, APT_NO)
------------------------------------------------------------------------------------------------------------------------------------------------------
SALARY
----------
10 UĞUR SİNAN SAĞIROĞLU 26
O_ADDRESSC('selami ali mah', 'c??nar apt', ' uskudar', 19)
1000
SQL>
Incidentally I had to make minor changes to the inserted values because the posted statement hurled
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
This is because your o_addressC type attributes are too small for strings with multi-byte characters.
Unless customers is an object table (create table customers of o_customers), you'll need to refer to the object's properties explicitly:
insert into customers
( id, name, age, address, salary)
values
( musteri.id, musteri.name, musteri.age, musteri.address, musteri.salary );
By the way, o_customer (no 's') would make more sense than o_customers for an object name.

I am getting error in compililing the trigger in oracle

Need help on this trigger which updating a record when user perform update on particular column.
Ex. here I have created a table orders as below.
CREATE TABLE orders
( order_id number(5),
quantity number(4),
status_c varchar2(15),
delete_date date,
deleted_by_id varchar2(10));
I have inserted 2 records in it as below.
insert into orders values (1,25,'FAILED',null,null);
insert into orders values (1,50,'QUEUED',null,null);
select * from orders;
ORDER_ID QUANTITY STATUS_C DELETE_DA DELETED_BY
1 25 FAILED
1 50 QUEUED
Now we can see the values for column STATUS_C as 'FAILED' and 'QUEUED'
So I whenever new user updates this table - orders , and make the status as 'DELETED' for status_c, then I need to capture his details such person_id and sysdate, So I have written a below trigger on that table - Orders
CREATE OR REPLACE TRIGGER orders_before_update
BEFORE UPDATE
ON orders
FOR EACH ROW
DECLARE
v_username varchar2(10);
BEGIN
If UPDATING then
if upper(:new.status_c) = 'DELETED' then
-- Find username of person performing UPDATE on the table
SELECT user INTO v_username
FROM dual;
-- Update delete_date field to current system date
:new.delete_date := sysdate;
-- Update deleted_by_id field to the username of the person performing the UPDATE
:new.deleted_by_id := v_username
end if;
end if;
END;
/
Warning: Trigger created with compilation errors.
I got error while compile.
I tried to udpate the table to see its impact,
update orders set status_c = 'DELETED' where order_id = 1;
update orders set status_c = 'DELETED' where order_id = 1
*
ERROR at line 1:
ORA-04098: trigger 'DISDBA.ORDERS_BEFORE_UPDATE' is invalid and failed re-validation
I need help what is the issue in trigger, and why it is not compiling.
When I checked the error using below query. it says.
`select * from user_errors where type = 'TRIGGER' and name` ='ORDERS_BEFORE_UPDATE';
NAME TYPE SEQUENCE LINE POSITION
------------------------------ ------------ ---------- ---------- ----------
TEXT
----------------------------------------------------------------------------------------------------
ORDERS_BEFORE_UPDATE TRIGGER 1 20 5
PLS-00103: Encountered the symbol "END" when expecting one of the following:
. ( * # % & = - + ; < / > at in mod not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like
between is null is not || is dangling
The symbol ";" was substituted for "END" to continue.
Need help on this.
Missing semi-colon on this line:
:new.deleted_by_id := v_username

Oracle SEQUENCE.Currval problem in CodeIgniter

I have a sequence named WCOMP_SEQ in oracle to generate auto increment column ON WCOMP table. When I insert a row to WCOMP table in SQLPlus, the row inserted and I can get the auto increment value using
SELECT WCOMP_SEQ.currval FROM dual
But when I ran insert a row using Database Class in CodeIgniter, the row inserted but when I ran the query above to get auto increment value I got Exception:
Exception: Undefined Index currval in E:...
How to fix this?
There is a way to get the value automatically assigned to a column: it is the RETURNING clause.
So, here is my sequence:
SQL> select emp_seq.currval from dual
2 /
CURRVAL
----------
8140
SQL>
I'm going to use it in an INSERT statement:
SQL> var seqval number
SQL> insert into emp
2 (empno, ename, deptno, sal, job)
3 values
4 (emp_seq.nextval, 'JELLEMA', 50, 4575, 'PAINTER')
5 returning empno into :seqval
6 /
1 row created.
SQL>
I returned the EMPNO into a SQL*Plus variable which I can print, and it has the same value as CURRVAL:
SQL> print :seqval
SEQVAL
----------
8141
SQL> select emp_seq.currval from dual
2 /
CURRVAL
----------
8141
SQL>
Your next question is, "does CodeIgniter support the RETURNING sysntax?" I have no idea, but I suspect it does not. Most non-Oracle frameworks don't.
There is always the option to wrap the INSERT statement in a stored procedure, but that's an architectural decision whoch many people dislike.
You can not fetch the SEQUENCE current value without issuing NEXTVAL (see here). So, if you do not want to increment the sequence value (by using NEXTVAL), you should instead query USER_SEQUENCES.
Something like this:
select Sequence_Name
, Last_Number
from user_sequences
where sequence_name = 'WCOMP_SEQ'
/
SEQUENCE_NAME LAST_NUMBER
------------- -----------
WCOMP_SEQ 20
Hope this helps.
In order to get currval on the sequence you will need to have at least one reference to the corresponding nextval for the sequence in the current user session. This is what causes it to set the currval value which would belong to the session.
If you are using it outside, it defeats the purpose which value could it return if there were other sessions active.

How can I implement conditional updating in Oracle?

I'm new to oracle and having a problem with one of my SQL Queries.
There are 2 Users: User1 and User2:
Tab1 Tab2
-------- --------
EmpNo EmpNo
EmpName EmpName
ContactNo Salary
Location
User2 has all privileges in User1.Tab1, and there is no foreign key relationship between the two tables.
The Problem:
I wanted to add a column in tab2 "NameDesignation" And I wanted to insert the value in this column after checking the following condition:
WHEN User1.Tab1.EmpNo = User2.Tab2.EmpNo THEN
INSERT INTO Tab2 VALUES (&designation)
I really have no idea how to do this, and was hoping for a little help. Any thoughts?
try this:
update user2.tab2.empno t2
set NameDesignation= &designation
where exists (select ''
from user1.tab1 t1
where t1.empno=t2.empno)
(statement updated to match the edited question)
You would need a set of triggers,
After insert or update:
CREATE OR REPLACE TRIGGER tab1_after_changed
AFTER INSERT OR UPDATE
ON tab1
FOR EACH ROW
BEGIN
DELETE FROM User2.Tab2 WHERE EmpNo=:NEW.EmpNo;
INSERT INTO User2.Tab2(EmpNo,EmpName,NameDesignation)
VALUES (:NEW.EmpNo,:NEW.EmpName, (SELECT DesignationName FROM Designation where DesignationID=:NEW.DesignationID));
END;
I just imagined a table with Designation (DesignationID number, DesignationName varchar2(xx)), and Tab1 having DesignationID(number).

Resources