Oracle differences using Quotes in case statement and insert - sql

I encountered this scenario where the insert based on '' on number column works fine while the case statement gives different error.
"inconsistent datatypes: expected %s got %s"
I have gone through some of the explanation given here (ORA-00932 inconsistent datatypes expected char got number ) and Oracle SQL CASE WHEN ORA-00932: inconsistent datatypes: expected CHAR got NUMBER 00932. 00000 - "inconsistent datatypes: expected %s got %s" and I understand that I need to use it without quotes but I wanted to understand the behavior of case statement. SQL server does not behave like this, but why only oracle. Is this oracle default behavior with case statement.
If I create and insert values, I can do it without any error.
create table testtbl (name varchar2(50), id number(10,2));
insert into testtbl values ('abc', '123');
insert into testtbl values ('test', '200');
When I try to update the column using case statement I am getting this error. I can use to_number or remove the quotes to avoid this error but wanted to understand why it happens with quotes when the column given in the else statement is number itself. Doesn't implicit conversion exist in Oracle?
update testtbl
set id = case when name = 'abc' then '5000' else id end;

Doesn't implicit conversion exist in Oracle?
It does. See documentation eg here.
Is this oracle default behavior with case statement.
Yes. From the documentation:
For both simple and searched CASE expressions, all of the return_exprs must either have the same datatype (CHAR, VARCHAR2, NCHAR, or NVARCHAR2, NUMBER, BINARY_FLOAT, or BINARY_DOUBLE) or must all have a numeric datatype.

Related

Why am I receiving the PSL-00103 Error in Oracle SQL?

I am trying to make a procedure that would insert a row into a table in Oracle SQL. However, I can't figure out a solid reason on why this issue exists when I write any type of procedure.
I have tried changing the syntax around a couple of times, but I still don't know how to remedy the issue.
Errors given:
Error at line 1: PLS-00103: Encountered the symbol ")" when expecting one of the following: in out table ... columns long double ref char time timestamp interval date binary national character nchar
Error at line 5: PL/SQL: SQL Statement ignored Error at line 6: PL/SQL: ORA-00984: column not allowed here
Code:
create or replace procedure insert_category(
category_name_param in categories.category_name%type)
as
begin
insert into categories (category_id, category_name)
values (category_id, category_name_param);
end;
It seems that procedure lacks in yet another parameter; see if this helps (I presumed that such a column exists in the table; can't be sure as you didn't post table description):
create or replace procedure insert_category(
category_name_param in categories.category_name%type,
category_id_param in categories.category_id%type --> this
)
as
begin
insert into categories
(category_id,
category_name)
values
(category_id_param, --> this
category_name_param);
end;

Getting ORA-06502: PL/SQL: numeric or value error: character to number conversion error in SQL trigger

I'm getting below error in the web methods adapter on the table which has the MIH_TRIGGER.
(65000/6502) ORA-06502: PL/SQL: numeric or value error: character to
number conversion error ORA-06512: at
"B2B_OPS_BUILD_ADMIN.MIH_TRIGGER", line 2 ORA-04088: error during
execution of trigger 'B2B_OPS_BUILD_ADMIN.MIH_TRIGGER'
Below is the MIH_TRIGGER fore reference which will update the data from OPS_BUILD_MIH table to OPS_BUILD_AUDITLOG table whenever OFFSET column is updated.
The OFFSET column in OPS_BUILD_MIH is NUMBER
The OLD_VALUE and NEW_VALUE columns in OPS_BUILD_AUDITLOG are VARCHAR2(100).
I'm trying to insert a numeric value which is in OFFSET column into the OLD_VALUE and NEW_VALUE varchar2 columns and getting this error.
create or replace TRIGGER "B2B_OPS_BUILD_ADMIN"."MIH_TRIGGER"
AFTER UPDATE OF OFFSET
ON OPS_BUILD_MIH
FOR EACH ROW
BEGIN
if ( nvl(:OLD.OFFSET,'xYz##!0') != nvl(:NEW.OFFSET,'xYz##!0')) then
INSERT INTO OPS_BUILD_AUDITLOG
(TABLE_NAME,
COLUMN_NAME,
OLD_VALUE,
NEW_VALUE,
UPDATED_BY,
UPDATED_DTM,
UUID)
VALUES
('OPS_BUILD_MIH',
'OFFSET',
:OLD.OFFSET,
:NEW.OFFSET,
:NEW.LAST_UPDATED_BY,
:NEW.LAST_UPDATED_DTM,
:OLD.MIH_ID);
end if;
END;
Can you please suggest a fix for this so that I can modify the above trigger accordingly.
Appreciate your help in advance.
Regards
Phani
As Gaj has already pointed out, the issue lies with your NVL - you're trying to compare a non-numeric string to a number, which won't work.
Whilst you could change the NVL to check for a numeric value you will never encounter, it would be far better to change the condition to:
:OLD.OFFSET != :NEW.OFFSET
or (:OLD.OFFSET is not null and :NEW.OFFSET is null)
or (:OLD.OFFSET is null and :NEW.OFFSET is not null)
That way, you don't have to make up a magic number that your actual values could never be; assuming such a number even exists!

Why am I getting ORA-00904: invalid identifier for deterministic function index?

create or replace function idxF(status IN char) return char deterministic is
retVal CHAR(1);
begin
dbms_output.put_line('P');
retVal:=CASE status
when 'P' then 'P'
when 'H' then 'H'
else null
end ;
return retVal;
end idxF;
create index setIndexOnStatus on ORDER(idXF(STATUS));
SQL Error: ORA-00904: "IDXF": invalid identifier
STATUS is a CHAR(1) column in ORDER table.
Why is the compiler saying that IDXF is an invalid identifier?
ORDER is a reserved word in Oracle (part of ORDER BY clause) so you shouldn't use it as a name for your table.
Technically, you can escape a reserved word with double quotes:
create index setIndexOnStatus on "ORDER"(idXF(STATUS));
Probably, this table was created like this in a first place.
This approach is extremely problematic because you'll need to escape every query to this table and it's not always possible, especially with auto-generated queries.
So, don't go this way, rename the table instead.
P.S. I couldn't reproduce ORA-00904 on this query. Invalid table name leads to ORA-00903: invalid table name. Escaped query works fine for me. If you still have ORA-00904 error then you'll need to build a reproducible example to demonstrate your problem (i.e. include CREATE TABLE statement and specify the Oracle version).

Insert table data with column datatype varchar2 to a table with column datatype as number

In oracle DB I have a table TABLE1 with column datatype defined as VARCHAR2(50). I have another table TABLE2 with column datatype defined as a NUMBER. The no of rows present in the TABLE1 is around 23k and they all seems to be number. But when I try the insert command I get the below error.
Error report -
SQL Error: ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause:
*Action:
This clearly means that there are few rows that are not numbers. But I am not able to identify those no numeric cases. How do I identify the non numeric rows.
P.S:
Oracle database version : 9.2.0.8.0
And yes I know its ancient.
Why are you storing numbers in a string? That is the fundamental problem.
You can avoid the rows using a where clause:
insert into table2( . . .)
select . . .
from table1 t1
where regexp_like(numbercol, '^[0-9]+$')
This assumes that "number" means "non-negative integer". Obviously the pattern can be generalized for other ranges and/or numeric formats.
You can just identify the non-numeric rows by running a similar select:
select . . .
from table1 t1
where not regexp_like(numbercol, '^[0-9]+$')
Below is the PL SQL block used to identify the discrepancy cases. The special character in my case was double quotes. There were few cases with issue so printing the output was feasible. If there are more number of discrepancy cases then capturing the error msg in a table column will be helpful.
declare
cursor cur is
select * from TABLE1 ; ----- cursor to loop through cases individually
begin
for rec in cur
loop
begin
insert into table2 (column1)
select to_number(column1)
from table1
where
column1=rec.column1 ;
exception when others
then
Dbms_Output.Put_Line('error for '||rec.column1||' '||substr(sqlerrm,0,150)); --- error msg with discrepancy case
end;
end loop;
end;
/

Oracle Error "inconsistent datatypes: expected CHAR got LONG"

I'm trying to run the following query to find views containing a given keyword:
select *
from ALL_VIEWS
where OWNER = 'SALESDBA'
and TEXT like '%rownum%';
I'm getting the following error message:
ORA-00932: inconsistent datatypes: expected CHAR got LONG
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 4 Column: 13
if I just select from ALL_VIEWS than I see the query (TEXT) in the TEXT field.
What am I doing wrong here?
Your problem is that TEXT is of type LONG - although Oracle deprecated this type a long, long time ago, they're still using it in their own views :-(
To convert a LONG to a (searchable) CLOB, you can use the TO_LOB() function (see Oracle documentation for TO_LOB().
Unfortunately, this doesn't work for simple SELECT statements. You'll have to create an intermediary table:
create table search_all_views as
select av.owner, av.view_name, to_lob(text) as text_clob
from ALL_VIEWS av;
Then, you can search using that table:
select *
from search_all_views
where text_clob like '%rownum%';
You could use TEXT_VC as the column to check criteria against. For example:
select *
from ALL_VIEWS
where OWNER = 'SALESDBA'
and TEXT_VC like '%rownum%';
I hope this helps.