数据库老人请来,PL/SQL中的VARCHAR2和LTRIM问题!

xueqilin_007 2009-07-17 10:59:05
问题简述:

一般认为声明时这样写V_OLDSTR VARCHAR2(50):='';的结果是V_OLDSTR为'',但是昨天写函数时遇到以下问题:

CREATE OR REPLACE FUNCTION F_MYSORT(V_STR IN VARCHAR2) --排序主函数
RETURN VARCHAR2 IS

V_OLDSTR VARCHAR2(50):='';
V_NEWSTR VARCHAR2(50):=''; --保存结果的串
V_RIGHT VARCHAR2(50):='';
V_LEFT VARCHAR2(50):='';
V_DATA NUMBER(9):=0; --当前数据
V_POS NUMBER(9):=0; --保存插入位置

BEGIN
V_OLDSTR:=V_STR||',';
V_RIGHT:=V_OLDSTR;
V_LEFT:=SUBSTR(V_RIGHT,1,INSTR(V_RIGHT,','));
--V_RIGHT:=LTRIM(V_RIGHT,V_LEFT);
V_RIGHT:=SUBSTR(V_RIGHT,LENGTH(V_LEFT)+1);

WHILE LENGTH(V_LEFT)>0 LOOP
V_DATA:=TO_NUMBER(SUBSTR(V_LEFT,1,LENGTH(V_LEFT)-1));
--V_DATA:=TO_NUMBER(RTRIM(V_LEFT,','));
IF V_NEWSTR='' THEN --目标串为空时
V_NEWSTR:=TO_CHAR(V_DATA)||',';
ELSE
V_POS:=F_FINDPOS(V_NEWSTR,V_DATA);
V_NEWSTR:=SUBSTR(V_NEWSTR,1,V_POS)||TO_CHAR(V_DATA)||','||SUBSTR(V_NEWSTR,V_POS+1);
END IF;

V_LEFT:=SUBSTR(V_RIGHT,1,INSTR(V_RIGHT,','));
--V_RIGHT:=LTRIM(V_RIGHT,V_LEFT);
V_RIGHT:=SUBSTR(V_RIGHT,LENGTH(V_LEFT)+1);
END LOOP;

DBMS_OUTPUT.PUT_LINE(SUBSTR(V_NEWSTR,1,LENGTH(V_NEWSTR)-1));
RETURN SUBSTR(V_NEWSTR,1,LENGTH(V_NEWSTR)-1);
END F_MYSORT;

程序会运行出错,刚开始一直找不到原有,后来发现把上面的红色语句改成
V_NEWSTR VARCHAR2(50):='*';

IF V_NEWSTR='*' THEN ...
就OK了,很无语,因为我测试时把它改成IF V_NEWSTR='' OR V_NEWSTR=NULL THEN 都不行,一样报错。
高手请告诉我为什么?麻烦了。

另外还有个小问题
* select ltrim('Mississippi','Mis') from dual;='ppi'
* select ltrim('63972Tech','123456789') from dual;='Tech'
LTRIM一般思想是去掉左边相同的子串,我想不通上面两句的执行思路?请高手解答。
...全文
227 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
谢谢各位,问题解决,可以结贴了
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
7楼点醒了,我要的功能实际上时REPLACE,呵,谢谢
geniuscobol_zy 2009-07-17
  • 打赏
  • 举报
回复
我在10g写

declare
name varchar2(20):=null;
begin
if name is null then
dbms_output.put_line('为空');
end if;
end;

是可以的
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
我是否可以理解为:=''是一种错误的初始化方法(写法)?
geniuscobol_zy 2009-07-17
  • 打赏
  • 举报
回复
ltrim(a,b) 是去掉a从左边第一个字符开始到第一个不在b中字符的位置之间的所有字符

rtrim(a,b) 是从右边开始去掉

eg:

ltrim('misisippmi','mis') 结果为 ppmi
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
受教了,3楼的答案很准确~谢谢
阿三 2009-07-17
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 xueqilin_007 的回复:]
我擦,改成IS NULL可以,不过为什么是NULL,我不是初始化过了吗?
[/Quote]
看看oracle的数据类型部分,对于null有专门的讲解
asdf_ndsc 2009-07-17
  • 打赏
  • 举报
回复
* select ltrim('Mississippi','Mis') from dual;='ppi'
* select ltrim('63972Tech','123456789') from dual;='Tech'


用 replace()

* select replace('Mississippi','Mis','') from dual;
* select replace('63972Tech','123456789','') from dual;
shiyiwan 2009-07-17
  • 打赏
  • 举报
回复
初始化为null不能用 := ''

:= null[Quote=引用 4 楼 xueqilin_007 的回复:]
我擦,改成IS NULL可以,不过为什么是NULL,我不是初始化过了吗?
[/Quote]
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
2楼方法也可以,不过为什么?
PL/SQL的初始化是什么原理?赋值''时为什么不可以?
xueqilin_007 2009-07-17
  • 打赏
  • 举报
回复
我擦,改成IS NULL可以,不过为什么是NULL,我不是初始化过了吗?
shiyiwan 2009-07-17
  • 打赏
  • 举报
回复
LTRIM:
Purpose

LTRIM removes from the left end of char all of the characters contained in set. If you do not specify set, it defaults to a single blank. If char is a character literal, then you must enclose it in single quotes. Oracle Database begins scanning char from its first character and removes all characters that appear in set until reaching a character not in set and then returns the result.

Both char and set can be any of the datatypes CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB, or NCLOB. The string returned is of VARCHAR2 datatype and is in the same character set as char.
shiyiwan 2009-07-17
  • 打赏
  • 举报
回复
如果你想达到''的效果,需要写成
V_OLDSTR VARCHAR2(50) := null;
阿三 2009-07-17
  • 打赏
  • 举报
回复
V_NEWSTR=NULL 改成 V_NEWSTR is NULL试试

17,134

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧