Regarding sql instr function - sql

Oracle 10g is the db.
The below query fails when extracting the date.
SELECT TO_CHAR ( TO_DATE ( SUBSTR (file_name , INSTR (file_name , '_', -1, 2)+ 2, 8), 'YYYYMMDD'), 'DD-MM-YYYY') from dual;
I noticed we receive the below two file name of different naming formats.
660.ASSD.0063.20100923.0409.PTH2.IAC1.gcr_H201009231416151671_bbor.ddr
660.ASSD.M2K_20110309121547_489.ddr
For one file the above query works . The other file 660.ASSD.M2K_20110309121547_489.ddr
it extracts "01103091" and does a to_date fails. How can i modify this query so it works for both the file formats.

Use REGEXP_SUBSTR
select TO_CHAR(TO_DATE(SUBSTR(REGEXP_SUBSTR('660.ASSD.0063.20100923.0409.PTH2.IAC1.gcr_H201009231416151671_bbor.ddr', '\d{14,17}'), 0, 8), 'yyyymmdd'), 'dd-mm-yyyy')
from dual;
select TO_CHAR(TO_DATE(SUBSTR(REGEXP_SUBSTR('660.ASSD.M2K_20110309121547_489.ddr', '\d{14,17}'), 0, 8), 'yyyymmdd'), 'dd-mm-yyyy')
from dual;

You can also use REGEXP_REPLACE to strip-out letters from the file name.
SELECT TO_CHAR ( TO_DATE ( SUBSTR (regexp_replace(file_name, '[A-Z][a-z]', '')
, INSTR (regexp_replace(file_name, '[A-Z][a-z]', '') , '_', -1, 2)+ 1, 8), 'YYYYMMDD'), 'DD-MM-YYYY')
FROM dual;

Related

Bad status request on Impala

Bad status for request 37563: TGetOperationStatusResp(status=TStatus(errorCode=None, errorMessage=None, sqlState=None, infoMessages=None, statusCode=0), operationState=5, errorMessage=None, sqlState=None, errorCode=None)
I am facing this when i tried to run the following query.
refresh sst_spot_quotes;
select
case
when maxrecordforSST >= hours_sub (CURRENT_TIMESTAMP(), 4) then ''
else 'error'
end as msg
from
(
select
to_timestamp (
CONCAT (
max(rdate),
MAX(
CONCAT (
LPAD (CAST(rhour as STRING), 2, '0'),
':',
LPAD (CAST(rminute as STRING), 2, '0'),
':',
LPAD (CAST(rsecond as STRING), 2, '0')
)
)
),
'yyyy-mmm-ddhh:mm:ss'
) as maxrecordforSST
from
sst_spot_quotes
where
rdate >= days_sub (to_date (CURRENT_TIMESTAMP()), 1)
) a
Could someone help to resolve this error.
The date format must be yyyy-MMM-ddhh:mm:ss. Pls note i made MMM as uppercase.
Could you please change and try?
Also, its not a good idea to get the max and then to_timestamp but reverse. Because calculating max on date will give correct maximum date than string.
You can give below SQL a try.
select
case
when maxrecordforSST >= hours_sub (CURRENT_TIMESTAMP(), 4) then ''
else 'error'
end as msg
from
(
select
MAX(to_timestamp (
CONCAT (
(rdate),
(
CONCAT (
LPAD (CAST(rhour as STRING), 2, '0'),
':',
LPAD (CAST(rminute as STRING), 2, '0'),
':',
LPAD (CAST(rsecond as STRING), 2, '0')
)
)
),
'yyyy-MMM-ddhh:mm:ss'
)) as maxrecordforSST
from
sst_spot_quotes
where
rdate >= days_sub (to_date (CURRENT_TIMESTAMP()), 1)
) a

How to extract date from text string

I need to extract the date (08-01-2021) from the below string that has no whitespace
select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' from dual
I tried to apply the REGEXP_SUBSTR function as shown below, but using this query I just removed 'Date-'
with x as
(select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' as str
from dual)
SELECT REGEXP_SUBSTR(STR, 'Date-([^ ]+)',1,1,'i',1)
FROM x;
Please advise
You are zero-padding the date values so each term has a fixed length and have a fixed prefix so you do not need to use (slow) regular expressions and can just use simple string functions:
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY')
FROM table_name;
(Note: if you still want it as a string, rather than as a date, then just use SUBSTR without wrapping it in TO_DATE.)
For example:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Outputs:
DATE_VALUE
08-JAN-21
db<>fiddle here
If the Date- prefix is not going to always be at the start then use INSTR to find it:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'Trans-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, INSTR(value, 'Date-') + 5, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Which outputs:
DATE_VALUE
08-JAN-21
08-FEB-21
If you can have multiple Date- substrings and you want to find the one that is either at the start of the string or has a - prefix then you may need regular expressions:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'TransDate-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(
REGEXP_SUBSTR(value, '(^|-)Date-(\d\d-\d\d-\d{4})([-.]|$)', 1, 1, 'i', 2),
'DD-MM-YYYY'
) AS date_value
FROM table_name;
db<>fiddle here
Just use a more precise regular expression:
SELECT REGEXP_SUBSTR(STR, 'Date-([0-9]{2}-[0-9]{2}-[0-9]{4})', 1, 1, 'i', 1)
FROM x;
Or for less accuracy but more conciseness:
SELECT REGEXP_SUBSTR(STR, 'Date-([-0-9]{10})', 1, 1, 'i', 1)

SQL INSERT INTO simultaneously in 2 tables in apex oracle

I have a script:
I write the data in test2!
INSERT INTO test2 (val)
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS val
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (
REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (
REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1;
I want to write it in another table myself.I want to write it down all in one request
INSERT INTO test3 (val,data_area,data_add )
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS val,
(select data_area from SEC_USERS_LIST where login = LOWER(:APP_USER)) as data_area,
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as data_add
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (
REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (
REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1;
You could try and use Oracle INSERT ALL syntax :
In a multitable insert, you insert computed rows derived from the rows returned from the evaluation of a subquery into one or more tables.
ALL into_clause
Specify ALL followed by multiple insert_into_clauses to perform an unconditional multitable insert. Oracle Database executes each insert_into_clause once for each row returned by the subquery.
Consider:
INSERT ALL
INTO test3 (val,data_area,data_add) VALUES (x_val, x_data_area, x_data_add)
INTO test2 (val) VALUES (x_val)
SELECT SUBSTR (:P1_FIRST, 1, 1)
|| TO_CHAR (
( TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ LEVEL
- 1))
AS x_val,
(select data_area from SEC_USERS_LIST where login = LOWER(:APP_USER)) as x_data_area,
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as x_data_add
FROM dual
CONNECT BY LEVEL <=
TO_NUMBER (REGEXP_SUBSTR (:P1_LAST, '\d+$'))
- TO_NUMBER (REGEXP_SUBSTR (:P1_FIRST, '\d+$'))
+ 1
;
NB: as far as concerns, the inline subquery that returns the current date is not needed and could be simplified as just:
to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') as x_data_add
Instead of:
(select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') "Right Now" from dual ) as x_data_add
Even more, as commented by Thomas Tschernich: if x_data_add is of datatype DATE, no casting should be necessary and you could simply use a default on the table column and omit it from the INSERT completely

Changing Odd Text String to Date SQL

Have a text string that I need to convert to date, however, it's not the generic yyyymmdd string. e.g. March 2018 is stored as '2018m3' as are all other dates. Is there a way to convert the string to a normal date in Oracle?
This may be helpful :
SQL> SELECT to_date('2018m3', 'YYYY"m"MM') FROM dual
2 /
Output
TO_DATE('2018M3','YYYY"M"MM')
-----------------------------
3/1/2018
If that is the format, you can do:
select add_months(to_date(substr(col, 1, 4) || '0101'),
to_number(replace(substr(col, -2), 'm', '')) - 1
)
An alternative method:
select to_date(substr(col, 1, 4) || regexp_substr(col, '[0-9]+', 1, 2), 'YYYYMM')

Invalid number format model

SELECT decode(to_number(to_char(01-04-2016, 'mm')),
1,
to_number(to_char(01-04-2016, 'yyyy')) - 1,
2,
to_number(to_char(01-04-2016, 'yyyy')) - 1,
3,
to_number(to_char(01-04-2016, 'yyyy')) - 1,
to_number(to_char(01-04-2016, 'yyyy'))) FROM DUAL;
whenever i execute this statement it shows invalid number format model.
Your query is invalid currently, as to_char expects a number or date, but the plain number 01-04-2016 doesn´t represent either of these.
The follow up mentioned in your comment to_char(01042016,'mm') wont work either, as the given number can´t be parsed with mm as it does expect a valid numberFormat and not a dateFormat, which mm isn´t.
In order for your query to work, wrap the pure date into a to_date and mention the current dateFormat given by the char:
SELECT decode(to_number(to_char(to_date('01-04-2016', 'dd-mm-yyyy'), 'mm')),
1,
to_number(to_char(to_date('01-04-2016', 'dd-mm-yyyy'), 'yyyy')) - 1,
2,
to_number(to_char(to_date('01-04-2016', 'dd-mm-yyyy'), 'yyyy')) - 1,
3,
to_number(to_char(to_date('01-04-2016', 'dd-mm-yyyy'), 'yyyy')) - 1,
to_number(to_char(to_date('01-04-2016', 'dd-mm-yyyy'), 'yyyy')))
FROM DUAL;