Passing char value to function - sql

I have the following function:
CREATE OR REPLACE FUNCTION BANINST1."F_COC_AUTO_AWARD_FILTER" (pidm number) return number
as
return_field number;
cursor get_pidm is
select distinct SHRDGMR.SHRDGMR_PIDM
from SATURN.SHRDGMR SHRDGMR,
SATURN.SORLCUR SORLCUR,
SATURN.SORLFOS SORLFOS,
DWSCHEMA.DAP_AUDIT_DTL#LINKDWTEST
where SORLCUR.SORLCUR_PIDM = SHRDGMR.SHRDGMR_PIDM
and SORLFOS.SORLFOS_PIDM = SORLCUR.SORLCUR_PIDM
and SORLCUR.SORLCUR_LEVL_CODE = SHRDGMR.SHRDGMR_LEVL_CODE
and SORLCUR.SORLCUR_DEGC_CODE = SHRDGMR.SHRDGMR_DEGC_CODE
and SORLFOS.SORLFOS_TERM_CODE = SORLCUR.SORLCUR_TERM_CODE
and SHRDGMR.SHRDGMR_PIDM = pidm
and SHRDGMR.SHRDGMR_DEGS_CODE = 'AW'
and SORLCUR.SORLCUR_PROGRAM in ('STCC', 'CC')
and DWSCHEMA.DAP_AUDIT_DTL.DAP_DEGREE in ('CPCC-CDS', 'CC1-CDS', 'CC2-CDS')
and SORLFOS.SORLFOS_MAJR_CODE <> DWSCHEMA.DAP_AUDIT_DTL.DAP_AUD_VALUE2
and trim(DWSCHEMA.DAP_AUDIT_DTL.DAP_STU_ID) = (select spriden_id from spriden where spriden_pidm = pidm and spriden_change_ind is null);
begin
open get_pidm;
fetch get_pidm into return_field;
close get_pidm;
return return_field;
end;
/
This is the call to the function from a where clause:
baninst1.f_coc_auto_award_filter#test(RAD_PRIMARY_MST.RAD_USER_DEF1) is not null
The function accepts a number data type parameter.
The passed column RAD_PRIMARY_MST.RAD_USER_DEF1 is a char(12) data type that has a value such as 293858.
The following error is returned when calling the function: ORA-01722: invalid number
I have tried to pass a number value to the function in several different ways:
baninst1.f_coc_auto_award_filter#test(to_number(trim(RAD_PRIMARY_MST.RAD_USER_DEF1))) is not null
baninst1.f_coc_auto_award_filter#test(cast(RAD_PRIMARY_MST.RAD_USER_DEF1 as number(8))) is not null
All attempts return the same error ORA-01722: invalid number
If I hard-code the D_PRIMARY_MST.RAD_USER_DEF1 value to a number, the function call works.
baninst1.f_coc_auto_award_filter#test(293858) is not null
How do I pass the char value from RAD_PRIMARY_MST.RAD_USER_DEF1 to the function?

This might be the keyword:
such as 293858
Are you sure that there aren't any non-numeric values in that column? With that datatype (char), there's always doubt. If you are storing numbers in there, why isn't it number?
This query should return invalid values which cause your code to break.
select * from d_primary_mst where not regexp_like(rad_user_def1, '^\d+$')
Also, if you are passing a string, why do you force the function to accept a number? Why don't you
CREATE OR REPLACE FUNCTION BANINST1.F_COC_AUTO_AWARD_FILTER
(pidm RAD_PRIMARY_MST.RAD_USER_DEF1%type)
return SHRDGMR.SHRDGMR_PIDM%type
as
return_field SHRDGMR.SHRDGMR_PIDM%type;
cursor get_pidm is
select distinct SHRDGMR.SHRDGMR_PIDM ...
By the way, get rid of double quotes when creating Oracle objects; they only cause problems.

Related

Inner join condition is disregarded - looks like an Oracle bug

How is this possible?: If I replace message_format_name with the literal 'MT202', the query works as expected. Otherwise, it returns 2 rows instead of the expected 1--same as if that condition was commented out.
It seems the parameter value passed in to the stored proc doesn't equal the value in ms.message_format_name for some strange reason.
Let me know if you need more details.
Thanks!
set define off;
create or replace PROCEDURE insert_mapping(
interface_name IN VARCHAR2,
message_format_name IN VARCHAR2,
determined_field_type IN VARCHAR2,
source_field IN VARCHAR2,
mapping_key IN VARCHAR2,
mapping_key_value1 IN VARCHAR2,
mapping_key_value2 IN VARCHAR2 DEFAULT NULL,
return_val OUT sys_refcursor)
AS
BEGIN
dbms_output.put_line('interface_name = ' || interface_name);
dbms_output.put_line('message_format_name = ' || message_format_name);
dbms_output.put_line('determined_field_type = ' || determined_field_type);
dbms_output.put_line('source_field = ' || source_field);
/* INSERT
INTO payments.multi_value_lookup_mapping
(
pk_multi_value_lkp_mapping,
fk_pk_multi_value_lookup_confg,
mapping_key,
mapping_key_value1,
mapping_key_value2,
created_by,
created_dt,
update_by,
update_dt
)*/
OPEN return_val FOR
SELECT payments.seq_multi_value_lookup_map.nextval,
mvlc.pk_multi_value_lookup_config,
mapping_key,
mapping_key_value1,
mapping_key_value2,
50000,
SYSDATE,
50000,
SYSDATE
FROM payments.multi_value_lookup_config mvlc, payments.message_source ms
WHERE (ms.pk_message_source = mvlc.fk_pk_message_source
AND ms.interface_name = interface_name
AND ms.message_format_name = message_format_name /*'MT202'*/
AND mvlc.mapping_column_name = source_field
AND mvlc.lookup_category_type = determined_field_type
);
END insert_mapping;
This is not an Oracle bug. First, you should never use commas in the FROM clause. You should always use explicit JOIN syntax.
But that is not your specific problem. Variable resolution and scoping is.
When you have a reference such as interface_name in a query, then Oracle looks first for columns with that name. It never sees the variables. Name the variables something distinguishing, so you end up with code that is more like this:
. . .
FROM payments.multi_value_lookup_config mvlc JOIN
payments.message_source ms
ON ms.pk_message_source = mvlc.fk_pk_message_source
WHERE ms.interface_name = v_interface_name
ms.message_format_name = v_message_format_name /*'MT202'*/
mvlc.mapping_column_name = v_source_field
mvlc.lookup_category_type = v_determined_field_type

Error creating function in DB2 with params

I have a problem with a function in db2
The function finds a record, and returns a number according to whether the first and second recorded by a user
The query within the function is this
SELECT
CASE
WHEN NUM IN (1,2) THEN 5
ELSE 2.58
END AS VAL
FROM (
select ROW_NUMBER() OVER() AS NUM ,s.POLLIFE
from LQD943DTA.CAQRTRML8 c
INNER JOIN LSMODXTA.SCSRET s ON c.MCCNTR = s.POLLIFE
WHERE s.NOEMP = ( SELECT NOEMP FROM LSMODDTA.LOLLM04 WHERE POLLIFE = '0010111003')
) AS T WHERE POLLIFE = '0010111003'
And works perfect
I create the function with this code
CREATE FUNCTION LIBWEB.BNOWPAPOL(POL CHAR)
RETURNS DECIMAL(7,2)
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
RETURN (
SELECT
CASE
WHEN NUM IN (1,2) THEN 5
ELSE 2.58
END AS VAL
FROM (
select ROW_NUMBER() OVER() AS NUM ,s.POLLIFE
from LQD943DTA.CAQRTRML8 c
INNER JOIN LSMODXTA.SCSRET s ON c.MCCNTR = s.POLLIFE
WHERE s.NOEMP = ( SELECT NOEMP FROM LSMODDTA.LOLLM04 WHERE POLLIFE = POL)
) AS T WHERE POLLIFE = POL
)
The command runs executed properly
WARNING: 17:55:40 [CREATE - 0 row(s), 0.439 secs] Command processed.
No rows were affected
When I want execute the query a get a error
SELECT LIBWEB.BNOWPAPOL('0010111003') FROM DATAS.DUMMY -- dummy has only one row
I get
[Error Code: -204, SQL State: 42704] [SQL0204] BNOWPAPOL in LIBWEB
type *N not found.
I detect, when I remove the parameter the function works fine!
With this code
CREATE FUNCTION LIBWEB.BNOWPAPOL()
RETURNS DECIMAL(7,2)
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
RETURN (
SELECT
CASE
WHEN NUM IN (1,2) THEN 5
ELSE 2.58
END AS VAL
FROM (
select ROW_NUMBER() OVER() AS NUM ,s.POLLIFE
from LQD943DTA.CAQRTRML8 c
INNER JOIN LSMODXTA.SCSRET s ON c.MCCNTR = s.POLLIFE
WHERE s.NOEMP = ( SELECT NOEMP FROM LSMODDTA.LOLLM04 WHERE POLLIFE = '0010111003')
) AS T WHERE POLLIFE = '0010111003'
)
Why??
This statement:
SELECT LIBWEB.BNOWPAPOL('0010111003') FROM DATAS.DUMMY
causes this error:
[Error Code: -204, SQL State: 42704] [SQL0204] BNOWPAPOL in LIBWEB
type *N not found.
The parm value passed into the BNOWPAPOL() function is supplied as a quoted string with no definition (no CAST). The SELECT statement assumes that it's a VARCHAR value since different length strings might be given at any time and passes it to the server as a VARCHAR.
The original function definition says:
CREATE FUNCTION LIBWEB.BNOWPAPOL(POL CHAR)
The function signature is generated for a single-byte CHAR. (Function definitions can be overloaded to handle different inputs, and signatures are used to differentiate between function versions.)
Since a VARCHAR was passed from the client and only a CHAR function version was found by the server, the returned error fits. Changing the function definition or CASTing to a matching type can solve this kind of problem. (Note that a CHAR(1) parm could only correctly handle a single-character input if a value is CAST.)

Why does this function always return 0

I don't know why this function always returns 0
CREATE OR REPLACE FUNCTION QTYDEPOT(
p_org_id IN NUMBER,
p_product_id IN NUMBER,
p_datefrom IN DATE,
p_dateto IN DATE)
RETURN NUMBER
AS
qty NUMBER;
BEGIN
SELECT COALESCE(SUM(C_InvoiceLine.qtyinvoiced), 0)
INTO qty
FROM C_InvoiceLine
INNER JOIN C_invoice
ON (c_invoiceline.C_INVOICE_ID = c_invoice.C_INVOICE_ID)
INNER JOIN C_BPartner
ON (c_invoice.C_BPARTNER_ID = c_bpartner.C_BPARTNER_ID)
WHERE C_BPartner.ISSALESREP = 'N'
AND C_BPartner.ISEMPLOYEE = 'N'
AND c_bpartner.ISCUSTOMER = 'Y'
AND c_invoiceline.AD_org_id = p_org_id
AND c_invoiceline.m_product_id= p_product_id
AND c_invoice.DateInvoiced BETWEEN p_datefrom AND p_dateto;
RETURN qty ;
END;
P.S : if I remove the date part of the close where
c_invoice.DateInvoiced BETWEEN p_datefrom AND p_dateto;
The function returns the real values.
I call it like this
SELECT
..
QTYDEPOT( 1000000, p.m_product_id,'7/7/2014','24/7/2014') as qtyDepot
try this:
SELECT
..
QTYDEPOT( 1000000, p.m_product_id,to_date('7/7/2014','dd/mm/yyyy'),to_date('24/7/2014','dd/mm/yyyy')) as qtyDepot
you have to specify the date format you are passing to the function,
hope this helps!
You have problems with DATE manipulation. I would suggest you to try calling your function like this :
SELECT
..
QTYDEPOT( 1000000, p.m_product_id,DATE('2014-07-07'),DATE('2014-07-24')) as qtyDepot
AS you can see, Oracle standard format is 'yyyy-mm-dd' I don't know if DATE(...) is needed, but I use to manipulate DATE like this: code is clearer.

ORACLE SQL Method Produces Warning

I'm having trouble getting the following member method to compile (count_single_buses). Would appreciate any advice on what might be wrong syntactically with my code.
CREATE OR REPLACE TYPE BodyModel2_Type AS OBJECT(
ModelID INTEGER,
ModelName VARCHAR2(45),
FloorType VARCHAR2(45),
Manufacturer VARCHAR2(45),
Length NUMBER(8,2),
Width NUMBER(8,2),
NoOfAxles INTEGER,
MEMBER FUNCTION count_single_buses(ModelID INTEGER) RETURN INTEGER);
/
CREATE OR REPLACE TYPE BODY BodyModel2_Type AS
MEMBER FUNCTION count_single_buses(ModelID INTEGER) RETURN INTEGER IS
N INTEGER;
BEGIN
N := (SELECT COUNT(BODYMODELREF) FROM SINGLEDECKBUS_TABLE S
WHERE S.BODYMODELREF = ModelID);
RETURN N;
END count_single_buses;
END;
--EDIT--
Thanks to #Ravi, I managed to solve the issue my correcting my SQL syntax and setting the resultset to a NUMBER, instead of INTEGER.
CREATE OR REPLACE TYPE BODY BodyModel_Type AS
MEMBER FUNCTION count_single_buses(thisModelID INTEGER) RETURN NUMBER IS
NUM NUMBER;
BEGIN
SELECT COUNT(S.BODYMODELREF) INTO NUM FROM SINGLEDECKBUS_TABLE S WHERE S.BODYMODELREF.MODELID = thisModelID;
RETURN NUM;
END count_single_buses;
END;
/
Still not sure why #Ravi's exact code still produced the warning, and thought that resultset when returning a count value could go into an integer. At any rate, the code works now. Thanks all.
Your BodyModel2_Type Type definition looks okay. However, the body definition is syntactically incorrect.
You cannot define a SQL statement directly to a variable, thus making this statement wrong.
N := (SELECT COUNT(BODYMODELREF) FROM SINGLEDECKBUS_TABLE S
WHERE S.BODYMODELREF = ModelID);
You will have to use Select... into statement in order to assign the result set of your SQL query into a variable. So, the right syntax should look like this
SELECT COUNT(BODYMODELREF) FROM SINGLEDECKBUS_TABLE S INTO N
WHERE S.BODYMODELREF = ModelID
AFAIK you don't have END the Type followed by the Type name like this END count_single_buses. It'll produce an error. So, overall your Type body specification should look like this:
CREATE OR REPLACE TYPE BODY BodyModel2_Type AS
MEMBER FUNCTION count_single_buses(ModelID INTEGER) RETURN NUMBER IS
N NUMBER;
BEGIN
SELECT COUNT(BODYMODELREF) FROM SINGLEDECKBUS_TABLE S INTO N
WHERE S.BODYMODELREF = ModelID;
RETURN (N);
END;
END;
/
I'm writing this off without any live environment available right now so please let me know if you come across any error in the above code.
Cheers.

How to pass a record as parameter for PL/pgSQL function?

I keep looking for this answer online but I cannot find it.
I am trying to pass one record over a PL/pgSQL function. I tried it in two ways.
Fist way :
CREATE OR REPLACE FUNCTION translateToReadableDate(mRecord dim_date%ROWTYPE) RETURNS void AS $$
That is the ouput :
psql:requestExample.sql:21: ERROR: syntax error at or near "%"
LINE 1: ... FUNCTION translateToReadableDate(mRecord dim_date%ROWTYPE) ...
^
Second way :
CREATE OR REPLACE FUNCTION translateToReadableDate(mRecord RECORD) RETURNS void AS $$
And there is the output
psql:requestExample.sql:21: ERROR: PL/pgSQL functions cannot accept type record
Someone does know how to do this please ?
CREATE OR REPLACE FUNCTION translateToReadableDate(mRecord dim_date) RETURNS void AS $$
BEGIN
SELECT dim_day.name || ' (' || dim_day_in_month.id || ') ' || dim_month.name || 'is the ' || dim_week.id || ' week of the year. ' AS "Une phrase", dim_quarter.id, dim_year.id
FROM dim_date dd
JOIN dim_day ON dd.day_id = dim_day.day_id
JOIN dim_day_in_month ON dd.day_in_month_id = day_in_month.day_in_month_id
JOIN dim_week ON dd.week_id = dim_week.week_id
JOIN dim_month ON dd.month_id = dim_month.month_id
JOIN dim_quarter ON dd.quarter_id = dim_quarter.quarter_id
JOIN dim_year ON dd.year_id = dim_year.year_id
WHERE dd.day_id = mRecord.day_id
AND dd.day_in_month_id = mRecord.day_in_month_id
AND dd.week_id = mRecord.week_id
AND dd.month_id = mRecord.month_id
AND dd.quarter_id = mRecord.quarter_id
AND dd.year_id = mRecord.year_id;
END;
$$ LANGUAGE plpgsql;
Try this:
CREATE OR REPLACE FUNCTION translateToReadableDate(mRecord dim_date) RETURNS void AS $$
dim_date must be a table.
EDIT:
Ok, now I'm really really confused.
A date should be a column, not a table. I can't understand why would you create a table with date values.
You can format dates no problem with to_char. Read this: Data Type Formatting Functions to learn how to. That function you created makes zero sense.
Are you outputting PL/pgSQL? Shouldn't the formatting be done by the middle tier? You should just return a Date from the database.
Lastly, I would recommend reading the PL/pgSQL Manual. There's lots of good stuff in there.