How to debug the error "Implicit conversion from datatype 'X' to 'Y' is not allowed"? - oracle

While running the below query, I am getting error for field error_num:
Implicit conversion from datatype 'VARCHAR' to 'INT' is not allowed.
Use the CONVERT function to run this query.
Below is the query
select top 100"Insert into KLG_TRN_SCE..dbBatchRequest values ('"
+ comp_nr
+"','"
+ ssn_nr
+"','"
+ convert(char(10),Version,101)
+"','"
+ plan_nr
+"','1"
+"','"
+ CAST(LEFT(error_num, 4) AS int)
+"',"
+ error_txt
+"',"
+ addname
+"',"
+ convert(char(10),adddate,101)
+"')"
From KLG_TRN_SCE..dcErrorBin
Where ssn_nr='603761193'

It appears you're trying to use Sybase or T-SQL against an oracle database. The syntax between databases vary slightly especially around dates, string concat, and string parsing.
So are you looking for execution against Oracle or another database? if oracle, the below should be close.
I'm not sure what you meant by version or what formats you wanted the dates to be in, but this seems to run. I used a with (Common table expression) to stage some data to ensure it ran after all the changes.
So your issues:
No such thing as top we could limit by a rowNum < 101; but an order by should be used
in oracle || is operator for string concat not +
convert(char(10),Version,101) you appear to believe is a date but this is not true in oracle unless version is a field with a date... in which case to_date(version,'DD/MM/YYYY') may be desired?
quotes "are used for field notation much like [] are in T-SQL so to build a dynamic insert, I concat chr(39).
CAST(LEFT(error_num, 4) AS int) is invalid you need to use substr(error_num, 1,4) in oracle
convert(char(10),adddate,101) is invalid in Oracle perhaps you mean to_date(adddate,'MM/DD/YYYY')
.
with dcErrorBin(comp_nr, ssn_nr, version,plan_nr, error_num, error_txt,Addname,adddate) as
(Select 1,'603761193',(SELECT WM_CONCAT(BANNER) FROM V$VERSION),'Three','1234-hello','Error_txt','AddName',sysdate from dual)
SELECT
'Insert into KLG_TRN_SCE..dbBatchRequest values (' || chr(39)
|| comp_nr||Chr(39)
||','
|| chr(39)||ssn_nr||Chr(39)
||','
|| chr(39)||replace(Version,',','~~') || chr(39)
||','
|| chr(39)||plan_nr||Chr(39)
||',1'
||','
|| CAST(substr(error_num,1,4) AS int)
||','
|| chr(39)||error_txt||Chr(39)
||','
|| chr(39)||addname||chr(39)
||','
|| 'to_date('||chr(39)||adddate||chr(39)||','||chr(39)||'DD-MON-YY'||chr(39)||')'
||')'
FROM dcErrorBin
WHERE ssn_nr='603761193'
and rowNum <= 100
ORDER BY ADDDate Desc; --Perhaps order by add date desc so you get most recent errors?
RESULTED IN:
Insert into KLG_TRN_SCE..dbBatchRequest values
('1'
, '603761193'
, 'Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
~~PL/SQL Release 11.2.0.4.0 - Production
~~CORE 11.2.0.4.0 Production
~~TNS for Linux: Version 11.2.0.4.0 - Production
~~NLSRTL Version 11.2.0.4.0 - Production'
, 'Three'
, 1
, 1234
, 'Error_txt'
, 'AddName'
, to_date('14-DEC-16','DD-MON-YY'))
The inserts would error out if
I'm using the wrong date formats
don't have the proper values wrapped in tics
error_num's 1st 4 characters are not numeric.

Related

"ORA-00936: missing expression" on DATE

at work we're undergoing a migration from DB2 for iSeries SQL to Oracle SQL and are experiencing some pains. I'd still consider myself a beginner with SQL and can't figure out what Oracle SQL doesn't like about this clause.
CASE
WHEN YYCOL IS NULL THEN NULL
ELSE max ( DATE ( MMCOL || '/' || DDCOL || '/' || YYCOL ) )
END AS COLUMN007
When querying with the above clause:
ORA-00936: missing expression
ELSE max ( DATE ( MMCOL || '/' || DDCOL || '/' || YYCOL ) )
^
If possible, is there some easy to digest documentation for moving from DB2 for iSeries SQL to Oracle SQL? Any help is appreciated!
You have to use -
CASE
WHEN YYCOL IS NULL THEN NULL
ELSE max ( TO_DATE ( MMCOL || '/' || DDCOL || '/' || YYCOL, 'MM/DD/YY' ) )
END AS COLUMN007
"so it only shows the date stamp" The to_date converts the provided string to oracle internal, binary DATE datatype, which also always includes the time down to the second. But to "show" a date, that DATE type has to be converted back to a string of characters. This is normally done by use of TO_CHAR, providing a DATE and a 'format mask'. Since you did not provide that, oracle was forced to do it implicitly, and use the effective value of NLS_DATE_FORMAT. If want it to only "show" the date, then
to_char(to_date(MMCOL||'/'||DDCOL||'/'||yycol,'mm/dd/yy'),'mm/dd/yyyy')
I encourage you to go to the official oracle docs and look up the to_date and to_char function. See also an article I wrote on it, at https://edstevensdba.wordpress.com/2011/04/07/nls_date_format/
As an aside, please quit using 2-digit years. 20 years ago I and thousands of guys like me were busting our butts to prevent a meltdown on 1-Jan-2000. And just last week I read an article that systems that had kicked the can down the road with a 'pivot date' were now coming to grief as of 1-Jan-2020. Please quit repeating the same mistakes we were supposed to have corrected 20 years ago.

Oracle. CAST COLLECT for date datatype

Consider the types:
CREATE OR REPLACE TYPE date_array AS TABLE OF DATE;
CREATE OR REPLACE TYPE number_array AS TABLE OF NUMBER;
CREATE OR REPLACE TYPE char_array AS TABLE OF VARCHAR2(80);
Queries:
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(ID) AS number_array)
FROM q;
return collection of numbers
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(STRING) AS char_array)
FROM q;
return collection of strings
WITH q AS
(SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(MyDate) AS date_array)
FROM q
return error invalid datatype.
Can anyone explain why the Date datatype behaves differently?
Here are my findings... it seems you are facing a bug caused by the fact that calculated dates seem to have a different internal representation from "database" dates. I did find a workaround, so keep on reading.
On my oracle dev installation (Oracle 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production) I am experiencing your same problem.
BUT... If I create a physical table containing your test data:
create table test_data as
SELECT LEVEL ID,
TRUNC(SYSDATE) + LEVEL MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5
and then run the "cast collect" operator on this physical table, it works as expected:
-- this one works perfectly
SELECT CAST(COLLECT(MyDate) AS date_array) from test_data
but all these examples still do NOT work:
-- here I just added 1 .. and it doesn't work
SELECT CAST(COLLECT(MyDate + 1) AS date_array)
from test_data
-- here I am extracting sysdate, instead of a physical column... and it doesn't work
SELECT CAST(COLLECT(sysdate) AS date_array)
from test_data
It feels like oracle doesn't think that calculated dates are the same thing of physical dates
So, I tried to "persuade" oracle that the data I am providing is actually a normal DATE value, using an explicit cast... and EUREKA! this does the job correctly:
WITH q AS
(SELECT LEVEL ID,
-- this apparently unnecessary cast does the trick
CAST( TRUNC(SYSDATE) + LEVEL AS DATE) MyDate,
to_char(LEVEL) STRING
FROM dual
CONNECT BY LEVEL < 5)
SELECT CAST(COLLECT(MyDate) AS date_array)
FROM q
Yes... but why??
It really seems that these two values are not exactly the same thing, even if the values we see are actually the same:
select sysdate, cast (sysdate as date) from dual
So I dug in the internal representation of the two values applying the "dump" function to both of them:
select dump(sysdate), dump(cast (sysdate as date)) from dual
and these are the results I got:
DUMP(SYSDATE ) -> Typ=13 Len=8: 226,7,11,9,19,20,47,0
DUMP(CAST(SYSDATEASDATE) as DUAL) -> Typ=12 Len=7: 120,118,11,9,20,21,48
Internally they look like two totally different data types! one is type 12 and the other is type 13... and they have different length and representation.
Anyway I discovered something more.. it seems someone else has noticed this: https://community.oracle.com/thread/4122627
The question has an answer pointing to this document: http://psoug.org/reference/datatypes.html
which contains a lengthy note about dates... an excerpt of it reads:
"What happened? Is the information above incorrect or does the DUMP()
function not handle DATE values? No, you have to look at the "Typ="
values to understand why we are seeing these results. ". The datatype
returned is 13 and not 12, the external DATE datatype. This occurs
because we rely on the TO_DATE function! External datatype 13 is an
internal c-structure whose length varies depending on how the
c-compiler represents the structure. Note that the "Len=" value is 8
and not 7. Type 13 is not a part of the published 3GL interfaces for
Oracle and is used for date calculations mainly within PL/SQL
operations. Note that the same result can be seen when DUMPing the
value SYSDATE."
Anyway, I repeat: I think this is a bug, but at least I found a workaround: use an explicit cast to DATE.

Missing right parenthesis in function [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am new to this forum. i got an error
ERROR - ORA-00907: missing right parenthesis
when i try to run my query, Please do help me out in solving this problem,Please do find the query below Thanks in advance!
I am writing a function as below -
create or replace
function ATOS_GET_GDC_ROLLUP (p_gdc in varchar, p_year in number, p_userid in number, p_gdcpara in varchar) return ATOS_CAPACITY_ROLLUP_TYPE_SI
as
v_capacity_rollup_si ATOS_CAPACITY_ROLLUP_TYPE_SI;
v_name varchar2(255);
v_month varchar2(20);
v_budget number;
v_supply number;
v_pipeline number;
v_demand number;
v_monthtext varchar2(3);
v_monthvalue number;
i number;
code number;
CURSOR c_get_capacity_rollup IS select par.INVESTMENT,
decode(par.partime,null,children.childtime,par.par time),
decode(par.BUDGET,null,children.BUDGET,0,children. BUDGET,par.BUDGET),
decode(par.SUPPLYSIDE,null,children.SUPPLYSIDE,0,c hildren.SUPPLYSIDE,par.SUPPLYSIDE),
decode(par.PIPELINE,null,children.PIPELINE,0,child ren.PIPELINE,par.PIPELINE),
decode(par.DEMANDSIDE,null,children.DEMANDSIDE,0,c hildren.DEMANDSIDE,par.DEMANDSIDE),
case (decode(par.monthvalue,null,children.monthvalue,pa r.monthvalue))
when 1 then 'Jan'
when 2 then 'Feb'
when 3 then 'Mar'
when 4 then 'Apr'
when 5 then 'May'
when 6 then 'Jun'
when 7 then 'Jul'
when 8 then 'Aug'
when 9 then 'Sep'
when 10 then 'Oct'
when 11 then 'Nov'
when 12 then 'Dec'
else ''
end as monthtext,
(decode(par.monthvalue,null,children.monthvalue,pa r.monthvalue)) monthvalue
from
(select
(budp.periodyear || '-' || lpad(budp.periodnumber, 2, '0')) partime,
reqp.name INVESTMENT,
budp.budget BUDGET,
budp.actual SUPPLYSIDE,
budp.user1 PIPELINE,
budp.user4 DEMANDSIDE,
budp.periodnumber monthvalue
from tr_request reqp
inner join tr_resourcebudget budp on reqp.requestid = budp.requestid
where budp.periodyear= p_year
and reqp.requestid = (select I_GDC.REQUESTID
from TR_REQUEST I_GDC
where I_GDC.NAME = p_gdcpara
and A7_GET_RQV (I_GDC.REQUESTID, 'Investment Category', 'C') = 'Global Delivery Centre (GDC)'
and (p_gdc = 'ALL' or p_gdc = I_GDC.NAME)
and exists (select null
from TR_REQUESTACCESS RA
where RA.REQUESTID = I_GDC.REQUESTID
and RA.RESOURCEID = p_userid)))par
FULL OUTER JOIN
(select
(budc.periodyear || '-' || lpad(budc.periodnumber, 2, '0')) childtime,
SUM(budc.budget) BUDGET,
SUM(budc.actual) SUPPLYSIDE,
SUM(budc.user1) PIPELINE,
SUM(budc.user4) DEMANDSIDE,
budc.periodnumber monthvalue
from tr_request reqc
inner join tr_resourcebudget budc on reqc.requestid = budc.requestid
where budc.periodyear= p_year
and reqc.requestid IN (SELECT requestid FROM TR_REQUEST
WHERE CONNECT_BY_ISLEAF=1
CONNECT BY PRIOR requestid = parentid
START WITH requestid = (select I_GDC.REQUESTID
from TR_REQUEST I_GDC
where I_GDC.NAME = p_gdcpara
and A7_GET_RQV (I_GDC.REQUESTID, 'Investment Category', 'C') = 'Global Delivery Centre (GDC)'
and (p_gdc = 'ALL' or p_gdc = I_GDC.NAME)
and exists ( select null
from TR_REQUESTACCESS RA
where RA.REQUESTID = I_GDC.REQUESTID
and RA.RESOURCEID = p_userid)))
group by budc.periodnumber, (budc.periodyear || '-' || lpad(budc.periodnumber, 2, '0')))children
ON par.partime = children.childtime;
begin
if not c_get_capacity_rollup%ISOPEN then
open c_get_capacity_rollup;
end if;
i := 0;
v_capacity_rollup_si := ATOS_CAPACITY_ROLLUP_TYPE_SI();
loop
fetch c_get_capacity_rollup into v_name, v_month, v_budget, v_supply, v_pipeline, v_demand, v_monthtext,v_monthvalue;
exit when c_get_capacity_rollup%NOTFOUND;
i := i + 1;
v_capacity_rollup_si.extend(1);
v_capacity_rollup_si(i) := ATOS_CAPACITY_ROLLUP_RECORD_SI(v_name, v_month, v_budget, v_supply, v_pipeline, v_demand, v_monthtext, v_monthvalue);
end loop;
close c_get_capacity_rollup;
return v_capacity_rollup_si;
end ATOS_GET_GDC_ROLLUP;
/
when i run below query :-
select * from table(ATOS_GET_GDC_ROLLUP('India',2013,400,'India' ))
i am getting missing paranthisis error at line 18 and 91. But when i run query for cursor then i am getting correct output.I confirm that parenthesis are balanced. Please tell me know what is wrong in above query. Please let me know if you need more details.
I am using below version-
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
"CORE 10.2.0.1.0 Production"
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
The error you're getting doesn't always mean there's an unmatched bracket. Sometimes the compiler throws that error when we have made a syntax error and it finds a keyword it is not expecting when it has an unpaired left bracket.
But then you say:
"when i run query for cursor then i am getting correct output.I
confirm that parenthesis are balanced."
Hmmm, okay then the problem is likely to be this:
"Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod"
That is the unpatched first release of 10gR2. Normally we would expect to be able to run in PL/SQL any query which we can run in SQL. However, there are sometimes bugs, especially in the initial version of a major release, which break the contract.
There have been three or four major patch sets (depending on your OS) over the years. Anybody still running on the original release is presumably doing so because they don't have a support contract and so can't patch their database. If so, that rules out upgrading your database as a potential solution.
The only other thing you can do is debug your query. It is extremely complicated with lots of nested sub-queries (and lots of parentheses). It is likely to be something in the depths of those sub-queries which is causing the problem. So, start removing some of the complexity from your query and seeing when your query starts working. Then you know which bit of logic you need to rewrite.
The other thing to try is simplifying the procedure. You don't need all that CURSOR and LOOP infrastructure. You could just use Plain Old SQL Query with BULK COLLECT to populate v_capacity_rollup_si. Or extract the query from the procedure and hide it behind a view. Either of these things might solve the problem, because the problem is the interaction between SQL and PL/SQL, and not the actual query.

PLSQL Date Filter Error

I have a table with data since 2012. I need to get data in this table from 31 days back from given date. so i wrote below query to get data.
select ('[' || work_date || '] ' || field_name || ' - ' ||work_desc) d
from DAILY_WORK
where TO_CHAR(work_date,'DD/MM/YYYY') >= TO_CHAR(to_date('30-Jan-13','dd-MON-yyyy') - (31),'DD/MM/YYYY')
order by work_date desc
When i execute this query, it returns data in below dates only.
31-AUG-12
31-OCT-12
30-DEC-12
31-DEC-12
But actually i need to get data from 2012-12-30 to 2013-01-30.
How could i do this ?
use this:
select ('[' || to_char(work_date, 'dd-MON-yyyy') || '] ' || field_name || ' - ' ||work_desc) d
from DAILY_WORK
where work_date >= to_date('30-Jan-2013','dd-MON-yyyy') - 31
order by work_date desc
You can use the below query:
select * from DAILY_WORK where work_date >= TRUNC(to_date('01-30-2013','MM/DD/YYYY')) - 31
Check date format which tool you are using As per tool i am using date format is 'MM/DD/YYYY'
This query give correct result.You can check.

How to use SELECT result record as DECODE parameters?

Is it possible to use SELECT result as DECODE parameters when this SELECT returns only one record with prepared string?
For example:
SELECT replace(replace(serialized_data)..)..) as result FROM table
Returns following result in ONE ROW:
0,'label0',1,'label1',2,'label2'
But when I put this to DECODE it's being interpreted as ONE PARAMETER.
Is there possiblity to convert this result "string" to "pure" sql code? ;)
Thanks for any help.
You could kind of replicate decode by use of instr and substr. An example below (which could probably be tidied up considerably but works):
select DTXT
,Nvl(
Substr(
DTXT
,Instr(DTXT, SEARCHTXT || VALMTCH)
+ Length(SEARCHTXT || VALMTCH)
, Instr(DTXT, VALSEP, Instr(DTXT, SEARCHTXT || VALMTCH))
- Instr(DTXT, SEARCHTXT || VALMTCH)
- Length(SEARCHTXT || VALMTCH))
,CASEOTHER)
as TXTMATCH
from (select '0=BLACK;1=GREEN;2=YELLOW;' as DTXT
,'1' as SEARCHTXT
,';' as VALSEP
,'=' as VALMTCH
,'OTHER' as CASEOTHER
from Dual)
You do need to have a semi-colon (VALSEP) at the end of the text though to ensure you can find the last value (though it's possible to work around that if I looked into it further).
list_agg or wm_concat depending on version of oracle.
http://docs.oracle.com/cd/E14072_01/server.112/e10592/functions087.htm
You can use dynamic SQL:
declare
DECTXT varchar2(4000);
begin
select replace(replace(serialized_data)..)..) as result into dectxt from table;
execute immediate 'select decode(col1,' || DECTXT || ') from tab1';
end;
This is just a quick example, not showing any output, etc.

Resources