Aberrant function behavior of PL/SQL procedure DBMS_OBFUSCATION_TOOLKIT.MD5 - sql

I use TOAD for executing my procedures and running my PL/SQL scripts.
Recently, I tried the dbms_obfuscation_toolkit.md5() function in PL/SQL to retrieve encrypted text of the string I pass as a parameter. I found that, the function gives the proper result when I call the function as a separate statement. However, when I call it via a SELECT query, it does not respond the same format.
Below, I have mentioned this peculiar case with the results that appear once I run it in TOAD application.
--CASE:1 (Proper result is obtained here)
DECLARE
vinput varchar2(255) := 'SRINI';
well varchar2(50);
BEGIN
WELL := DBMS_OBFUSCATION_TOOLKIT.MD5(input_string =>VINPUT);
dbms_output.put_line(well);
END;
Output: Áýg¿Zq!Ù´¿Ke>ÏQ
--CASE:2 (Unexpected response is obtained here)
DECLARE
vinput varchar2(255) := 'SRINI';
well varchar2(50);
BEGIN
SELECT DBMS_OBFUSCATION_TOOLKIT.MD5(VINPUT)
INTO WELL
FROM DUAL;
dbms_output.put_line(well);
END;
Error Output:
ORA-06550: line 5, column 37:
PLS-00307: too many declarations of 'MD5' match this call
ORA-06550: line 5, column 12:
PL/SQL: ORA-00904: "DBMS_OBFUSCATION_TOOLKIT"."MD5": invalid identifier
ORA-06550: line 5, column 5:
PL/SQL: SQL Statement ignored
Why is there such a disparity in the results, even though both of them are syntactically and semantically correct ? Please provide your opinion and feedback.

Your function calls are not identical, syntactically nor semantically. If you call the function in PL/SQL as you did in SQL, you will get the same exact error:
SQL> DECLARE
2 vinput VARCHAR2(255) := 'SRINI';
3 well VARCHAR2(50);
4 BEGIN
5 WELL := DBMS_OBFUSCATION_TOOLKIT.MD5(vinput);
6 dbms_output.put_line(well);
7 END;
8 /
ORA-06550: Ligne 5, colonne 12 :
PLS-00307: too many declarations of 'MD5' match this call
This is because the function called MD5 is overloaded in the package DBMS_OBFUSCATION_TOOLKIT and you need to specify which function exactly to call.
In Oracle 11g, you can use the same synthax as PL/SQL:
SQL> DECLARE
2 vinput VARCHAR2(255) := 'SRINI';
3 well VARCHAR2(50);
4 BEGIN
5 SELECT DBMS_OBFUSCATION_TOOLKIT.MD5(input_string => VINPUT)
6 INTO WELL FROM DUAL;
7 dbms_output.put_line(well);
8 END;
9 /
Áýg¿Zq!Ù´¿Ke>ÏQ
PL/SQL procedure successfully completed
Before 11g, you can define a wrapper function:
SQL> CREATE OR REPLACE FUNCTION wrap_md5(input_string VARCHAR2)
2 RETURN dbms_obfuscation_toolkit.varchar2_checksum
3 IS
4 BEGIN
5 RETURN dbms_obfuscation_toolkit.md5(input_string => input_string);
6 END;
7 /
Function created
SQL> DECLARE
2 vinput VARCHAR2(255) := 'SRINI';
3 well VARCHAR2(50);
4 BEGIN
5 SELECT wrap_md5(VINPUT)
6 INTO WELL FROM DUAL;
7 dbms_output.put_line(well);
8 END;
9 /
Áýg¿Zq!Ù´¿Ke>ÏQ
PL/SQL procedure successfully completed

select dbms_obfuscation_toolkit.md5(input_string => 'SRINI') from dual; use this in select for the such type of function uses input string.

Related

How to write a procedure to square a number in oracledb

CREATE OR REPLACE PROCEDURE sqr(n IN NUMBER, res OUT NUMBER)
IS
BEGIN
res:= n*n;
Dbms_Output.PUT_LINE(res);
Dbms_Output.PUT_LINE('PL/SQL procedure successfully completed');
END;
/
DECLARE
ans NUMBER;
BEGIN
EXECUTE sqr(15, :ans);
END;
/
I'm new to SQL, trying to create a query to square a number using procedure i dont know how to do it. i was able to come with code above but for some reason i cant connect to DB!
Help needed. (ignore if there are any mistakes in my que framing)
Code you wrote is ... well, not that bad. With some changes, it works:
SQL> SET SERVEROUTPUT ON
SQL> CREATE OR REPLACE PROCEDURE sqr(n IN NUMBER, res OUT NUMBER)
2 IS
3 BEGIN
4 res:= n*n;
5 END;
6 /
Procedure created.
SQL> DECLARE
2 ans NUMBER;
3 BEGIN
4 sqr(15, ans);
5 Dbms_Output.PUT_LINE(ans);
6 END;
7 /
225
PL/SQL procedure successfully completed.
Though, you'd rather create a function (instead of a procedure):
SQL> create or replace function f_sqr (n in number)
2 return number
3 is
4 begin
5 return n*n;
6 end;
7 /
Function created.
SQL> select f_sqr(15) ans from dual;
ANS
----------
225
SQL>
But, nothing of that matters because you said
for some reason i cant connect to DB!
That's the real problem, and you shared absolutely no information about it. Which tool did you use? Do you have a database at all? Where is it? On your own computer or on a server (available to you through the network)? How exactly did you try to connect? What did Oracle say?

how to pass in array in procedure call in oracle

I have a procedure that takes in an array in postgres, this syntax works:
SELECT * from myMethod(array['test','test'], array[''], 554, 73430, 322234, 'shazam');
the array keyword is what I am referring to. this works in postgres but I cannot find the documentation to understand how this work in oracle. how do i pass in arrays to function call?
the error when running the above is:
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
Error at Line: 4 Column: 38
If you have the type:
CREATE TYPE array IS TABLE OF VARCHAR2(200);
and create your function:
CREATE FUNCTION myMethod(
p_words IN array,
p_suffixes IN array,
p_value1 IN INT,
p_value2 IN INT,
p_value3 IN INT,
p_prefix IN VARCHAR2
) RETURN array PIPELINED DETERMINISTIC
IS
value VARCHAR2(200);
BEGIN
FOR i IN 1 .. p_words.COUNT LOOP
value := p_prefix || p_words(i);
FOR j IN 1 .. p_suffixes.COUNT LOOP
value := value || p_suffixes(j);
END LOOP;
PIPE ROW ( value );
END LOOP;
END;
/
Then you can do:
SELECT * from myMethod(array('test1','test2'), array('ab','cd'), 554, 73430, 322234, 'shazam');
In earlier Oracle versions, you may need to use:
SELECT * from TABLE( myMethod(array('test1','test2'), array('ab','cd'), 554, 73430, 322234, 'shazam') );
and it outputs:
| COLUMN_VALUE |
| :-------------- |
| shazamtest1abcd |
| shazamtest2abcd |
db<>fiddle here
Here's an example; I'm using built-in sys.odcivarchar2list type. You'd use your own (if this doesn't suit your needs).
SQL> create or replace procedure p_arr (par_array in sys.odcivarchar2list) is
2 begin
3 dbms_output.put_line(par_array(1));
4 end;
5 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> exec p_arr(sys.odcivarchar2list('A', 'B'));
A
PL/SQL procedure successfully completed.
SQL>

is there a function without an input but return something

CREATE OR REPLACE FUNCTION FN_MULTAS_TOTAL
RETURN INTEGER
IS
V_TOTAL INT;
BEGIN
SELECT SUM(MULTA)
INTO V_TOTAL
FROM DETALLE_ARRIENDO;
RETURN V_TOTAL;
END;
im working on SQL Developer 11 and i have to call it with
exec FN_MULTAS_TOTAL;
and get an integer value
No problem with such a function:
SQL> create or replace function fn_multas_total
2 return integer
3 is
4 v_total int;
5 begin
6 select sum(multa)
7 into v_total
8 from detalle_arriendo;
9 return v_total;
10 end;
11 /
Function created.
However, you don't call it with exec - it is used in SQL*Plus or SQL Developer or some other tools which support it; it is a "shortcut" for an anonymous begin-end PL/SQL block:
SQL> exec p_test
PL/SQL procedure successfully completed.
SQL> begin
2 p_test;
3 end;
4 /
PL/SQL procedure successfully completed.
It is used for procedures, not functions. You can't just
SQL> begin
2 detalle_arriendo;
3 end;
4 /
detalle_arriendo;
*
ERROR at line 2:
ORA-06550: line 2, column 3:
PLS-00221: 'DETALLE_ARRIENDO' is not a procedure or is undefined
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
SQL>
which means that you have to declare a variable and fetch function's result into it, e.g.
SQL> declare
2 l_result number;
3 begin
4 l_result := fn_multas_total;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
Usually, we use functions as
SQL> select fn_multas_total from dual;
FN_MULTAS_TOTAL
---------------
100
SQL>
If you desperately want to use exec, then you still have to declare a variable and
SQL> var result number
SQL> exec :result := fn_multas_total;
PL/SQL procedure successfully completed.
SQL> print :result
RESULT
----------
100
SQL>

how to make a select query with functions pl sql

Function 1:
create or replace function get_books (l_id in number)
return varchar
is l_return varchar2(100);
begin
select books into l_return from people where id=l_id;
return l_return;
end
/
Function 2:
create or replace function get_author (l_id in number)
return varchar
is l_return varchar2(100);
begin
select author in l_return from authors where id=l_id;
return l_return;
end
/
I want to make a select with 2 functions, I want to display books and authors.
is it possible?
Yes, it is possible. For example:
select get_books (1) book,
get_author(1) author
from dual;
Presumably, both functions return a single value. If any of those selects (used in functions) returns more than one row, it'll fail.
As of the procedure: code you posted is invalid so I fixed it.
SQL> create or replace procedure get_categories (l_categories in varchar2,
2 l_id in number,
3 l_boolean out boolean,
4 l_error out varchar2)
5 is
6 begin
7 -- INSERT INTO categories (id, categories)
8 -- VALUES (l_categories, l_id);
9
10 l_boolean := true;
11 commit;
12 exception
13 when others
14 then
15 l_boolean := false;
16 l_error := sqlerrm;
17 end;
18 /
Procedure created.
As it returns 2 OUT parameters, you have to declare variables to accept those values (v_boolean and v_error). Furthermore, as you can't directly display Boolean value, use CASE and display a string instead.
Procedure can't be called as a function within the SQL SELECT statement so you have to use another PL/SQL piece of code; an anonymous PL/SQL block is OK.
SQL> set serveroutput on
SQL> declare
2 v_categories varchar2(10) := 'ABC';
3 v_id number := 1;
4 v_boolean boolean;
5 v_error varchar2(200);
6 begin
7 get_categories(l_categories => v_categories,
8 l_id => v_id,
9 l_boolean => v_boolean,
10 l_error => v_error
11 );
12
13 dbms_output.put_line(case when v_boolean then 'true' else 'false' end ||' - '||
14 v_error
15 );
16 end;
17 /
true -
PL/SQL procedure successfully completed.
SQL>

Oracle DDL execution with immediate mode and errors

After doing about two hours' worth of research on various issues with execute immediate and error handling, I don't think I've encountered exactly the problem I am about to present. I have reduced my issue to the sample below. The issue is:
When I execute a procedure create in immediate mode with the create text in a variable and a syntax error in the create text, the execute immediate call throws an error indicating that it failed. But I can't get at the underlying error or its text.
However, when I create the same proc directly in sqlplus (w/o intermediate mode), getting the error works perfectly.
So, how does one get at the error that causes immediate mode to fail?
I have interspersed the output with my comments (MOP) and reduced the number of blank lines:
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Mar 25 15:57:06 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> set serveroutput on
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
This is good. There's a compilation error. So, now let me ask what that compilation error is:
SQL> show errors;
No errors.
This is no good. There's a compilation error. What was it!?!?!? Contrast that with:
SQL> create or replace procedure MOPMOP
2 as
3 begin
4 select 1 from dual;
5 end;
6 /
Warning: Procedure created with compilation errors.
This is good. There's a compilation error. So, now let me ask what that compilation error is:
SQL> show errors;
Errors for PROCEDURE MOPMOP:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
And this is good. There's a compilation error. And now I know what is is.
So, how do I get intermediate mode to spit out the underlying (00428) error?
when you run show errors on its own it will show the errors for any prior "create" / "alter" that sqlplus itself did, which is this case is nothing (as it was hidden from sqlplus because of the dynamic SQL)
you have to expcitly say you want to see the errors of the procedure for this case:
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
SQL> show errors procedure mopmop
Errors for PROCEDURE MOPMOP:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
as the create ran server side and not through sqlplus, sqlplus didn't know about the failure, so couldnt fetch the errors correctly.
also if you had a prior failure, it would retain that:
SQL> create or replace procedure MOPMOP2
2 as
3 begin
4 select 1 from dual;
5 end;
6 /
Warning: Procedure created with compilation errors.
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
SQL> show errors
Errors for PROCEDURE MOPMOP2:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
You cannot use select 1 from dual... in PL/SQL. Must use select into. In both cases you are creating PL/SQL procedures not some SQL script.
declare
x number;
begin
select 1 into x from dual;
end;
/
declare
procedure MOPMOP
as
x number;
begin
select 1 into x from dual;
dbms_output.put_line(x);
end MOPMOP;
begin
MOPMOP;
end;
/
Avoid ORA-24344 - although I probably would never use dynamic sql for this:
declare
eSQL varchar(568);
x number;
begin
eSQL := 'create or replace procedure MOPMOP as
begin
select 1 into x from dual;
end;';
execute immediate eSQL;
EXCEPTION WHEN OTHERS THEN NULL;
end;
/