I'm trying to create a procedure named "Greetings" in the oracle apex. The Procedure Greetings runs with some error throwing up called "Success with compilation error". Is there anything wrong with my below code.
Code:
create table tb_Animals (
txt_Name varchar(20) Primary Key,
int_Weight number
);
insert into tb_Animals values ('Dog',30);
insert into tb_Animals values ('Cat',15);
CREATE OR REPLACE PROCEDURE greetings
AS
BEGIN
select * from tb_Animals;
END;
In PL/SQL, you have to insert those values into something, usually a variable, However, if you're selecting the whole table contents, then it has to be something else; one option might be a refcursor. For example:
SQL> CREATE OR REPLACE PROCEDURE greetings
2 AS
3 rc sys_refcursor;
4 BEGIN
5 open rc for
6 select * from tb_Animals;
7 END;
8 /
Procedure created.
SQL>
It is now correct as far as compilation is concerned, but - actual "solution" depends on what you really want to do.
Two problems I see here:
The code you provided is a SQL script that will create the procedure, not run the procedure. The error is telling you that the procedure has been created, but that it has an error. You can see the precise error by entering "SHOW ERRORS" at the sqlplus prompt after the create command completes.
The problem with the procedure itself is that you have to do something with the data you've selected. It needs to be processed into variables, or used in a for/next loop for some purpose. Simply selecting data into nothing won't work - PL/SQL is a programming language, not a scripting language. See here for a beginner's guide: https://oracle-base.com/articles/misc/introduction-to-plsql. I can't offer any more specific guidance than that since you've not provided any info on what your procedure is actually trying to do.
If you just want your script to return the data you just inserted into the table as a confirmation, just run the select statement without the procedural stuff, like this (and don't forget to commit your changes!):
create table tb_Animals (
txt_Name varchar(20) Primary Key,
int_Weight number
);
insert into tb_Animals values ('Dog',30);
insert into tb_Animals values ('Cat',15);
commit;
select * from tb_Animals;
Related
I'm taking my first steps in Pl/SQL and am struggling with triggers. I've tried creating the trigger below but am receiving this error:
Error at line 2: PL/SQL: SQL Statement ignored
PL/SQL: ORA-00942: table or view does not exist
To clarify: I have checked the name of the table over and over, and it does exist. It is also in the same schema as the trigger I'm trying to create. The 'customer_seq.NEXTVAL' refers to a sequence created previously that runs without errors.
The code is as follows:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
INSERT INTO customer_id VALUES ('c-', customer_seq.NEXTVAL);
END;
Thanks in advance for any help.
You probably intend something like this:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
SELECT customer_seq.NEXTVAL INTO :NEW.customer_id
FROM dual;
END;
It is unclear what the purpose of 'C_' is. If it is part of the customer id, I would advise you to stick to numbers.
Also note that more recent versions of Oracle support generated always as identity -- which is much preferred over defining a sequence and trigger.
N.B, the problem I'm facing is not related to the business logic, but rather, with the stored procedured itself. it's a very weird problem I'm facing and I haven't had this kind of problem before.
I'm modifying a stored procedure written in PL/SQL - called "MY_STORED_PROC" - and, each time I change its content, the previous changes still in the result of the execution of the SP.
This is the sample of the stored procedure:
create or replace PROCEDURE MY_STORED_PROC
(
V_USER IN VARCHAR2 DEFAULT NULL,
V_NUMBER_PARAM IN NUMBER DEFAULT 0,
V_ORIGIN IN NUMBER DEFAULT 0
)
AS
CV_1 SYS_REFCURSOR;
V_SAMPLE NUMBER;
BEGIN
SELECT BAP.APA_CNAME
INTO V_USER_DB
FROM BH_APPLICATION_PARAM BAP
WHERE BAP.APA_NCODE = 84;
INSERT INTO T_DEBUG (ERR_LINE, MESSAGE_INFO)
SELECT ID, 'EXAMPLE_MESSAGE'
FROM <my_table>
WHERE <ID = 1>;
END MY_STORED_PROC;
In the previous structure, I have the EXAMPLE_MESSAGE string which is inserted in T_DEBUG table when this SP is executed and the condition is met.
Now, after change the EXAMPLE_MESSAGE string sample with another text and compile and execute the SP, the message EXAMPLE_MESSAGE still shows in the results.
I don't understand why - if only this SP has the given string sample
and the table T_DEBUG is truncated before the SP is called.
What I had tried:
Execute DELETE FROM T_DEBUG; and TRUNCATE TABLE T_DEBUG before calling the SP.
Execute DROP PROCEDURE MY_STORED_PROC, then execute CREATE OR REPLACE PROCEDURE MY_STORED_PROC (with and without declaring the schema name) with the logic of the procedure changed completely.
Compile and "Compile for debug" the SP - i.e: MY_STORED_PROC with and without schema name.
Example:
CREATE OR REPLACE PROCEDURE <SCHEMA>.MY_STORED_PROC ...
CREATE OR REPLACE PROCEDURE MY_STORED_PROC ...
Modify the SP for truncate the table T_DEBUG "which contains the string sample" - this action (before the SP makes any action "i.e. insert data in T_DEBUG").
Dropping the stored procedure: DROP PROCEDURE MY_STORED_PROC; and execute: CREATE OR REPLACE PROCEDURE <SCHEMA>.MY_STORED_PROC ....
Check the T_DEBUG table and it does not contain any trigger - it's a single table with no additional features or characteristics (like indexes, triggers, back-up table(s), etc).
Compile the (SP) with the following intentional exception:
-- Generate intentional DivisionByZero unhandled exception:
/*SELECT 1/0
INTO V_SAMPLE
FROM DUAL;*/
In the later point, the exception ORA-01476 is raised and, in my opinion, the SP is taking the changes, but, after all these changes, I cannot explain why the sample string stays (even changing the content of the SP).
In (30/10/2020) I also added: 'SAMPLE - ' || TO_CHAR(SYSDATE) as a string sample, then removed, then compile the SP - without this code - and I still got this sample string with date of 30/10/2020 - date when I added such sample, despite the fact I executed this SP at 05/11/2020.
Is there any way to "refresh" the stored procedure or what other tests can be made for refresh this stored procedured?
I'm not the database administrator of this database, but, I could get more information for share with the DBA - I already explain my problem to they, but, no help has been provided.
Okay, that does sounds weird.
There should be no "refresh" required, the stored procedure is stored in the database and that's the one that gets executed. As long as you aren't using EBR then there's no risk of different versions being called as long as you are executing exactly the same procedure.
The most likely explanation is some silly mistake that you've overlooked, so start by simplifying your procedure further. You've already confirmed with the error message that it is being called each time. Remove the other parts of your code so it's just the insert into t_debug statement, maybe make it so that it selects from dual rather than your other table with a filter. Remove the arguments for the procedure. Try inserting into a different new table (maybe you have a trigger). If you still manage to replicate the behaviour when you have simplified it to:
drop table my_table;
create table my_table (my_string varchar2(200));
create or replace procedure my_proc
is
begin
insert into my_table (my_string)
select 'error 1' from dual;
end;
/
exec my_proc
select * from my_table;
delete my_table;
create or replace procedure my_proc
is
begin
insert into my_table (my_string)
select 'error 2' from dual;
end;
/
exec my_proc
select * from my_table;
Then there's a problem.
I think the two most likely causes are:
you are changing the code in an IDE,but forgetting to 'compile' it.
you have the same procedure in two different schemas, and you are not executing the same one you are editing.
I finally could solve this problem.
The problem was data-related; the database itself has too many tables and it's complex, so, I had to generate a full test of the program - after changing the text sample in the stored procedure MY_STORED_PROC to:
'Testing in LBASPOC - DATE: ' || TO_CHAR(SYSDATE, 'dd/MM/yyyy HH:mi:ss')
The result was as follows:
Testing in LBASPOC - DATE: 09/11/2020 10:11:30
When I generated more testings, new records were added in T_DEBUG table - and the DATE value did change in each test results:
Samples:
Testing in LBASPOC - DATE: 09/11/2020 10:12:29
Testing in LBASPOC - DATE: 09/11/2020 10:21:55
Testing in LBASPOC - DATE: 09/11/2020 10:37:41
I then discovered that - in other parts of the program (i.e the database) - another records were added (in a table called "T_OBSERV") - those records were based on records from table "T_DEGUB".
The solution was: modify the SP "MY_STORED_PROC" for "before do any action" - delete the duplicated records in "T_OBSERV".
I was very sure the problem were in the SP itself, but, the problem was really in the duplicated data.
I have written a oracle stored procedure and creating an error log table if that doesn't exist.
SELECT COUNT(*)
INTO v_count
FROM all_tables
WHERE TABLE_NAME = 'ERROR_LOG';
IF v_count =0 THEN
cr_table := 'CREATE TABLE ERROR_LOG ( ERROR_LOG_ID NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, IDENTIFIER VARCHAR2(100), ERROR_MESSAGE VARCHAR2(1000),created_by varchar2(100 ), created_date TIMESTAMP DEFAULT systimestamp )';
execute immediate cr_table;
then issuing an insert statement below in the code as
INSERT
INTO error_log
(
identifier,
error_message,
created_by
)
VALUES
(
v_identifier,
'Success',
v_user
);
But the SP is throwing compilation error with
PL/SQL: ORA-00942: table or view does not exist
If I create the table manually, offline, and compile then it works.
any help?
if you use execute immediate to create a table, it exists in the PL/SQL context, not in SQL context, you have to execute the INSERT by using execute immedation too.
Or you have to make the insert inside an other BEGIN.. END block.
Before using the stored procedure, please create a view or table where you are going to insert the values using the SP. So it will avoid the compiler error in the run time.
This is too long for a comment.
The table doesn't exist when the code is compiled. Hence, you are getting a compile-time error. At compilation time, Oracle doesn't know that the table will exist when executed.
One solution is to use dynamic SQL for the insert as well.
A better solution is to set up the database with the appropriate tables before the code can ever be executed. Creating permanent tables dynamically in conditional code is usually a sign of a poorly designed application.
I'm trying to get my head around triggers, but I'm getting errors
Error(2,4): PL/SQL: SQL Statement ignored
Error(2,8): PL/SQL: ORA-00922: missing or invalid option
when creating the following trigger:
CREATE TRIGGER TableTrigger
AFTER UPDATE ON TestTable
FOR EACH ROW
BEGIN
set serveroutput on format wrapped;
DBMS_OUTPUT.put_line('TABLE UPDATED!');
END;
Which works on the following table:
CREATE TABLE TestTable
(
test1 INT,
test2 INT,
test3 INT,
PRIMARY KEY (test1)
);
I'm not sure what to do, does anyone have any suggestions?
Using DBMS_OUTPUT in triggers is not best practice. If you want to see that something was done create a logging table or an audit history table or set auditing of update on for that table.
DBMS_OUTPUT is useful when you are running a PL/SQL procedure or package from SQLPlus or other IDE.
Different versions of SQL may or may not show you the output of the buffer from a trigger.
I'm using pl\sql developer and I have a report table with a number(38) ID column.
I want to keep track of all updates for this table so I created another table like this:
CREATE TABLE reportUpdate (report_id number(38), updatedate number(32));
And I created a trigger:
CREATE or REPLACE TRIGGER BeforeUpdateReport
BEFORE
UPDATE ON REPORT
FOR EACH ROW
Begin
INSERT INTO reportUpdate
Values(old.ID,sysdate);
END;
And when I run it, I get an error, saying: trigger 'SYSTEM.BEFOREUPDATEREPORT' is invalidand failed re-validation.
Can someone please help
You can use show errors after you see compiled with warnings, or query the user_errors view to see what is wrong later.
One obvious thing is that you haven't prefixed the old reference with a colon:
CREATE or REPLACE TRIGGER BeforeUpdateReport
BEFORE
UPDATE ON REPORT
FOR EACH ROW
Begin
INSERT INTO reportUpdate
Values(:old.ID,sysdate);
END;
/
It's also better to specify the target table fields in the insert statement:
INSERT INTO reportUpdate (report_id, updatedate)
Values(:old.ID,sysdate);
But you have update_date defined in your table creation script as number(32), which doesn't make sense. As #realspirituals pointed out, it should be:
CREATE TABLE reportUpdate (report_id number, updatedate date);