PL/SQL UTL_HTTP.REQUEST - Curly Braces/Semicolon - oracle

I'm trying to call a URL using the UTL_HTTP package in Oracle Autonomous Database and getting an ORA-06512:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "SYS.UTL_HTTP", line 1810
ORA-06512: at "SYS.UTL_HTTP", line 144
ORA-06512: at "SYS.UTL_HTTP", line 1745
ORA-06512: at line 1
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
All network ACLS etc. are configured correctly.
The URL in question requires JSON directly in the URL which I understand is bad practice, however I don't have control over the API. If I remove the curly braces ( {} ) and semicolons ( : ), the request using UTL_HTTP works but the output is incorrect as the JSON becomes invalid.
I've tried encoding the URL using an online encoder as well as the UTL_URL.ESCAPE function, which gives the same error as above.
The encoding from UTL_URL.ESCAPE IS:
An example of the URL format is:
https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}
I've tried a straight select using utl_http.request:
SELECT UTL_HTTP.REQUEST('https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}') FROM DUAL;
And calling using PL/SQL:
declare
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
val VARCHAR2(2000);
str varchar2(1000);
begin
req := UTL_HTTP.BEGIN_REQUEST('https://example.com/rest.php?entity=contact&action=get&json={"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}');
resp := UTL_HTTP.GET_RESPONSE(req);
LOOP
UTL_HTTP.READ_LINE(resp, val, TRUE);
DBMS_OUTPUT.PUT_LINE(val);
END LOOP;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY
THEN
UTL_HTTP.END_RESPONSE(resp);
END;
/
How do I call this url using UTL_HTTP?

They talk about this a bit in the UTL_URL documentation, but colons are reserved characters - they're valid in some parts of a URL, but not in others. (Curly braces are not allowed at all.) There's been some debate about whether or not they're valid in the Query portion of a URL - the ABNF in the RFC seems to say yes, but a lot of implementations don't allow it.
By default, UTL_URL.ESCAPE doesn't escape reserved characters (because that would screw up the https:// part, etc), but you can change that by passing TRUE as the second argument. In general, best practice seems to be escaping reserved characters in any query string that might contain them:
req := UTL_HTTP.BEGIN_REQUEST('https://example.com/rest.php?entity=contact&action=get&json='
|| utl_url.escape('{"name": "Lorum Ipsum", "end_date": {"IS NULL": 1}, "return": "id,contact_id"}'
,TRUE));
See if that helps?

Related

Error ORA-25448 when creating job chain rule using dbms_scheduler.define_chain_rule

When I attempt to create the following oracle chain rule:
BEGIN
SYS.DBMS_SCHEDULER.DEFINE_CHAIN_RULE (
chain_name => 'MIGRATE_EISDB_CHAIN',
condition => ':MIGRATION_STEP_1.state=''RUNNING'' AND select decode(TIME_COMPLETED, null, 0, 1) from MIGRATION_PROGRESS where MIGRATION_STEP = "MIGRATE_AEP_TO_EP" > 0',
rule_name => 'continue_migration',
action => 'START MIGRATION_STEP_2',
comments => 'continue the migration - step 2');
END;
/
The chain, steps and the first rule were created successfully, but I
get this error when creating the second rule with a condition:
Error report - ORA-25448: rule EISYSNEW1.CONTINUE_MIGRATION has
errors ORA-00936: missing expression ORA-06512: at
"SYS.DBMS_ISCHED", line 1646 ORA-06512: at "SYS.DBMS_SCHEDULER",
line 1619 ORA-06512: at line 2
25448. 00000 - "The %s %s.%s has errors."
*Cause: An attempt to load the specified rule or expression failed due
to errors in the rule or expression.
*Action: Check the rule or expression and retry the operation.
Question:
Why is this happening?? Oracle's documentation says that this condition should be legal. What am I missing in the expression for this condition?? FYI: It does create when I omit the part after the 'AND'.
condition => ':MIGRATION_STEP_1.state=''RUNNING'' AND select decode(TIME_COMPLETED, null, 0, 1) from MIGRATION_PROGRESS where MIGRATION_STEP = "MIGRATE_AEP_TO_EP" > 0',
I don't see where Oracle's documentation says that the condition is legal. It doesn't look too legal to me.
You need to make the nested SELECT a subquery, by wrapping it in parentheses. Unless MIGRATE_AEP_TO_EP is a column name, you may also want to replace the double-quotes around MIGRATE_AEP_TO_EP to single quotes. As the rule itself is a string literal, you will need to escape each of the single quotes with a second single quote, as you have with RUNNING:
condition => ':MIGRATION_STEP_1.state=''RUNNING'' AND (select decode(TIME_COMPLETED, null, 0, 1) from MIGRATION_PROGRESS where MIGRATION_STEP = ''MIGRATE_AEP_TO_EP'') > 0',

Character to number conversion

I have a column with for eg values:
*.4176,
*0.2734,
$1.53,
$122.00,
D0.4645,
D.2464,
*0.3426,
*.3426,
$0.0/$2.50,
-0.0/-2.50
I need to write a query to display only the numerical part in numerical format. I want to create a detail object for the main object in business object.
I tried using translate but it has a lot of hardcoding and the slash is creating problem to convert it into TO_BINARY_DOUBLE. Is there anyother way to avoid hardcoding and still display numbers in numerical format?
Try this:
SELECT TRANSLATE('*4176', ' */''', ' ') FROM DUAL;
This is the case when you have the symbol * in the column, just to get the idea. Perform some more translates for the other cases as well.
Cheers
I require output in following format:
Cost Formula Cost Formula Code Cost Formula Value Cost calculation
$520.80 $ 520.8
*1 * 1
-0.0/-$20 -0.0/-$20
+0.0/-$36 +0.0/-$36
select
cost_formula,
case
when TRANSLATE(COST_FORMULA,'1234567890.-+ABCDEFGHIJKLMNOPQRSTUVWXYZ!##%^&*()~`_[]{};<>:"*$',' ')='/'
then ''
else TRANSLATE(COST_FORMULA,'1234567890.-+',' ')
END code,
case
when TRANSLATE(COST_FORMULA,'1234567890.-+ABCDEFGHIJKLMNOPQRSTUVWXYZ!##%^&*()~`_[]{};<>:"*$',' ')='/'
then '0'
else TO_BINARY_DOUBLE(RTRIM(LTRIM(TRANSLATE(UPPER(COST_FORMULA),'ABCDEFGHIJKLMNOPQRSTUVWXYZ!##%^&*()~`_[]{};<>:"*$','0'))))
END value,
case
when TRANSLATE(COST_FORMULA,'1234567890.-+ABCDEFGHIJKLMNOPQRSTUVWXYZ!##%^&*()~`_[]{};<>:"*$',' ')='/'
then cost_formula
else ''
END Calculation
FROM RSE.RSE_SO_F_ORDERS;
I am using this query to get the required format. But the numerical part is throwing the following error:
ORA-00932: inconsistent datatypes: expected CHAR got BINARY_DOUBLE
00932. 00000 - "inconsistent datatypes: expected %s got %s"
And i want the numerical part to be as a float.

Why doesn't translate work on some characters?

I am trying to remove certain characters from a VARCHAR2 using translate. Characters 160 (some kind of space) and 243 (paragraph control character?), however, appear to be "phantom" characters that are undetectable by both INSTR and TRANSLATE. LENGTH works, but only if it's the only character in a string. LENGTH(CHR(160)) returns 1, but LENGTH(CHR(160) || CHR(110)) also returns 1 when you'd think it would return 2. I've found that REPLACE works in stripping these phantom characters from a string, but I like translate better because it's easier to read and maintain whereas a long nesting or REPLACE functions is just cumbersome.
Is there some other way to strip these characters from a VARCHAR2 without using replace?
EDIT: It appears that character 243 elsewhere registers as ≤. However, Oracle has no problem displaying this character when I selected it explicitly. When I select CHR(243), it just displays the block replacement character. Plus, this source points 243 to the paragraph character which makes more sense since that's a control code.
What about using a regular expression? This removes your trouble characters by replacing char 160 or 243 with nothing:
SQL> select regexp_replace('abc' || chr(160) || chr(243) || 'def', '(' || chr(160) || '|' || chr(243) || ')', '') from dual;
REGEXP
------
abcdef
SQL>

Character to number conversion error

declare
l_tot number := 0;
begin
for i in 1..apex_application.g_f08.count loop
l_tot := l_tot + nvl(to_number(apex_application.g_f08(i)),0);
end loop;
if l_tot = nvl(to_number(:P21_TOTAL_PRICE),0) then
return true;
else
return false;
end if;
end;
Got below error with above code
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
Error occurred with :P21_TOTAL_PRICE. What is the wrong ? How can i correct this ?
Rather than using REPLACE you should use the more powerful REGEXP_REPLACE function. http://www.orafaq.com/wiki/REGEXP_REPLACE
You can then remove any non-numeric character from the string before then using the TO_NUMBER function.
In your case it would be something like:
REGEXP_REPLACE(:P21_TOTAL_PRICE, '[^0-9]+', '');
See my answer to almost the exact same question here: Oracle To_Char function How to handle if it's already a string
The error rises because the number that you're representing is actually a character string involving commas etc. When you put a to_number to that, Oracle cannot replace the commas.
You might want to use replace function to strip off the commas
Change
if l_tot = nvl(to_number(:P21_TOTAL_PRICE),0) then
to
if l_tot = nvl(to_number(replace(:P21_TOTAL_PRICE,',','')),0) then

ORA-06502: PL/SQL: numeric or value error: character string buffer too small error

I have an oracle function which is given below. when I run this in sql-developer it gives an error
ORA-06502: PL/SQL: numeric or value error: character string buffer too
small error.
However the DBMS_OUTPUT.PUT_LINE(FINAL_RESULT) line in the function is printing the expected output in the output window.
Can anyone help me in this??
create or replace
FUNCTION AVERAGE_WORKFORCE(PERIOD in varchar2, YR in varchar2) RETURN CLOB AS
FINAL_RESULT CLOB:=null;
STRING_QUERY_TEXT CLOB:=null;
OUTPUT_RESULT CLOB:=null;
BEGIN
FINAL_RESULT:='<FINAL_RESULT><HEADER><NAME> </NAME> <NAME>SENIOR DIRECTOR</NAME> <NAME>DIRECTOR</NAME> <NAME>EXECUTIVE</NAME> <NAME>MANAGER</NAME><NAME>CASHIER</NAME><NAME>EMPLOYEE</NAME></HEADER>';
STRING_QUERY_TEXT:='SELECT XMLElement("tuple",XMLElement("DESC",''Average number of registered employees''), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''SENIOR DIRECTOR'')), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''DIRECTOR'')), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''MANAGER'')), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''EXECUTIVE'')), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''CASHIER'')), XMLElement("PERMANENT_EMP",GET_COUNT_AVERAGE_WORKFORCE('''||PERIOD||''','''||YR||''',''EMPLOYEE''))) FROM DUAL';
EXECUTE_QUERY_RETURN_RESULT(STRING_QUERY_TEXT,OUTPUT_RESULT);
FINAL_RESULT:=FINAL_RESULT||''||OUTPUT_RESULT;
FINAL_RESULT:=FINAL_RESULT||''||'</FINAL_RESULT>';
DBMS_OUTPUT.PUT_LINE(FINAL_RESULT);
RETURN FINAL_RESULT;
END AVERAGE_WORKFORCE;
With apologies to Alex and Tony (who have obviously thought the same thing).
Your code is showing the expected output so the DBMS_OUTPUT line must have succeeded.
DBMS_OUTPUT.PUT_LINE(FINAL_RESULT);
QED the exception is happening after this point. We have one more line in the function.
RETURN FINAL_RESULT;
An educated guess is that the problem is as Alex mentions - the result is too big for the variable defined in the calling code in SQL Developer (i.e. it is not a CLOB, but a string that is too small for the result).
If this is generated code, it may be a bug with SQL Developer and CLOB functions.
Have you tried doing a SELECT function FROM DUAL instead?
Try this DBMS_OUTPUT.ENABLE(200000);
The easiest fix is to limit the line length to 255 characters by inserting some newlines. See this.

Resources