Oracle statement - oracle

Tables records as below
D:\HOME\DOC\FILE\2001\12\TT-12S2Q99-EE-EE1.pdf
D:\HOME\DOC\FILE\2002\02\TT-12S2Q94-EE-EE1.xml
D:\HOME\DOC\FILE\2005\05\TT-12S2Q98-EE-EE1.pdf
D:\HOME\DOCS\TEMPFILE\TT-12S2Q88-EE-EE1.pdf
I want to extract those file names only. The result should be
TT-12S2Q99-EE-EE1
TT-12S2Q94-EE-EE1
TT-12S2Q98-EE-EE1
TT-12S2Q88-EE-EE1
Anyone can give me a hand ?

You can use INSTR with the third parameter negative to search backwards in the string from the end (something I didn't know you could do until a few minutes ago). Combine that with a SUBSTR and you should have what you want:
SQL> select filename from mytable;
FILENAME
--------------------------------------------------------------------------------
C:\path\to\some\file.txt
SQL> select substr(filename, instr(filename, '\', -1) + 1) from mytable;
SUBSTR(FILENAME,INSTR(FILENAME,'\',-1)+1)
--------------------------------------------------------------------------------
file.txt

Take a look at the SUBSTR and INSTR functions.
If you're still stuck after that, post your best attempt at what you've done.

Related

How substr works on dates

I am trying to understand a query in my application where it uses substr function.
I have gone through the documentation for substr, which looks simple and clear.
Now below is my query without using substr:
select last_day(to_date(to_char(add_months(TO_DATE('2004/10/25', 'yyyy/mm/dd'),1),'YYYY')||'0201','YYYYMMDD')) from dual;
This gives me result as 2/29/2004. The above query just returns last day of Feb in simple words.
Now I am using substr as below:
select substr(last_day(to_date(to_char(add_months(TO_DATE('2004/10/25', 'yyyy/mm/dd'),1),'YYYY')||'0201','YYYYMMDD')),5,1) from dual;
So here the start value is 5 & length is 1, so I am expecting output as 2 looking at 2/29/2004. but the actual output is E, I am not clear from where this E is coming as result.
You cannot use SUBSTR() on DATE values. SUBSTR() works only on strings!
When you run SUBSTR({DATE_VALUE}, ...) then Oracle actually does following:
SELECT
SUBSTR(
TO_CHAR(
{DATE_VALUE}, (SELECT VALUE FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT')
), ...
)
FROM dual;
What is the purpose of this query? Do you like to find out whether input year is a leap-year?
Try this instead -
select substr(to_char(last_day(to_date(to_char(add_months(TO_DATE('2004/10/25', 'yyyy/mm/dd'),1),'YYYY')||'0201','YYYYMMDD')),'dd/mm/yyyy'),5,1)
from dual;

REGEXP_SUBSTR for portion of string

I would like to get:
82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
from the following expression
LASTNAME_FIRSTNAME_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
Does someone know how I can get this using regexp_substr ?
EDIT
Basically I have a field which has 7 sets each separated by _ . The string I gave is just one example. I wanted to retrieve everything after the second _ . There is no fixed character length so I can not use a substr function. Hence I was using regexp_substr. I was able to get away by using a simplified version
Select FILE_NAME, ( (REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,3)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,4)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,5)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,6)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+',1,7)) ) as RegExp
from tbl
Here is some more data from the FILE_NAME field
LAST_FIRST_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
SMITH_JOHN_82961_0130BPQX9QZN9G4P5RDTPA9HR4R_MR_1_1of1
LASTNAME_FIRSTNAME_99999_01V0MU4XUQK0Y24Y9RYTFA7W1CM_MR_3_1of1
To get everything after the second underscore, you do not need regular expressions, but can use something like the following:
select substr(FILE_NAME, instr(FILE_NAME, '_', 1, 2) +1 ) from tbl
The instr returns the position of the second occurrence of '_', starting by the first character; the substr simply gets everything starting from the position given by instr + 1
From your Requirement, you can just go ahead and use the simple SUBSTRfunction. Its faster, and it addresses the simple need to remove the String LASTNAME_FIRSTNAME.
select substr('LASTNAME_FIRSTNAME_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1', 20) data_string
from dual;
Output:
data_string
-----------------
82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
Unless you have another underlying logic you need to address?
Kindly clarify so i can edit the answer accordingly.

Shorten the Table Names in Oracle

I have a requirement where i read table_name from user_tables and append 6 letters after the table_name at run time for e.g.
prev_table_name= F_ALIGN_PROF_PRD_MTH_SLS_NM2
New_table_name = prev_table_name_ABCDE
so new table name is exceeding the limit of 30 characters and i am getting an error.
to overcome this problem i am looking for a method so i can shorten the table_name at run time and append my 6 letters to it.
Kindly suggest any workaround fo this problem
How about something like this, then?
select substr(substr('F_ALIGN_PROF_PRD_MTH_SLS_NM2', 1, 24),
1,
instr(substr('F_ALIGN_PROF_PRD_MTH_SLS_NM2', 1, 24), '_', -1)) substr_table_name
from dual;
SUBSTR_TABLE_NAME
---------------------
F_ALIGN_PROF_PRD_MTH_
Do you want such result ?
select SUBSTR('prev_table_name_ABCDE' , 1, 6) from dual
Result : prev_t
If you want readable name you can take to last '_'
SELECT SUBSTR('prev_table_name_ABCDE', 1 ,INSTR('prev_table_name_ABCDE', '_',1,3)-1)
FROM dual;
Result :prev_table_name
I found one way to do it (its an temporary solution but it will work)
Read the table name and remove all vowels and numbers from it.
how about creating a a new table to store the old and new tablename?
my_table
oldname F_ALIGN_PROF_PRD_MTH_SLS_NM2
newname TEMP_ABCD

How to put double quote in oracle output records

This is a oracle output records with pipe delimiter
04/22/2015|695|1074795|CRUSE|AXDE|01/29/1963|88359|||||
I want to change like this
"04/22/2015"|"695"|"1074795"|"CRUSE"|"AXDE"|"01/29/1963"|"88359"|||||
What is the query in Perl?
I want to change like this
"04/22/2015"|"695"|"1074795"|"CRUSE"|"AXDE"|"01/29/1963"|"88359"|||||
I won't say this is an elegant way to do it, since it is always better to fix the source itself. In your case, whatever is generating the output, you could simply concatenate the double-quotation marks to the column names.
Anyway, you could do it in SQL using REPLACE and RTRIM:
SQL> WITH DATA AS(
2 SELECT '04/22/2015|695|1074795|CRUSE|AXDE|01/29/1963|88359|||||' str FROM dual
3 )
4 SELECT '"'||rtrim(REPLACE(REPLACE(str, '|', '"|"'), '""',''),'"') str FROM DATA;
STR
---------------------------------------------------------------------
"04/22/2015"|"695"|"1074795"|"CRUSE"|"AXDE"|"01/29/1963"|"88359"|||||
SQL>
check this
select '"04/22/2015"|"695"|"1074795"|"CRUSE"|"AXDE"|"01/29/1963"|"88359"|||||' as str from dual
STR
---------------------------------------------------------------------
"04/22/2015"|"695"|"1074795"|"CRUSE"|"AXDE"|"01/29/1963"|"88359"|||||

Oracle 11.2 to_number multiple commas

In Oracle 11.2, is there some number format, nf, that will work with to_number to parse arbitrary length varchar2s containing digits and commas?
I can achieve this without a number format, by using regexp_replace, but I'd prefer to achieve the same thing using just a number format.
e.g., the following 2 statements work:
select to_number(regexp_replace('12,345', ',', '')) from dual;
select to_number(regexp_replace('1,234,567', ',', '')) from dual;
but I'd prefer:
select to_number('12,345', nf) from dual;
select to_number('1,234,567', nf) from dual;
where nf is one number format string that works for both statements.
If I try nf = '99,999', the first statement works, but the second fails.
Thanks.
Oracle won't complain if the number format is too long, so you can use a model that has enough digits to cope with the biggest number you can receive:
SQL> select to_number('12,345',
2 '999G999G999G999G999G999G999G999G999G999G999G999G999') from dual;
TO_NUMBER('12,345','999G999G999G999G999G999G999G999G999G999G999G999G999')
-------------------------------------------------------------------------
12345
SQL> select to_number('1,234,567',
2 '999G999G999G999G999G999G999G999G999G999G999G999G999') from dual;
TO_NUMBER('1,234,567','999G999G999G999G999G999G999G999G999G999G999G999G999')
----------------------------------------------------------------------------
1234567
SQL> select to_number('999,999,999,999,999,999,999,999,999,999,999,999,999',
2 '999G999G999G999G999G999G999G999G999G999G999G999G999') from dual;
TO_NUMBER('999,999,999,999,999,999,999,999,999,999,999,999,999','999G999G999G999
--------------------------------------------------------------------------------
1.0000E+39
I've used the G group separator instead of a fixed comma to support globalisation, but the effect is the same.
The only caveat is that the source number has to have the right grouping so it matches the formatting exactly for the digits it does have:
SQL> select to_number('1,2345',
2 '999G999G999G999G999G999G999G999G999G999G999G999G999') from dual;
select to_number('1,2345',
*
ERROR at line 1:
ORA-01722: invalid number
Although I support Alex Poole's answer, here's another crude but effective way of solving the problem that should perform better than doing a regex.
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_of_numbers (
example_num VARCHAR2(50)
)
/
INSERT INTO table_of_numbers (example_num)
VALUES ('12,345')
/
INSERT INTO table_of_numbers (example_num)
VALUES ('1,234,567')
/
Query 1:
SELECT TO_NUMBER(example_num, RPAD('9', LENGTH(example_num) - 1, '9')) fudge
FROM table_of_numbers
Results:
| FUDGE |
-----------
| 12345 |
| 1234567 |
If you need to match the commas, then you could do something slightly more sophisticated with INSTR and LPAD to make sure you generate the right mask.
For this :
select to_number('1,234,567', nf) from dual;
Use nf = 9,999,999 will work.

Resources