I have several Tables that contains just id and description in that particular schema, i wonder if it is possible to write one generic function which will read something like:
create or replace FUNCTION tab_lookup (key_field char,key_value char,from_table char,return_field char) RETURN char IS
a varchar2(1000);
BEGIN
select &return_field into a
from &from_table
where &key_field=key_value;
return(a);
exception
when others
then
return('*ERR*');
END;
i want to use it at inside package application which only 50 users will be using.
Modified your version, by changing it using Dynamic SQL and changed the Input parameters' Datatype as VARCHAR2
CREATE OR REPLACE FUNCTION tab_lookup (key_field VARCHAR2,
key_value VARCHAR2,
from_table VARCHAR2,
return_field VARCHAR2,
return_type VARCHAR2)
RETURN VARCHAR2 IS
result_a varchar2(1000);
query_string VARCHAR2(4000);
/*version 0.1*/
BEGIN
query_string := 'SELECT '||return_field||
'FROM '||from_table||
'WHERE '||key_field || ' = :key_value ';
IF(return_type = 'SQL') THEN
result_a := query_string;
ELSE
//this line will not work in forms 6i remove the using key_value word
EXECUTE IMMEDIATE query_string USING key_value into result_a;
END IF;
RETURN (result_a);
EXCEPTION
// add DBMS_ASSERT Exceptions
WHEN
NO_DATA_FOUND THEN
RETURN(NULL);
WHEN
TOO_MANY_ROWS THEN
RETURN('**ERR_DUPLICATE**');
WHEN OTHERS
THEN
RETURN('*ERR_'||SQLERRM);
END;
Related
I want to handle exception using oracle as I haven't done it before. below is my stored procedure.
create or replace
PROCEDURE GET_VALID_LATLONG
(
P_XYCORDINATE IN VARCHAR2,
P_SAPID IN VARCHAR2,
OUTR4GSTATENAME OUT SYS_REFCURSOR
)
AS
v_counter number:=0;
BEGIN
DBMS_OUTPUT.ENABLE;
OPEN OUTR4GSTATENAME FOR
SELECT DISTINCT(R4GSTATECODE),R4GSTATENAME
FROM R4G_LB.R4GSTATEBOUNDARY_EVW
WHERE SDE.ST_INTERSECTS(SDE.ST_GEOMETRY('POINT
('||P_XYCORDINATE||')', 3),SHAPE) = 1;
END GET_VALID_LATLONG;
how to handle the exception?
UPDATE
I added like this, is it fine when error occurs ??
create or replace
PROCEDURE GET_VALID_LATLONG
(
P_XYCORDINATE IN VARCHAR2,
P_SAPID IN VARCHAR2,
OUTR4GSTATENAME OUT SYS_REFCURSOR
)
AS
v_counter number:=0;
BEGIN
DBMS_OUTPUT.ENABLE;
OPEN OUTR4GSTATENAME FOR
SELECT DISTINCT(R4GSTATECODE),R4GSTATENAME
FROM R4G_LB.R4GSTATEBOUNDARY_EVW
WHERE SDE.ST_INTERSECTS(SDE.ST_GEOMETRY('POINT
('||P_XYCORDINATE||')', 3),SHAPE) = 1;
EXCEPTION
WHEN OTHERS THEN
NULL;
END GET_VALID_LATLONG;
A list of pre-defined exceptions can be found in the Oracle docs, for example here.
https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/07_errs.htm
You can use this list of exception names in your exception clause, for example
WHEN TOO_MANY_ROWS THEN
NULL; -- whatever you wish to do here.
create or replace PROCEDURE find_Doctor (p_SSN in number) AS
BEGIN
select drName, drPhone
from clients
where SSN = p_SSN;
END find_Doctor;
I've got this stored procedure and I just want to output the resulting table from that call. Is there an easy way to do this without declaring a temporary table? I can't just make is a normal SQL query because I have to call it from a java program.
In a Procedure you would need variable to hold the result output of the SQL query. You can then use the variable. Use this:
CREATE OR REPLACE PROCEDURE find_Doctor (p_SSN IN NUMBER)
AS
var_nm VARCHAR2 (100);
var_ph NUMBER;
BEGIN
SELECT drName, drPhone
INTO var_nm, var_ph
FROM clients
WHERE SSN = p_SSN;
DBMS_OUTPUT.put_line ('Doc Name - ' || var_nm || 'Doc Ph. No-' || var_ph);
END find_Doctor;
Edit:
I can't just make is a normal SQL query because I have to call it from
a java program.
You can then use SYS_REFCUSOR to return results, which can be mapped to a JDBC ResultSet.
CREATE OR REPLACE PROCEDURE find_Doctor (p_SSN IN NUMBER,
VAR OUT SYS_REFCURSOR)
AS
BEGIN
OPEN VAR FOR
SELECT drName, drPhone
FROM clients
WHERE SSN = p_SSN;
END find_Doctor;
You should define out parameters drName and drPhone:
create or replace PROCEDURE find_Doctor (p_SSN in number, p_drName OUT
VARCHAR2, p_drPhone OUT VARCHAR2) AS
BEGIN
select drName, drPhone
into p_drName, p_drPhone
from clients
where SSN = p_SSN;
END find_Doctor;
Easy way is to learn tool you're used and best practices for it.
For me, best way is remove senseless procedure and just selects data you need. But if you adherent of 'SP only' approach you can use ref cursor to retrive required data:
create or replace function find_Doctor (p_SSN in number)
return sys_refcursor as
v_result sys_refcursor;
BEGIN
open v_result for
select drName, drPhone
from clients
where SSN = p_SSN;
return v_result;
END find_Doctor;
New PL/SQL person here. I have a (successfully compiled) PL/SQL function block that manipulates a table in my database by adding a new term to it:
create or replace FUNCTION add_new_term
(TERM_ID_IN IN NUMBER, TERM_IN IN VARCHAR2, IS_METATERM_IN IN NUMBER)
RETURN VARCHAR2
IS
add_term CV_TERMS.TERM_NAME%TYPE; --TERM_NAME is VARCHAR2 type
BEGIN
INSERT INTO CV_TERMS (TERM_ID, TERM_NAME, IS_METATERM)
VALUES (TERM_ID_IN, TERM_IN, IS_METATERM_IN);
dbms_output.put_line('New term successfully added to CV_TERMS table: ' || TERM_IN);
RETURN add_term;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
raise_application_error (-20001, 'You have tried to insert a duplicate term.');
WHEN OTHERS THEN
raise_application_error (-20002, 'An error has occurred inserting a term - '|| SQLCODE ||' -ERROR- '|| SQLERRM);
END add_new_term;
I call this function like calling a stored procedure:
DECLARE
add_term_success cv_terms.term_name%type;
BEGIN
add_term_success := add_new_term(cv_terms_pk.NEXTVAL, 'TESTTT', 0);
END;
SQLDeveloper tells me the procedure was successfully completed, however, the term has not been added to the table. I created the sequence cv_terms_pk independently (it's not in the table CV_TERMS' SQL). Does it need to be there? Am I passing it improperly? Or is something wrong with my add_term declaration? Ideas?
After the DML INSERT you have to commit the transaction.
create or replace FUNCTION add_new_term
(TERM_ID_IN IN NUMBER, TERM_IN IN VARCHAR2, IS_METATERM_IN IN NUMBER)
RETURN VARCHAR2 IS
add_term CV_TERMS.TERM_NAME%TYPE; --TERM_NAME is VARCHAR2 type
BEGIN
INSERT INTO CV_TERMS(TERM_ID, TERM_NAME, IS_METATERM
VALUES (TERM_ID_IN, TERM_IN, IS_METATERM_IN);
COMMIT; ---LINE ADDED ...
I have the following code
CREATE OR REPLACE FUNCTION slow_function (p_in IN NUMBER)
RETURN NUMBER
AS
BEGIN
DBMS_LOCK.sleep(1);
RETURN p_in;
END;
/
CREATE OR REPLACE PACKAGE cached_lookup_api AS
FUNCTION get_cached_value (p_id IN NUMBER)
RETURN NUMBER;
PROCEDURE clear_cache;
END cached_lookup_api;
/
CREATE OR REPLACE PACKAGE BODY cached_lookup_api AS
TYPE t_tab IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
g_tab t_tab;
g_last_use DATE := SYSDATE;
g_max_cache_age NUMBER := 10/(24*60); -- 10 minutes
-- -----------------------------------------------------------------
FUNCTION get_cached_value (p_id IN NUMBER)
RETURN NUMBER AS
l_value NUMBER;
BEGIN
IF (SYSDATE - g_last_use) > g_max_cache_age THEN
-- Older than 10 minutes. Delete cache.
g_last_use := SYSDATE;
clear_cache;
END IF;
BEGIN
l_value := g_tab(p_id);
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Call function and cache data.
l_value := slow_function(p_id);
g_tab(p_id) := l_value;
END;
RETURN l_value;
END get_cached_value;
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
PROCEDURE clear_cache AS
BEGIN
g_tab.delete;
END;
-- -----------------------------------------------------------------
END cached_lookup_api;
/
I want to pass two parameters "pi_value1" and "pi_value2" both of varchar2 to the function slow_function instead of "p_in". Is is possible to cache the results with two in parameters in oracle 10g .
the above code works fine with 1 parameter.
Please any one explain?
You'd need to create a two-dimensional array type to cache the values. Something along the lines of this (omitting the cache expiration code since that isn't changing)
CREATE OR REPLACE PACKAGE BODY cached_lookup_api
AS
TYPE t_pi_value2_tbl IS TABLE OF NUMBER
INDEX BY VARCHAR2(100);
TYPE t_cache IS TABLE OF t_pi_value2_tbl
INDEX BY VARCHAR2(100);
g_cache t_cache;
FUNCTION get_cached_value( p_pi_value1 IN VARCHAR2,
p_pi_value2 IN VARCHAR2 )
IS
BEGIN
RETURN g_cache(p_pi_value1)(p_pi_value2);
EXCEPTION
WHEN no_data_found
THEN
g_cache(p_pi_value1)(p_pi_value2) := slow_function( p_pi_value1, p_pi_value2 );
RETURN g_cache(p_pi_value1)(p_pi_value2);
END;
END;
I am working on this for my homework. When I run it, I get the error:
PACKAGE PKG_Q4 Compiled.
Warning: execution completed with warning
PACKAGE BODY PKG_Q4 Compiled.
50/12 PLS-00330: invalid use of type name or subtype name.
I've looked into this but I cant seem to find a way to fix it. It is pointing to this line:
INTO v_Room_Number, v_Pet_Status, v_Customer_Source_Description, v_Invoice_Total
Here is my code:
CREATE OR REPLACE PACKAGE BODY PKG_Q4
AS
FUNCTION FN_Q4
(p_First_Name VARCHAR2, p_Last_Name VARCHAR2)
RETURN VARCHAR2
AS
v_Output VARCHAR2(500);
v_Room_Number NUMBER(3,0);
v_Pet_Status CHAR(1);
v_Customer_Source_Description VARCHAR2(30);
v_Invoice_Total NUMBER(7,2);
v_First_Name VARCHAR2(15);
v_Last_Name VARCHAR2(20);
v_Customer_Code CHAR(4);
v_Registration_Status_Code CHAR(1);
BEGIN
SELECT First_Name, Last_Name
INTO v_First_Name, v_Last_Name
FROM Customer
WHERE First_Name = p_First_Name AND
Last_Name = p_Last_Name;
Select Registration_Status_Code
INTO v_Registration_Status_Code
FROM Registration_Status;
IF v_Registration_Status_Code = 'N' THEN
SELECT Room.Room_Number, Room.Pet_Status, Customer_Source.Customer_Source_Description, Invoice.Invoice_Total
INTO v_Room_Number, v_Pet_Status, v_Customer_Source_Description, v_Invoice_Total
FROM Registration , Customer , Customer_Source , Room , Invoice
WHERE Customer.customer_code = Registration.customer_code AND
Customer_Source.customer_source_code = Customer.customer_source_code AND
Room.room_number = Registration.room_number AND
Registration.registration_number = Invoice.registration_number;
v_Output := 'Room Number:' || v_Room_Number ||'Pet Status:' || v_Pet_Status ||
'Customer Source Code:' || v_Customer_Source_Description ||'Total Cost:' || v_Invoice_Total;
END IF;
Return Varchar2;
I'd wager the problem is actually this line, at the very bottom of the code excerpt:
Return Varchar2;
"Varchar2" is a type, you can't use it as the argument of a RETURN statement. In the function declaration, RETURN VARCHAR2 is correct usage, indicating the type of the value returned by the function. The actual RETURN statement should return a value of that type, like
RETURN 'This is a string literal';
In your case, I'm guessing you want:
RETURN v_Output;