下面是一个 *plsql * 游标。
CURSOR get_customer_balance(cust_id_ IN VARCHAR2) IS
SELECT t.cust_balance
FROM customer_tab t
WHERE t.customer_id =cust_id_;
程序机构
OPEN get_customer_balance(123456789);
FETCH get_customer_balance INTO balance_;
CLOSE get_customer_balance;
- 在customer_tab中,customer_id是一个数字类型列。即使游标参数是varchar2,也可以正常工作。对于某些值,这给予误差。此外,任何错误都将仅在运行时发生。*
是否有一个 * 范围的varchar2* 可以自动 * 转换为数字?***
2条答案
按热度按时间cotxawn71#
在customer_tab中,
customer_id
是number类型列vs.
CURSOR get_customer_balance(cust_id_ IN VARCHAR2) IS
意思是你故意做错事
不仅如此,你应该传递一个
number
--事实上,你应该传递customer_tab.customer_id%type
,这样游标声明就应该是关于你的问题:Oracle将尝试隐式地将您传递的任何数据类型转换为有效数字。有时它会成功(例如,如果你传递
'10'
),有时不会('ABC'
或'15XF4'
)。没有“范围”;这取决于实际价值。如果你愿意,可以看看Tom Kyte的<a=href=”https://blogs.oracle.com/connect/post/on-implicit-conversions-and-more“>关于隐式转换和更多内容,其中包括:
问题出在你的代码上。您的开发人员编写了一个非常讨厌的bug,这个bug被称为“隐式转换”。
cczfrluj2#
摘要:永远不要依赖数据类型之间的隐式转换。
是否有一个范围的
VARCHAR2
可以在SQL中自动转换为NUMBER
?任何可以从
VARCHAR2
隐式转换为NUMBER
的value
都可以使用TO_NUMBER(value)
(使用隐式格式模型)成功显式转换。一般来说,这将匹配正则表达式:
其中
D
是NLS_NUMERIC_CHARACTERS
会话参数指定的十进制分隔符。还有进一步的限制,因为
NUMBER
只能存储(大约)38位数字,但你可以转换更大的字符串,它会截断数字超过数字的精度。例如,给定样本数据:
然后你可以使用
CAST
函数显式地在数据类型之间执行转换:其中(当
NLS_NUMERIC_CHARACTERS
是.,
时)输出:| 值|铸件(值编号)|
| --|--|
| 0 | 0 |
| +00001234| 1234 |
| -00001234|-1234|
| -00001234|-1234|
| -00001234.5678 | -1234.5678 |
| .1234|.1234|
| .1234e4| 1234 |
| .1234E-004| 00001234|
| 1234E-004|.1234|
但是,你应该永远依赖于数据类型之间的隐式转换。
如果我们更改会话参数:
然后,
NLS_NUMERIC_CHARACTERS
从.,
更改为,
,并且完全相同的查询和相同的数据:现在
ORA-01722: invalid number
失败,因为它现在期望十进制值使用,
作为小数点(根据法国和许多其他国家的正常约定)而不是.
,现在所有带有.
的字符串都无效。由于任何用户都可以随时更改其会话参数,因此您不能(也不应该)依赖隐式转换始终有效。
如果您想要对任何会话参数都有效的数字,则不能使用小数分隔符,只能使用整数有效数和可选指数:
fiddle