Sorting results on Oracle as ASCII - oracle

I'm doing a query that returns a VARCHAR2 and some other fields. I'm ordering my results by this VARCHAR2 and having some problems related to the linguistic sort, as I discovered on Oracle documentation. For example:
SELECT id, my_varchar2 from my_table ORDER BY MY_VARCHAR2;
Will return:
ID MY_VARCHAR2
------ -----------
3648 A
3649 B
6504 C
7317 D
3647 0
I need it to return the string "0" as the first element on this sequence, as it would be comparing ASCII values. The string can have more than one character so I can't use the ascii function as it ignores any characters except for the first one.
What's the best way to do this?

For that case, you should be able to just order by the BINARY value of your characters;
SELECT id, my_varchar2
FROM my_table
ORDER BY NLSSORT(MY_VARCHAR2, 'NLS_SORT = BINARY')
SQLFiddle here.

Related

Oracle APEX apex_string.split order by

Does apex_string.split always guarantee that the order of the rows returned is the order of the characters of the string ?
Can I rely on the rownum to always correspond to 1 for the first character of the split string ?
or do I need to add a order by rownum ?
What is the method to get the rows in the same order of the characters of the string ?
My requirement is to insert the rows returned by apex_string.split in the same order as the characters of the string.
I am currently executing the below, will this maintain the character order ?
select t.column_value value, rownum seq
from table(apex_string.split('test','')) t
bulk collect into ins_arr;
for i in ins_arr.first..ins_arr.last
loop
/* execute insert statement */
insert into table (seq, value )
values (ins_arr.seq,ins_arr.value);
end loop
The insert should result in
seq
value
1
t
2
e
3
s
4
t
Thank you in advance,
I don't think it's guaranteed, becuase if it was, it would be in the documentation. But I think you can accomplish what you want by changing your routine. (Note, I have not verified this.)
insert into table (seq, value)
select t.column_value value,
row_number() over (order by t.column_value)
from table(apex_string.split('test','')) t
I think you can do the same with rownum, but I'm never 100% sure what order the rownum and the order by happen in.

ORACLE SUBQUERY NOT WORKING IN (IN CONDITION)

I need help
i have records 123,456,789 in rows when i am execute like
this one is working
select * from table1 where num1 in('123','456')
but when i am execute
select * from table1 where num1 in(select value from table2)
no resultset found - why?
Check the DataType varchare2 or Number
try
select * from table1 where num1 in(select to_char(value) from table2)
Storing comma separated values could be the cause of problem.
You can try using regexp_substr to split comma.
First and foremost, an important thing to remember: Do not store numbers in character datatypes. Use NUMBER or INTEGER. Secondly, always prefer VARCHAR2 datatype over CHAR if you wish to store characters > 1.
You said in one of your comments that num1 column is of type char(4). The problem with CHAR datatype is that If your string is 3 characters wide, it stores the record by adding extra 1 space character to make it 4 characters. VARCHAR2 only stores as many characters as you pass while inserting/updating and are not blank padded.
To verify that you may run select length(any_char_col) from t;
Coming to your problem, the IN condition is never satisfied because what's actually being compared is
WHERE 'abc ' = 'abc' - Note the extra space in left side operator.
To fix this, one good option is to pad the right side expression with as many spaces as required to do the right comparison.The function RPAD( string1, padded_length [, pad_string] ) could be used for this purpose.So, your query should look something like this.
select * from table1 where num1 IN (select rpad(value,4) from table2);
This will likely utilise an index on the column num1 if it exists.
The other one is to use RTRIM on LHS, which is only useful if there's a function based index on RTRIM(num1)
select * from table1 where RTRIM(num1) in(select value from table2);
So, the takeaway from all these examples is always use NUMBER types to store numbers and prefer VARCHAR2 over CHAR for strings.
See Demo to fully understand what's happening.
EDIT : It seems You are storing comma separated numbers.You could do something like this.
SELECT *
FROM table1 t1
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE ',' ||t2.value|| ',' LIKE '%,' || rtrim(t1.num1) || ',%'
);
See Demo2
Storing comma separated values are bound to cause problems, better change it.
Let me tell you first,
You have stored values in table2 which is comma seperated.
So, how could you match your data with table1 and table2.
Its not Possible.
That's why you did not get any values in result set.
I found the Solution using string array
SELECT T.* FROM TABLE1 T,
(SELECT TRIM(VALUE)AS VAL FROM TABLE2)TABLE2
WHERE
TRIM(NUM1) IN (SELECT COLUMN_VALUE FROM TABLE(FUNC_GETSTRING_ARRAY(TABLE2.VAL)))
thanks

Oracle change any string to a number

I'm having this problem we have this database witch IDS are stored in varchar2 type this ids contains Letters.
Is there any solution to convert a string to a number no matter what the value if this string.
for example there is : SELCT ASCII('t') FROM DUAL; result : 116.
but ASCII accept only one CHAR Hope you get the idea. sorry for my english
use oracle translate method to replace A-Z or a-z characters with numbers.
then use to_number to get number from it.
select translate('A1B2C3', 'ABC', '456') from dual; --result '415263'
select to_number(translate('A1B2C3', 'ABC', '456')) from dual; --result 415263
translate function documentation
The Oracle/PLSQL TRANSLATE function replaces a sequence of characters in a string with another set of characters. However, it replaces a single character at a time.
For example, it will replace the 1st character in the string_to_replace with the 1st character in the replacement_string. Then it will replace the 2nd character in the string_to_replace with the 2nd character in the replacement_string, and so on.
EDIT: After discussing further with the OP, it turns out he needed a function (in the mathematical sense) from short strings to integers. Such a function is ORA_HASH. The OP decided that ORA_HASH is likely what is needed for his project.
https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions112.htm#SQLRF06313
The solution below is kept for historical perspective.
You could use the analytic function DENSE_RANK to assign numbers to strings.
For example:
with
employees ( id, first_name, last_name ) as (
select 'ABC', 'Jane', 'Smith' from dual union all
select 'ABD', 'Jane', 'Dryer' from dual union all
select 'XYZ', 'Mike', 'Lopez' from dual
)
-- End of simulated inputs (for testing purposes only).
-- Solution (SQL query) begins below this line.
select id, dense_rank() over (order by id) as num_id, first_name, last_name
from employees
;
ID NUM_ID FIRST_NAME LAST_NAME
--- ------ ---------- ---------
ABC 1 Jane Smith
ABD 2 Jane Dryer
XYZ 3 Mike Lopez

convert varchar2 value to decimal in oracle VIEW

i need to select a varchar2 value '>45%' (from table ABC, column name XYZ) as decimal, like select statement should return 0.45.
How to achieve this? i am not getting how to do this with regular_expression, or by Trimming and converting to number.
This should do it. Removes characters > and % and devide the result by 100. the character string is converted automatically to number
select regexp_replace('>45%', '\>|\%', '') / 100 from dual
Another approach: Remove all non-number characters:
select regexp_replace('>45%', '[^0-9]', '')/100 from dual

oracle truncates the value after saving an id with precisions?

I have a table. it has a column with datatype NUMBER(38,20). it is an id column. out application generates the id. i am trying to insert record with an id value of 105.00010. but it inserts only 105.0001. May i know the reason why it is truncating one value(0). it porperly inserts records from 105.00001 to 105.00009. while inserting 105.00010 it is truncating. Please help me.
column size is **NUMBER(38,20)**
Thanks!
See the following test case:
WITH data_values
AS (SELECT 105.0001 AS test_val FROM dual
UNION ALL
SELECT 105.00010 AS test_val FROM dual)
SELECT test_val,
TO_NUMBER(test_val, '999.99999') AS NUM,
TO_CHAR(test_val, '999.99999') AS STR
FROM data_values;
Results in:
TEST_VAL NUM STR
105.0001 105.0001 105.00010
105.0001 105.0001 105.00010
The value after the final non zero digit is irrelevent to Oracle. Both your numbers are equivalent.
The rightmost zeros after the decimal are insignificant, so the value is not truncated, it is still the same value.
If you need it to stay the same you may need to treat the value as a varchar2.

Resources