Oracle SQL developer shows invalid number for the code below - sql

I'm trying to subtract two columns which holds "systimestamp" as the date and time value. i'm getting
'ORA-01722: invalid number'
as the error message. Would be of great help if somebody can help out.
I tried googling this error and it says the character string might not be a valid literal . It works fine for other records , only problem is when i'm trying to subtract it.
SELECT ETL_BATCH_ID,
ETL_BATCH_GROUP_NAME,
TO_CHAR(BATCH_START_TS,'DD-MON-YY')
|| ' '
||TO_CHAR(BATCH_START_TS,'HH24:MI:SS') "BATCH_START_TS",
TO_CHAR(DW_DM_END_TS ,'DD-MON-YY')
||' '
||TO_CHAR(DW_DM_END_TS , 'HH24:MI:SS') "DW_DM_END_TS" ,
(TO_CHAR(DW_DM_END_TS , 'HH24:MI:SS')) - (TO_CHAR(BATCH_START_TS,'HH24:MI:SS')) "COMPLETION_TIME"
FROM bi_etl.bi_etl_batch
WHERE ETL_BATCH_GROUP_NAME = 'CMD';
For ex ,
BATCH_START_TS || DW_DM_END_TS || COMPLETION_TIME
01-OCT-19 3:18:00 ||01-OCT-19 3:20:00 || 00:02:00
So the completion time is (DW_DM_END_TS) - (BATCH_START_TS) = COMPLETION_TIME
But it's throwing the particular error as shown above

Apply Substraction directly on those timestamp values :
select DW_DM_END_TS - BATCH_START_TS as "COMPLETION_TIME"
from bi_etl_batch;
COMPLETION_TIME
-000000000 00:02:00.000000
Demo
Substraction is impossible and has no sense among two string type values.

U cann't any arifmetic operation on char.
so change To_char -> To_date, or remove to_char if fields is date

For an exact result, You need to retrieve hour, minute and second from the difference in the timestamp , Like the following:
SELECT
ETL_BATCH_ID,
ETL_BATCH_GROUP_NAME,
BATCH_START_TS,
DW_DM_END_TS,
LPAD(EXTRACT(HOUR FROM COMPLETION_TIME), 2, 0)
|| ':'
|| LPAD(EXTRACT(MINUTE FROM COMPLETION_TIME), 2, 0)
|| ':'
|| LPAD(ROUND(EXTRACT(SECOND FROM COMPLETION_TIME)), 2, 0) AS COMPLETION_TIME
FROM
(
SELECT
ETL_BATCH_ID,
ETL_BATCH_GROUP_NAME,
TO_CHAR(BATCH_START_TS, 'DD-MON-YY')
|| ' '
|| TO_CHAR(BATCH_START_TS, 'HH24:MI:SS') "BATCH_START_TS",
TO_CHAR(DW_DM_END_TS, 'DD-MON-YY')
|| ' '
|| TO_CHAR(DW_DM_END_TS, 'HH24:MI:SS') "DW_DM_END_TS",
DW_DM_END_TS - BATCH_START_TS "COMPLETION_TIME"
FROM
BI_ETL.BI_ETL_BATCH
WHERE
ETL_BATCH_GROUP_NAME = 'CMD'
);
Example:
SQL> SELECT
2 LPAD(EXTRACT(HOUR FROM DIFF), 2 , 0) || ':' ||
3 LPAD(EXTRACT(MINUTE FROM DIFF), 2 , 0) || ':' ||
4 LPAD(ROUND(EXTRACT(SECOND FROM DIFF)), 2 , 0) as diff
5 FROM
6 (
7 SELECT
8 SYSTIMESTAMP - ( SYSTIMESTAMP - 2 / 1440 ) AS DIFF
9 FROM
10 DUAL
11 );
DIFF
--------------------------
00:02:01
SQL>
Cheers!!

Related

ORA-01722: invalid number with RPAD

There is a case where I want to take the date of birth and pad it with eight ' ' empty spaces
This is what I have
CASE
WHEN Date_of_Birth IS NULL THEN rpad(' ', 8, ' ')
ELSE substr(
(replace(
to_char(to_date(DATE_OF_BIRTH,'YYYY-MM-DD HH24:MI:SS'), 'MM/DD/YYYY'),
'/',
''
) + rpad(' ',(length(' ') * 8),' '))
,1,8
)
END Date_of_Birth_1,
The DATE_OF_BIRTH is NVARCHAR2. I'm getting the error saying that RPAD is an invalid number,
I figured changing the date to a to_char would change it to a string then to add the spaces at the end of it.
You appear to want to convert the string DATE_OF_BIRTH column from YYYY-MM-DD HH24:MI:SS format to MMDDYYYY format and if it is NULL then provide 8 spaces.
That can be achieved without the complicated use of string functions using:
COALESCE(
TO_CHAR(TO_DATE(DATE_OF_BIRTH,'YYYY-MM-DD HH24:MI:SS'), 'MMDDYYYY'),
' '
) AS Date_of_Birth_1,
Note: there is no need to replace the / separators in a date or to remove trailing spaces if you never include them in the first palce.
by the + sign, did you mean to concatenate strings like in Javascript? String concatenation in Oracle uses ||
Aside from that, you should also check to make sure date_of_birth is in fact in the YYYY-MM-DD HH24:MI:SS format in your data or you can get the same error.
It is the concatenation operator (as Paul already said).
Though, you could simplify that code.
date_of_birth is the original value, stored in the table
date_of_birth_1 is result based on your code
date_of_birth_2 is result on my (simplified) code
SQL> set null 'null'
SQL> select
2 id,
3 date_of_birth,
4 --
5 CASE WHEN Date_of_Birth IS NULL THEN
6 rpad(' ', 8, ' ')
7 ELSE substr( (replace( to_char(to_date(DATE_OF_BIRTH,'YYYY-MM-DD HH24:MI:SS'), 'MM/DD/YYYY'), '/', '' ) || rpad(' ',(length(' ') * 8),' ')) ,1,8 )
8 END Date_of_Birth_1,
9 --
10 case when date_of_birth is null then ' '
11 else to_char(to_date(date_of_birth, 'yyyy-mm-dd hh24:mi:ss'), 'mmddyyyy')
12 end date_of_birth_2
13 from test;
ID DATE_OF_BIRTH DATE_OF_BIRTH_1 DATE_OF_BIRTH_2
---------- -------------------- -------------------- --------------------
1 2020-08-25 13:20:28 08252020 08252020
2 2015-03-18 03182015 03182015
3 null
SQL>

Requesting help converting DB2 sql to Oracle

Looking for a little help converting a query from DB2 to Oracle. I'm using an existing SQL query to add to a new report, but that report query has been written in DB2 SQL. I am trying to convert it to Oracle, and having issues with how the dates are setup.
trunc_timestamp(CASE ......
ELSE ((
CASE
WHEN
TRFRDATE IS NULL OR
TRFRTIME IS NULL
THEN
NULL
ELSE timestamp(substr(char(TRFRDATE), 1, 4) || '-' ||
substr(char(TRFRDATE), 5, 2) || '-' || substr(char(TRFRDATE), 7, 2)
|| '-' || substr(digits(TRFRTIME), 1, 2) || '.' ||
substr(digits(TRFRTIME), 3, 2) || '.' || substr(digits(TRFRTIME), 5, 2)
|| '.000000')
END) + (-1) DAY)
END, 'dd') AS "NewOrderDate",
As you can see above, I have a case statement that will be converted to a timestamp, the difficult part is the last part, where after calculating the timestamp, I need to subtract -1 day, and that's where I keep falling into one error or the other.
Just to be clear, the ELSE part of the above query is just concatenating the date and time and converting to timestamp. Any help figuring this out would be great.
EDIT: My query now is this, and im getting the following error: hour must be between 1 and 12
SELECT CASE
WHEN
CASE
WHEN
CARRSERV IN ('1DYT','1PRT','SATN')
THEN 1
WHEN
CARRSERV IN ('2DYT','SAT2')
THEN 2
ELSE 3
END = 1 AND
TO_CHAR(
CASE
WHEN TFRDATE IS NULL OR TFRTIME IS NULL THEN NULL
ELSE TO_TIMESTAMP(substr(TFRDATE, 1, 2) || '-' || substr(TFRDATE, 4, 3) || '-' ||
substr(TFRDATE, 8, 2) || ' ' || substr(TFRTIME, 1, 2) || '.' ||
substr(TFRTIME, 3, 2) || '.' || substr(TFRTIME, 5, 2))
END,'hh24:mi:ss') > TO_CHAR('17:00:00','hh24:mi:ss')
THEN
CASE
WHEN TFRDATE IS NULL OR TFRTIME IS NULL THEN NULL
ELSE TO_TIMESTAMP(substr(TFRDATE, 1, 2) || '-' || substr(TFRDATE, 4, 3) || '-' ||
substr(TFRDATE, 8, 2) || ' ' || substr(TFRTIME, 1, 2) || '.' ||
substr(TFRTIME, 3, 2) || '.' || substr(TFRTIME, 5, 2))
END
END AS NEW_DATE from table
If I get this right you're truncating any hour/minute/second/... portion anyway so just ignore it from the beginning.
You can simply use to_date() to convert a string into a date:
...
to_date(trfrdate, 'YYYYMMDD') - 1 AS "NewOrderDate"
...
But you should really consider to use appropriate data types and strings types aren't appropriate for date/times, date/time types are. You could for example have one date column instead of trfrdate and trfrtime.
And it's a CASE expression you have there, not a statement. SQL knows no control flow statements at all.

SQL: Converting number to time

I have a database column having the following values
column (hh/mm/ss)
042336
050623
Now using sql i want to covert it to like
column
04:23:63:000
05:06:23:000
I have been trying to_date function but no success yet.
You have a string so you can use string operations to insert the additional characters:
select (substr(x, 1, 2) || ':' || substr(x, 3, 2) || ':' || substr(x, 5, 2) || ':000')
from (select '042336' as x from dual) t

Oracle - String to Double - Dynamic Scale

I am in the situation that inside the database various double values are stored as a string.
(this can not be changed due to some other reasons!)
The numbers can have a different amount of numbers after & before the decimal separator.
The decimal separator of the stored values is a .
The default decimal separator of the database might possibly change in the future.
Examples:
1.1
111.1
1.111
11.11
1.1111
I now need to select those as numbers to be able to compare for bigger or smaller values, etc.
Therefore I tried to convert the strings to numbers. I found a hint at this answer: click.
Unfortunately using this as a test:
SELECT TO_NUMBER('10.123', TRANSLATE('10.123', ' 1,234.567890', TO_CHAR(9999.9, '9G999D9') || '99999'))
FROM DUAL;
Somehow converts the number to 10123, completely removing the decimal separation, so this query gives no result (just for verification):
SELECT * FROM(SELECT TO_NUMBER('10.123', TRANSLATE('10.123', ' 1,234.567890', TO_CHAR(9999.9, '9G999D9') || '99999')) AS NUM
FROM DUAL) WHERE NUM < 11;
So I stepped through the single parts to see if I can find an error:
SELECT TO_CHAR(9999.9, '9G999D9') FROM DUAL; -- 9.999,9
SELECT TO_CHAR(9999.9, '9G999D9') || '99999' FROM DUAL; -- 9.999,999999
SELECT TRANSLATE('10.123', ' 1,234.567890', ' 9.999,999999')
FROM DUAL; -- 99,999
SELECT TRANSLATE('10.123', ' 1,234.567890', TO_CHAR(9999.9, '9G999D9') || '99999')
FROM DUAL; -- 99,999
As you can see I get a . as group separator and a , as decimal separator for the database.
I do not understand why it does not correctly convert the number.
Thank you already for any help!
Try using this version of to_number
TO_NUMBER( string1 [, format_mask] [, nls_language])
For example:
SELECT to_number('1.1111','9G990D00000', 'NLS_NUMERIC_CHARACTERS = ''.,''') FROM DUAL
You can try this,
alter session set NLS_NUMERIC_CHARACTERS = '.,';
WITH INPUT_TEST AS (
SELECT '.' decimal_operator, '1.1' num_in_char from dual
UNION ALL
SELECT '.' decimal_operator, '111.1 ' from dual
UNION ALL
SELECT '.' decimal_operator, '1.111 ' from dual
UNION ALL
SELECT '.' decimal_operator, '11.11 ' from dual
UNION ALL
SELECT '.' decimal_operator, '1.1111' from dual)
SELECT TO_NUMBER(REPLACE(num_in_char, '.', decimal_separator)) to_num
FROM input_test a, (select SUBSTR(value, 1, 1) decimal_separator
from nls_session_parameters
where parameter = 'NLS_NUMERIC_CHARACTERS') b;
TO_NUM
----------
1.1
111.1
1.111
11.11
1.1111
alter session set NLS_NUMERIC_CHARACTERS = ',.';
Run the select statement above again.
TO_NUM
----------
1,1
111,1
1,111
11,11
1,1111

Oracle SQL inserting parenthesis into phone number

The original format:
123-456-7890
My goal format:
(123)456-7890
I wanted to go the route of concatenating between substrings but I continually get flagged for errors. I am unsure of a better method to go about implementing a way to format.
My query:
select || '(' || substr(telephone,0, 3)|| ')' ||
substr(telephone,4, 3)|| ' '||
substr(telephone,7, 4)) as telephone,
from book;
My current error:
"missing expression"
You have an extra dangling parenthesis at the end of your SELECT, and you also have a dangling concatenation operator || in the front. Try this:
SELECT '(' || SUBSTR(telephone, 0, 3) || ')' ||
SUBSTR(telephone, 4, 3) || ' ' || SUBSTR(telephone, 7, 4) AS telephone
FROM book
Update:
You should really use this query, because it turns out you also had a problem with forming your desired output as well:
SELECT '(' || SUBSTR(telephone, 1, 3) || ')' || SUBSTR(telephone, 5, 8) AS telephone
FROM book
You can use regular expressions to do.
select regexp_replace
(phoneNo,
'([[:digit:]]{3})\-([[:digit:]]{3})\-([[:digit:]]{4})',
'(\1)\2-\3'
)
from(
select '123-456-7890' as phoneNo from dual)
Output
(123)456-7890
SELECT '123-456-7890','('||SUBSTR('123-456-7890',1,3)||')'||SUBSTR('123-456-7890',5,8) FROM dual;
Using SUBSTR:
SQL> WITH sample_data AS(
2 SELECT '123-456-7890' num FROM dual
3 )
4 -- end of sample_data mimicking real table
5 SELECT num,
6 '('
7 || SUBSTR(num, 1, 3)
8 ||
9 ')'
10 || SUBSTR(num, 5, 8) AS my_num
11 FROM sample_data;
NUM MY_NUM
------------ ---------------
123-456-7890 (123)456-7890
SQL>
Remember, the index for SUBSTR starts from 1. It is bad practice to use 0 as starting index.
You could also do it using REGEXP_REPLACE.
Pattern: (\d{3})(-)(\d{3})(-)(\d{4})
Expression: regexp_replace(num, '(\d{3})(-)(\d{3})(-)(\d{4})', '(\1)\3\4\5')
For example,
SQL> WITH sample_data AS(
2 SELECT '123-456-7890' num FROM dual
3 )
4 -- end of sample_data mimicking real table
5 SELECT num,
6 regexp_replace(num, '(\d{3})(-)(\d{3})(-)(\d{4})', '(\1)\3\4\5') my_num
7 FROM sample_data;
NUM MY_NUM
------------ ---------------
123-456-7890 (123)456-7890
SQL>