Oracle configuration. "create or replace" function create invalid object - oracle

I recently moved my database to a new server (both Oracle 11g).
In the new host, there is a weird behavior, that whenever I run something like:
create or replace test_trigger
before insert or update
on test_table
for each row
begin
select 1 from dual;
end;
/
The trigger created is invalid without any error in log. I tried to recompile, it still invalid.
It only happen with the function "create or replace". If I drop the trigger and re-create again, it would be valid.
My question is, did I config something incorrectly? How can I check it? Thank you.

Code you posted won't compile, not in any Oracle database I know. Why? Wrong syntax.
Here's a demonstration:
SQL> create or replace test_trigger
2 before insert or update
3 on test_table
4 for each row
5 begin
6 select 1 from dual;
create or replace test_trigger
*
ERROR at line 1:
ORA-00922: missing or invalid option
SQL> end;
SP2-0042: unknown command "end" - rest of line ignored.
SQL> /
So, what's wrong with it?
create (or replace) wants to know what you're going to create. "test_trigger"? As far as Oracle is concerned, that could be "mickey_mouse" and the result will be the same. It is the trigger keyword that is missing
SELECT in PL/SQL requires an INTO clause, so that you could store the result into something
in order to be able to do that, you have to declare a variable
Here's code that, actually, compiles:
SQL> create or replace trigger test_trigger --> this
2 before insert or update
3 on test_table
4 for each row
5 declare
6 l_dummy number; --> this
7 begin
8 select 1
9 into l_dummy --> this
10 from dual;
11 end;
12 /
Trigger created.
SQL>
So, it seems that you misinterpret reality.

Related

Oracle SELECT <var name> AS <column name> equivalent after stored procedure where <var name> is an outbound parameter (JDBC/SQL Only no SQL*Plus)

Does Oracle have a way other than using using DBMS_OUTPUT to render the content of returned variables coming back out of a stored procedure via SELECT?
I'm aware of functions too, but I don't have a say in rewriting things, in case that's what people are thinking of responding with.
DECLARE
NAME TIDAL.JOBMST.JOBMST_NAME%TYPE; -- Oracle syntax to base the type of variable upon a column in a table. It resolves to varchar2(256)
BEGIN
TIDAL.GETJOBNAMEFORID(1,NAME); -- 'NAME' is an outbound parameter of stored procedure and gets bound to variable 'NAME' in DECLARE above.
DBMS_OUTPUT.PUT_LINE('Name: ' || NAME); -- || is Oracle string concat `+` anywhere else!
END;
The program that processes this SQL via JDBC needs to be able to render output as a CSV, XML or raw payload. It can only do all these options with the "select" style output. (probably using Java's Resultset API)
The DBMS_OUTPUT.PUTLINE doesn't generate output within the program that processes the SQL. DBeaver does. So this doesn't work for me either.
I thought there would be some awkward SELECT :NAME FROM DUAL or SELECT NAME: = NAME INTO DUAL syntax I could use to render it, since Oracle won't allow a SELECT without a FROM akin to SQL Server (see below), but the solution eludes me.
In this case the result is a scalar, but it could equally be one or more records, or rows of a single column..
I would like to use AS in order to be able to label the column(s) for a downstream processes too.
Can someone tell me if this is possible?
The code has to pass JDBC SQL parser syntax checks and generates no ORA error code. The bulk of the solutions I see on Oracle on the internet seem flaky. SQL*Plus answers with things like var or exec or print don't seem to work with JDBC SQL. I've been trying to validate things via DBeaver too - and most of the time a colon prepends variable names it seems to prompt for input so I'm not sure if that/my Oracle knowledge, is muddying the waters and I should try SQL Developer to validate code instead.
This would be the equivalent in SQL Server of what I want to achieve in Oracle:
DECLARE
#NAME varchar(256),
EXEC GETJOBNAMEFORID
1
#NAME = #NAME OUTPUT;
SELECT #NAME As Name
Other that this canned example I don't have visibility to the stored procedures to know if a sys_refcursor is in use on outbound parameters either.
Is it possible? Kind of. This is SQL*Plus (command-line tool):
Procedure with an OUT parameter (just like yours):
SQL> create or replace procedure p_test (par_deptno in dept.deptno%type,
2 par_dname out dept.dname%type)
3 as
4 begin
5 select dname
6 into par_dname
7 from dept
8 where deptno = par_Deptno;
9 end;
10 /
Procedure created.
Declare a variable:
SQL> var v_dname varchar2(20);
Execute the procedure:
SQL> exec p_test(10, :v_dname);
PL/SQL procedure successfully completed.
Print the result:
SQL> print v_dname
V_DNAME
--------------------------------------------------------------------------------
ACCOUNTING
SQL>
What if the procedure returns many rows? Then you could return refcursor:
SQL> create or replace procedure p_test (par_deptno in dept.deptno%type,
2 par_dname out sys_refcursor)
3 as
4 begin
5 open par_dname for
6 select dname
7 from dept
8 where deptno <= par_deptno;
9 end;
10 /
Procedure created.
SQL> var v_dname refcursor
SQL>
SQL> exec p_test(40, :v_dname);
PL/SQL procedure successfully completed.
SQL> print v_dname
DNAME
--------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS
SQL>

Can't create TRIGGER

I need to create a script to delete some data in a database, the table doesn't have the CASCADE constraint and I don't have the right to edit them.
So I'm trying to create a TRIGGER to simulate a Cascade delete on a table (and I will remove it just after the script get executed).
Here is my trigger:
CREATE TRIGGER delete_workspace_on_delete_result
BEFORE DELETE ON RESULT
FOR EACH ROW
BEGIN
DELETE FROM WORKSPACE WHERE workspace_result_id = :old.id;
END;
/
I don't understand why it's not working, I just follow the Oracle documentation but I have this error:
Error report -
ERROR: syntax error at or near "BEGIN"
Position: 87
I'm not used to Oracle but can't find a way to make this work by my own.
I don't see anything wrong, it works. Though:
won't work on Oracle 11g or lower because trigger name is too long (can be max 30 characters)
will work on 12c and above
consider using create or replace; if it exists and you try to create it again, it'll fail
Demo on 11g:
SQL> CREATE TABLE workspace (workspace_result_id NUMBER);
Table created.
SQL> CREATE TABLE result (id NUMBER);
Table created.
SQL> CREATE TRIGGER delete_workspace_on_delete_result
2 BEFORE DELETE
3 ON RESULT
4 FOR EACH ROW
5 BEGIN
6 DELETE FROM WORKSPACE
7 WHERE workspace_result_id = :old.id;
8 END;
9 /
CREATE TRIGGER delete_workspace_on_delete_result
*
ERROR at line 1:
ORA-00972: identifier is too long
SQL> CREATE TRIGGER delete_workspace_on_del_result
2 BEFORE DELETE
3 ON RESULT
4 FOR EACH ROW
5 BEGIN
6 DELETE FROM WORKSPACE
7 WHERE workspace_result_id = :old.id;
8 END;
9 /
Trigger created.
SQL>

How to catch the event where in PL/SQL code the first commit occurs in Oracle?

Is the way in Oracle automatically catch the event where in PL/SQL code the first commit occurs?
I have a big problem with PL/SQL procedure which should not do any commits but it does a commit somewhere.
This procedure runs a huge amount of pl/sql code, a lot of dynamic pl/sql code, some packages are wrapped and some packages are not granted for debug.
Maybe someone had it a similar problem and can help me?
Your PL/SQL block will never COMMIT the changes until and unless you have explicitly mentioned COMMIT.
However, you might have DDL statements executed as dynamic SQL which might be going for an implicit commit. Search for the commit in the code.
You could look into USER_SOURCE.
SELECT *
FROM USER_SOURCE
WHERE NAME = '<PROCEDURE NAME IN UPPER CASE>'
AND TYPE = 'PROCEDURE'
AND UPPER(TEXT) LIKE '%COMMIT%'
Update
To find the DDL statements, you could look for keywords like CREATE, DROP, ALTER
SELECT *
FROM USER_SOURCE
WHERE NAME = '<PROCEDURE NAME IN UPPER CASE>'
AND TYPE = 'PROCEDURE'
AND UPPER(TEXT) LIKE '%CREATE%'
OR UPPER(TEXT) LIKE '%DROP%'
OR UPPER(TEXT) LIKE '%ALTER%'
I found the answer:
ALTER SESSION DISABLE COMMIT IN PROCEDURE
This command disables the possibility of commit and, what is most
important for me the oracle error message shows the exact place where
in pl/sql code the commit is.
SQL> create or replace procedure tst_commit is
2 begin
3 dbms_output.put_line('before commit');
4 COMMIT;
5 dbms_output.put_line('after commit');
6 end tst_commit;
7 /
Procedure created
SQL> BEGIN
2 EXECUTE IMMEDIATE 'ALTER SESSION DISABLE COMMIT IN PROCEDURE';
3 INSERT INTO viliusg.log VALUES(SYSDATE,'test commit');
4 tst_commit;
5 dbms_output.put_line('THE END');
6 END;
7 /
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION DISABLE COMMIT IN PROCEDURE';
INSERT INTO viliusg.log VALUES(SYSDATE,'test commit');
tst_commit;
dbms_output.put_line('THE END');
END;
ORA-00034: cannot COMMIT in current PL/SQL session
ORA-06512: at "FORPOST.TST_COMMIT", line 4
ORA-06512: at line 4

creating insert trigger error

i'm trying to create a trigger that sets the id from a predefined sequence.
CREATE SEQUENCE seq_list_status
START WITH 1
INCREMENT BY 1
;
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual;
/
i'm getting the error below while creating the trigger
Error starting at line 1 in command:
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
select seq_list_status.nextval into :new.id from dual
Error at Command Line:4 Column:4
Error report:
SQL Error: ORA-04079: invalid trigger specification
04079. 00000 - "invalid trigger specification"
*Cause: The create TRIGGER statement is invalid.
*Action: Check the statement for correct syntax.
i googled it but it seems all ok. any idea for what could be wrong?
Triggers are program units. Consequently we must wrap the code body in BEGIN and END. Try this
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/
Unfortunately the examples in the SQL Reference are not as helpful as we would like. But it does link to other useful documents, such as the App Developers Guide.
you are missing the begin end
CREATE OR REPLACE TRIGGER trg_list_status_insert
BEFORE INSERT ON list_status
FOR EACH ROW
BEGIN
select seq_list_status.nextval into :new.id from dual;
END;
/

Can't create trigger using SQLPlus in Oracle

I'm Learning Oracle and wanted to try creating a trigger. I tried this example form a book in sqlplus.
SQL> CREATE OR REPLACE TRIGGER policy_bull BEFORE insert or update
2 ON emp
3 FOR EACH ROW
4 BEGIN
5 :new.salary := 200;
6 END
7 /
ERROR at line 1:
ORA-04089: cannot create triggers on objects owned by SYS
even though I logged in as SYS using
sqlplus "sys/oracle as sysdba"
You need to type / on a blank line to tell SQLPLUS to run the statement.
Oracle forbids creating triggers on objects owned by SYS.
Did you create the table emp as SYS? You probably want to be a regular user to do that. emp doesn't sound like a system table.
I think a semi-colon is missing after END.
Also mention SYS.emp
SQL> CREATE OR REPLACE TRIGGER policy_bull BEFORE insert or update
2 of SALARY on EMP
3 FOR EACH ROW
4 BEGIN
5 :new.salary := 200;
6 END
7 /
you have to type the column where the "NEW SALARY" is ppl its SALARY so ...or update of SALARY on EMP...

Resources