Reputation: 758
I have many tables with a date in their name. For example MY_TABLE_2021_06_01, MY_TABLE_2021_06_02, etc
. I'm trying to extract the date from the table name and see if any tables are more than an year old. This is my code:
select * from (
select
table_name,
to_date(substr(table_name,-2,2)||'/'||substr(table_name,-5,2)||'/'||substr(table_name,-10,4),'DD/MM/YYYY') TABLE_DATE
from
all_tables
where
owner = 'my_schema'
and table_name like '%_20%'
)
where
TABLE_DATE < trunc(sysdate)-365;
The above code works fine if I don't include the where clause where table_date < trunc(sysdate)-365
. If I run the code with the where clause then I get the
ORA-01858: a non-numeric character was found where a numeric was expected 01858. 00000 - "a non-numeric character was found where a numeric was expected" *Cause: The input data to be converted using a date format model was incorrect. The input data did not contain a number where a number was required by the format model. *Action: Fix the input data or the date format model to make sure the elements match in number and type. Then retry the operation.
I tried a different and long-winded approach to see if I can get my code to work and it still throws the same error. My new code:
select * from (
select table_name, case when table_date < old_date then 1 else 0 end as OLD_TABLE from (
select
table_name,
to_date(substr(table_name,-2,2)||'/'||substr(table_name,-5,2)||'/'||substr(table_name,-10,4),'DD/MM/YYYY') TABLE_DATE,
trunc(sysdate)-365 OLD_DATE
from
all_tables
where
owner = 'my_schema'
and table_name like '%_20%'
)
)
where
old_table = 1
order by
old_table desc;
Again the above code works fine if I don't include where old_table = 1
clause but gives the same ORA-01858 error when the where clause is included. I don't understand this because the field OLD_TABLE
isn't a date field but still getting a date format error.
Upvotes: 1
Views: 2654
Reputation: 142733
Not all tables that satisfy these conditions:
owner = 'my_schema'
and table_name like '%_20%'
have "valid" date format, or it doesn't match format mask you used.
Note: if table name is MY_TABLE_2021_06_01
, why do you TO_DATE(..., 'DD/MM/YYYY')
?
2021_06_01
certainly isn't in DD/MM/YYYY
format, but rather YYYY_MM_DD
or YYYY_DD_MM
(can't tell, 06
can be both month or day; the same goes for 01
). Maybe your code will start working once you fix that.
If not, then list all tables with names like %_20%
and see which one(s) of them violate rules you set.
Example which works for me: sample tables first:
SQL> CREATE TABLE my_table_2021_06_01
2 (
3 id NUMBER
4 );
Table created.
SQL> CREATE TABLE some_other_table_2020_02_17
2 (
3 id NUMBER
4 );
Table created.
Query to extract tables whose "names" are older than 1 year:
SQL> WITH
2 tables
3 AS
4 (SELECT table_name,
5 TO_DATE (REGEXP_SUBSTR (table_name, '\d+_\d+_\d+'),
6 'yyyy_mm_dd') datum
7 FROM all_tables
8 WHERE owner = 'SCOTT'
9 AND table_name LIKE '%20%')
10 SELECT table_name
11 FROM tables
12 WHERE datum <= ADD_MONTHS (TRUNC (SYSDATE), -12);
TABLE_NAME
------------------------------
SOME_OTHER_TABLE_2020_02_17
SQL>
Upvotes: 1
Reputation: 1269853
I would use this logic to extract the dates:
select to_date(substr(table_name, -10) default null on conversion error, 'YYYY_MM_DD')
This should then work for comparisons to sysdate
.
This both handles table names that don't match the format and simplifies the date arithmetic.
Upvotes: 0