What Causes the Numeric Overflow in this PL/SQL Function? - oracle

I can run this command on Oracle 10.2 without problem:
SQL> select instr(unistr('foo'), chr(4050596145)) as hazit from dual;
HAZIT
----------
0
So I tried to encapsulate it into a function:
CREATE OR REPLACE FUNCTION hazit(string IN VARCHAR2) RETURN INTEGER
AS
BEGIN
RETURN instr(unistr(string), chr(4050596145));
END;
/
Function created.
But I get a numeric overflow error when I try to use it:
SQL> select hazit('foo') FROM DUAL;
select hazit('foo') FROM DUAL
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at "DWHEELER.HAZIT", line 4
What gives?

I don't have an explanation but this seems to work:
CREATE OR REPLACE FUNCTION hazit(string IN VARCHAR2) RETURN NUMBER IS
i number;
BEGIN
select instr(unistr(string), chr(4050596145))
into i from dual;
return i;
END;
/
Here is a fiddle

Related

Can cursor be use in UPDATE and DELETE in Function

I have one doupt while I try to use UPDATE and DELETE method.
So starting from basic function something like
FUNCTION GET_ANSWER(p_questionId IN INT)
RETURN SYS_REFCURSOR IS
rc SYS_REFCURSOR;
/*getAnswer*/
BEGIN
OPEN rc FOR
SELECT * FROM answers WHERE AnswerID = p_questionId;
RETURN rc;
END GET_ANSWER;
While I try to use DELETE or UPDATE method I get error message
Error(3529,1): PLS-00103: Encountered the symbol "DELETE" when expecting one of the following: ( - + case mod new not null select with <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification>
Error(3530,1): PLS-00103: Encountered the symbol "RETURN"
Error(3536,1): PLS-00103: Encountered the symbol "END"
FUNCTION DELETE_ACTIVITY(p_activityId IN INT)
RETURN SYS_REFCURSOR IS
rc SYS_REFCURSOR;
BEGIN
OPEN rc FOR
DELETE FROM activities WHERE id = p_activityId;
RETURN rc;
END DELETE_ACTIVITY;
What is wrong here ? Wher did I made mistake ?
Don't do it via cursor, but simply
DELETE FROM answers WHERE AnswerID = p_questionId;
Also, make it a procedure, not a function.
As of UPDATE, well - it depends on what you want to update and how, but - generally:
update answers set
some_column = some_value
where ansewrID = p_questionId
Why a procedure and not a function:
SQL> create or replace function f_test return number is
2 begin
3 delete from test;
4 return 1;
5 end;
6 /
Function created.
SQL> select f_test from dual;
select f_test from dual
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SCOTT.F_TEST", line 3
SQL>
However, if a function is an autonomous transaction, you can do that, but - not recommended:
SQL> create or replace function f_test return number is
2 pragma autonomous_transaction;
3 begin
4 delete from test;
5 commit;
6 return 1;
7 end;
8 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
1
SQL>
Cursors are only used for SELECT statements. You cannot open a cursor for an INSERT, UPDATE or DELETE statement.
See the documentation
An explicit cursor definition has this syntax:
CURSOR cursor_name [ parameter_list ] [ RETURN return_type ] IS
select_statement;

Oracle function to return value from select with union

I am trying to add this function to oracle db but it keeps throwing the following errors:
10/72 PLS-00049: bad bind variable 'COMMITID'
12/90 PLS-00049: bad bind variable 'COMMITID'
14/76 PLS-00049: bad bind variable 'COMMITID'
17/16 PL/SQL: ORA-00933: SQL command not properly ended
CREATE OR REPLACE FUNCTION GetLatestProfileChangeDateTime(commitId IN NUMBER)
RETURN DATE
AS
testing DATE;
BEGIN
select max(a) as dateOfChange
INTO testing
from
(
select max(created_date) a from image_set where reference_id = :commitId and created_date is not null
union
select max(date_of_change) a from preferred_agent_info_history where commit_id = :commitId and date_of_change is not null
union
select max(date_of_change) a from commit_history where commit_id = :commitId and date_of_change is not null
)
RETURN testing;
END;
The inner select statement works fine but when I try to implement it within a function, I can't get it to accept it. I've even tried removing the parameter binding in the select statements for a starting place but it will throw different errors.
You don't need bind variables in your function; you are using the function parameter in the SQL part of the function, so you can simply refer to it by its name.
For example:
SQL> create or replace function f1(p IN number) return number is
2 retVal number;
3 begin
4 select :p * 2 into retVal from dual;
5 return retVal;
6 end;
7 /
Warning: Function created with compilation errors.
SQL> sho err
Errors for FUNCTION F1:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/12 PLS-00049: bad bind variable 'P'
The right way:
SQL> create or replace function f1(p IN number) return number is
2 retVal number;
3 begin
4 select f1.p * 2 into retVal from dual;
5 return retVal;
6 end;
7 /
Function created.
SQL> select f1(3) from dual;
F1(3)
----------
6

Function created with compilation error in PLSQL

When I compile the below code I am getting a error message "Function created with compilation errors"
create or replace function find_port(ip_ID in int) RETURN int
is
t_count number;
count varchar;
begin
select is_rail into count from table where id = ip_ID;
case
when count ='True' then t_count:=1;
when count ='False' then t_count:=0;
end case;
end;
/
i am getting a error message "Function created with compilation errors"
So the question you should be asking is, "how do I get a list of compilation errors for my PL/SQL code?"
Other people have told you how to fix the current errors in your code, but the more important skill is that you find out how to diagnose your code for yourself.
Oracle is a database, and it stores metadata in a set of special views called the data dictionary. These views include views for compilation errors. This query will work in any SQL environments:
select name, type, line, text -- or just *, obvs
from user_errors ue
order by ue.name, ue.type, ue.sequence;
There are also ALL_ERRORS and DBA_ERRORS views. Find out more.
In SQL*Plus you can run sho err (short for show errors). IDEs like PL/SQL Developer or Oracle SQL Developer will show compilation errors automatically.
Once you know how to get the text of the errors you need to know that LINE will tell you the line where the error is raised. Although with certain classes of error (such as missing commas or unmatched brackets) the indicated line may not be the line where the actual error resides. Unfortunately there is still a need for interpretation and understanding, which requires experience.
Actually, COUNT can be used as a PL/SQL variable:
SQL> create or replace function f_test return int is
2 count number;
3 begin
4 select 1 into count from dual;
5 return 2;
6 end;
7 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
2
SQL>
However, you can't return it:
SQL> create or replace function f_test return int is
2 count number;
3 begin
4 select 1 into count from dual;
5 return count;
6 end;
7 /
Warning: Function created with compilation errors.
SQL> show err
Errors for FUNCTION F_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PL/SQL: Statement ignored
5/10 PLS-00204: function or pseudo-column 'COUNT' may be used inside a
SQL statement only
SQL>
Here, #priya, you can see how to help yourself - SHOW ERR will tell you what's wrong with your code.
Apart from that, CASE statement you used was invalidly written; should have been similar to this:
SQL> create or replace function f_test return int is
2 l_count number;
3 t_count number;
4 begin
5 select 1 into l_count from dual;
6
7 t_count := case when l_count = 1 then 1
8 when l_count = 2 then 2
9 end;
10
11 return t_count;
12 end;
13 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
1
SQL>
count is a SQL function and thus not a better choice to be used as a PL/SQL variable. The CASE block can be used within the select statement.
Furthermore, your function does not RETURN any value.
create or replace function find_port(ip_ID in int) RETURN int
is
t_count number;
begin
select case
when is_rail = 'True' then 1
when is_rail = 'False' then 0
end into t_count from yourtable where id=ip_ID;
RETURN t_count;
end;

Oracle STANDARD_HASH not available in PLSQL?

I'm trying to use STANDARD_HASH Oracle (12c) function in PL/SQL but seems not available:
SQL> exec dbms_output.put_line(STANDARD_HASH('test'));
BEGIN dbms_output.put_line(STANDARD_HASH('test')); END;
*
ERROR at line 1:
ORA-06550: line 1, column 28:
PLS-00201: identifier 'STANDARD_HASH' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
From sql is working just fine:
SQL> select STANDARD_HASH('test') from dual;
STANDARD_HASH('TEST')
----------------------------------------
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
Why? What is the best way to implement the STANDARD_HASH in PLSQL?
Regards
Seems like it isn't yet a part of PL/SQL in 12c.
As a workaround, use SELECT INTO in PL/SQL:
SQL> set serveroutput on
SQL> DECLARE
2 str VARCHAR2(40);
3 BEGIN
4 SELECT STANDARD_HASH('test') INTO str FROM dual;
5 dbms_output.put_line(str);
6 END;
7 /
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
PL/SQL procedure successfully completed.
SQL>
I would suggest to create a function, and use it whenever you need it in PL/SQL.
For example,
SQL> CREATE OR REPLACE FUNCTION STANDARD_HASH_OUTPUT(str IN VARCHAR2)
2 RETURN VARCHAR2
3 AS
4 op VARCHAR2(40);
5 BEGIN
6 SELECT STANDARD_HASH(str) INTO op FROM dual;
7 RETURN op;
8 END;
9 /
Function created.
Call the function directly in PL/SQL block:
SQL> BEGIN
2 dbms_output.put_line(STANDARD_HASH_OUTPUT('test'));
3 END;
4 /
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
PL/SQL procedure successfully completed.
SQL>
For text, STANDARD_HASH is the same as DBMS_CRYPTO.HASH with SHA1:
begin
dbms_output.put_line(dbms_crypto.hash(cast('test' as clob), dbms_crypto.hash_sh1));
end;
/
Output:
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
For other data types, it's not documented how they are passed to the hash function.
standard hash allows you to specify hash algorithm. Algorithms are SHA1, SHA256, SHA384, SHA512, and MD5. If you omit this argument, then SHA1 is used.
To get a more familiar GUID than sys_guid provides:
LOWER (CAST (standard_hash (SYS_GUID (), 'MD5') AS VARCHAR2 (40)))
I've tested on 20.5 million records with no collisions...

executing a function in sql plus

I created a function in oracle that inserts records in specific tables and return an output according to what occurs within the function. e.g (ins_rec return number)
How do I call this function and see its output in sql plus
declare
x number;
begin
x := myfunc(myargs);
end;
Alternatively:
select myfunc(myargs) from dual;
One option would be:
SET SERVEROUTPUT ON
EXEC DBMS_OUTPUT.PUT_LINE(your_fn_name(your_fn_arguments));
As another answer already said, call select myfunc(:y) from dual; , but you might find declaring and setting a variable in sqlplus a little tricky:
sql> var y number
sql> begin
2 select 7 into :y from dual;
3 end;
4 /
PL/SQL procedure successfully completed.
sql> print :y
Y
----------
7
sql> select myfunc(:y) from dual;

Resources