ORA-01722- Invalid Number - sql

I have a query in the package throwing error
ORA-01722 : invalid number.
I tried many ways but no luck.
select h.column
from table1 h,table2 c
where c.created_date='17-MAY-17'
and nvl(c.acct_nmbr,0)=nvl(to_number(h.v_acct_num),0)
c.acct_nmbr is of NUMBER(19,0)
h.v_acct_num is of varchar2(4000 byte)
Please suggest me the solution

If you are using Oracle 12.2 or higher then you can use the TO_NUMBER with ON CONVERSION ERROR clause as follows:
SELECT
H.COLUMN
FROM
TABLE1 H
JOIN TABLE2 C
ON NVL(C.ACCT_NMBR, 0) = NVL(TO_NUMBER(H.V_ACCT_NUM DEFAULT -999 ON CONVERSION ERROR), 0)
-- use any number which is impossible in your column
-- so that it do not match any random records.
WHERE
C.CREATED_DATE = DATE '2017-05-17';
Note:
Use standard ANSI joins
Use DATE literal wherever you want to convert string to date or TO_DATE function
Cheers!!

Obviously v_acct_num column contains non-numeric values. to_number() function has restriction that the value in the argument shouldn't contain any non-numeric character, otherwise the system hurls with ORA-01722 : invalid number. If you're sure about the data matches when non-numeric characters are extracted then use regexp_replace(t2.v_acct_num,'[^[:digit:]]') within the collation of the join's on clause :
select t2.column
from table1 t1
join table2 t2 on nvl(t1.acct_nmbr,0) = nvl(regexp_replace(t2.v_acct_num,'[^[:digit:]]'),0)
where t2.created_date = date'2017-05-17'
Use ANSI-92 standard for Join, and ISO-8601 standard for date syntaxes.

Identify what data is non-numeric:
select * from table1 h
where regexp_like(h.v_acct_num, '[^0-9]')
and delete them
.
Hope it helps.

Related

ORA-01722: invalid number, but removing DECODE statement returns results

I have a SQL query (below) where I'm getting an ORA-01722: invalid number error. Pretty common.
SELECT pt.DISPLAYNAME PARAM_NAME,
DECODE(rp.PARAMTYPE, 'POVLOC', l.PARTNAME, p.PARAM_VALUE) PARAM_VALUE
FROM schema2.OTHER_PARAMS p
JOIN schema2.TPARAMETER rp
ON rp.R_ID = 10230
AND p.PARAM_NAME = rp.PARAMNAME
JOIN schema2.TPARAMETER_TL pt
ON rp.PARAMID = pt.PARAMID
AND pt.LANGUAGE = 'en'
LEFT JOIN schema2.TPARTITION l
ON l.PARTITION = p.PARAM_VALUE
WHERE p.F_ID = 3669
ORDER BY rp.SEQ
Once I remove the DECODE statement and just have the PARAMTYPE column I get results. 1 column with PARAM_NAME (DISPLAYNAME column), the other with PARAM_VAL (PARAMTYPE column). All the datatypes in the DECODE are Varchar, so there are no conversions from number to char or vice versa. That's usually the most common reason this invalid number error occurs.
If it's not clear from above, what I want to do is insert some if/then logic on the PARAMTYPE column to update it. I was thinking about using a CASE statement for the PARAMTYPE variable, but I'm not sure what the best way to go about it is.
If your DECODE result values have both number and varchar, then you should force the first one to be a varchar to avoid convertion errors. In your case, just replace l.PARTNAME by TO_CHAR(l.PARTNAME).

How to select rows that have numbers as a value?

I have got a table with a column that is type of VARCHAR2(255 BYTE). I would like to select only these rows that have numbers as a value, so I discard any other values as for example "lala","1z". I just want to have pure numbers from 1 to ..... 999999999 (just digital numbers in other words) :P
Could you tell me how to make it?
if you're using Oracle 12c r2 or later then use the built-in validate_conversion() function:
select *
from your_table
where validate_conversion(cast(your_column as number)) = 0
validate_conversion() returns 0 when the proposed conversion would succeed and 1 when it wouldn't. It also supports date and timestamp conversions. Find out more.
Something like this is the usual option. You could use regexp, but it's usually a bit slower.
select column1
from tableA
where translate(column1, '1234567890', '') is null;
Here's the regexp version kfinity referred to. The regex matches a line consisting of 1 or more digits.
select column1
from tableA
where regexp_like(column1, '^\d+$');
You don't want zero to start a number. So it seems like regular expressions are the way to go:
where regexp_like(column1, '^[1-9][0-9]*$');

SELECT MAX keeps converting DATETIME to VARCHAR

Trying to write something that produces the MAX date for a record and then show all records that have a MAX date less than today, but the SQL query keeps converting the DATETIME field to a VARCHAR so I'm unable to use maxdate < GetDate()
The code I'm trying to use is
'Max Day'=(SELECT MAX (del.original_stop) FROM del, line WHERE del.obj_id=T2.obj_id AND del.type=0 AND line.opt <> 1)
T2.obj_id is defined in a LEFT OUTER JOIN in my main FROM clause.
Any ideas?
*Updating w/full query
SELECT
T1.doc AS "Document",
T1.owner AS "Own",
T1.last_up AS "Last Updated (EST)",
"Dollars"=ISNULL((SELECT CAST(SUM(fund_amt) AS DECIMAL(16,2)) FROM c_fund T3 WHERE T2.obj_id=T3.obj_id),0),
"Max Day"=(SELECT MAX(del.orig_stop) FROM del, line WHERE del.obj_id=T2.obj_id AND del.del_type=0 AND line.opt <> 1)
FROM
dsk T1 LEFT OUTER JOIN doc_object T2 ON T1.obj_id=T2.obj_id
WHERE
T1.icon_id=4
AND
T1.last_up >= '2018/01/21' AND T1.last_up <= '2018/01/24'
ORDER BY
"Last Updated (EST)" desc
And I know about the commas in the FROM clause, will fix those shortly.
Use as to assign aliases:
select (SELECT MAX(del.original_stop)
FROM del JOIN
line
ON del.obj_id=T2.obj_id AND del.type=0 AND line.opt <> 1
) as max_day,
. . .
Also, never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
If original_stop is a string, then my first advice is to fix the data. You should be storing dates and times in native formats, not as strings.
If for some reason you cannot fix the data model, then you can use convert() . You'll need to peruse the formats available for the function.

ORA-01722: invalid number error

I am running the below mentioned query in my Oracle client and i am getting
ORA-01722: invalid number
error. I know the issue is due to the TAG_VALUE column being of type "varchar2" and i am converting it to number and then using that field in where clause. I have tried using "CAST" function but that is also not helping.
If i run the query neglecting the last where condition with code WHERE (P.TAG_VALUE > '100') then i am getting the result but including the last where clause gives me error.
SELECT DISTINCT
count(P.CREATED_DATETIME)
FROM
(
select OUTPUT_TAG_ID,TO_NUMBER(TAG_VAL,'9999.99') AS
TAG_VALUE,TAG_VAL_TS,CREATED_DATETIME
from OV80STG.PRCSD_DATA_OUTPUT_ARCHIVE
where MODEL_CODE='MDLADV1538'
AND TAG_VAL <> 'U_Transfer_rate'
) P
WHERE
(P.TAG_VALUE > '100')
Any suggestion will be appreciated. Thanks.
Remove the single quotes from around the value in the where, you don't need them when its an integer. query will be like this:
SELECT DISTINCT
COUNT(P.CREATED_DATETIME)
FROM
(
SELECT
OUTPUT_TAG_ID,
TO_NUMBER(TAG_VAL, '9999.99') AS TAG_VALUE,
TAG_VAL_TS,
CREATED_DATETIME
FROM OV80STG.PRCSD_DATA_OUTPUT_ARCHIVE
WHERE MODEL_CODE = 'MDLADV1538'
AND TAG_VAL <> 'U_Transfer_rate'
) P
WHERE(P.TAG_VALUE > 100);
TO_NUMBER function returns a numeric value so, as mentioned in comment, you shouldn't compare it with string value.
I solved the issue by including outer where clause inside the subquery and then I got the required result without any error.

ORA-01797: this operator must be followed by ANY or ALL error

While I am executing the query,
select *
from file_log f
where F.DCP_SRCE_FILENM_FK in ('ABC','DEF') and
F.TRANS_DT>=to_date('08/25/2017','mm/dd/yyyy') and
F.TRANS_DT<=('08/30/2017','mm/dd/yyyy')
am getting the following error:
ORA-01797: this operator must be followed by ANY or ALL.
Could you all please help me in writing the proper query so that this error would go?
Just use the date keyword and ISO constants:
select *
from file_log f
where F.DCP_SRCE_FILENM_FK in ('ABC','DEF') and
F.TRANS_DT >= date '2017-08-25' and
F.TRANS_DT <= date '2017-08-30';
You are getting the error because the second constant is missing to_date(). But you might as well use the proper syntax for a date constant.
You are missing TO_DATE:
select *
from file_log f
where F.DCP_SRCE_FILENM_FK in ('ABC','DEF') and
F.TRANS_DT>=to_date('08/25/2017','mm/dd/yyyy') and
F.TRANS_DT<=TO_DATE('08/30/2017','mm/dd/yyyy') -- Missing on this line
Why it is throwing that exception:
The SQL parser cannot discern that you intended to use a TO_DATE function and assumes the final line is trying to compare F.TRANS_DT with one (ANY) or both (ALL) the values ('08/30/2017','mm/dd/yyyy') so is assuming the query should have the syntax:
select *
from file_log f
where F.DCP_SRCE_FILENM_FK in ('ABC','DEF') and
F.TRANS_DT>=to_date('08/25/2017','mm/dd/yyyy') and
F.TRANS_DT<= ANY ('08/30/2017','mm/dd/yyyy')
Which is a syntactically valid query. It would not, however, execute as trying to parse the F.TRANS_DT <= 'mm/dd/yyyy' comparison will result in trying to implicitly convert the string on the right-hand side to a date which is almost certain to fail with ORA-01858: a non-numeric character was found where a numeric was expected. But the SQL parser has done its best to suggest what is missing to make the query valid.
For those who end up searching for ORA-01797 error:
This error appears when right side of a logical operator ( =, !=, >, <, <=, >= ) contains multiple values.
Possible solutions:
Make sure right hand side of the logical operator contains a single value.
Handle multiple values by using IN instead of ( = ) and NOT IN instead of ( != )
Handle multiple values by using ALL, ANY or SOME as documented.