ORA 06502 Error PL/SQL - sql

I am trying to execute a simple statement and i got an error while executing.
begin
dbms_output.put_line('Addition: '||4+2);
end;
Error:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 2
But when i executed with * operator, it worked fine.
begin
dbms_output.put_line('Addition: '||4*2);
end;
Does anyone know the reason behind it?

It is due the Operator Precedence.
Multiplication has higher precedence than concatenation. So, 'Addition: '||4*2 evaluates to 'Addition: '||8 and to 'Addition: 8'.
Addition has same precedence as concatenation and operators with equal precedence are evaluated from left to right.
So, 'Addition: '||4+2 evaluates to 'Addition: 4' + 2, which subsequently fails as you cannot add number to characters.
In such cases, you should always use brackets to explicitly specify the order of evaluation, like this 'Addition: '|| (4+2)

In my opinion, the actual problems is that this code is relying on implicit data type conversion by the Oracle kernel. Always use explicit data type conversion. For instance:
begin
dbms_output.put_line('Addition: ' || to_char(4+2));
end;
There are many other cases where you will run into unexpected errors due to implicit data type conversion. Like in equal joining a varchar with number. As long as the varchar contains only numeric values, it works fine (although maybe slow due to index not being used). But as soon as you insert one row with non numeric data, you will run into an error when that row is being hit. Making the data type conversion explicit ensures that Oracle does not by accident chose the wrong side of an equal join to convert.

Related

Why does implicit conversion from some numeric values work but not others?

This is something that has only just started happening today for me.
If I run this:
select '185.37' * 2.00
select '0.16' * 2.00
The first query returns this error:
Arithmetic overflow error converting varchar to data type numeric.
Where as the second query returns 0.32 as expected.
This is on SQL Server 15.0.2080.9.
I know I can fix the issue by casting to decimal or numeric, but why does the error only occur for the higher numbers? And why has this only started occurring today? This query has been used as part of an ETL that we've been using without changing anything for the past few years.
It tries to convert your string to a numeric(3,2) because that's the type on the right of the multiplication1. If you can force your value to be a larger numeric type:
select '185.37' * (102.00 - 100.00)
Then it works fine (produces 370.74) because it'll now attempt to convert it to a numeric(5,2).
Rather than doing it by a trick, however, I'd pick an appropriate numeric type for this and explicitly perform the required conversion, to better document what you want to occur:
select CONVERT(numeric(5,2),'185.37') * 2.00
1And it has a higher precedence.
EDIT (by Gordon Linoff):
SQL Server's use of type precedence for this purpose is explicitly stated in the documentation:
For comparison operators or other expressions, the resulting data type will depend on the rules of data type precedence.
There might be just a little confusion because the documentation is not clear that the scale and precision of numerics is explicitly part of the type (that is, what gets converted is numeric(3, 2) rather than numeric(?, ?) with appropriate scale and precision).
For below mentioned SQL Left side is varchar datatype and right side is a numeric datatype numeric(3,2) .
select '185.37' * 2.00
After implicit conversion from varchar to numeric, result data type will be numeric(3,2) but actual result 370.74 need a datatype of numeric(5,2) so this expression fails with overflow error. you can see the datatype of these in below sample code.
select 2.00 as colDatatype,185.37 as colDatatype2, 370.74 as colDatatype3 into #tempdata
SELECT * FROM tempdb.INFORMATION_SCHEMA.columns WHERE table_name like'#tempdata%';
In such cases explicitly cast the expression to desired out datatype and not merely
depend on implicit conversion of data types. You can refer the Datatype conversion chart on the website but here result data type after implicit conversion is not know.
Microsoft link

ORA-01722 invalid number on different numbers?

I have a condition in a query:
ABS ( FIB.QUANT1 ) = ( OI.KLINE * :intv1000 ) / 1000.000000
when I run the query with intv1000 = 1000000 - query runs ok.
when I run the query with intv1000 = 1000 I get ORA-01722 (not immediately, after about 5-6 seconds).
Any Idea why ?
QUANT1 - NUMBER(16,2)
KLINE - NUMBER(38)
The condition is self generated from the application, So I can't really change it.
Thank you
The ORA-01722 is an invalid number error.
You would get this error when a non-number -- typically a string -- has to be converted to a number. For example here.
This conversion can occur in many different ways although the three most common are:
to_number()
cast()
implicit conversion
The expression you have highlighted may or may not have anything to do with where the error actually occurs. What it is saying is that:
When :intv1000 = 1000000 then the row(s) with the problem data are filtered out.
When intv1000 = 1000 then the row(s) with the problem data are being processed.
Arrggh. This is very hard to determine. I would suggest starting by looking at the query and finding all explicit conversions to see if they are a problem.
If you find no back data, then you need to resort to looking at all comparisons (including joins), arithmetic expressions, and function calls to find the problem.
In general, I strongly recommend avoiding implicit conversion. Use explicit conversion to avoid such problems! Note: I do make an exception for conversion to strings with string functions and operators. These are usually pretty safe.

SQL Server: +(unary) operator on non-numeric Strings

I am surprised! This statement below is valid in SQL SERVER:
SELECT +'ABCDEF'
Has SQL Server defined + as a Unary operator for string types?
Here is my own answer to this question (Please also see the update at the end):
No, there isn't such unary operator defined on the String expressions. It is possible that this is a bug.
Explanation:
The given statement is valid and it generates the below result:
(No column name)
----------------
ABCDEF
(1 row(s) affected)
which is equivalent to doing the SELECT statement without using the + sign:
SELECT 'ABCDEF'
Being compiled without giving any errors, in fact being executed successfully, gives the impression that + is operating as a Unary operation on the given string. However, in the official T-SQL documentation, there is no mentioning of such an operator. In fact, in the section entitled "String Operators", + appears in two String operations which are + (String Concatenation) and += (String Concatenation); but neither is a Unary operation. Also, in the section entitled "Unary Operators", three operators have been introduced, only one of them being the + (Positive) operator. However, for this only one that seems to be relevant, it soon becomes clear that this operator, too, has nothing to do with non-numeric string values as the explanation for + (Positive) operator explicitly states that this operator is applicable only for numeric values: "Returns the value of a numeric expression (a unary operator)".
Perhaps, this operator is there to successfully accept those string values that are successfully evaluated as numbers such as the one that has been used here:
SELECT +'12345'+1
When the above statement is executed, it generates a number in the output which is the sum of both the given string evaluated as a number and the numberic value added to it, which is 1 here but it could obviously be any other amount:
(No column name)
----------------
12346
(1 row(s) affected)
However, I doubt this explanation is the correct as it raises to below questions:
Firstly, if we accept that this explanation is true, then we can conclude that expressions such +'12345' are evaluated to numbers. If so, then why is it that these numbers can appear in the string related functions such as DATALENGTH, LEN, etc. You could see a statement such as this:
SELECT DATALENGTH(+'12345')
is quite valid and it results the below:
(No column name)
----------------
5
(1 row(s) affected)
which means +'12345' is being evaluated as a string not a number. How this can be explained?
Secondly, while similar statements with - operator, such as this:
`SELECT -'ABCDE'`
or even this:
`SELECT -'12345'`
generate the below error:
Invalid operator for data type. Operator equals minus, type equals varchar.
Why, shouldn't it generate an error for similar cases when + operator has been wrongly used with a non-numeric string value?
So, these two questions prevent me from accepting the explanation that this is the same + (unary) operator that has been introduced in the documentation for numeric values. As there is no other mentioning of it anywhere else, it could be that it is deliberately added to the language. May be a bug.
The problem looks to be more severe when we see no error is generated for statements such as this one either:
SELECT ++++++++'ABCDE'
I do not know if there are any other programming languages out there which accept these sort of statements. But if there are, it would be nice to know for what purpose(s) they use a + (unary) operator applied to a string. I cannot imagine any usage!
UPDATE
Here it says this has been a bug in earlier versions but it won't be fixed because of backward compatibility:
After some investigation, this behavior is by design since + is an unary operator. So the parser accepts "+ , and the '+' is simply ignored in this case.
Changing this behavior has lot of backward compatibility implications so we don't intend to change it & the fix will introduce unnecessary changes for application code.

Stop concat removing leading 0

Hoping someone can help.
I am attempting to add a ||'m' to my query but when I add the concat it removes the leading zero.
With out the ||'m' I get this result:
0.00
With the concat I get this result for example:
.0m
edit:
Here is the query:
round(MAX(city_longitude),1) - round(MIN(city_longitude),1)||'m'
Cheers
Try wrapping the whole ROUND statement in a TO_CHAR giving it a format mask.
TO_CHAR(round(MAX(city_longitude),1) - round(MIN(city_longitude),1), '0.00')||'m'
This way you effectively concatenate a string with a string whereas you are currently concatenating a numeric with a string forcing an implicit conversion.
Implicit conversions are usually frowned upon as they can lead to unexpected results.
Oracle says:
Oracle recommends that you specify explicit conversions, rather than
rely on implicit or automatic conversions, for these reasons:
• SQL statements are easier to understand when you use explicit
datatype conversion functions.
• Implicit datatype conversion can have a negative impact on
performance, especially if the datatype of a column value is converted
to that of a constant rather than the other way around.
• Implicit conversion depends on the context in which it occurs and
may not work the same way in every case. For example, implicit
conversion from a datetime value to a VARCHAR2 value may return an
unexpected year depending on the value of the NLS_DATE_FORMAT
parameter.
• Algorithms for implicit conversion are subject to change across
software releases and among Oracle products. Behavior of explicit
conversions is more predictable.
Number formats are here:
http://www.oradev.com/oracle_number_format.jsp
Hope it helps...

ORA-01438: value larger than specified precision allows for this column

We get sometimes the following error from our partner's database:
<i>ORA-01438: value larger than specified precision allows for this column</i>
The full response looks like the following:
<?xml version="1.0" encoding="windows-1251"?>
<response>
<status_code></status_code>
<error_text>ORA-01438: value larger than specified precision allows for this column ORA-06512: at "UMAIN.PAY_NET_V1_PKG", line 176 ORA-06512: at line 1</error_text>
<pay_id>5592988</pay_id>
<time_stamp></time_stamp>
</response>
What can be the cause for this error?
The number you are trying to store is too big for the field. Look at the SCALE and PRECISION. The difference between the two is the number of digits ahead of the decimal place that you can store.
select cast (10 as number(1,2)) from dual
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
select cast (15.33 as number(3,2)) from dual
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
Anything at the lower end gets truncated (silently)
select cast (5.33333333 as number(3,2)) from dual;
CAST(5.33333333ASNUMBER(3,2))
-----------------------------
5.33
The error seems not to be one of a character field, but more of a numeric one. (If it were a string problem like WW mentioned, you'd get a 'value too big' or something similar.) Probably you are using more digits than are allowed, e.g. 1,000000001 in a column defined as number (10,2).
Look at the source code as WW mentioned to figure out what column may be causing the problem. Then check the data if possible that is being used there.
Further to previous answers, you should note that a column defined as VARCHARS(10) will store 10 bytes, not 10 characters unless you define it as VARCHAR2(10 CHAR)
[The OP's question seems to be number related... this is just in case anyone else has a similar issue]
This indicates you are trying to put something too big into a column. For example, you have a VARCHAR2(10) column and you are putting in 11 characters. Same thing with number.
This is happening at line 176 of package UMAIN. You would need to go and have a look at that to see what it is up to. Hopefully you can look it up in your source control (or from user_source). Later versions of Oracle report this error better, telling you which column and what value.
FYI:
Numeric field size violations will give
ORA-01438: value larger than specified precision allowed for this column
VARCHAR2 field length violations will give
ORA-12899: value too large for column...
Oracle makes a distinction between the data types of the column based on the error code and message.
One issue I've had, and it was horribly tricky, was that the OCI call to describe a column attributes behaves diffrently depending on Oracle versions. Describing a simple NUMBER column created without any prec or scale returns differenlty on 9i, 1Og and 11g
From http://ora-01438.ora-code.com/ (the definitive resource outside of Oracle Support):
ORA-01438: value larger than specified precision allowed for this column
Cause: When inserting or updating records, a numeric value was entered that exceeded the precision defined for the column.
Action: Enter a value that complies with the numeric column's precision, or use the MODIFY option with the ALTER TABLE command to expand the precision.
http://ora-06512.ora-code.com/:
ORA-06512: at stringline string
Cause: Backtrace message as the stack is unwound by unhandled exceptions.
Action: Fix the problem causing the exception or write an exception handler for this condition. Or you may need to contact your application administrator or DBA.
It might be a good practice to define variables like below:
v_departmentid departments.department_id%TYPE;
NOT like below:
v_departmentid NUMBER(4)
It is also possible to get this error code, if you are using PHP and bound integer variables (oci_bind_by_name with SQLT_INT).
If you try to insert NULL via the bound variable, then you get this error or sometimes the value 2 is inserted (which is even more worse).
To solve this issue, you must bind the variable as string (SQLT_CHR) with fixed length instead. Before inserting NULL must be converted into an empty string (equals to NULL in Oracle) and all other integer values must be converted into its string representation.