dbms_output cannot print boolean? - sql

I am learning cursors and I cannot print the boolean value in the
dbms_output.put_line();
The code is
DECLARE
CURSOR c_employees_3i is
SELECT * FROM employees_3i;
row_count BOOLEAN;
BEGIN
OPEN c_employees_3i;
row_count := c_employees_3i%isopen;
Dbms_Output.put_line(bool_to_text(row_count));
CLOSE c_employees_3i;
END;
I get this error
ORA-06550: line 8, column 22:
PLS-00201: identifier 'BOOL_TO_TEXT' must be declared
ORA-06550: line 8, column 1:
PL/SQL: Statement ignored
Please help me to rectify the error. Thanks

The function bool_to_text does not exist (and AFAIK, Oracle never had such a function).
You can use diutil.bool_to_int to convert the Boolean to an Integer and print that:
begin
dbms_output.put_line(sys.diutil.bool_to_int(true));
end;

Related

How to fix strange oracle PL/SQL error - "PLS-00049: bad bind variable"

I am trying to write an execute an oracle PL/SQL function that return the number of records within a table, where one of the fields matches a certain name.
Here is my code:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO :v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
execute getNum();
I keep getting strange errors:
Function GETNUM compiled
LINE/COL ERROR
--------- ------------------------------------------------------------- 6/22 PLS-00049: bad bind variable 'V_X' Errors: check compiler log
Error starting at line : 85 in command - BEGIN getNum(); END; Error
report - ORA-06550: line 1, column 7: PLS-00905: object
B7011343.GETNUM is invalid ORA-06550: line 1, column 7: PL/SQL:
Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
First thing is to correct your function as pmdba wrote in his answer.
This would then be a correct function:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
Then you need to call your function in correct way. This is one way of calling it:
select getNum from dual;
here is a small demo
Drop the ":" from the select statement:
create or replace function getNum
return number
as
v_x number;
begin
SELECT COUNT(*) INTO v_x
FROM UserResponses WHERE NHSPlatform_Name = 'Improvement Data and Analytics';
return v_x;
end;
/
select getNum() from dual;
Try this:
SQL> VARIABLE ret_val NUMBER;
SQL> execute :ret_val := getnum;
PL/SQL procedure successfully completed.
SQL> select :ret_val from dual;

Why a type cannot be constrained?

I am struggling with the following code:
DECLARE
TOTACID TAB_OF_ID(50);
RES NUMBER;
BEGIN
SELECT DISTINCT ID INTO TOTACID
FROM TABLE_B;
FOR indx IN 1 .. TOTACID.COUNT
LOOP
RES := F_IMPORT(TOTACID(indx));
DBMS_OUTPUT.PUT_LINE ('Moved ID ' || RES);
END LOOP;
END;
/
When I run it, it fails with the error:
Error report -
ORA-06550: line 2, column 11:
PLS-00566: type name "TAB_OF_ID" cannot be constrained
ORA-06550: line 5, column 19:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
ORA-06550: line 5, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Where TAB_OF_ID has been declared as follows:
create or replace TYPE TAB_OF_ID AS table of NUMBER(19,2);
I don't understand what is wrong. It seems that I cannot declare TOTACID TAB_OF_ID(50) but in a function I created some days ago I could declare LIS_ID TAB_OF_ID := TAB_OF_ID(50); and it works properly.
What is the difference with the script I have here?
Obviously TOTACID TAB_OF_ID(50) is different to LIS_ID TAB_OF_ID := TAB_OF_ID(50); The command is like
{variable name} {data type} := {inital value};
where := {inital value} is optional.
TOTACID TAB_OF_ID(50) would mean
{variable name} {inital value};
which is not valid syntax.
You can not declare the variable by assigning your table a fixed number of records, so you need something like:
DECLARE
TOTACID TAB_OF_ID;
RES NUMBER;
BEGIN
SELECT DISTINCT ID bulk collect INTO TOTACID
FROM TABLE_B;
...
END;
/
Also, notice that you are fetching more than one value, so you need BULK COLLECT INTO.
About
LIS_ID TAB_OF_ID := TAB_OF_ID(50);
here you are not declaring a variable with a given number of records, but you are assigning to a variable the 50th value of the table.

Common table expression defining a function in a cursor

Does somebody know if it is possible to use the a common table expression that defines a local function inside a PL/SQL cursor?
For example this code produce an error for me:
DECLARE
CURSOR LV_CUR IS
WITH function fct2(x number) return number is
begin
return 2*x;
end;
TEMP_AV AS
(
SELECT
fct2(LEVEL)
FROM
DUAL
CONNECT BY LEVEL < 10
)
SELECT
*
FROM
TEMP_AV;
BEGIN
FOR I IN LV_CUR
LOOP
NULL;
dbms_output.put_line(i.level);
END LOOP;
END;
The error is :
ORA-06550: Ligne 3, colonne 18 :
PL/SQL: ORA-00905: mot-clé absent
ORA-06550: Ligne 3, colonne 3 :
PL/SQL: SQL Statement ignored
ORA-06550: Ligne 6, colonne 5 :
PLS-00103: Encountered the symbol "END" when expecting one of the following:
begin function pragma procedure subtype type
current cursor delete
exists prior
I am able to execute the query (with the common table expression including a function definition) outside PL/SQL.
Yes and no. The 12.1 docs for the CURSOR statement explicitly say:
Restriction on select_statement
This select_statement cannot have a WITH clause.
This docs are wrong in this case, since you can have a WITH clause, it apparently just can't have the new 12c PL/SQL declarations in it. This block works fine, for example.
DECLARE
CURSOR LV_CUR IS
WITH
TEMP_AV AS
(
SELECT
level
FROM
DUAL
CONNECT BY LEVEL < 10
)
SELECT
*
FROM
TEMP_AV;
BEGIN
FOR I IN LV_CUR
LOOP
NULL;
dbms_output.put_line(i.level);
END LOOP;
END;
/

How do I convert this procedure to a PLSQL block correctly ? Reference to uninitialized function

The following block compiles correctly .(Unimportant parts redacted)
CREATE OR REPLACE PROCEDURE testProc
IS
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h;
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids;
BEGIN
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
However, when I attempt to convert it into a plsql block
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h; --ORA-06531: Reference to uninitialized collection :-(
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids;
BEGIN
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
I get the 'ORA-06531: Reference to uninitialized collection ' error as annotated above. I tried searching around and came across this and based on the examples here
I came up with this
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h();
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids :=l_ids();
BEGIN
test_h_list.EXTEND(100);
l_ids.EXTEND(100);
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
But this throws an error saying PLS-00222: no function with name 'test_h' exists in this scope. Any idea on what I might be missing?
MCVE
Script -
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h(); --Line 3
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
test_h_list.EXTEND(100);
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN -- Just print the failure to logs
NULL;
END;
END LOOP;
END;
/
Error Report -
Error starting at line 1 in command:
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h();
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
test_h_list.EXTEND(100);
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
END LOOP;
END;
Error report:
ORA-06550: line 3, column 23:
PLS-00222: no function with name 'TEST_H' exists in this scope
ORA-06550: line 3, column 13:
PL/SQL: Item ignored
ORA-06550: line 9, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 9, column 3:
PL/SQL: Statement ignored
ORA-06550: line 11, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 11, column 3:
PL/SQL: Statement ignored
ORA-06550: line 12, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 12, column 3:
PL/SQL: Statement ignored
ORA-06550: line 13, column 13:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 13, column 3:
PL/SQL: Statement ignored
ORA-06550: line 27, column 15:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 27, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Elapsed: 00:00:00.011
In your MCVE you're mixing up different types of PL/SQL table. Your test_h types is indexed so doesn't need to be initialized and can't be extended - since it's a sparse table type. So removing the := test_h() and the extend line makes this work:
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h; -- do no instantiate := test_h(); --Line 3
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
-- test_h_list.EXTEND(100); -- do not extend either
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN -- Just print the failure to logs
NULL;
END;
END LOOP;
END;
/
PL/SQL procedure successfully completed.
Your original first anonymous block wasn't doing either of those things, and had the same sparse table type for test_h, so should not have been getting the ORA-06531. You would have seen it if you'd removed the INDEX BY VARCHAR2(100) from the type definition, but that isn't what you showed.
You could also have got it from trying to refer to elements of l_id_list without initialising that - but as presented in the question, it would always have been initalized implicitly by the bulk collect in the loop, even if the real table being queried was empty - you'd just have an empty PL/SQL table.
The code you originally showed doesn't throw the error; and the MCVE is doing something different, closer to your second anonymous block than the first one.

Oracle : Execute Stored Procedure with table type input variable

When I tried to debug an existing app, I found 1 method which is execute a stored procedure showing an error. I want to execute the Stored Procedure on my Oracle SQLDeveloper, given procedure :
type numTableType is table of NUMBER index by binary_integer;
PROCEDURE up_correction_status(p_exp_check_id IN numTableType, p_status_id NUMBER, p_user_id NUMBER, p_return OUT NUMBER);
but, how to declare value of numTableType ?
I tried to :
var p_return NUMBER;
execute "PKG_PDM_DASHBOARD".up_approved_corr_status(1, 2, 11, :p_return);
print p_return;
Found this error :
Error starting at line 2 in command:
execute "PKG_PDM_DASHBOARD".up_approved_corr_status(1, 2, 11, :p_return)
Error report:
ORA-06550: line 1, column 8:
PLS-00306: wrong number or types of arguments in call to 'UP_APPROVED_CORR_STATUS'
ORA-06550: line 1, column 8:
PL/SQL: Statement ignored
just want to execute it and get return value
Your type usage is possible within a package. Outside a package you have to create type.
For execution of procedures with such complex type parameters use a pl/sql anonymous block.
Execution template:
declare
X tableType;
begin
X(1) := 1;
P(X);
end;