I am trying to write a PLSQL code to revers the number
SET SERVEROUTPUT ON;
DECLARE
v_num number :=120;
v_store_values NUMBER;
v_length NUMBER;
v_output NUMBER;
BEGIN
SELECT LENGTH(v_num) INTO v_length FROM DUAL;
FOR v_counter IN 1..v_length LOOP
SELECT SUBSTR(v_num,-(v_counter),v_counter) INTO v_store_values FROM DUAL;
DBMS_OUTPUT.PUT_LINE(v_store_values);
END LOOP;
END;
/
It gives me the output :
0
2
1
But I want the output on horizontal : 021
You don't really need PL/SQL; consider
SQL> select listagg(substr('120', -level, 1)) result
2 from dual
3 connect by level <= length('120');
RESULT
--------------------------------------------------------------------------------
021
SQL>
If it has to be PL/SQL:
SQL> declare
2 result varchar2(20);
3 begin
4 select listagg(substr('120', -level, 1)) result
5 into result
6 from dual
7 connect by level <= length('120');
8
9 dbms_output.put_line(result);
10 end;
11 /
021
PL/SQL procedure successfully completed.
SQL>
You can use the simple REVERSE function below but Please note it is an undocumented feature.
select reverse(to_char(120))
from dual;
OR you can use the supported utl_raw.reverse
select utl_raw.cast_to_varchar2(utl_raw.reverse(utl_raw.cast_to_raw (to_char(120))))
from dual;
Related
I am migrating Microsoft Sql Server Database to Oracle 19c, a query migrated is failing:
DECLARE cardnum varchar2(100);
BEGIN
MyProcedure('ES', cardnum );
SELECT cardnum;
END;
The error returned is:
PL/SQL: ORA-00923: FROM keyword not found where expected
I think that the error is in the line 4:
SELECT cardnum;
The procedure sets the value of the variable, therefore I need to return the value of the variable "cardnum".
What should i use instead of select clausule?
Note --> this query is used from net core with Dapper.
Thank you!
Well, you already have cardnum, procedure set it as its OUT parameter, you don't have to do anything about it.
SQL> create or replace procedure myprocedure(par_1 in varchar2, par_2 out varchar2) is
2 begin
3 par_2 := 'ABC';
4 end;
5 /
Procedure created.
SQL> declare
2 cardnum varchar2(100);
3 begin
4 myprocedure('ES', cardnum);
5
6 dbms_output.put_line('Cardnum = ' || cardnum);
7 end;
8 /
Cardnum = ABC
PL/SQL procedure successfully completed.
SQL>
If you want to select it, you can - but PL/SQL requires an INTO clause. For example:
SQL> declare
2 cardnum varchar2(100);
3 l_var varchar2(100);
4 begin
5 myprocedure('ES', cardnum);
6
7 select cardnum into l_var from dual;
8 end;
9 /
PL/SQL procedure successfully completed.
SQL>
It depends on what you actually want to do with cardnum ...
CREATE TABLE test_table
(
col1 NUMBER(10),
col2 NUMBER(10)
);
INSERT INTO test_table
VALUES (1, 2);
I am writing a stored procedure wherein if I give a table name as an input, that should give me the table data and column details.
For example:
SELECT *
FROM <input_table_name>;
But this causes an error that the SQL command has not ended properly even though I have taken care of this.
My attempt:
CREATE OR REPLACE PROCEDURE sp_test(iv_table_name IN VARCHAR2,
p_out_cur OUT SYS_REFCURSOR)
AS
lv_str VARCHAR2(400);
lv_count NUMBER(1);
lv_table_name VARCHAR2(255):=UPPER(iv_table_name);
BEGIN
lv_str := 'SELECT * FROM '||lv_table_name;
SELECT COUNT(1) INTO lv_count FROM all_tables WHERE table_name = lv_table_name;
IF lv_count = 0 THEN
dbms_output.put_line('Table does not exist');
ELSE
OPEN p_out_cur FOR lv_str;
END IF;
END sp_test;
Tool used: SQL developer(18c)
In dynamic SQL, you do NOT terminate statement with a semicolon.
EXECUTE IMMEDIATE 'SELECT * FROM '||lv_table_name||';';
-----
remove this
Anyway, you won't get any result when you run that piece of code. If you really want to see table's contents, you'll have to switch to something else, e.g. create a function that returns ref cursor.
Sample data:
SQL> SELECT * FROM test_table;
COL1 COL2
---------- ----------
1 2
3 4
Procedure you wrote is now correct:
SQL> CREATE OR REPLACE PROCEDURE sp_test (iv_table_name IN VARCHAR2,
2 p_out_cur OUT SYS_REFCURSOR)
3 AS
4 lv_str VARCHAR2 (400);
5 lv_count NUMBER (1);
6 lv_table_name VARCHAR2 (255) := UPPER (iv_table_name);
7 BEGIN
8 lv_str := 'SELECT * FROM ' || lv_table_name;
9
10 SELECT COUNT (1)
11 INTO lv_count
12 FROM all_tables
13 WHERE table_name = lv_table_name;
14
15 IF lv_count = 0
16 THEN
17 DBMS_OUTPUT.put_line ('Table does not exist');
18 ELSE
19 OPEN p_out_cur FOR lv_str;
20 END IF;
21 END sp_test;
22 /
Procedure created.
Testing:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_rc SYS_REFCURSOR;
3 l_col1 NUMBER (10);
4 l_col2 NUMBER (10);
5 BEGIN
6 sp_test ('TEST_TABLE', l_rc);
7
8 LOOP
9 FETCH l_rc INTO l_col1, l_col2;
10
11 EXIT WHEN l_rc%NOTFOUND;
12
13 DBMS_OUTPUT.put_line (l_col1 || ', ' || l_col2);
14 END LOOP;
15 END;
16 /
1, 2 --> contents of the
3, 4 --> TEST_TABLE
PL/SQL procedure successfully completed.
SQL>
A function (instead of a procedure with the OUT parameter):
SQL> CREATE OR REPLACE FUNCTION sf_test (iv_table_name IN VARCHAR2)
2 RETURN SYS_REFCURSOR
3 AS
4 lv_str VARCHAR2 (400);
5 lv_count NUMBER (1);
6 lv_table_name VARCHAR2 (255) := UPPER (iv_table_name);
7 l_rc SYS_REFCURSOR;
8 BEGIN
9 lv_str := 'SELECT * FROM ' || lv_table_name;
10
11 SELECT COUNT (1)
12 INTO lv_count
13 FROM all_tables
14 WHERE table_name = lv_table_name;
15
16 IF lv_count = 0
17 THEN
18 raise_application_error (-20000, 'Table does not exist');
19 ELSE
20 OPEN l_rc FOR lv_str;
21 END IF;
22
23 RETURN l_rc;
24 END sf_test;
25 /
Function created.
Testing:
SQL> SELECT sf_test ('liksajfla') FROM DUAL;
SELECT sf_test ('liksajfla') FROM DUAL
*
ERROR at line 1:
ORA-20000: Table does not exist
ORA-06512: at "SCOTT.SF_TEST", line 18
SQL> SELECT sf_test ('TEST_TABLE') FROM DUAL;
SF_TEST('TEST_TABLE'
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
COL1 COL2
---------- ----------
1 2
3 4
SQL>
I'm using oracle 11 XE & Application Express 4.0.2.00.09 and I have this function that I want to print it's cursor. I don't know how to read the return of this function when it's called.
CREATE OR REPLACE FUNCTION stuff
RETURN sys_refcursor IS
rf_cur sys_refcursor;
BEGIN
OPEN rf_cur FOR
SELECT ename
FROM emp
WHERE sal = (SELECT MAX(sal)
FROM emp);
RETURN rf_cur;
END;
A simple option is to just select it (as any other function), but I guess that's not what you want:
SQL> select stuff from dual;
STUFF
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ENAME
----------
KING
Another option requires PL/SQL (I guess that is what you're looking for):
SQL> set serveroutput on
SQL> declare
2 l_rc sys_refcursor;
3 l_ename emp.ename%type;
4 begin
5 l_rc := stuff;
6 fetch l_rc into l_ename;
7 dbms_output.put_line(l_ename);
8 end;
9 /
KING
PL/SQL procedure successfully completed.
SQL>
I'm trying to send variable schema name to cursor via procedure input
Here is my lame try, but you can see what I want to do:
CREATE OR REPLACE PROCEDURE HOUSEKEEPING
(SCHEMANAME in varchar2)
IS
CURSOR data_instances IS select table_name
from SCHEMANAME.table_name where TYPE='PERMANENT' and rownum<200 ;
BEGIN
DBMS_OUTPUT.PUT_LINE(SCHEMANAME);
END;
/
it throws expected
PL/SQL: ORA-00942: table or view does not exist
is there lawful way to make schema name work as variable? thanks
There is a way; you'll need some kind of dynamic SQL because you can't use schema (or object) names like that. For example, you could use refcursor instead.
Sample table:
SQL> create table table_name as
2 select 'EMP' table_name, 'PERMANENT' type from dual union all
3 select 'DEPT' , 'TEMPORARY' from dual union all
4 select 'BONUS' , 'PERMANENT' from dual;
Table created.
Procedure; note the way I composed SELECT statement first (so that I could display it and check whether it is correct), and then used it in OPEN. Loop is here to ... well, loop through the cursor. I'm just displaying table names I found - you'd probably do something smarter.
SQL> create or replace procedure housekeeping (par_schemaname in varchar2)
2 is
3 l_str varchar2(500);
4 l_rc sys_refcursor;
5 l_table_name varchar2(30);
6 begin
7 l_str := 'select table_name from ' ||
8 dbms_assert.schema_name(upper(par_schemaname)) ||
9 '.table_name where type = ''PERMANENT'' and rownum < 200';
10 open l_rc for l_str;
11
12 loop
13 fetch l_rc into l_table_name;
14 exit when l_rc%notfound;
15
16 dbms_output.put_line(l_table_name);
17 end loop;
18 close l_rc;
19 end;
20 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> exec housekeeping('SCOTT');
EMP
BONUS
PL/SQL procedure successfully completed.
SQL>
In a stored procedure I am filtering out list of employees whose role is SUPER.ADMIN
In such a case I used like expression as below
Emp.Role_nm Like ''''||p_rolenm||''''
p_rolenm I have mentioned in stored procedure as VARCHAR2
When ever I pass a value to p_rolenm as SUPER.ADMIN it's throwing error as identifier SUPER.ADMIN is not declared.
How I can escape . (Dot) in PL/SQL statements?
Why do you use that many single quotes? You don't need any (at least, I think so):
Sample data:
SQL> create table test (id number, role varchar2(20));
Table created.
SQL> insert into test
2 select 1, 'CLERK' from dual union all
3 select 2, 'SUPER.ADMIN' from dual;
2 rows created.
SQL> select * from test;
ID ROLE
---------- --------------------
1 CLERK
2 SUPER.ADMIN
SQL> set serveroutput on;
Procedure (anonymous, though, but that doesn't matter):
SQL> declare
2 p_rolenm varchar2(20) := 'SUPER.ADMIN';
3 l_id number;
4 begin
5 select id into l_id
6 from test
7 where role = p_rolenm;
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
If you need like, then
SQL> declare
2 p_rolenm varchar2(20) := 'PER.ADM'; --> I changed this ...
3 l_id number;
4 begin
5 select id into l_id
6 from test
7 where role like '%' || p_rolenm || '%'; --> ... and this
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
If you used dynamic SQL, then
SQL> declare
2 p_rolenm varchar2(20) := 'PER.ADM';
3 l_id number;
4 l_str varchar2(200); --> new variable for execute immediate
5 begin
6 l_str := q'[select id from test where role like '%' || :a || '%']';
7 execute immediate l_str into l_id using p_rolenm;
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
Shortly, I don't understand what you are doing. Try to follow my examples. If it still doesn't work, post your SQL*Plus session.