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
Related
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)
Hi i'm trying to execute my query and unfortunately trows me wih error of ORA-01722: invalid number
SELECT L.NEVENTLOGIDN, LPAD (nuserid, 6, '0') nuserid, u.susername,
TO_CHAR (TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + ( (ndatetime) / (60 * 60 * 24)), 'YYYY-MM-DD HH24:MI:SS')
date_time, l.nreaderidn, r.sname,
CASE WHEN l.nreaderidn IN (SELECT GETREADERSBYFUNC('OUT', 'LOCKER') devices FROM dual ) THEN 'O'
WHEN l.nreaderidn IN (SELECT GETREADERSBYFUNC('IN', 'LOCKER') devices FROM dual ) THEN 'I' END logtype
FROM TB_EVENT_LOG l, TB_READER r, TB_USER u
WHERE
l.nreaderidn IN ( SELECT GETREADERSBYDESC('LOCKER') devices FROM dual)
AND NDATETIME >= ((TO_DATE ('2020-01-27' || ' 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM') ) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60
AND ndatetime <= ((TO_DATE ('2020-01-28' || ' 12:00:00 PM', 'YYYY-MM-DD HH:MI:SS PM') ) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60
AND l.nuserid = u.suserid
AND l.nreaderidn = r.nreaderidn
ORDER BY 2, 4
I think the reason of error is this below.
1
CASE WHEN l.nreaderidn IN (SELECT GETREADERSBYFUNC('OUT', 'LOCKER') devices FROM dual ) THEN 'O'
sample data of GetReaderbyfunc
'544381428','544381436','544381433','544381424','544381043'
2
WHEN l.nreaderidn IN (SELECT GETREADERSBYFUNC('IN', 'LOCKER') devices FROM dual ) THEN 'I' END logtype
3
WHERE
l.nreaderidn IN ( SELECT GETREADERSBYDESC('LOCKER') devices FROM dual)
SELECT GETREADERSBYFUNC('OUT', 'LOCKER') devices FROM dual
result is below
'544381428','544381436','544381433','544381424','544381043'
because the nreaderidn is a number type but when i put the result of it like bellow it is working
SELECT GETREADERSBYDESC('LOCKER') devices FROM dual
result is bellow
'544381050','544381441','544381428','544381436','544381431','544381064','544381433','544381435','544381424','544381043'
WHERE
l.nreaderidn IN ( '544381428','544381436','544381433','544381424','544381043')
functions
getreadersbyfunc (p_func VARCHAR2, p_desc VARCHAR2)
RETURN VARCHAR2
IS
retVal VARCHAR2(1024);
BEGIN
for cur_rec in (SELECT nreaderidn FROM tb_reader where sdescription = p_desc and upper(sname) like '%' || upper(p_func) || '%')
loop
if retVal is NULL then
retVal := '''' || cur_rec.nreaderidn || '''';
else
retVal := retVal || ',''' || cur_rec.nreaderidn || '''';
end if;
end loop;
return retVal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
getreadersbydesc (p_description VARCHAR2)
RETURN VARCHAR2
IS
retVal VARCHAR2(1024);
BEGIN
for cur_rec in (SELECT nreaderidn FROM tb_reader where sdescription = p_description)
loop
if retVal is NULL then
retVal := '''' || cur_rec.nreaderidn || '''';
else
retVal := retVal || ',''' || cur_rec.nreaderidn || '''';
end if;
end loop;
return retVal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END;
I'm not allowed to change the data type of nreaderidn and to modify the oracle function.
Is There a way to solve this?
Thank you in advance
Your function returns a comma separated list of numbers, which needs to be split.
Try th
Eg:
SELECT
regexp_substr(GETREADERSBYFUNC('OUT', 'LOCKER'), '[^,]+', 1, level)
FROM dual
connect by
regexp_substr(GETREADERSBYFUNC('OUT', 'LOCKER'), '[^,]+', 1, level) is not null
Your query would then look like:
SELECT L.NEVENTLOGIDN, LPAD (nuserid, 6, '0') nuserid, u.susername,
TO_CHAR (TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + ( (ndatetime) / (60 * 60 * 24)), 'YYYY-MM-DD HH24:MI:SS')
date_time, l.nreaderidn, r.sname,
CASE WHEN l.nreaderidn IN (SELECT
regexp_substr(GETREADERSBYFUNC('OUT', 'LOCKER'), '[^,]+', 1, level) FROM dual
connect by regexp_substr(GETREADERSBYFUNC('OUT', 'LOCKER'), '[^,]+', 1, level) is not null ) THEN 'O'
WHEN l.nreaderidn IN (SELECT
regexp_substr(GETREADERSBYFUNC('IN', 'LOCKER'), '[^,]+', 1, level) FROM dual
connect by regexp_substr(GETREADERSBYFUNC('IN', 'LOCKER'), '[^,]+', 1, level) is not null) THEN 'I' END logtype
FROM TB_EVENT_LOG l, TB_READER r, TB_USER u
WHERE
l.nreaderidn IN ( SELECT
regexp_substr(GETREADERSBYFUNC('LOCKER'), '[^,]+', 1, level) FROM dual
connect by regexp_substr(GETREADERSBYFUNC('LOCKER'), '[^,]+', 1, level) is not null)
AND NDATETIME >= ((TO_DATE ('2020-01-27' || ' 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM') ) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60
AND ndatetime <= ((TO_DATE ('2020-01-28' || ' 12:00:00 PM', 'YYYY-MM-DD HH:MI:SS PM') ) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60
AND l.nuserid = u.suserid
AND l.nreaderidn = r.nreaderidn
ORDER BY 2, 4
This will not give you an error:
SELECT *
from TB_READER l
where cast(l.nreaderidn as varchar2(1024)) in (select GETREADERSBYDESC('LOCKER') devices FROM dual)
Just use the cast of the nreaderidn column.
But also be aware that you will search a varchar like for example '2' in the string(not an series of characters but one string) '1','2','3' so this will not retun any results.
Here is also a small example where you can see the errir being produced without a cast and solved when the cast is added:
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=776ecd951aff56500938ac064b34788c
I have a column called duration_d which is varchar2 and the data in that table looks like below
duration_d
-----------
12:25
01:35
12:10
04:21
12:18
12:24
I tried below query
SELECT SUM( to_date( duration_d, 'mi:ss' ))
FROM table
GROUP BY calling_number;
When I execute it following error is coming
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
can any one tell me how to make sum it?
To get the total as fractions of a day you can use:
SELECT SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ) AS total
FROM your_table
Which gives the result:
TOTAL
------------------------------------------
0.0383449074074074074074074074074074074074
To convert this to an interval data type you can use NUMTODSINTERVAL:
SELECT NUMTODSINTERVAL(
SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ),
'DAY'
) AS total
FROM your_table
Which gives the result:
TOTAL
-------------------
+00 00:55:13.000000
Please try below:
with x as
(select sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE)
SELECT
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Will work only if the duration is always [MI:SS].
Also you can add the group by as per your requirement.
Converting Seconds to the required duration format Reference.
Group By
with x as
(select calling_number,sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE
group by calling_number)
SELECT calling_number,
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Use a combination of SUBSTR, to_char, to_date, NVL, INSTR, reverse and SUM.
SELECT "calling_number",
to_char(to_date(SUM(NVL(SUBSTR("duration_d", 0, INSTR("duration_d", ':')-1), "duration_d"))*60 +
SUM(substr("duration_d", - instr(reverse("duration_d"), ':') + 1)),'sssss'),'hh24:mi:ss') AS SUM_DURATION_D
FROM yourtable
GROUP BY "calling_number"
Output
calling_number SUM_DURATION_D
1 00:26:10
2 00:29:03
SQL Fiddle: http://sqlfiddle.com/#!4/9b0a81/33/0
Correct spelling as below
SELECT SUM( TO_DATE( duration_d, 'mi:ss' ) )
FROM YOURTABLE Group By calling_number
I'm writing a block of code to populate a time dimension in Oracle 11gR2 using SQL Developer
Table Structure
KEY Number(8,0)
HRS Varchar2
MINS Varchar2
SECS Varchar2
I'm new to PL/SQL - the way i would normally think of doing in pseudo-code would be but the for loops in PL/SQL don't seem to work this way:
key = 1
for (hrs=0; hr<=23; hr++)
{
for (min=0; min<=59; min++)
{
for (sec=0; sec<=59; sec++)
{
insert (KEY, tochar(hrs:mins:secs), tochar(hr), tochar(min), tochar(sec))
SK=+1
}
}
}
I've tried this from an answer i found:
insert into Dim_TIME
(Key,
TIME_IN24_NAME,
TIME_HOUR24,
TIME_MINUTE,
TIME_SECOND)
select
to_char(t, 'HH24:MI:SS'),
to_number(to_char(t, 'HH24'), '00'),
to_number(to_char(t, 'MI'), '00'),
to_number(to_char(t, 'SS'), '00')
from (
select trunc(sysdate) + (level - 1)/86400 as t
from dual
connect by level <= 86400
);
But not sure how i would increment the key (the column field is not auto-increment).
Any ideas how i could achieve this?
Thanks
You can create a SEQUENCE to increment the field KEY.
CREATE SEQUENCE dim_time_seq;
And use it in your code like this,
INSERT INTO dim_time
(KEY,
time_in24_name,
time_hour24,
time_minute,
time_second)
SELECT
dim_time_seq.nextval,
to_char(t, 'HH24:MI:SS'),
to_number(to_char(t, 'HH24'), '00'),
to_number(to_char(t, 'MI'), '00'),
to_number(to_char(t, 'SS'), '00')
FROM (
SELECT trunc(SYSDATE) + (LEVEL - 1)/86400 AS t
FROM dual
CONNECT BY LEVEL <= 86400
);
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;