Oracle SQL TO_CHAR Function return values - sql

I don't understand why these two code results are identically the same? I thought if I have quotes it just concatenate strings. Why not first one is 300.5100? I know second one is 400.5 anyway. Thank you
Select to_char('300.5' + '100') From Dual;
Select to_char(300.5 + 100) From Dual;

To concatenate strings in SQL you have to use ||. The + is only there to add numbers. If you didn't pass '300.5' + '100' you would simply get an error, e.g. the following is invalid SQL:
select '300.5' + '100'
from dual;
But as to_char() expects a number as the input parameter Oracle implicitly converts those strings to numbers and then adds them, just like in the second statement.

concatenation is
'xxx' || 'yyy'
your example allows the literals to be converted to numeric then treated as normal numbers.

Related

Add number + varchar to get string concatenation

How can I add 5596 + 00003 to get 559600003 in SQL Server?
I tried with the following query:
select 5596 + '00003'
But it is giving 5599 and I want this to show 559600003.
You can also use CONCAT():
SELECT CONCAT(5596, '00003')
CONCAT() does not require any explicit conversion.
SQL Server attempts to return the result in the datatype of the first part of the calculation which in your case is a number. It can happily convert the second part of the calculation into a number, and therefore does so.
To obtain the result you want you must convert the first part of the calculation to a string e.g.
select convert(varchar, 5596) + '00003'
Note: convert(varchar,x) uses a default length of 30 which is probably enough for most numbers.
CONCAT(), as in one of the other answers is probably a better solution.
You can use CAST
SELECT CAST(5596 AS varchar) + '00003'; -- return 559600003
Because :
CAST is more easier to read than CONVERT
CAST is ANSI-SQL compliant : it means that the CAST function can be used by many databases
But in case you have a date type CONVERT is more flexible and contains more options than CAST
For more details take a look : https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15

TO_Char number format model in Oracle

I don't understand fully how can I use the to_char function to convert a number to a string with the appropriate format model.
The actual number has this type of format:
Uses comma as decimal separator
Always 5 decimal numbers
The integer numbers can up to 6 (potentially can be infinite, but for now they were never more than 6)
The number can be positive or negative
The number can begin with a 0
I've tried to use the to_char but I am not able to achieve a result that works with all the conditions
Some examples of how the output should be are
0,00235 or 156,45623 or -0,0235 or -156,45623
Keep in mind that you are transforming a number into a string. The number does not have any sense of "," or "." or anything--it is a number.
The trick is to get the TO_CHAR function to convert the internal number to the string representation that you want.
There are a few problems to worry about: getting the radix point (decimal) correct and dealing with padding.
Here is a working example:
SELECT to_char(0.00235,'FM99999999999999990D99999', 'NLS_NUMERIC_CHARACTERS = '',.''') FROM DUAL;
0,00235
SELECT to_char(156.45823,'FM99999999999999990D99999', 'NLS_NUMERIC_CHARACTERS = '',.''') FROM DUAL;
156,45823
SELECT to_char(-0.0235,'FM99999999999999990D99999', 'NLS_NUMERIC_CHARACTERS = '',.''') FROM DUAL;
-0,0235
SELECT to_char(-156.45623,'FM99999999999999990D99999', 'NLS_NUMERIC_CHARACTERS = '',.''') FROM DUAL;
-156,45623
SELECT to_char(123456789.45623,'FM99999999999999990D99999', 'NLS_NUMERIC_CHARACTERS = '',.''') FROM DUAL;
123456789,45623
The relevant parts of the mask:
FMis used to trim leading and trailing blanks that Oracle normally uses to pad out numbers.
D is the radix point, depending on your NLS settings.
NLS_NUMERIC_CHARACTERS ... is an override of your local NLS settings--this might not be necessary if your locale uses a comma for the decimal, but it is a way you can force this behavior in a database with, say, North American settings.
Shamelessly stolen from this post from #Vadzim.
You should be able to get the format you're looking for by using this pattern:
rtrim(to_char(num, 'FM999999999999990.99'), '.')
https://rextester.com/QRSD48676
SELECT rtrim(to_char('0,00235', 'FM999999999999990.99999'), '.') FROM DUAL\\
SELECT rtrim(to_char('156,45623', 'FM999999999999990.99999'), '.') FROM DUAL\\
SELECT rtrim(to_char('-0,0235', 'FM999999999999990.99999'), '.') FROM DUAL\\
SELECT rtrim(to_char('-156,45623', 'FM999999999999990.99999'), '.') FROM DUAL\\
Results:
0.00235
156.45623
-0.0235
-156.45623

REPLACE WITH NVL

select to_number(replace(nvl('-100,000',0),'',','),'999,999,999.99')from dual;
... produces the output: 100000
Now I use the same expression in my procedure with table column:
select to_number(replace(nvl(TABLEA.VOLUME,0),'',','),'999,999,999.99')from TABLEA;
... and get the output: INVALID NUMBER
Column VOLUME in TABLEA is of type VARCHAR2.
Most certainly the contents of column VOLUME are stored as strings without the grouping character ( , ). Thus the strings violate the format in the conversion with to_number.
In addition, the argument order in REPLACE makes no sense.
Finally, you want to swap the calls to NVL and REPLACE.
So - assuming that you want to parse numbers with 2 fractional digits given as strings - use the following:
select to_number ( nvl ( replace (TABLEA.VOLUME, ',', ''), 0), '999999999.99') from TABLEA;
Seems you want to convert the string values to money format.
First, consider replace as you did by switching '' and ',' parameters in the argument order to remove the commas, and making suitable for numeric conversion as :
to_number(replace(nvl(str,0),',','')),
and then apply the money format as :
with tableA as
(
select '-100,000' as volume
from dual
)
select to_char(
to_number(replace(nvl(volume,0),',',''))
,'fm999G999G990D00','NLS_NUMERIC_CHARACTERS = ''.,''')
as Money
from tableA;
MONEY
-----------
-100,000.00
Depending on the currency displaying style the order of dot and comma can be switched as
'NLS_NUMERIC_CHARACTERS = '',.''' to display the money as -100.000,00.
P.S. first of all, you need to make sure all the data for volume column can be casted to number to be able to use to_number() conversion.
Demo

Leading Zeros getting truncated using SUBSTRING

One of the values in the column is
089-002007
I wish to extract all the numbers after '-'
SELECT SUBSTR(EMP_NO,5)
FROM Table_Name
However, I get the output as '2007', the leading zeros got truncated. I have multiple values where it starts with 0 after the '-'.
how can I fix this?
Looks like it's implicitly changing the result to int, hence chopping off leading zeroes. I would suggest CAST-ing the SELECT
SELECT CAST(SUBSTR(EMP_NO,5) AS VARCHAR(10))
FROM Table_Name
What platform and version of DB2?
You should be getting '002007' back given the code you've shown.
The output of SUBSTR() is already varchar.
The DBMS wouldn't change it from varchar to int, unless you've tried to treat it like an int.
select substr('089-002007',5)
from sysibm.sysdummy1
Returns
SUBSTR
002007
On the other hand,
select substr('089-002007',5) + 0
from sysibm.sysdummy1
Returns
Numeric Expression
2,007

TO_NUMBER - returning $

I'm having trouble understanding why the following queries return the given results.
Query 1:
SELECT TO_NUMBER('$1,000.95', '$999,999.999')
FROM dual;
returns 1000.95.
Why doesn't this query return $1000.95 or $1,000.95? Does the TO_NUMBER function remove all formatting (other than .)?
Query 2:
SELECT TO_NUMBER('1,000.95', '$999,999.999')
FROM dual;
returns ORA-01722: invalid number.
I suppose I understand this one a little better - the format mask doesn't match the number format. Is there a way to return a $ in the number (other than using CONCAT or ||)?
The function TO_NUMBER returns a number, the $ character is ASCII and is never going to be represented in a number field. To add a $ character you will need to represent the number as a string.
SELECT TO_NUMBER('$1,000.95', 'L999G999D999') FROM dual;