How to compare Hexadecimal values in oracle SQL - sql

I have a column with HEXADECIMAL values and I want to do a comparison with other HEXADECIMAL value like below but I am getting inaccurate results
SELECT vc_vin_vis_start_range FROM ok_dc.gms3_vc_mme_vin_si_detail
WHERE TO_NUMBER(vc_vin_vis_start_range) >= TO_NUMBER('100001');
Is there a way to compare two HEXADECIMAL values in a query.
Any help is appreciated!

Use TO_NUMBER( hex_value, , 'xxxxxxxxxx' ) (where the number of xs is the maximum length of your hexadecimal VARCHAR2 column):
Oracle Setup:
CREATE TABLE ok_dc.gms3_vc_mme_vin_si_detail ( vc_vin_vis_start_range ) AS
SELECT '1' FROM DUAL UNION ALL
SELECT 'FFFFF' FROM DUAL UNION ALL
SELECT '100001' FROM DUAL UNION ALL
SELECT '100002' FROM DUAL UNION ALL
SELECT NULL FROM DUAL;
Query:
SELECT vc_vin_vis_start_range
FROM ok_dc.gms3_vc_mme_vin_si_detail
WHERE TO_NUMBER(vc_vin_vis_start_range, 'xxxxxxxxxx') >= TO_NUMBER('100001', 'xxxxxxxxxx');
Output:
VC_VIN_VIS_START_RANGE
----------------------
100001
100002

Assuming the column vc_vin_vis_start_range does not have null values, then I would do:
SELECT vc_vin_vis_start_range FROM ok_dc.gms3_vc_mme_vin_si_detail
WHERE TO_NUMBER(vc_vin_vis_start_range,
rpad('x', length(vc_vin_vis_start_range) , 'x'))
>= TO_NUMBER('100001', 'xxxxxx');
The rpad() function builds an hex format according to the each value you want to convert.

Related

Find value that is not a number or a predefined string

I have to test a column of a sql table for invalid values and for NULL.
Valid values are: Any number and the string 'n.v.' (with and without the dots and in every possible combination as listed in my sql command)
So far, I've tried this:
select count(*)
from table1
where column1 is null
or not REGEXP_LIKE(column1, '^[0-9,nv,Nv,nV,NV,n.v,N.v,n.V,N.V]+$');
The regular expression also matches the single character values 'n','N','v','V' (with and without a following dot). This shouldn't be the case, because I only want the exact character combinations as written in the sql command to be matched. I guess the problem has to do with using REGEXP_LIKE. Any ideas?
I guess this regexp will work:
NOT REGEXP_LIKE(column1, '^([0-9]+|n\.?v\.?)$', 'i')
Note that , is not a separator, . means any character, \. means the dot character itself and 'i' flag could be used to ignore case instead of hard coding all combinations of upper and lower case characters.
No need to use regexp (performance will increase by large data) - plain old TRANSLATE is good enough for your validation.
Note that the first translate(column1,'x0123456789','x') remove all numeric charcters from the string, so if you end with nullthe string is OK.
The second translate(lower(column1),'x.','x') removes all dots from the lowered string so you expect the result nv.
To avoid cases as n.....v.... you also limit the string length.
select
column1,
case when
translate(column1,'x0123456789','x') is null or /* numeric string */
translate(lower(column1),'x.','x') = 'nv' and length(column1) <= 4 then 'OK'
end as status
from table1
COLUMN1 STATUS
--------- ------
1010101 OK
1012828n
1012828nv
n.....v....
n.V OK
Test data
create table table1 as
select '1010101' column1 from dual union all -- OK numbers
select '1012828n' from dual union all -- invalid
select '1012828nv' from dual union all -- invalid
select 'n.....v....' from dual union all -- invalid
select 'n.V' from dual; -- OK nv
You can use:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR LOWER(column1) IN ('nv', 'n.v', 'nv.', 'n.v.');
Which, for the sample data:
CREATE TABLE table1 (column1) AS
SELECT '12345' FROM DUAL UNION ALL
SELECT 'nv' FROM DUAL UNION ALL
SELECT 'NV' FROM DUAL UNION ALL
SELECT 'nV' FROM DUAL UNION ALL
SELECT 'n.V.' FROM DUAL UNION ALL
SELECT '...................n.V.....................' FROM DUAL UNION ALL
SELECT '..nV' FROM DUAL UNION ALL
SELECT 'n..V' FROM DUAL UNION ALL
SELECT 'nV..' FROM DUAL UNION ALL
SELECT 'xyz' FROM DUAL UNION ALL
SELECT '123nv' FROM DUAL;
Outputs:
COUNT(*)
5
or, if you want any quantity of . then:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR REPLACE(LOWER(column1), '.') = 'nv';
Which outputs:
COUNT(*)
9
db<>fiddle here

How to convert quarter in Oracle SQL

I am currently working on Oracle SQL and have the following string values:
'1/2019', '2/2019', '3/2019', '4/2019'.
This values should be transformed like the following:
'1/2019' should be convert to '01.01.2019'
'2/2019' should be convert to '01.04.2019'
'3/2019' should be convert to '01.07.2019'
'4/2019' should be convert to '01.10.2019'
Is there a way in Oracle SQL to implement this transformation or is it necessary to write my own implementation (for example with SQL Case)?
I may take a bit of string manipulation, but this should solve your question:
WITH test_data (date_string) AS
(
select '1/2019' from dual union all
select '2/2019' from dual union all
select '3/2019' from dual union all
select '4/2019' from dual
)
SELECT ADD_MONTHS(TO_DATE('01/01/'||SUBSTR(td.date_string, -4), 'MM/DD/YYYY'), (SUBSTR(td.date_string, 1, 1)-1)*3)
FROM test_data td;
with
test_inputs (str) as (
select '1/2019' from dual union all
select '2/2019' from dual union all
select '3/2019' from dual union all
select '4/2019' from dual
)
select str, add_months(to_date(str, 'mm/yyyy'), 2 * substr(str, 1, 1) - 2) as qtr
from test_inputs
;
STR QTR
------ -----------
1/2019 01-JAN-2019
2/2019 01-APR-2019
3/2019 01-JUL-2019
4/2019 01-OCT-2019
The with clause is for testing only; what you are looking for is the formula in the main select.
I left the result in date data type (displayed here using my current session's settings). If you need to convert back to string in the specific format you requested, you can wrap within to_char(..., 'dd.mm.yyyy').

ORA-01722: invalid number rows start with comma transfer VARCHAR2 TO_NUMBER

I have following source data in VARCHAR2 format
,00100000004749745
,100000001490116
,125
,200000002980232
,25
,439999997615814
,5
0
1
1,10000002384186
1,5
100
2,1800000667572
3
3,29999995231628
96
999
What is the formula to transfer it to NUMBER?
With the following
INSERT INTO table_b.column_b
SELECT
TO_NUMBER (column_a,'9999999999D9999999999999999999999',
'nls_numeric_characters= ''.,''') as my_numbers
FROM table_a.column_a;
I get an error
ORA-01722: invalid number error message.
I assume that it is because rows starting with comma e.g (,125).
In destination table I need in number format the data like this
0,00100000004749745
0,100000001490116
0,125
0,200000002980232
0,25
0,439999997615814
0,5
0
1
...
Also tried to put zero '0' in front of comma and them change it to number with
Select
column_a,
TO_NUMBER (column_a,'9999D9999999999999999999999',
'nls_numeric_characters= ''.,''') as my_number
from
(SELECT DISTINCT
'0'|| column_a
FROM table_a.column_a
WHERE column_a LIKE (',125')
);
but the result was
0,125 125
As Vasyl stated, your nls_numeric_characters needs to be adjusted. The query below demonstrates how to convert the string to a number.
WITH
my_numbers (column_a)
AS
(SELECT ',00100000004749745' FROM DUAL
UNION ALL
SELECT ',100000001490116' FROM DUAL
UNION ALL
SELECT ',125' FROM DUAL
UNION ALL
SELECT ',200000002980232' FROM DUAL
UNION ALL
SELECT ',25' FROM DUAL
UNION ALL
SELECT ',439999997615814' FROM DUAL
UNION ALL
SELECT ',5' FROM DUAL
UNION ALL
SELECT '0' FROM DUAL
UNION ALL
SELECT '1' FROM DUAL
UNION ALL
SELECT '1,10000002384186' FROM DUAL
UNION ALL
SELECT '1,5' FROM DUAL
UNION ALL
SELECT '100' FROM DUAL
UNION ALL
SELECT '2,1800000667572' FROM DUAL
UNION ALL
SELECT '3' FROM DUAL
UNION ALL
SELECT '3,29999995231628' FROM DUAL
UNION ALL
SELECT '96' FROM DUAL
UNION ALL
SELECT '999' FROM DUAL)
SELECT n.column_a,
TO_NUMBER (n.column_a,
'9999999999D9999999999999999999999999999',
'nls_numeric_characters= '', ''') AS column_a_as_number
FROM my_numbers n;
Looks like you use wrong nls_numeric_characters values. Try to replace 'nls_numeric_characters=''.,''' with 'nls_numeric_characters='', '''
Explanation: Your nls_numeric_characters defined . as a decimal delimiter and , as a group delimiter, but, according to your example, you assume that the decimal delimiter is ,

How to apply padding on the Decimal Values in Oracle?

I need help on applying padding on the Decimal values in Oracle.
E.g.:
-36693.76 should be displayed as -000036693.76
367.2 should be displayed as +000000367.20
Padding should be (9,2) and sign also should be displayed.
You can use to_char() with the appropriate format mask:
TO_CHAR(the_column,'S000000000.00')
The S indicates the position of the sign. The 0 indicates to display a 0 if no value is available for that digit (a 9 would display a blank)
The following:
with sample_data(the_column) as (
select 367.2 from dual
union all
select -36693.76 from dual
union all
select 1.234 from dual
union all
select 1.236 from dual
)
select TO_CHAR(the_column,'S000000000.00') as the_column
from sample_data;
returns:
THE_COLUMN
-------------
+000000367.20
-000036693.76
+000000001.23
+000000001.24
Note how 1.234 got rounded to 1.23 and 1.236 to 1.24
Here's your query.
with cte(num) AS(
select 367.2 from dual
union all
select -36693.76 from dual
)
select case when num < 0 then concat('-', TO_CHAR(num*-1,'000000000.00')) else concat('+', TO_CHAR(num,'000000000.00')) end
from cte
result:

In SQL sort by Alphabets first then by Numbers

In H2 Database when i have applied order by on varchar column Numbers are coming first then Alphabets. But need to come Alphabets first then Numbers.
I have tried with
ORDER BY IF(name RLIKE '^[a-z]', 1, 2), name
but getting error like If condition is not available in H2.
My Column Data is Like
A
1-A
3
M
2-B
5
B-2
it should come like
A
B-2
M
1-A
2-B
3
5
try this out
SELECT MYCOLUMN FROM MYTABLE ORDER BY REGEXP_REPLACE (MYCOLUMN,'(*)(\d)(*)','}\2') , MYCOLUMN
One thing can be done is by altering the ASCII in order by clause.
WITH tab
AS (SELECT 'A' col FROM DUAL
UNION ALL
SELECT '1-A' FROM DUAL
UNION ALL
SELECT '3' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT '2-B' FROM DUAL
UNION ALL
SELECT '5' FROM DUAL
UNION ALL
SELECT 'B-2' FROM DUAL)
SELECT col
FROM tab
ORDER BY CASE WHEN SUBSTR (col, 1, 1) < CHR (58) THEN CHR (177) || col ELSE col END;
I have Used CHR(58) as ASCII value of numbers end at 57. and CHR(177) is used as this is the maximum in the ASCII table.
FYR : ASCII table
Given the example dataset, I'm not sure if you need further logic than this- so I'll refrain from making further assumptions:
DECLARE #temp TABLE (myval char(3))
INSERT INTO #temp VALUES
('A'), ('1-A'), ('3'), ('M'), ('2-B'), ('5'), ('B-2')
SELECT myval
FROM #temp
ORDER BY CASE WHEN LEFT(myval, 1) LIKE '[a-Z]'
THEN 1
ELSE 2
END
,LEFT(myval, 1)
Gives output:
myval
A
B-2
M
1-A
2-B
3
5