Oracle Invalid number ORA-01722: invalid number 01722. 00000 - "invalid number" - oracle

i am trying to multiply string value which is 33.000000 but i am getting error ORA-01722.
Can you please advise how to proper convert/cast this field in order to multiply?
select c1.name as Model,
p22.value as basisAMT,
p23.value as TotalAMT
MODEL BasisAMT TotalAMT
Auto 0.000000 0.000000
Auto 22.000000 33.000000
Auto 0.000000 0.000000
Auto 0.000000 0.000000
But then i am trying to do
select c1.name as Model,
100 * p22.value as basisAMT,
p23.value as TotalAMT
The error appears.

can you debug code that you cannot see? No? So why do you expect that of others?
It is illogical to do math on a character string. The fact that the characters in the string are all numeric doesn't change the fact that computers treat them as characters, no different than
'my name is fred' * 23
And we don't even know that all the characters are numeric. It could be padded with space characters.
You need to look at the TO_NUMBER() function.

Related

Best data type for hex values in Oracle database

What is the best data type for storing hex values in an Oracle database? With a 33-byte value like this:
0x54906a620d3c1e82c8e812b0f8d1214beafc05c74820c1dd3675b0c38f4a83aa
is there a preferred data type that will:
a) use minimal disk space, and
b) be queryable via that full string?
To store that value, I can use VARCHAR2(132). But does that use 132 bytes on the disk, or 33 bytes?
If it uses 132 bytes on the disk, then what data type could I use to store only 33 bytes? And will that datatype allow me to use the full string in a query, like:
SELECT * FROM TABLE WHERE FIELD = '0x54906a620d3c1e82c8e812b0f8d1214beafc05c74820c1dd3675b0c38f4a83aa'
or would it require me to convert my 132 characters to 33 bytes before using in a SQL query?
if "a8" is a hex value of a single byte, will varchar2 store 1 byte, or will it store 2 bytes (one for the letter 'a' and one for the number 8)?
The latter, if you store it as a string.
You can store as RAW:
These data types are intended for binary data or byte strings.
For example:
create table test (hex_value raw(128));
insert into test (hex_value) values (hextoraw('54906a620d3c1e82c8e812b0f8d1214beafc05c74820c1dd3675b0c38f4a83aa'));
select hex_value, dump(hex_value)
from test
where hex_value = hextoraw('54906a620d3c1e82c8e812b0f8d1214beafc05c74820c1dd3675b0c38f4a83aa');
HEX_VALUE
DUMP(HEX_VALUE)
0x54906A620D3C1E82C8E812B0F8D1214BEAFC05C74820C1DD3675B0C38F4A83AA
Typ=23 Len=32: 84,144,106,98,13,60,30,130,200,232,18,176,248,209,33,75,234,252,5,199,72,32,193,221,54,117,176,195,143,74,131,170
You can see from the dump that it is stored in 32 bytes. (The RAW value is converted implicitly to a string for display, and the 0x is being added by db<>fiddle; other clients won't show that, and might not show RAW values at all.)
You can convert back to a string if you need to, which will then be 64 bytes:
select rawtohex(hex_value), dump(rawtohex(hex_value)) from test;
RAWTOHEX(HEX_VALUE)
DUMP(RAWTOHEX(HEX_VALUE))
54906A620D3C1E82C8E812B0F8D1214BEAFC05C74820C1DD3675B0C38F4A83AA
Typ=1 Len=64: 53,52,57,48,54,65,54,50,48,68,51,67,49,69,56,50,67,56,69,56,49,50,66,48,70,56,68,49,50,49,52,66,69,65,70,67,48,53,67,55,52,56,50,48,67,49,68,68,51,54,55,53,66,48,67,51,56,70,52,65,56,51,65,65
fiddle

Select all characters in a string until a specific character Ruby

So what I want is to get n characters until it hits a specific character.
i have this String :
a='2.452811139617034,42.10874821716908|3.132087902867818,42.028314077306646|-0.07934861041448178,41.647538468746916|-0.07948265046522918,41.64754863599606'
How can I make it to only get to the character | , but without getting that character,
and get it like this:
2.452811139617034,42.10874821716908
You can avoid creating an unnecessary Array (like Array#split) or using a Regex (like Array#gsub) by using.
a = "2.452811139617034,42.10874821716908|3.132087902867818,42.028314077306646|-0.07934861041448178,41.647538468746916|-0.07948265046522918,41.64754863599606"
a[0,a.index('|')]
#=>"2.452811139617034,42.1087482171"
This means select characters at positions 0 up to the index of the first pipe (|). Technically speaking it is start at position 0 and select the length of n where n is the index of the pipe character which works in this case because ruby uses 0 based indexing.
As #CarySwoveland astutely pointed out the string may not contain a pipe in which case my solution would need to change to
#to return entire string
a[0,a.index('|') || a.size]
# or
b = a.index(?|) ? a[0,b] : a
# or to return empty string
a[0,a.index('|').to_i]
# or to return nil
a[0,a.index(?|) || -1]
You can simply do it like this:
a.split('|').first
a[/[^|]+/]
#=> "2.452811139617034,42.10874821716908"
The regular expression simply matches as many characters other than '|' that it can.
I'm always curious as to the performance of various options and so I took the liberty of looping through some of the approaches suggested. I named them as follows:
split_all = a.split('|').first
partition = a.partition('|').first
split_two = a.split('|', 2).first
string_brack_args = a[0,a.index('|')]
string_brack_range = a[0...a.index('|')]
gsub_regex = a.gsub(/\|.*$/, "")
plain_regex = a[/[^|]+/]
The results were as follows (slowest at top):
user system total real
gsub_regex 0.170000 0.000000 0.170000 ( 0.162666)
split_all 0.110000 0.000000 0.110000 ( 0.109498)
split_two 0.040000 0.000000 0.040000 ( 0.041792)
partition 0.040000 0.000000 0.040000 ( 0.037161)
string_brack_range 0.030000 0.000000 0.030000 ( 0.034021)
plain_regex 0.040000 0.000000 0.040000 ( 0.033468)
string_brack_args 0.020000 0.000000 0.020000 ( 0.022455)
That's nearly an eight-fold increase in efficiency between the slowest and fastest. Even some of the little things make a huge difference. Granted, I looped through these 100_000 times, so the difference is pretty small for the one instance, but even something as simple as using using split(str, 2) vs split(str) is well over twice as fast. In fact, the faster half of the approaches listed average 3 times as fast as the slower half.
One approach uses a gsub replacement:
a = "2.452811139617034,42.10874821716908|3.132087902867818,42.028314077306646|-0.07934861041448178,41.647538468746916|-0.07948265046522918,41.64754863599606"
output = a.gsub(/\|.*$/, "")
puts output # 2.452811139617034,42.10874821716908

Format string in Oracle

I'm building a string in oracle, where I get a number from a column and make it a 12 digit number with the LPad function, so the length of it is 12 now.
Example: LPad(nProjectNr,12,'0') and I get 000123856812 (for example).
Now I want to split this string in parts of 3 digit with a "\" as prefix, so that the result will look like this \000\123\856\812.
How can I archive this in a select statement, what function can accomplish this?
Assuming strings of 12 digits, regexp_replace could be a way:
select regexp_replace('000123856812', '(.{3})', '\\\1') from dual
The regexp matches sequences of 3 characters and adds a \ as a prefix
It is much easier to do this using TO_CHAR(number) with the proper format model. Suppose we use \ as the thousands separator.... (alas we can't start a format model with a thousands separator - not allowed in TO_CHAR - so we still need to concatenate a \ to the left):
See also edit below
select 123856812 as n,
'\' || to_char(123856812, 'FM000G000G000G000', 'nls_numeric_characters=.\') as str
from dual
;
N STR
--------- ----------------
123856812 \000\123\856\812
Without the FM format model modifier, TO_CHAR will add a leading space (placeholder for the sign, plus or minus). FM means "shortest possible string representation consistent with the model provided" - that is, in this case, no leading space.
Edit - it just crossed my mind that we can exploit TO_CHAR() even further and not need to concatenate the first \. The thousands separator, G, may not be the first character of the string, but the currency symbol, placeholder L, can!
select 123856812 as n,
to_char(123856812, 'FML000G000G000G000',
'nls_numeric_characters=.\, nls_currency=\') as str
from dual
;
SUBSTR returns a substring of a string passed as the first argument. You can specify where the substring starts and how many characters it should be.
Try
SELECT '\'||SUBSTR('000123856812', 1,3)||'\'||SUBSTR('000123856812', 4,3)||'\'||SUBSTR('000123856812', 7,3)||'\'||SUBSTR('000123856812', 10,3) FROM dual;

Split string with Ruby regex

We have a CSV file. A specific column was to have many entries and those were to be separated with a newline character "\n", which didn't happen. Sample data of the affected column are as follows.
30 units - R135 50 units - R225 80 units - R360
Is there a method to split this into three columns? The number of columns is not fixed. I guess we will have to use many space characters (more than two) to split entries. I need:
data = "that long string"
# Some operation
result = ["30 units - R135", "50 units - R225", "80 units - R360"]
I tried some thing like this. But it didn't work. The result was the same string.
a.split('/(\s){3,}/')
What approach could be taken to split the data?
A statement like
a.split('/(\s){3,}/')
will split the string in a at occurrences of the string /(\s){3,}/, which (unsurprisingly) occurs nowhere in the target string, so it remains instact.
You need to specify a regexp by writing
data = '30 units - R135 50 units - R225 80 units - R360'
result = data.split /\s{3,}/
p result
output
["30 units - R135", "50 units - R225", "80 units - R360"]
the correct regex for this is:
a.split(/\s{3,}/)
a nice place to try out regex expressions:
http://rubular.com/ (you may not need it , but i love it too much so sharing :) )

Oracle Builtin String Character Classes

Does Oracle have built-in string character class constants (digits, letters, alphanum, upper, lower, etc)?
My actual goal is to efficiently return only the digits [0-9] from an existing string.
Unfortunately, we still use Oracle 9, so regular expressions are not an option here.
Examples
The field should contain zero to three letters, 3 or 4 digits, then zero to two letters. I want to extract the digits.
String --> Result
ABC1234YY --> 1234
D456YD --> 456
455PN --> 455
No string constants, but you can do:
select translate
( mystring
, '0'||translate (mystring, 'x0123456789', 'x')
, '0'
)
from mytable;
For example:
select translate
( mystring
, '0'||translate (mystring, 'x0123456789', 'x')
, '0'
)
from
( select 'fdkhsd1237ehjsdf7623A#L:P' as mystring from dual);
TRANSLAT
--------
12377623
If you want to do this often you can wrap it up as a function:
create function only_digits (mystring varchar2) return varchar2
is
begin
return
translate
( mystring
, '0'||translate (mystring, 'x0123456789', 'x')
, '0'
);
end;
/
Then:
SQL> select only_digits ('fdkhsd1237ehjsdf7623A#L:P') from dual;
ONLY_DIGITS('FDKHSD1237EHJSDF7623A#L:P')
-----------------------------------------------------------------
12377623
You can check the list for predefined datatypes on Oracle here, but you are not going to find what are you looking for.
To extract the numbers of an string you can use some combination of these functions:
TO_NUMBER, to convert an string to number.
REPLACE, to remove occurences.
TRANSLATE, to convert chars.
If you provide a more concise example will be easier to give you a detailed solution.
If you are able to use PL/SQL here, another approach is write your own regular expression matcher function. One starting point is Rob Pike's elegant, very tiny regular expression matcher in Chapter 1 of Beautiful Code. One of the exercises for the reader is to add character classes. (You'd first need to translate his 30 lines of C code into PL/SQL.)

Resources