英文:
When running on sas it gives ERROR: CLI open cursor error: [Oracle][ODBC][Ora]ORA-01722: invalid number
问题
proc sql;
connect to odbc(user='' pwd='' datasrc='');
create table Hums_Table(compress=yes) as
select * from connection to odbc
(
select prop.cust_pivotal_id, prop.cust_pivotal_app_id, prop.cust_renew_flag, prop.is_cust_split, prop.cont_agt_brk_channel, prop.cont_plan_id, prop.decision_id_fk, deci.decision, prop.cust_corr_pin_code, prop.cust_corr_city_code_fk, pl.sum_assured, pl.product_name, Ct.City_name from ADMIN.t_proposal_info Prop
inner join ADMIN.t_plan_type PL on replace(prop.cont_plan_id,'~',NULL)=PL.plan_code
inner join ADMIN.t_underwriting_decision deci on prop.decision_id_fk=deci.o_id
inner join admin.t_city CT on prop.cust_corr_city_code_fk=ct.city_name
left join admin.T_tele_docsapp_data doc on replace(prop.cust_app_no,'~',NULL)=doc.application_no
where Prop.create_date between '01-Mar-2023' and '31-Mar-2023'
);
disconnect from odbc;
quit;
在运行SAS时出现错误:CLI打开游标错误:[Oracle][ODBC][Ora]ORA-01722:无效的数字。
英文:
proc sql;
connect to odbc(user='' pwd='' datasrc='');
create table Hums_Table(compress=yes) as
select * from connection to odbc
(
select prop.cust_pivotal_id, prop.cust_pivotal_app_id, prop.cust_renew_flag, prop.is_cust_split, prop.cont_agt_brk_channel, prop.cont_plan_id, prop.decision_id_fk, deci.decision, prop.cust_corr_pin_code, prop.cust_corr_city_code_fk, pl.sum_assured, pl.product_name, Ct.City_name from ADMIN.t_proposal_info Prop
inner join ADMIN.t_plan_type PL on replace(prop.cont_plan_id,'~',NULL)=PL.plan_code
inner join ADMIN.t_underwriting_decision deci on prop.decision_id_fk=deci.o_id
inner join admin.t_city CT on prop.cust_corr_city_code_fk=ct.city_name
left join admin.T_tele_docsapp_data doc on replace(prop.cust_app_no,'~',NULL)=doc.application_no
where Prop.create_date between '01-Mar-2023' and '31-Mar-2023'
);
disconnect from odbc;
quit;
When running on sas it gives ERROR: CLI open cursor error: [Oracle][ODBC][Ora]ORA-01722: invalid number
答案1
得分: 1
Oracle会尝试在执行比较之前对数据类型进行对齐。例如,考虑表T,其中有一列你期望是数字类型的:
SQL> create table t ( my_semi_numeric_value varchar2(10));
Table created.
SQL>
SQL> insert into t values ('10');
1 row created.
SQL> insert into t values ('20');
1 row created.
SQL>
SQL> set autotrace traceonly explain
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 14 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 14 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("MY_SEMI_NUMERIC_VALUE")>0)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
SQL> set autotrace off
你可以看到在执行计划中,我们在列周围默默添加了TO_NUMBER函数,因为你在比较时使用了数字(> 0)。因此,当前查询将正常运行:
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
MY_SEMI_NU
----------
10
20
但如果有人在该列中插入了一些错误的数据,例如:
SQL> insert into t
2 values ('~10');
1 row created.
现在当我运行该查询时,TO_NUMBER函数将失败,因此你的查询也将失败:
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
where my_semi_numeric_value > 0
*
ERROR at line 3:
ORA-01722: invalid number
根据你的数据库版本,你可以自行处理这个问题:
SQL> select *
2 from t
3 where to_number(my_semi_numeric_value default -1 on conversion error) > 0 ;
MY_SEMI_NU
----------
10
20
但正如其他人提到的,你需要检查查询中使用的每个列的数据类型,包括你的连接列。
英文:
Oracle will try to get the data types aligned before doing a comparison. For example, consider table T with a column that you expect to be numeric
SQL> create table t ( my_semi_numeric_value varchar2(10));
Table created.
SQL>
SQL> insert into t values ('10');
1 row created.
SQL> insert into t values ('20');
1 row created.
SQL>
SQL> set autotrace traceonly explain
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 14 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 14 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("MY_SEMI_NUMERIC_VALUE")>0)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
SQL> set autotrace off
You can see in the execution plan, we silently added a TO_NUMBER around the column because you were comparing with a numeric (> 0). The query will hence run fine as it currently stands
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
MY_SEMI_NU
----------
10
20
but what if someone puts some bad data in that column, eg
SQL> insert into t
2 values ('~10');
1 row created.
Now when I run that query, the TO_NUMBER function will fail and hence so will your query
SQL> select *
2 from t
3 where my_semi_numeric_value > 0;
where my_semi_numeric_value > 0
*
ERROR at line 3:
ORA-01722: invalid number
Depending on your database version, you can handle this yourself
SQL> select *
2 from t
3 where to_number(my_semi_numeric_value default -1 on conversion error) > 0 ;
MY_SEMI_NU
----------
10
20
but as others have mentioned, you need to check the datatypes of each column that you are using in the query, including your joins
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论