--pkg
create or replace package cur_pkg as
type t_cur is ref cursor;
procedure open_cur_spr_ppl (spr_id in number,
spr_name in varchar2,
spr_family in varchar2);
end cur_pkg;
--pkg_body
create or replace package body cur_pkg as
procedure open_cur_spr_ppl (spr_id in number,
spr_name in varchar2,
spr_family in varchar2)
is
v_curs t_cur;
begin
open v_curs for
select spravochnik_id, spravochnik_name, spravochnik_family
from spravochnik_people
where spravochnik_id >= 1770;
loop
FETCH v_curs INTO spr_id, spr_name, spr_family;
EXIT WHEN v_curs%notfound;
dbms_output.put_line('ID:' || spr_id || 'Name:' || spr_name || 'Family:' || spr_family);
end loop;
close v_curs;
end open_cur_spr_ppl;
end cur_pkg;
I want to output the data for the cursor.
Please advise how to implement it correctly.
The problem is these lines. I don't know how to do it correctly.
FETCH v_curs INTO spr_id, spr_name, spr_family;
EXIT WHEN v_curs%notfound;
dbms_output.put_line('ID:' || spr_id || 'Name:' || spr_name || 'Family:' || spr_family);
One of the errors in your procedure was trying to use:
FETCH v_curs INTO spr_id, spr_name, spr_family;
Where spr_id, spr_name, spr_family are all declared as IN parameters and cannot be written to. You would want to declare them as local variables instead.
When you want to retrieve a cursor, normally you do not open a cursor and print it to the database console immediately as that makes the procedure only useful for that one thing and most times you are going to want to return the cursor without reading it.
Instead, you would open the cursor and then return it as an OUT parameter to the calling scope so that they can read it and, if necessary, format and output it separately. If you did want to print it to the console then you can split that off into a separate procedure:
CREATE PACKAGE cur_pkg AS
TYPE t_cur is ref cursor;
PROCEDURE open_cur_spr_ppl (
p_cur OUT SYS_REFCURSOR
);
PROCEDURE print_cur_spr_ppl (
p_cur IN SYS_REFCURSOR
);
end cur_pkg;
CREATE PACKAGE BODY cur_pkg AS
PROCEDURE open_cur_spr_ppl (
p_cur OUT SYS_REFCURSOR
)
is
begin
open p_cur for
select spravochnik_id,
spravochnik_name,
spravochnik_family
from spravochnik_people
where spravochnik_id >= 1770;
end open_cur_spr_ppl;
PROCEDURE print_cur_spr_ppl (
p_cur IN SYS_REFCURSOR
)
is
v_id spravochnik_people.spravochnik_id%TYPE;
v_name spravochnik_people.spravochnik_name%TYPE;
v_family spravochnik_people.spravochnik_family%TYPE;
c_id_width CONSTANT PLS_INTEGER := 10;
c_name_width CONSTANT PLS_INTEGER := 30;
c_family_width CONSTANT PLS_INTEGER := 30;
begin
-- Header
DBMS_OUTPUT.PUT_LINE(
LPAD('ID', c_id_width, ' ')
|| ' | ' || RPAD('NAME', c_name_width, ' ')
|| ' | ' || RPAD('FAMILY', c_family_width, ' ')
);
DBMS_OUTPUT.PUT_LINE(
LPAD(':', c_id_width, '-')
|| ' | ' || RPAD(':', c_name_width, '-')
|| ' | ' || RPAD(':', c_family_width, '-')
);
LOOP
FETCH p_cur INTO v_id, v_name, v_family;
EXIT WHEN p_cur%notfound;
DBMS_OUTPUT.PUT_LINE(
LPAD(v_id, c_id_width, ' ')
|| ' | ' || RPAD(v_name, c_name_width, ' ')
|| ' | ' || RPAD(v_family, c_family_width, ' ')
);
END LOOP;
CLOSE p_cur;
end print_cur_spr_ppl;
end cur_pkg;
Then if you want to call it you can use:
DECLARE
v_cur SYS_REFCURSOR;
BEGIN
cur_pkg.open_cur_spr_ppl(v_cur);
cur_pkg.print_cur_spr_ppl(v_cur);
END;
/
Which, for the sample data:
CREATE TABLE spravochnik_people (spravochnik_id, spravochnik_name, spravochnik_family) AS
SELECT 1800, 'Alice', 'Abbot' FROM DUAL UNION ALL
SELECT 1900, 'Betty', 'Baron' FROM DUAL;
Outputs:
ID | NAME | FAMILY
---------: | :----------------------------- | :-----------------------------
1800 | Alice | Abbot
1900 | Betty | Baron
db<>fiddle here
If someone need
--pkg
create or replace package cur_pkg as
type t_cur is ref cursor;
procedure open_cur_spr_ppl (spr_id in out spravochnik_people.spravochnik_id%TYPE,
spr_name in out spravochnik_people.spravochnik_name%TYPE,
spr_family in out spravochnik_people.spravochnik_family%TYPE);
end cur_pkg;
--pkg_body
create or replace package body cur_pkg as
procedure open_cur_spr_ppl (spr_id in out spravochnik_people.spravochnik_id%TYPE,
spr_name in out spravochnik_people.spravochnik_name%TYPE,
spr_family in out spravochnik_people.spravochnik_family%TYPE)
is
v_curs t_cur;
begin
open v_curs for
select spravochnik_id, spravochnik_name, spravochnik_family
from spravochnik_people;
loop
FETCH v_curs INTO spr_id, spr_name, spr_family;
EXIT WHEN v_curs%notfound;
end loop;
close v_curs;
end open_cur_spr_ppl;
end cur_pkg;
Related
I want populate my table of objects and I try of different ways but I canĀ“t. With this code I have an extensive error: "Encountered the symbol "L_T_O_TYPE" when expecting one of the following: .(*#_-+/", it is a big message
CREATE OR REPLACE TYPE O_Type AS OBJECT (
depar_id NUMBER,
depar_name VARCHAR2(20),
man_id NUMBER,
loca_id NUMBER,
CONSTRUCTOR FUNCTION O_Type(
depar_id NUMBER,
depar_name VARCHAR2,
man_id NUMBER,
loca_id NUMBER)
RETURN SELF AS RESULT
);
CREATE OR REPLACE TYPE BODY O_Type IS
CONSTRUCTOR FUNCTION O_Type(
depar_id NUMBER,
depar_name VARCHAR2,
man_id NUMBER,
loca_id NUMBER,
)RETURN AS SELF AS RESULT IS
BEGIN
self.depar_id := depar_id;
self.depar_name := depar_name;
self.man_id := man_id;
self.loca_id := loca_id;
RETURN;
END;
END;
/
CREATE OR REPLACE TYPE T_o_type AS TABLE OF O_Type;
/
DECLARE
CURSOR C_depar IS SELECT *
FROM departments;
TYPE T_C_DEPAR IS TABLE OF C_depar%ROWTYPE;
L_TABLE T_C_DEPAR;
l_T_o_type T_o_type;
BEGIN
l_T_o_type := T_o_type();
OPEN C_depar;
LOOP
FETCH C_depar BULK COLLECT INTO L_TABLE;
EXIT WHEN C_depar%NOTFOUND;
FORALL i IN 1..L_TABLE.count
l_T_o_type(i) : = T_o_type(L_TABLE.DEPARTMENT_ID, L_TABLE.DEPARTMENT_NAME, L_TABLE.MANAGER_ID , L_TABLE.LOCATION_ID)
END LOOP;
CLOSE C_depar;
END;
/
Can someone tell me the best way to populate my object table?
"Best" is subjective.
If you want all the rows in a single collection, use SELECT ... BULK COLLECT INTO:
DECLARE
l_depts T_o_type;
BEGIN
SELECT O_Type(id, name, man_id, loc_id)
BULK COLLECT INTO l_depts
FROM departments;
FOR i IN 1 .. l_depts.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(
l_depts(i).depar_id
|| ' ' || l_depts(i).depar_name
|| ' ' || l_depts(i).man_id
|| ' ' || l_depts(i).loca_id
);
END LOOP;
END;
/
If you want to process the rows in batches then you can use:
DECLARE
CURSOR C_depar IS
SELECT O_Type(id, name, man_id, loc_id)
FROM departments;
l_depts T_o_type;
BEGIN
OPEN C_depar;
LOOP
FETCH C_depar BULK COLLECT INTO L_depts LIMIT 10;
FOR i IN 1 .. l_depts.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(
l_depts(i).depar_id
|| ' ' || l_depts(i).depar_name
|| ' ' || l_depts(i).man_id
|| ' ' || l_depts(i).loca_id
);
END LOOP;
EXIT WHEN C_depar%NOTFOUND;
END LOOP;
CLOSE C_depar;
END;
/
db<>fiddle here
I am building a function on PL/SQL using Oracle 11g.
I am trying to use a table variable within an EXECUTE IMMEDIATE statement, but it is not working, as you can see:
ERROR at line 1:
ORA-00904: "CENTER_OBJECTS": invalid identifier
ORA-06512: at "HIGIIA.KNN_JOIN", line 18
The code I am using is...
First, the type definitions
CREATE TYPE join_t IS OBJECT (
inn char(40),
out char(40)
);
/
CREATE TYPE join_jt IS TABLE OF join_t;
/
CREATE TYPE blob_t IS OBJECT (
id CHAR(40),
fv BLOB
);
/
CREATE TYPE blob_tt IS TABLE OF blob_t;
/
The function is:
create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2, blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER ) RETURN join_jt
IS
var_fv BLOB;
var_id CHAR(40);
center_objects blob_tt := blob_tt();
retval join_jt := join_jt ();
join_table join_jt := join_jt();
sql_stmt1 varchar2(400);
sql_stmt2 varchar2(400);
BEGIN
sql_stmt1 := 'SELECT blob_t(ROWIDTOCHAR(rowid),' || blob_col1 || ') FROM ' || tab_out;
sql_stmt2 := 'SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) FROM ' || tab_inn || ' r WHERE ' || dist_alg || '_knn(r.' || blob_col2 || ', center_objects(idx).' || blob_col1 || ')<=' || kv;
dbms_output.put_line(sql_stmt2);
EXECUTE IMMEDIATE sql_stmt1 BULK COLLECT INTO center_objects;
for idx in center_objects.first()..center_objects.last()
loop
--SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) BULK COLLECT INTO join_table FROM londonfv r WHERE manhattan_knn(r.fv, center_objects(idx).fv) <=5;
EXECUTE IMMEDIATE sql_stmt2 BULK COLLECT INTO join_table;
for idx2 in join_table.first()..join_table.last()
loop
retval.extend();
retval(retval.count()) := join_table(idx2);
end loop;
end loop;
RETURN retval;
END;
/
To run the function:
select * from TABLE(knn_join('london','cophirfv','fv','fv','manhattan',5));
I am trying to use run the statement 'SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) BULK COLLECT INTO join_table FROM london r WHERE manhattan_knn(r.fv, center_objects(idx).fv) <=5' using the EXECUTE IMMEDIATE, but it does not work because I am using a variable in it.
Can someone give me a hand on it?
Thanks in advance!
You can't refer to a local PL/SQL variable inside a dynamic SQL statement, because it is out of scope within the SQL context used by the dynamic call. You could replace your first call:
SELECT join_t(ROWIDTOCHAR(r.rowid), center_objects(idx).id) FROM ' ...
with a bind variable:
SELECT join_t(ROWIDTOCHAR(r.rowid), :id FROM ' ...
EXECUTE IMMEDIATE ... USING center_objects(idx).id ...
but you can't do what when the object attribute is variable too:
... ', center_objects(idx).' || blob_col1 || ')<='...
although - at least in the example you've shown - the only object attribute name available is fv, regardless of the table column names passed in to the function - so that could be hard-coded; and thus a bind variable could be used:
... ', :fv)<='...
EXECUTE IMMEDIATE ... USING center_objects(idx).id, center_objects(idx).fv ...
and the kv value should also be a bind variable, so you'd end up with:
create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2,
blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER )
RETURN join_jt
IS
center_objects blob_tt := blob_tt();
retval join_jt := join_jt ();
join_table join_jt := join_jt();
sql_stmt1 varchar2(400);
sql_stmt2 varchar2(400);
BEGIN
sql_stmt1 := 'SELECT blob_t(ROWIDTOCHAR(rowid),' || blob_col1 || ') FROM ' || tab_out;
sql_stmt2 := 'SELECT join_t(ROWIDTOCHAR(r.rowid), :id) FROM ' || tab_inn || ' r WHERE '
|| dist_alg || '_knn(r.' || blob_col2 || ', :fv)<= :kv';
dbms_output.put_line(sql_stmt1);
dbms_output.put_line(sql_stmt2);
EXECUTE IMMEDIATE sql_stmt1 BULK COLLECT INTO center_objects;
for idx in center_objects.first()..center_objects.last()
loop
EXECUTE IMMEDIATE sql_stmt2 BULK COLLECT INTO join_table
USING center_objects(idx).id, center_objects(idx).fv, kv;
for idx2 in join_table.first()..join_table.last()
loop
retval.extend();
retval(retval.count()) := join_table(idx2);
end loop;
end loop;
RETURN retval;
END;
/
As far as I can tell you could still do the join within the dynamic SQL statement, and eliminate the loops and the need for the intermediate center_objects and join_table collections:
create or replace FUNCTION knn_join (tab_inn IN varchar2, tab_out IN varchar2,
blob_col1 IN varchar2, blob_col2 IN varchar2, dist_alg in VARCHAR2, kv in NUMBER )
RETURN join_jt
IS
retval join_jt;
sql_stmt varchar2(400);
BEGIN
sql_stmt := 'SELECT join_t(ROWIDTOCHAR(tinn.rowid), ROWIDTOCHAR(tout.rowid))'
|| ' FROM ' || tab_inn || ' tinn JOIN ' || tab_out || ' tout'
|| ' ON ' || dist_alg || '_knn(tinn.fv, tout.fv) <= :kv';
dbms_output.put_line(sql_stmt);
EXECUTE IMMEDIATE sql_stmt BULK COLLECT INTO retval USING kv;
RETURN retval;
END;
/
When you call it as you've shown:
select * from TABLE(knn_join('london','cophirfv','fv','fv','manhattan',5));
that's the equivalent of the hard-coded:
SELECT join_t(ROWIDTOCHAR(tinn.rowid), ROWIDTOCHAR(tout.rowid))
FROM london tinn
JOIN cophirfv tout
ON manhattan_knn(tinn.fv, tout.fv) <= 5
... so I guess you can verify whether that hard-coded version gives you the results you expect first. (Adding sample data and expected results to the question would have helped, of course).
That join condition may be expensive, depending on what the function is doing, how may rows are in each table (as every row in each table has to be compared with every row in the other), whether you actually have other filters, etc. The loop version would be even worse though. Without more information there isn't much to be done about that anyway.
As an aside, using varchar2 instead of char for the object attributes would be more normal; that's also the data type returned by the rowidtochar() function.
I got this procedure:
create or replace procedure TEST_PROCEDURE(
time_in in varchar2,
repository_in in varchar2,
iteration_in in varchar2,
tar_table_in in varchar2
)
is
delete_stmt varchar2(2000);
insert_stmt varchar2(2000);
begin
delete_stmt := 'delete from ' || tar_table_in || ' where time=' || time_in ||' and repository=' || repository_in || '
and iteration=' || iteration_in || '; commit;';
execute immediate delete_stmt;
insert_stmt := 'insert into ' || tar_table_in || ' (some columns)
SELECT ' || repository_in || ' as repository, ' || iteration_in || ' as iteration, t1.* FROM dual
left join
json_table((select json_response from TEST_TABLE where repository=repository_in), ''$[*]''
COLUMNS
time varchar2(64) PATH ''$.time'',
session_id varchar2(256) PATH ''$.session_id''
) t1
on 1=1';
execute immediate insert_stmt;
end;
It currently throws an ORA-00933 error at the "execute immediate delete_stmt;" line, which hints to something foul in the query string.
I can't seem to find the location of either a missing quote, or semi-colon that would end the command. Anyone able to spot what I'm missing?
If you are using SQL Dynamic, then your values in your dynamic query are missing quotes.
Don't use commit inside execute immediate.
You do the delete, then the insert, then you commit the transaction.
It should be
create or replace procedure TEST_PROCEDURE(
time_in in varchar2,
repository_in in varchar2,
iteration_in in varchar2,
tar_table_in in varchar2
)
is
delete_stmt varchar2(2000);
insert_stmt varchar2(2000);
begin
delete_stmt := 'delete from ' || tar_table_in || ' where time= ''' || time_in || ''' and repository= ''' || repository_in || '''
and iteration = ''' || iteration_in || ''' ';
execute immediate delete_stmt;
insert_stmt := 'insert into ' || tar_table_in || ' (some columns)
SELECT ''' || repository_in || ''' as repository, ''' || iteration_in || ''' as iteration, t1.* FROM dual
left join
json_table((select json_response from TEST_TABLE where repository=repository_in), ''$[*]''
COLUMNS
time varchar2(64) PATH ''$.time'',
session_id varchar2(256) PATH ''$.session_id''
) t1
on 1=1';
execute immediate insert_stmt;
commit;
end;
Whenever trying to debug dynamic sql, assign the statement to a variable (which you do already) then use dbms_output to show the exact statement that will be executed:
SQL> create or replace procedure my_proc (time_in in varchar2,
2 repository_in in varchar2,
3 iteration_in in varchar2,
4 tar_table_in in varchar2)
5 as
6 v_sql varchar2(1000);
7 begin
8 v_sql:='delete from ' ||
9 tar_table_in ||
10 ' where time=' ||
11 time_in ||
12 ' and repository=' ||
13 repository_in || '
14 and iteration=' ||
15 iteration_in ||
16 '; commit;';
17
18 dbms_output.put_line('====== begin debug line ======');
19 dbms_output.put_line(v_sql);
20 dbms_output.put_line('====== end debug line ======');
21 end;
22 /
Procedure created.
SQL> show errors
No errors.
SQL> set serverout on
SQL> exec my_proc('aaaa','bbbb','cccc','dddd');
====== begin debug line ======
delete from dddd where time=aaaa and repository=bbbb
and iteration=cccc;
commit;
====== end debug line ======
PL/SQL procedure successfully completed.
SQL> --
SQL> drop procedure my_proc;
Procedure dropped.
I have the following code, my question is how can I be sure the encryption key in l_key has not been changed?
create or replace PACKAGE BODY "ENCRYPT_DECRYPT_PASSWORD"
AS
l_key RAW(128) := utl_raw.cast_to_raw('secret');
------------------------------------------------------------------------
FUNCTION encrypt_val( p_val IN VARCHAR2 ) RETURN VARCHAR2
IS
l_encrypted RAW(2048);
l_val RAW(2048) := utl_raw.cast_to_raw(p_val);
BEGIN
l_encrypted := dbms_crypto.encrypt
( src => l_val,
typ => dbms_crypto.des_cbc_pkcs5,
key => l_key );
return utl_raw.cast_to_varchar2(l_encrypted);
END encrypt_val;
-----------------
-----------------
-----------------
FUNCTION decrypt_val( p_val IN varchar2 ) RETURN VARCHAR2
IS
l_decrypted RAW(2048);
l_val RAW(2048) := utl_raw.cast_to_raw(p_val);
BEGIN
l_decrypted := dbms_crypto.decrypt
( src => l_val,
typ => dbms_crypto.des_cbc_pkcs5,
key => l_key );
return utl_raw.cast_to_varchar2(l_decrypted);
END decrypt_val;
-----------------
-----------------
-----------------
PROCEDURE encrypt_table_passwords(table_name IN varchar2,
column_name IN varchar2,
table_id IN varchar2) IS
BEGIN
EXECUTE IMMEDIATE
'begin
for c1 in (select * from ' || table_name ||') loop
update ' || table_name || ' set ' || column_name || ' = ENCRYPT_DECRYPT_PASSWORD.encrypt_val(c1.' || column_name || ') where ' || table_id || ' = c1.'||table_id||' and ' || column_name ||
' is not null; end loop; end;';
END encrypt_table_passwords;
-----------------
-----------------
-----------------
FUNCTION get_decrypted_password( table_name IN varchar2,column_name IN varchar2,table_id IN varchar2,table_id_val IN varchar2 ) RETURN VARCHAR2
IS
encrypted_pas varchar2(100);
decrypted_pas varchar2(100);
BEGIN
EXECUTE IMMEDIATE 'select ' || column_name || ' from ' || table_name || ' where ' || table_id || ' = ' || table_id_val
INTO encrypted_pas;
Select decrypt_val(encrypted_pas) into decrypted_pas from dual;
--return decrypt_val(encrypted_pas);
return decrypted_pas;
END get_decrypted_password;
END encrypt_decrypt_password;
I tried the following which I found on the web, but it appears it doesn't work for my oracle version:
DECLARE
v_x RAW(128);
BEGIN
SELECT ENCRYPT_DECRYPT_PASSWORD.l_key x
INTO v_x
FROM DUAL;
DBMS_OUTPUT.put_line (v_x);
END;
/
I get "component 'L_KEY' must be declared" and "invalid identifier".
The reason I want to investigate is that I had decryption errors which went away after I changed the password column from varchar(99) to nvarchar2(100) and after I regenerated the encrypted password.
I get "component 'L_KEY' must be declared" and "invalid identifier".
L_KEY is declared in your package BODY. That means its scope is private, restricted to the code of the body. Only things declared in the package SPEC are public and can be accessed outside the package scope.
If you need to check its actual value you need to extend your package with a function which returns L_KEY. You probably don't want to expose it in Production so be careful. You may wish to consider using conditional compilation just to be sure nothing accidentally leaks.
I have this stored procedure to create index on table:
CREATE OR REPLACE PROCEDURE create_index (
in_tb VARCHAR2,
in_index VARCHAR2,
in_columns VARCHAR2,
lc_status OUT NUMBER
) AS
lc_affected NUMBER;
lc_stmt VARCHAR2(1500);
BEGIN
lc_stmt := 'BEGIN EXECUTE IMMEDIATE ''CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')''; END;';
dbms_output.put_line(lc_stmt);
dbms_utility.exec_ddl_statement(lc_stmt);
lc_affected := SQL%rowcount;
dbms_output.put_line('AFFECTED -->' || lc_affected);
IF ( lc_affected > 0 ) THEN
lc_status := 1;
ELSE
lc_status := 1;
END IF;
END create_index;
/
I execute the stored procedure using:
SET SERVEROUTPUT ON;
DECLARE
lc_status NUMBER;
BEGIN
create_index('TABLE_1_LOAD', 'ON_RUN_INDEX', 'MY_ID', lc_status);
END;
However, the index is not getting created in table TABLE_1_LOAD.
The output is:
BEGIN EXECUTE IMMEDIATE 'CREATE INDEX ON_RUN_INDEX ON TABLE_1_LOAD (MY_ID)'; END;
AFFECTED -->
PL/SQL procedure successfully completed.
I am not able to understand why the stored procedure is not creating indexes. Can you please help?
The dynamic statement you are trying to run via exec_ddl_statement is not DDL. It contains DDL, but embedded in an anonymous PL/SQL block, which is not the same thing. It looks like the dbms_utility procedure is just silently ignoring it for that reason.
If you simplify your statement to remove the unnecessary block then it will work:
...
BEGIN
lc_stmt := 'CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')';
...
Demo:
create table table_1_load (my_id number);
Table TABLE_1_LOAD created.
CREATE OR REPLACE PROCEDURE create_index (
in_tb VARCHAR2,
in_index VARCHAR2,
in_columns VARCHAR2,
lc_status OUT NUMBER
) AS
lc_affected NUMBER;
lc_stmt VARCHAR2(1500);
BEGIN
lc_stmt := 'CREATE INDEX '
|| in_index
|| ' ON '
|| in_tb
|| ' ('
|| in_columns
|| ')';
dbms_output.put_line(lc_stmt);
dbms_utility.exec_ddl_statement(lc_stmt);
lc_affected := SQL%rowcount;
dbms_output.put_line('AFFECTED -->' || lc_affected);
IF ( lc_affected > 0 ) THEN
lc_status := 1;
ELSE
lc_status := 1;
END IF;
END create_index;
/
Procedure CREATE_INDEX compiled
SET SERVEROUTPUT ON;
DECLARE
lc_status NUMBER;
BEGIN
create_index('TABLE_1_LOAD', 'ON_RUN_INDEX', 'MY_ID', lc_status);
END;
/
CREATE INDEX ON_RUN_INDEX ON TABLE_1_LOAD (MY_ID)
AFFECTED -->
PL/SQL procedure successfully completed.
The 'affected' number is still null, because execute_ddl_statement doesn't cause SQL%rowcount to be set, so you can't rely on that to tell you anything. But the index has been created:
select object_type, object_name from user_objects where created > trunc(sysdate);
OBJECT_TYPE OBJECT_NAME
------------------- ------------------------------
TABLE TABLE_1_LOAD
PROCEDURE CREATE_INDEX
INDEX ON_RUN_INDEX
You could run your original statement with execute immediate, and that would actually set SQL%rowcount, but as you still haven't run any DML it's meaningless really. To show that, with the (still unnecessary) anonymous block you get 1; without the block, using the same simplified statement as above, you get 0.