Variable in SQL -> ERROR PLS-00103: Encountered the symbol "SELECT" - sql

How can iterate a variable in select? I receive a error
DECLARE
ESTACION_ID NUMBER(6) :=3;
BEGIN
SELECT
100*TOTAL_TAX_AMB1/(SELECT COUNT(*) FROM ITV2 WHERE ITV2.C_RESULTADO=1 AND ITV2.C_ESTACION_ID= ESTACION_ID ) AS TAXIS_Y_AMBULANCIAS_PRIMERA
...
END;

you can use a USING clause to bind a variable
DECLARE
ESTACION_ID NUMBER(6) :=3;
v_sql varchar2(32767);
BEGIN
v_sql := 'SELECT 100*TOTAL_TAX_AMB1/(SELECT COUNT(*) FROM ITV2 WHERE ITV2.C_RESULTADO=1 AND ITV2.C_ESTACION_ID= :1) AS TAXIS_Y_AMBULANCIAS_PRIMERA
...'
EXECUTE IMMEDIATE v_sql INTO ... USING ESTACION_ID;
END;

Related

Encountered the symbol "EXCEPTION" error in stored procedure

I am programming a procedure in an Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production.
I have an exception inside a LOOP because I don't want the procedure to exit the LOOP if an exception is thrown.
create or replace procedure PARSE_REGISTER_MESSAGE
IS
HOTELS_TO_PROCESS number := 5000;
cursor unparsed_messages is
SELECT REGISTER_psd_id, message
FROM
( SELECT REGISTER_psd_id, message
FROM cc_owner.REGISTER_psd
WHERE parsed != 1
OR parsed IS NULL
ORDER BY CREATION_DATE DESC)
WHERE rownum < HOTELS_TO_PROCESS;
BEGIN
FOR psd_rec in unparsed_messages
LOOP
p_msg.parse_msg (psd_rec.REGISTER_psd_id, null, psd_rec.message);
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_code INTEGER := SQLCODE;
BEGIN
of_owner.p_db_trc.add_error
( 'PARSE_REGISTER_MESSAGE','',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack );
END;
END LOOP;
END;
But I can't compile the package due this error:
Error(25,10): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
( begin case declare end exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
I Also tried:
create or replace procedure PARSE_REGISTER_MESSAGE
IS
HOTELS_TO_PROCESS number := 5000;
cursor unparsed_messages is
SELECT REGISTER_psd_id, message
FROM
( SELECT REGISTER_psd_id, message
FROM cc_owner.REGISTER_psd
WHERE parsed != 1
OR parsed IS NULL
ORDER BY CREATION_DATE DESC)
WHERE rownum < HOTELS_TO_PROCESS;
psd_rec unparsed_messages%ROWTYPE;
BEGIN
FOR psd_rec in unparsed_messages
LOOP
BEGIN
p_msg.parse_msg (psd_rec.REGISTER_psd_id, null, psd_rec.message);
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_code INTEGER := SQLCODE;
BEGIN
of_owner.p_db_trc.add_error
( 'PARSE_REGISTER_MESSAGE','',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack );
END;
END LOOP;
END;
But then I got this error:
Error(48,4): PLS-00103: Encountered the symbol ";" when expecting one of the following: loop
Try using Begin after loop keyword as one BEGIN is missing
FOR psd_rec in unparsed_messages
LOOP
BEGIN
p_msg.parse_msg (psd_rec.REGISTER_psd_id, null, psd_rec.message);
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_code INTEGER := SQLCODE;
BEGIN
of_owner.p_db_trc.add_error
( 'PARSE_REGISTER_MESSAGE','',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack );
END;
The syntax for a PLSQL block / procedure is :
DECLARE
-- Here you declare all the varaible used in block
BEGIN
-- Here you write the body of the Block
EXCEPTION
-- Here you write the exceptions which you want to handle.
END;
Now when i look at your code, you have written Exception block inside the FOR LOOP, which will work only if you use the above syntax. In you case the scope of Exception block is not identified by Oracle and hence it throws error.
FOR psd_rec IN unparsed_messages
LOOP
p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);
EXCEPTION --<-- Wrong way of using Excepton block. Scope of this Exception block is not resolved
WHEN OTHERS
THEN
DECLARE
l_code INTEGER := SQLCODE;
BEGIN
of_owner.p_db_trc.add_error
( 'PARSE_REGISTER_MESSAGE','',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack );
END;
You must modify your code as below to include the Exception block in for loop;
CREATE OR REPLACE PROCEDURE PARSE_REGISTER_MESSAGE
IS
HOTELS_TO_PROCESS NUMBER := 5000;
l_code INTEGER := SQLCODE;
CURSOR unparsed_messages
IS
SELECT REGISTER_psd_id, MESSAGE
FROM ( SELECT REGISTER_psd_id, MESSAGE
FROM cc_owner.REGISTER_psd
WHERE parsed != 1 OR parsed IS NULL
ORDER BY CREATION_DATE DESC)
WHERE ROWNUM < HOTELS_TO_PROCESS;
BEGIN
FOR psd_rec IN unparsed_messages
LOOP
BEGIN
p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);
EXCEPTION
WHEN OTHERS
THEN
of_owner.p_db_trc.add_error (
'PARSE_REGISTER_MESSAGE',
'',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack);
END;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END;
You second try has missing END statement and thats why you were getting error. See below:
CREATE OR REPLACE PROCEDURE PARSE_REGISTER_MESSAGE
IS
HOTELS_TO_PROCESS NUMBER := 5000;
l_code INTEGER := SQLCODE;
CURSOR unparsed_messages
IS
SELECT REGISTER_psd_id, MESSAGE
FROM ( SELECT REGISTER_psd_id, MESSAGE
FROM cc_owner.REGISTER_psd
WHERE parsed != 1 OR parsed IS NULL
ORDER BY CREATION_DATE DESC)
WHERE ROWNUM < HOTELS_TO_PROCESS;
psd_rec unparsed_messages%ROWTYPE;
BEGIN
FOR psd_rec IN unparsed_messages
LOOP
BEGIN
p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);
EXCEPTION
WHEN OTHERS
THEN
BEGIN
of_owner.p_db_trc.add_error (
'PARSE_REGISTER_MESSAGE',
'',
l_code,
sys.DBMS_UTILITY.format_error_stack,
sys.DBMS_UTILITY.format_error_backtrace,
sys.DBMS_UTILITY.format_call_stack);
END;
END;
END LOOP;
END;

PL/SQL if table not exist create

Hello i use oracle SQL developer
I have create a procedure, and i need to check if a table exist, if not exist i must create how can do?
I have try this
DECLARE v_emp int:=0;
BEGIN
SELECT count(*) into v_emp FROM dba_tables;
if v_emp = 0 then
EXECUTE IMMEDIATE 'create table EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';
end if;
END;
but give me an error 00103 because not find table
Just execute the create and watch the exception if thrown. Oracle would never replace the DDL of a table.
declare
error_code NUMBER;
begin
EXECUTE IMMEDIATE 'CREATE TABLE EMPLOYEE(AGE INT)';
exception
when others then
error_code := SQLCODE;
if(error_code = -955)
then
dbms_output.put_line('Table exists already!');
else
dbms_output.put_line('Unknown error : '||SQLERRM);
end if;
end;
You can run this for example:
if (select count(*) from all_tables where table_name = 'yourTable')>0 then
-- table exists
else
-- table doesn't exist
end if;
You should try following,
declare
nCount NUMBER;
v_sql LONG;
begin
SELECT count(*) into nCount FROM dba_tables where table_name = 'EMPLOYEE';
IF(nCount <= 0)
THEN
v_sql:='
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)';
execute immediate v_sql;
END IF;
end;

Oracle 12c - SQL string build issue

This is a follow up to a previous question: Dynamically build select statement in Oracle 12c
I am trying to build a select statement dynamically but having a problem building the column alias names. The column alias name must be retrieved from MAIN_TABLE. Please refer to the code inside <> below:
declare
upper_level number;
t_sql varchar2(1000);
t_sql_val varchar2(500);
l_sql varchar2(1000);
begin
--upper_level will always be given
select 3 into upper_level from dual;
--build the fixed string
l_sql:='SELECT ID,
Title,
Desc,
Type,';
for lvl in 1..upper_level
loop
--build the column names and alias names
t_sql:=t_sql||'TYPE_'||lvl||' <SELECT TYPE_'||lvl||' FROM MAIN_TABLE WHERE ID = 1>,';
end loop;
--finish building the statement
t_sql:=rtrim(t_sql,',');
l_sql:=l_sql||t_sql;
l_sql:=l_sql||' FROM SCHEMA.TABLE
WHERE ID = 1;';
--dbms_output.put_line(l_sql);
end;
This was my attempt:
declare
upper_level number;
t_sql varchar2(1000);
v_sql varchar2(1000);
v_sql_val varchar2(1000);
t_sql_val varchar2(500);
l_sql varchar2(1000);
begin
--upper_level will always be given
select 3 into upper_level from dual;
--build the fixed string
l_sql:='SELECT ID,
Title,
Desc,
Type,';
for lvl in 1..upper_level
loop
--build the column names and alias names
t_sql:='TYPE_'||lvl||;
v_sql:='SELECT '||t_sql||' FROM MAIN_TABLE WHERE ID=1';
EXECUTE IMMEDIATE v_sql into v_sql_val;
t_sql:=t_sql||' '||v_sql_val||',';
end loop;
--finish building the statement
t_sql:=rtrim(t_sql,',');
l_sql:=l_sql||t_sql;
l_sql:=l_sql||' FROM SCHEMA.TABLE
WHERE ID = 1;';
dbms_output.put_line(l_sql);
end;
My attempted result:
SELECT ID,
Title,
Desc,
Type,TYPE_3 LVL_3 FROM SCHEMA.TABLE
WHERE ID = 1;
My expected result:
SELECT ID,
Title,
Desc,
Type,TYPE_1 LVL_1, TYPE_2 LVL_2, TYPE_3 LVL_3 FROM SCHEMA.TABLE
WHERE ID = 1;
How can I achieve this?
I have figured out how to achieve expected result:
declare
upper_level number;
t_sql varchar2(1000);
v_sql varchar2(1000);
v_sql_val varchar2(1000);
t_sql_val varchar2(500);
l_sql varchar2(1000);
begin
--upper_level will always be given
select 3 into upper_level from dual;
--build the fixed string
l_sql:='SELECT ID,
Title,
Desc,
Type,';
for lvl in 1..upper_level
loop
--build the column names and alias names
t_sql:=t_sql||'TYPE_'||lvl||'_CD';
v_sql:='SELECT TYPE_'||lvl||'_CD FROM MAIN_TABLE WHERE ID=1';
EXECUTE IMMEDIATE v_sql into v_sql_val;
t_sql:=t_sql||' '||v_sql_val||',';
end loop;
--finish building the statement
t_sql:=rtrim(t_sql,',');
l_sql:=l_sql||t_sql;
l_sql:=l_sql||' FROM SCHEMA.TABLE
WHERE ID = 1;';
dbms_output.put_line(l_sql);
end;

procedure to delete duplicate records using dynamic sql

i have successfully implemented a proc which can delete delete duplicate records from a table .
Carrying on i am further trying to generalize this procedure using Dynamic sql But i get the following error when compiling itself .
ERROR line 13, col 7, ending_line 14, ending_col 14, Found ''SELECT ROWID, ERR_MOD
FROM '', Expecting: ( SELECT -or- WITH
Here is my code :-
CREATE OR REPLACE PROCEDURE BIOCON.proc_dedup (
p_tblname IN VARCHAR2,
p_cname IN varchar2,
p_cvalue IN varchar2,
p_out OUT VARCHAR2:=0
)
IS
v_cnt NUMBER;
CURSOR TMP
IS
'SELECT ROWID, ERR_MOD
FROM ' || p_tblname||
'WHERE '|| p_cname '='||''p_cvalue '';
BEGIN
BEGIN
'SELECT COUNT ( * )
INTO v_cnt
FROM ' || p_tblname||
'WHERE '|| p_cname' = '||''p_cvalue'';
EXCEPTION
WHEN OTHERS
THEN
p_out:=1;
end;
FOR REC IN tmp
LOOP
IF v_cnt = 1
THEN
EXIT;
ELSE
'DELETE FROM '|| p_tblname||
'WHERE ROWID = REC.ROWID';
END IF;
v_cnt := v_cnt - 1;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
p_out := 2;
END;
/
Hi you cannot create a dynamic query for normal cursors in such cases you should use ref cursors and follow the the steps below
--create a query string
--open the ref cursor
and please use execute immediate for execution of delete statements...
CREATE OR REPLACE PROCEDURE BIOCON.proc_dedup (
p_tblname IN VARCHAR2,
p_cname IN varchar2,
p_cvalue IN varchar2,
p_out OUT VARCHAR2:=0
IS
v_cnt NUMBER;
v_string varchar2(200);
TYPE ref_cur IS REF CURSOR
ref_cursor_name ref_cur;
BEGIN
v_string:='SELECT ROWID, ERR_MOD FROM ' || p_tblname|| 'WHERE '|| p_cname
'='||''p_cvalue '';
OPEN cursor_variable_name FOR v_string;
.....
.....
EXECUTE IMMEDIATE 'DELETE FROM '|| p_tblname|| 'WHERE ROWID = REC.ROWID';--you need execute immediate for this
.....
.....

Cursor and table cannot be found

I have a procedure that will select MAX from some tables, but for some reason it is not able to find these tables. Could anybody help me?
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols order by table_name;
begin
FOR asd in c1
LOOP
temp := asd.table_name;
varible1 := '"'||temp||'"';
select max("id") into last_val from varible1 ;
END LOOP;
end;
For example, the first table name is acceptance_form and for select I need to use "acceptance_form".
Code after edit:
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols where column_name = 'id';
begin
FOR asd in c1
LOOP
temp := asd.table_name;
execute immediate 'select NVL(max('||'id'||'),0) from "'||varible1||'"' into last_val;
END LOOP;
end;
Can't cuz db is Case sensitive Oracle express 10g tables and rows was created like this
CREATE TABLE "ADMINMME"."acceptance_form"
(
"group_id" NUMBER(9, 0),
"id" NUMBER(4, 0) DEFAULT '0' NOT NULL ,
"is_deleted" NUMBER(4, 0),
"name" NVARCHAR2(30) NOT NULL
);
Can u tell me how to handle exception sequence dosn't exist for this;
Nevermind exception was in wrong block :)
declare
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols where column_name = 'id';
begin
FOR asd in c1
LOOP
temp := asd.table_name;
execute immediate 'select NVL(max("id"),0)+1 from "'||temp||'"' into last_val;
begin
EXECUTE IMMEDIATE 'drop sequence "seq_'|| temp||'"';
EXECUTE IMMEDIATE 'create SEQUENCE "seq_'|| temp ||'" MINVALUE '||last_val||'MAXVALUE 999999999999999999999999999 INCREMENT BY 1 NOCACHE';
EXECUTE IMMEDIATE 'select '||temp||'.nextval from dual';
EXECUTE IMMEDIATE 'ALTER SEQUENCE "seq_'||temp||'" INCREMENT BY 1';
exception when others then
null;
end;
END LOOP;
end;
Dynamic sql doesn't work in that way.
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols order by table_name;
begin
FOR asd in c1
LOOP
temp := asd.table_name;
begin
execute immediate 'select max(id) from '||temp into last_val;
dbms_output.put_line('max(id) for table: ' ||temp||' = '||last_val);
exception when others then
dbms_output.put_line('Failed to get max(id) for table: ' ||temp);
end;
END LOOP;
end;
You can't use a variable for the table name.
What you can do is creating the complete sql statement as a string and use execute immediate
Here are some examples how to do that: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDGJEGD