How to check if i have the rights to create functions? - oracle

So i'm trying to create a stored function but i keep getting this error:
Error report -
ORA-00604: error occurred at recursive SQL level 1
ORA-20900: No access to modify schema
ORA-06512: at line 3
00604. 00000 - "error occurred at recursive SQL level %s"
*Cause: An error occurred while processing a recursive SQL statement
(a statement applying to internal dictionary tables).
*Action: If the situation described in the next error on the stack
can be corrected, do so; otherwise contact Oracle Support.
Fact is, 2-3 hours ago i created some functions and worked like a charm. I can't really understand what is happenning.
Code here (i don't know if this is relevant, as the function doesnt even go to compile)
CREATE OR REPLACE FUNCTION wsxsxfunct(x_data number)
return ECHIPE.id_echipa%type IS
y ECHIPE.id_echipa%type;
BEGIN
SELECT ID_ECHIPA INTO y
FROM ECHIPE E, PILOTI P, REZULTATE R, CURSE C
WHERE P.ID_PILOT = R.ID_PILOT
AND E.ID_ECHIPA = P.ECHIPA
AND R.ID_CURSA = C.ID_CURSA
AND EXTRACT(MONTH FROM C.DATA_CURSA) = x_data;
RETURN y;
EXCEPTION
WHEN NO_DATA_FOUND
THEN dbms_output.put_line('Nu a avut loc nicio cursa in luna ' || x_data);
RAISE_APPLICATION_ERROR(-20000,
'Nu exista angajati cu numele dat');
WHEN TOO_MANY_ROWS
THEN dbms_output.put_line('Au avut loc mai multe curse in luna ' || x_data);
RAISE_APPLICATION_ERROR(-20001,
'Exista mai multi angajati cu numele dat');
WHEN OTHERS
THEN dbms_output.put_line('Trebuie sa apelezi functia cu un numar intre 1-12, reprezentand numarul lunii');
RAISE_APPLICATION_ERROR(-20002,'Alta eroare!');
END;
/
Ignore those messages from the code. thanks
EDIT:
I tried old codes from the functions i created a few hours ago, and i'm still getting the same error report.

ORA-20900 (and generally errors between 20000 and 20999) are 'custom' errors, namely, they come from a call to RAISE_APPLICATION_ERROR.
Thus this is not a (native) privileges issue. Most likely is that an administrator has created a DDL trigger which blocks your attempt to create a function (and potentially other objects).
Speak to your DBA.

Related

How to create a trigger in Oracle that fires before a number is updated and checks to see if that number is authorised?

I want my trigger to determined that ApprUserNo = SubmitUserNo or OrgParentNo. Here's my trigger so far :
CREATE OR REPLACE TRIGGER cteam_Trigger1
BEFORE INSERT OR UPDATE OF ApprUserNo
ON cteam_ExpenseReport
FOR EACH ROW
DECLARE
ApprOrgNo cteam_Users.UserOrgNo%TYPE;
SubUserOrgNo cteam_Users.UserOrgNo%TYPE;
UserOrgParentOrg cteam_OrgUnit.OrgParentNo%TYPE;
Unauthorized EXCEPTION;
ErrorMessage VARCHAR2(200);
BEGIN
SELECT UserOrgNo
INTO ApprOrgNo
FROM cteam_Users
WHERE UserOrgNo = :NEW.ApprUserNo;
SELECT UserOrgNo
INTO SubUserOrgNo
FROM cteam_Users
WHERE UserOrgNo = :NEW.SubmitUserNo;
SELECT DECODE OrgParentNo (UserOrgParentNo,'Null',Raise Unauthorized )
INTO UserOrgParentNo
FROM cteam_OrgUnit;
WHERE UserOrgParentNo = :NEW.OrgParentNo;
EXCEPTION
WHEN Unauthorized THEN
ErrorMessage := 'Unauthorised to update ' ;
END;
The trigger is fine up until the SELECT DECODE section.
FROM cteam_OrgUnit; - the semicolon shouldn't be there.
Your DECODE is formatted incorrectly. It might be that you wanted to write:
DECODE(OrgParentNo
UserOrgParentNo, 'Null',
Raise Unauthorized)
but you can't have an executable statement such as RAISE UNAUTHORIZED in a DECODE, which only deals with values. I suggest you rewrite your code as
CREATE OR REPLACE TRIGGER cteam_Trigger1
BEFORE INSERT OR UPDATE OF ApprUserNo ON cteam_ExpenseReport
FOR EACH ROW
DECLARE
vUserOrgParentNo cteam_OrgUnit.OrgParentNo%TYPE;
BEGIN
SELECT ou.OrgParentNo
INTO vUserOrgParentNo
FROM cteam_OrgUnit ou
WHERE ou.OrgParentNo = :NEW.OrgParentNo;
IF vUserOrgParentNo <> :NEW.ApprUserNo THEN
RAISE_APPLICATION_ERROR(-20000, 'Unauthorised to update');
END IF;
END;
I removed the SELECT statements where data was being fetched and never used; likewise, I removed the variables associated with those SELECTs. I replaced the DECODE with a CASE expression because I find a CASE expression is easier to read. I suggest that you prefix variables with an extra character, such as the v I added to vUserOrgParent, to prevent variable names from conflicting with column names in your tables. This is a potential source of problems which is easier to fix this way than any other. I also took some guesses as to the correct column names in your tables - if they're wrong feel free to fix them up.
Also - triggers cannot return error messages. The only way they can "communicate" with other code is by raising exceptions. I added a call to RAISE_APPLICATION_ERROR so the trigger can raise a known exception number.

Getting Unknown Command error on IF-THEN-ELSE

I have the following query that I am using in Oracle 11g
IF EXISTS (SELECT * FROM EMPLOYEE_MASTER WHERE EMPID='ABCD32643')
THEN
update EMPLOYEE_MASTER set EMPID='A62352',EMPNAME='JOHN DOE',EMPTYPE='1' where EMPID='ABCD32643' ;
ELSE
insert into EMPLOYEE_MASTER(EMPID,EMPNAME,EMPTYPE) values('A62352','JOHN DOE','1') ;
END IF;
On running the statement I get the following output:
Error starting at line : 4 in command -
ELSE
Error report -
Unknown Command
1 row inserted.
Error starting at line : 6 in command -
END IF
Error report -
Unknown Command
The values get inserted with error when I run it directly. But when I try to execute this query through my application I get an oracle exception because of the error generated :
ORA-00900: invalid SQL statement
And hence the values are not inserted.
I am relatively new to Oracle. Please advise on what's wrong with the above query so that I could run this query error free.
If MERGE doesn't work for you, try the following:
begin
update EMPLOYEE_MASTER set EMPID='A62352',EMPNAME='JOHN DOE',EMPTYPE='1'
where EMPID='ABCD32643' ;
if SQL%ROWCOUNT=0 then
insert into EMPLOYEE_MASTER(EMPID,EMPNAME,EMPTYPE)
values('A62352','JOHN DOE','1') ;
end if;
end;
Here you you the update on spec, then check whether or not you found a matching row, and insert in case you didn't.
"what's wrong with the above query "
What's wrong with the query is that it is not a query (SQL). It should be a program snippet (PL/SQL) but it isn't written as PL/SQL block, framed by BEGIN and END; keywords.
But turning it into an anonymous PL/SQL block won't help. Oracle PL/SQL does not support IF EXISTS (select ... syntax.
Fortunately Oracle SQL does support MERGE statement which does the same thing as your code, with less typing.
merge into EMPLOYEE_MASTER em
using ( select 'A62352' as empid,
'JOHN DOE' as empname,
'1' as emptype
from dual ) q
on (q.empid = em.empid)
when not matched then
insert (EMPID,EMPNAME,EMPTYPE)
values (q.empid, q.empname, q.emptype)
when matched then
update
set em.empname = q.empname, em.emptype = q.emptype
/
Except that you're trying to update empid as well. That's not supported in MERGE. Why would you want to change the primary key?
"Does this query need me to add values to all columns in the table? "
The INSERT can have all the columns in the table. The UPDATE cannot change the columns used in the ON clause (usually the primary key) because that's a limitation of the way MERGE works. I think it's the same key preservation mechanism we see when updating views. Find out more.

ORA-01403: no data found IN ORACLE PL/SQL

I have an oracle error executing this PL/SQL in the second line: SELECT ....
But for God's sake ! I've already check if there is some null values
IF zocRole IS NOT NULL and devices.unit_id IS NOT NULL THEN
SELECT unit_role_id INTO unitRoleId FROM T_UNIT_ROLE WHERE role_id = zocRole AND unit_id = devices.unit_id;
END IF;
As mentioned above, this exception is thrown because your implicit cursor returns no rows. You would also get an exception if more than one row is returned.
You could instead use an Explicit Cursor Oracle Documents This is really just a named SQL statement (into which you can pass parameters if you like).
You then open the cursor, fetch (each fetch will attempt to retrieve one row) and close. You can then check whether the fetch returned any data. It takes slightly longer to code but can look cleaner.
I remember that years ago there was some debate about the relative speed of implicit vs explicit cursors but I've not heard anyone talk about this for a long time so I assume they perform the same
The best way to control the execution in a procedure/function plsql is adding blocks: BEGIN/EXCEPTION.
IF zocRole IS NOT NULL AND devices.unit_id IS NOT NULL
THEN
BEGIN
SELECT unit_role_id
INTO unitRoleId
FROM T_UNIT_ROLE
WHERE role_id = zocRole
AND unit_id = devices.unit_id
;
EXCEPTION
WHEN OTHERS
THEN dbms_output.put_line(SQLCODE||'-'||SUBSTR(SQLERRM, 1, 200));
END
;
END IF
;

Oracle Trigger fails after several times it is triggerd

I have two triggers. One trigger for UPDATE and INSERT and one trigger for DELETE.
create or replace
TRIGGER insup_trigger
BEFORE INSERT OR UPDATE ON USER_GROUPS
FOR EACH ROW
BEGIN
UPDATE PROJECTS
SET TOUCHED = 1
WHERE ID IN (SELECT PJ_ID
FROM PROJECT_ROLES_GROUPS
WHERE GRP_ID = :NEW.GRP_ID);
END;
and the trigger for delete:
create or replace
TRIGGER MARK
BEFORE DELETE ON USER_GROUPS
FOR EACH ROW
BEGIN
UPDATE PROJECTS
SET TOUCHED = 1
WHERE ID IN (SELECT PJ_ID
FROM PROJECT_ROLES_GROUPS
WHERE GRP_ID = :OLD.GRP_ID);
END;
Now these triggers work fine a few times but after that the errors are thrown
ORA-01013: user requested cancel of current operation
ORA-06512: at "MARK", line 3
ORA-04088: error during execution of trigger 'MARK'
Triggering the triggers from SQL Developer by doing manual insert and delete does not trigger the error, this error appears from an .net applications that does the inserts and deletes.
Am I missing something ?
EDIT:
Reading the comments I got the hint that the problem might be in the vb.net code. I had:
adTrans = ADOCon.BeginTransaction()
adCMD = New OdbcCommand(vsSQL, ADOCon)
adCMD.Transaction = adTrans
Try
adCMD.ExecuteNonQuery()
adTrans.Commit() <- here is the error it should be
-> adCMD.Transaction.Commit()
Return True
Catch ex As Exception
' Try to rollback the transaction
Try
adTrans.Rollback()
If vbSuppressOutput = False Then
MsgBox(ex.Message)
End If
System.Threading.Thread.Sleep(20)
Catch
' Do nothing here; transaction is not active.
End Try
Return False
End Try
So I tried with the modified code and I cannot reproduce the problem anymore.
Thank you very very very much for your spot on comments!
The edit of the question is wrong.
As the comments suggested the problem was that I did not commit the transactions done with SQL Developer.
Because of that the transactions done with the VB.net application were unable to complete and the errors were generated.

Error in Oracle procedure, object is invalid

Where is the bug? Compilation ends with errors and I have no idea where I'm going wrong.
create or replace
PROCEDURE make_payoff(user_id_argument number)
is
begin
payoff_amount:= 0;
CURSOR Clicks IS
SELECT c.cpc FROM click as c JOIN widget w ON w.id = c.widget_id JOIN website web ON web.id = w.website_id WHERE web.user_id = user_id_argument AND c.payoff_id IS NULL;
BEGIN
FOR Click IN Clicks
LOOP
payoff_amount:= payoff_amount + Click.cpc;
END LOOP;
INSERT INTO payoff (user_id, amount) VALUES (user_id_argument, payoff_amount);
COMMIT;
end;
I'm getting:
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object S10306.MAKE_PAYOFF is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
EDIT:
I've fixed Cursor name but error is the same
This is the error you get when you try to use the procedure. Not the error you get when you compile it. You need to find the error you get when you compile the procedure, probably using show errors and attempt to solve that problem.
Your problem is that for click in click should be for click in clicks... Not the extra s, so you are looping through the cursor.
Additionally, in your cursor you've written FROM click as c, which is not valid in Oracle. This should be FROM click c
And two BEGINs... remove the first one.
Alex Poole has noted that you've also not declared the type of the variable payoff_amount. You should declare this as a number:
payoff_amount number := 0;
However, there is no need to do this, no need to loop, no need to use a procedure at all. This is possible with a single SQL statement:
insert into payoff (user_id, amount)
select 'user_id_argument', sum(c.cpc)
from click c
join widget w
on w.id = c.widget_id
join website web
on web.id = w.website_id
where web.user_id = user_id_argument
and c.payoff_id IS NULL;
You missed s.
FOR Click IN Clicks
LOOP
payoff_amount:= payoff_amount + Click.cpc;
END LOOP;
Anyway, don't name variables and cursors so close to database fields. Add some prefix, for example, to differentiate easily.
I created a procedure for my user under the user sys. When starting the procedure, I received the same errors as yours. The procedure was valid. Recompiling the object under different users did not help solve the problem. I drop the procedure and created it as my user. Problem solved.

Resources