我有以下查询,它在“Oracle SQL Developer”中工作。
在BIRT Eclipse中,我得到ORA-01722“非数字”错误。
使用TO_NUMBER()转换数字没有帮助。你有什么想法吗?
select INSTR_NR, VALID_FROM, PRICE, return, sqrt(ema)* 2.326347874041 as VaR1d
from
(select INSTR_NR, VALID_FROM, PRICE from
(select DATA_IDC, ATTR_IDC, VALUE as INSTR_NR
from DLEATTRDAT
where ATTR_IDC = 'FUND:fund:index_abbi_ref'
and LOCKSTATE = 0) x left join
(select DATA_IDC, VALID_FROM, VALUE as PRICE
from DLEATTRDAT
where ATTR_IDC = 'FUND:instr:EUR_price') y
on x.INSTR_NR = y.DATA_IDC)
model
partition by (INSTR_NR)
dimension by (VALID_FROM)
measures (PRICE,0 return,0 ema)
rules
( return[any] order by VALID_FROM
= nvl2
( PRICE[cv()-1]
, POWER ( ln ( PRICE[cv()] / (PRICE[cv()-1]) ), 2)
, POWER (ln ( PRICE[cv()] / (PRICE[cv()-3]) ), 2) )
,
ema[any] order by VALID_FROM
= nvl2
( return[cv()-1]
, .06 * return[cv()] + .94 * ema[cv()-1]
, return[cv()] ) )
order by INSTR_NR, VALID_FROM desc
答案 0 :(得分:1)
从您的查询中我得出结论,DLEATTRDAT表或视图中的列VALUE是VARCHAR2。 在您的查询中,您有时将其用作文本值(INSTR_NR),有时也用作数值(PRICE)。
简而言之,这是一个数据模型设计缺陷(我从经验中可以看出,我们在应用程序中遇到了类似的问题)。
稍后在您的查询中,您在数值计算中使用PRICE。
不幸的是,查询优化器可能会选择在之前或执行数值计算之前评估过滤器限制where ATTR_IDC = 'FUND:instr:EUR_price'
。
在这种一刀切的表格中,这是一个常见的陷阱。
在你的情况下,似乎优化器首先选择应用WHERE子句,然后进行转换,但是当从BIRT调用时,优化器反过来做了导致ORA-01722。
这既不是BIRT也不是DB中的错误;这是查询的问题以及我们人类思考Oracle DB应该如何工作的方式。
幸运的是, 方法可以在不重新处理数据模型的情况下处理此问题。
AFAIK WITH子句通常会强制优化器临时存储结果,因此处理此问题的一种方法可能是逻辑上等效但技术上不同的查询:
WITH x as (
select DATA_IDC, ATTR_IDC, VALUE as INSTR_NR
from DLEATTRDAT
where ATTR_IDC = 'FUND:fund:index_abbi_ref'
and LOCKSTATE = 0
),
y as (
select DATA_IDC, VALID_FROM, VALUE as PRICE
from DLEATTRDAT
where ATTR_IDC = 'FUND:instr:EUR_price'
)
select INSTR_NR, VALID_FROM, PRICE, return, sqrt(ema)* 2.326347874041 as VaR1d
from
(select INSTR_NR, VALID_FROM, PRICE
from x left join y
on x.INSTR_NR = y.DATA_IDC)
model
partition by (INSTR_NR)
dimension by (VALID_FROM)
measures (PRICE,0 return,0 ema)
rules
( return[any] order by VALID_FROM
= nvl2
( PRICE[cv()-1]
, POWER ( ln ( PRICE[cv()] / (PRICE[cv()-1]) ), 2)
, POWER (ln ( PRICE[cv()] / (PRICE[cv()-3]) ), 2) )
,
ema[any] order by VALID_FROM
= nvl2
( return[cv()-1]
, .06 * return[cv()] + .94 * ema[cv()-1]
, return[cv()] ) )
order by INSTR_NR, VALID_FROM desc
查看执行计划。 如果它没有创建SYS_xxxxx内联视图,优化器提示可能会有所帮助。
根据DLEATTRDAT表的大小,新查询可能比原始查询慢一点。
无论如何,您的查询中还有另一个错误:您正在使用从VARCHAR2到NUMBER的隐式转换,因为您在数值计算中使用PRICE。
所以你应该进一步修改可以查询并在适当的地方添加一个明确的TO_NUMBER。