How to access emp table in oracle 10g - sql

When I execute select * from emp SQL*Plus hangs even I logged in through run as administrator also.
But when I do desc emp and when I insert a record and select count(*) from emp it works fine.

It might be because of oracle error during the execution of creation of the table.
Try droping the table and creating the table.
delete from emp;
drop table emp;
After that create the table again.

Related

table EMP is mutating, trigger/function may not see it error

I have a table EMP in my apex oracle database that contains an attribute of salary named sal. I have another table EMPSAL that has 3 attributes named averageSal, minSal, maxSal which are to be updated using triggers whenever any DML operation is performed on the EMP table's sal column. Here is the trigger used for upgrading:
create or replace trigger empsal_update_trigger
AFTER update on emp
for each row
declare
avgSal2 emp.sal%type;
minSal2 emp.sal%type;
maxSal2 emp.sal%type;
begin
select avg(sal), min(sal), max(sal) into avgSal2, minSal2, maxSal2 from emp;
delete from empsal;
insert into empsal values(avgSal2, minSal2, maxSal2);
end;
The insert and delete triggers work fine, but the update one given above gives error whenever A record is updated in EMPSAL. I have tried using before keyword instead of after but it's no use.
You don't need a row level trigger for this case, but use a statement level one. Even no need to use local variable definition through use of INSERT INTO ... SELECT... statement.
So, just remove FOR EACH ROW such as
CREATE OR REPLACE TRIGGER empsal_update_trigger AFTER UPDATE ON emp
BEGIN
DELETE empsal;
INSERT INTO empsal
SELECT AVG(sal), MIN(sal), MAX(sal)
FROM emp;
END;
/

In my table i don't have a column but i want to use in where condition is it possible or not

Suppose i have two database having same table name but columns name(empno,employee_no) are different so, i want to use single query in both of the table query is given below but i want in a single query.
In where condition i have mention there two different column is it possible or not to write in a single query.
select ename
from emp
where empno = '1234'---- in 1st databse
select ename
from emp
where employee_no = '5678' ---- in 2nd database
I want to execute a single query in both database which have two different column of empno and employee_no.
Can anyone please help with same.
One simple method is:
Create view in both the database with same name and same alias for empno and employee_no.
--In first db
CREATE VIEW MY_TAB_V AS
SELECT EMPNO AS ENO,
...
FROM MY_TAB;
--In second db
CREATE VIEW MY_TAB_V AS
SELECT EMPLOYEE_NO AS ENO,
...
FROM MY_TAB;
Now, you will be able to execute following query in both the databases:
Select * from MY_TAB_V where ENO=1234;
Create a simple view so that you will be able to even update the tables using that view.
Cheers!!
It is possible to have a dynamic SQL statement that queries different columns depending on what is available, by combining DBMS_XMLGEN.GETXML with the data dictionary. However, this solution is weird, slow, and buggy, and should be a last resort. It's usually better to put this level of dynamicism in an application or a PL/SQL block.
--Conditional select on EMP depending on which column exists.
--
--Convert XML to regular values.
select extractvalue(xml, '/ROWSET/ROW/ENAME') empname
from
(
--Convert to XMLType.
--(This is nontrivial because NULL must be handled oddly.)
select
case when xml is null then
xmltype('<?xml version="1.0"?><ROWSET><ROW><ENAME></ENAME></ROW></ROWSET>')
else xmltype(xml)
end xml
from
(
--Get dynamic result as XML.
select dbms_xmlgen.getxml('select ename from emp where '||column_name||' = 1234') xml
from dba_tab_columns
where owner = user
and table_name = 'EMP'
and column_name in ('EMPNO', 'EMPLOYEE_NO')
)
);
Use these commands to test the statement:
drop table emp;
create table emp(ename varchar2(100), empno number);
insert into emp values ('asdf', 1234);
commit;
<run the above SELECT>
drop table emp;
create table emp(ename varchar2(100), employee_no number);
insert into emp values ('qwer', 1234);
commit;
<run the above SELECT>

trigger mutating error

I have emp table in schema1 and emp_fianl in schema2.
emp
empid ename estatus
1 abc incomplete
2 xyz complete
3 ifg incomplete
4 mno incomplete
Emp_final
empid ename estatus
2 xyz complete
I have to create a trigger to insert data in Schema2 emp_final table when the estatus in schema1 emp table changes to complete.
I have written below trigger for the same:
Create or replace trigger tri_emp_final
After update on emp
BEGIN
IF :new.estatus='complete' then
Insert into emp_final
(select :old.empid,:old.ename,:new.estatus from schem1.emp);
END IF;
END;
/
I am getting mutating error message for the above code. When I am trying to update the status in emp table. I am a java developer and do not have much experience in Oracle, SQL. Can anyone please help?
First thing: we you want to use :old and :new, your trigger MUST be FOR EACH ROW. So you need to change : before update on emp for each row.
Second: like Goran Stefanović wrote, you don't make that select to insert, just use the :old values.
Use
Create or replace trigger tri_emp_final
After update on emp for each row
BEGIN
IF :new.estatus='complete' then
Insert into emp_final ( empid , ename , estatus)
Values
(:old.empid,:old.ename,:new.estatus );
END IF;
END;
/
You can find a working demo here

Oracle audit delete: how to audit what was deleted?

Firstly, I am quite new in the oracle audit trail thing. So, I have to audit the actions of a particular user.
My issue is that when I check the dba_fga_audit_trail, I see in the sql_text column that the user ran a delete statement, but I do not know what it is that he deleted. This is what is written in the cell from the sql_text column:
DELETE FROM USR WHERE USR_ID = :B
Could you please help me find a way to store in the audit trail what line was deleted from a particular table?
You need to create a table to hold the deleted data, which will have one row per deletion. Then, create a trigger on the USR table which will run after delete. This trigger will select the data you want to audit from the 'dummy' :OLD table, and insert it into your audit table.
My issue is that when I check the dba_fga_audit_trail, I see in the sql_text column that the user ran a delete statement, but I do not know what it is that he deleted.
You need to set audit_trail to DBMS_FGA.DB + DBMS_FGA.EXTENDED sends the audit trail to the SYS.FGA_LOG$ table in the database and includes SQL Text and SQL Bind.
For example,
SELECT * FROM emp WHERE empno = 9998;
INSERT INTO emp (empno, ename, sal) VALUES (9998, 'Bill', 1);
UPDATE emp SET sal = 10 WHERE empno = 9998;
DELETE emp WHERE empno = 9998;
ROLLBACK;
-- Check the audit trail.
CONN sys/password AS SYSDBA
SELECT sql_text FROM dba_fga_audit_trail;
SQL_TEXT
--------------------------------------
SELECT * FROM emp WHERE empno = 9998
INSERT INTO emp (empno, ename, sal) VALUES (9998, 'Bill', 1)
UPDATE emp SET sal = 10 WHERE empno = 9998
DELETE emp WHERE empno = 9998
4 rows selected.
You can also have a look at Tim Hall's demo.

PL/SQL Trigger to sum rows and update other rows

I tried to do the following:
Write a trigger such that the budget of a department is the sum of salaries paid to employees in the department (remember employees work only a percent of time in a department). The DEPT table includes Dept ID (Did), Budget, ManagerID, the Employee(EMP) table includes EMPID(eid), SALARY, BONUS, AGE, and the WORKS table includes eid, Did, working_time.
The code I wrote was:
CREATE TRIGGER BUDGET_CHK
BEFORE
INSERT OR UPDATE OF BUDGET OR DELETE ON DEPT
FOR EACH ROW
BEGIN
UPDATE DEPT
SET BUDGET =
(SELECT SUM(E.SALARY)
FROM EMP E, WORKS W, DEPT D
WHERE E.eid=W.eid AND D.did=W.did
GROUP BY W.did)
END;
I am new to oracle. Can someone correct me on this? Thanks!
Errors (from comments below):
pl/sql: sql statement ignored
ORA-00933 sql command not properly ended
Error(16): PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following: ( begin case declare end exception exit for goto if
loop mod null pragma raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> << continue close
current delete fetch lock insert open rollback savepoint set sql execute
commit forall merge pipe purge
You have several problems in one spot.
You missed ";" symbol after UPDATE statement - this is the technical error.
Your UPDATE statement changes ALL rows in DEPT table - I don't think this is that you expect.
Your subquery can return more than 1 row - this means you will get "ORA-01427: single-row subquery returns more than one row" runtime error
Probably you want something like:
UPDATE DEPT D
SET BUDGET =
(SELECT SUM(E.SALARY)
FROM EMP E, WORKS W
WHERE E.eid=W.eid
AND D.did=W.did)
WHERE EXISTS (SELECT *
FROM EMP E, WORKS W
WHERE E.eid=W.eid
AND D.did=W.did
);
You create row-level trigger on DEP table and try to change DEPT table inside the body - you should learn about "mutating table problem": http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936
In the multiuser environment when several transactions can change data in tables
your code will get irrelevant results due to transaction isolation. Please learn Oracle concepts: http://docs.oracle.com/cd/B28359_01/server.111/b28318/consist.htm
CREATE OR REPLACE TRIGGER dept_trigger before
INSERT OR UPDATE OF budget ON dept
FOR EACH row
declare
l_budget NUMBER;
BEGIN
SELECT SUM(sal) INTO l_budget
FROM employees e
INNER JOIN works w
ON w.eid =e.eid;
IF :new.budget < l_budget THEN
raise_application_error(-20001,'Out of budget');
END IF;
END;
From Your description it might work.