formatting a number to a display string - oracle

Converting a number to a string for example 20000000.00 like this 20 000 000.00 with gap. Please help me

One option is to use to_char function with nls_numeric_characters set to a dot (decimal point) and space (group separator):
SQL> with test (col) as
2 (select 20000000.00 from dual union all
3 select 12345.324 from dual)
4 select to_char(col, '999G999G999G990D00', 'nls_numeric_characters=''. ''') result
5 from test;
RESULT
-------------------
20 000 000.00
12 345.32
SQL>

Related

Need to remove only character which are at the end

Need to remove only characters at the end.
2014JP34343DD
2013GH43422
Output:
2014JP34343
2013GH43422
Tried regexp fuctions and even simple substr and instr function but not able to remove it.
regexp_replace seems to be a simple option:
SQL> with test (col) as
2 (select '2014JP34343DD' from dual union all
3 select '2013GH43422' from dual
4 )
5 select col,
6 regexp_replace(col, '[[:alpha:]]+$') result
7 from test;
COL RESULT
------------- -------------
2014JP34343DD 2014JP34343
2013GH43422 2013GH43422
SQL>

Order and filter follow different criteria in Oracle?

I'm having a problem while trying to apply a filter in an Oracle (12.2.0.1.0) query.
When I query for the values of a column in a table using order by that same column, I get
75A0000000
7597953181
7597953182
But then, when I try to filter the rows with the column between the first and the last value I'm not getting results at all.
This works perfectly fine if the column has only numeric values, but it gets it all wrong when there is some alphabetic value in the middle.
It seems like Oracle is following the criteria A<0 when ordering a result but A>0 when filtering that result.
This can be reproduced using this query:
select * from (
WITH DATA AS
(SELECT '1, A, 2' str FROM dual)
SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM DATA
CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0)
where str>='1' and str<='A'
order by str
The result of this query is
A
1
2
that should mean A is less than 1, but the filter applied to make it return some values is just the opposite : str values greater or equal than 1 and less or equal than A.
Anybody knows why? Thanks in advance.
To me, it looks as if it is about binary or linguistic sort.
Sample data:
SQL> select * from test;
C
-
1
A
2
Sort by col, as is:
SQL> select col, ascii(col)
2 from test
3 order by col;
C ASCII(COL)
- ----------
A 65
1 49
2 50
Or, sort by col's ASCII code:
SQL> select col, ascii(col)
2 from test
3 order by ascii(col);
C ASCII(COL)
- ----------
1 49
2 50
A 65
Explicitly stating binary or linguistic sort:
SQL> select col
2 from test
3 order by nlssort(col, 'nls_sort=binary'); --> binary
C
-
1
2
A
SQL> select col
2 from test
3 order by nlssort(col, 'nls_sort=croatian'); --> linguistic
C
-
A
1
2
SQL>
Or, alter session and set nls_sort you want:
SQL> alter session set nls_sort='binary';
Session altered.
SQL> select * From test order by col;
C
-
1
2
A
SQL>
If you get unexpected result, check what's nls_sort set in your session:
SQL> select * from nls_session_parameters where parameter = 'NLS_SORT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT BINARY
SQL>
Using your query:
SQL> select * from (
2 WITH DATA AS
3 (SELECT '1, A, 2' str FROM dual)
4 SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
5 FROM DATA
6 CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0)
7 where str>='1' and str<='A'
8 order by nlssort(str, 'nls_sort=binary'); --> this
STR
-------
1
2
A
SQL>

Insert Birthdate with only YY format for period before 2000 Oracle DB

I have afile where i recieve Birthdates and insert them into my Database.
the format is like the following
03-JUN-52
I use the following script to insert the date
update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-YY');
and i also used
update data."PersonBDates" set BIRTHDATE = to_date('13-SEP-47', 'DD-MON-RR');
but when i check if find it 2074 not 1947.
How to insert this date into my oracle database?
Generally speaking, RR should work, but - not in all cases. You'll have to fix data first because RR will return different values:
for years from 00 to 49 you'll get this century, 20xx, while
50 to 99 will return previous century, 19xx
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> select
2 to_date('03-07-52', 'dd-mm-rr') rr1,
3 to_date('03-07-52', 'dd-mm-yy') yy1 ,
4 --
5 to_date('03-07-47', 'dd-mm-rr') rr2,
6 to_date('03-07-47', 'dd-mm-yy') yy2
7 from dual;
RR1 YY1 RR2 YY2
---------- ---------- ---------- ----------
03.07.1952 03.07.2052 03.07.2047 03.07.2047
SQL>
As you can see, both RR and YY format mask for year 47 return 2047.
What to do? Concatenate 19 to all years, e.g.
SQL> with test (col) as
2 (select '03-07-52' from dual union all
3 select '03-07-47' from dual
4 )
5 select col,
6 to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr') result
7 ---------------- ---------------
8 -- this is "03-07-" "19" the last 2 digits
9 --
10 from test;
COL RESULT
-------- ----------
03-07-52 03.07.1952
03-07-47 03.07.1947
SQL>
[EDIT]
If your current inserting script works OK - which I doubt, regarding error code you mentioned in a comment:
ORA-01858: a non-numeric character was found where a numeric was expected
which means that not all input data have the same, expected & correct format of DD-MON-YY, then a simple way to fix birthdates might be this:
subtract 100 years from all dates whose year is larger than 2000
Here's how:
SQL> create table test (birthdate date);
Table created.
SQL> insert into test
2 select to_date('03-07-52', 'dd-mm-rr') from dual union all
3 select to_date('03-07-47', 'dd-mm-rr') from dual;
2 rows created.
SQL> select * from test;
BIRTHDATE
----------
03.07.1952
03.07.2047
SQL> update test set
2 birthdate = add_months(birthdate, -100 * 12)
3 where extract (year from birthdate) > 2000;
1 row updated.
SQL> select * from test;
BIRTHDATE
----------
03.07.1952
03.07.1947
SQL>
You can modify that, of course, if there's someone who actually was born in 2000 or later.
As of error you got (ORA-01858), well, fixing it depends on how exactly you're entering those values into a table.
if it was a SQL*Loader, invalid values would be rejected and stored into the .bad file and you could fix them and reprocess them later
if it was using an external tables, you could use a where clause and omit invalid rows; for example, use regexp_like
Or, your best option is to make sure that all input values are valid dates. Then any option you choose (I mentioned previously) would work without ORA-xxxxx errors.
Alternate way of concatenating 19 to all years, as Littlefoot suggested.
to_date(regexp_replace('13-SEP-47', '([0-9]+$)', '19\1'), 'DD-MON-YYYY')
I would suggest to implement the solution where 01 is not considered as 1901 but 2001 or something similar (I assume that birthday year is not 1901 for any person in your system).
Case when substr(col, -2) < to_char(sysdate,'YY')
then to_date(col, 'DD-MON-YY')
else to_date(substr(col, 1, 6) || '19' || substr(col, -2), 'dd-mm-rrrr'
End
Cheers!!

How to sort texts with '_' in Oracle exactly like EXCEL?

In Excel When I sort the texts in ascending order, results shows as below. Text with the underscore character precedes the others. And in Excel cell, when I type in ="_" < "A", then "True" shows as expected.
C10_
C10A
C20_
C20A
But, In Oracle, when I sort in ascending order, results shows as below.
(I guess, Oracle treats '_' < 'A' False)
C10A
C10_
C20A
C20_
How can I make Oracle sort the list exactly as Excel does? I have changed ASC to DESC, but the result was not what I expect.
My sorting code is as below,
WITH DATAA AS (
SELECT *
FROM
(
SELECT 'C10_'rr FROM DUAL
UNION
SELECT 'C10A' rr FROM DUAL
UNION
SELECT 'C20_' rr FROM DUAL
UNION
SELECT 'C20A' rr FROM DUAL
)
)
SELECT *
FROM DATAA
ORDER BY rr ASC;
You can achieve this by altering the sorting method using NLS_SORT as following:
According to ORACLE Documentation:
NLS_SORT specifies the type of sort for character data. It overrides
the default value that is derived from NLS_LANGUAGE.
NLS_SORT contains either of the following values:
NLS_SORT = BINARY | sort_name
BINARY specifies a binary sort. sort_name specifies a linguistic sort
sequence.
Here is how you can achieve the result.
SQL> -- Your original query
SQL> --
SQL> WITH DATAA AS (
2 SELECT *
3 FROM
4 (
5 SELECT 'C10_'rr FROM DUAL UNION
6 SELECT 'C10A' rr FROM DUAL UNION
7 SELECT 'C20_' rr FROM DUAL UNION
8 SELECT 'C20A' rr FROM DUAL )
9 )
10 SELECT *
11 FROM DATAA
12 ORDER BY rr ASC;
RR
----
C10A
C10_
C20A
C20_
--
SQL> -- Now altering the sorting method
SQL> --
SQL> --
SQL> alter session set NLS_SORT = German;
Session altered.
SQL> --
SQL> --
SQL> -- Now see the result
SQL> --
SQL> --
SQL> WITH DATAA AS (
2 SELECT *
3 FROM
4 (
5 SELECT 'C10_'rr FROM DUAL UNION
6 SELECT 'C10A' rr FROM DUAL UNION
7 SELECT 'C20_' rr FROM DUAL UNION
8 SELECT 'C20A' rr FROM DUAL )
9 )
10 SELECT *
11 FROM DATAA
12 ORDER BY rr ASC;
RR
----
C10_
C10A
C20_
C20A
SQL>
Cheers!!

Generate Random String in PL/SQL (oracle 12c)

I'm trying to generate a Random String using PL/SQL with only 2 fixed words. It's this possible?
Is this what you're looking for?
SQL> with
2 -- two fixed words
3 test as
4 (select 'fixed words' col from dual),
5 -- split them to rows
6 inter as
7 (select level lvl, regexp_substr(col, '.', 1, level) let
8 from test
9 connect by level <= length(col)
10 )
11 -- aggregate them back, randomly
12 select listagg(let, '') within group (order by dbms_random.value(1, max_lvl)) result
13 from inter
14 join (select max(lvl) max_lvl from inter) on 1 = 1;
RESULT
--------------------------------------------------------------------------------
reiosdwxf d
SQL> /
RESULT
--------------------------------------------------------------------------------
fe ixoddrws
SQL> /
RESULT
--------------------------------------------------------------------------------
wdxeorsdfi
SQL>

Resources