应该如何实现这个编码?

movingboy2 2003-08-22 12:12:27
在数据库中有一个地区表t_Area,有如下字段

ID:地区在表中的唯一标志号,从一个Sequence取得,仅在内部使用
Code:地区的编码,由用户填写
Name:地区的名称,由用户填写
Parent:上级地区的ID,顶级地区该字段值为Null
HelperCode:辅助编码,由系统自动填写,仅在内部使用

可以看出,该表用ID和Parent字段实现了一个树形结构。但仅用这两个字段实现树形结构也有不足的地方,如查询某个地区下所有子地区,Sql语句就比较麻烦了。所以我设计了HelperCode字段来实现快速查询。
HelperCode的编码规则如下:

1.该码是变长码,共5级
2.每级是定长的3位,取值为001~999
3.编码不可以重复

这样查询某个地区下的所有子地区,只要用一个like条件就可以了,如HelperCode like '001002%'。

现在我填写HelperCode的方法是:
1.用户在客户端为某个节点增加一个子节点时
2.取得该节点的直接子节点中HelperCode最大者
3.将该值增加1作为新增的子节点的HelperCode

这种方式的弊端在于并发处理时,可能两个客户端同时在树上增加节点,可能新增的节点会使用同一个HelperCode。我想把这个编码的生成过程移到数据库中实现,把它写到一个存储过程中,但同样可能存在多个用户同时调用的问题。我应该怎样解决呢?或者这个方案有没有更好的实现方法了?
...全文
31 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
tcmis 2003-08-22
  • 打赏
  • 举报
回复
用substr和like都可以达到你想要的数据啊,,,
zjhclf 2003-08-22
  • 打赏
  • 举报
回复
用的着吗?直接
select * from t_area where parent='001002';
查的不是一个地区下的所有子地区么?
helpercode有什么用呢?
movingboy2 2003-08-22
  • 打赏
  • 举报
回复
to beckhambobo(beckham):

我查了Oracle的connect by关键字的帮助,看到下面这一段:

However, some part of the condition must use the PRIOR operator to refer to the parent row. The part of the condition containing the PRIOR operator must have one of the following forms:

PRIOR expr comparison_operator expr

expr comparison_operator PRIOR expr

上面最后两个表达式有什么区别呢?(我试了,确实有区别,但不明白其中的规律)我再找prior关键字的帮助,找不到更多的信息了。
movingboy2 2003-08-22
  • 打赏
  • 举报
回复
to beckhambobo(beckham):

你的这段代码对我非常有用!眼前豁然开朗!谢谢!
初步学会了使用connect by关键字。好东东!

select distinct id
from aa
connect by prior id = fid
start with fid =v_id;
beckhambobo 2003-08-22
  • 打赏
  • 举报
回复
我用 HelperCode like '001%'就可以取出前4条记录

已取了五条记录了,
001
001001
001001001
001001002
001002

本人方法如下:
SQL> select * from aa;

ID FID
-- ---
1 0
2 1
3 1
4 2
5 3
6 4
6 5

7 rows selected

SQL>
SQL> select lpad(id,level*2+length(id),' ') id
2 from aa
3 connect by prior id = fid
4 start with fid = 0;

ID
--------------------------------------------------------------------------------
1
2
4
6
3
5
6

7 rows selected

create function get_dept(p_id varchar2)
return varchar2
as
v_ret varchar2(20);
cursor t_sor(v_id varchar2) is
select distinct id
from aa
connect by prior id = fid
start with fid =v_id;
begin
for v_sor in t_sor(p_id) loop
v_ret:=v_ret||'/'||v_sor.id;
end loop;
return(v_ret);
end;
/

SQL> select id,get_dept(id) from aa;

ID GET_DEPT(ID)
-- -------------------------------------------------------------------------------
1 /2/3/4/5/6
2 /4/6
3 /5/6
4 /6
5 /6
6
6

这样就在查询语句中where ... 控制节点
movingboy2 2003-08-22
  • 打赏
  • 举报
回复
to beckhambobo(beckham) :
1.我没有认为这样实现性能差,只是不方便。:)
2.如果没有HelperCode,要实现我提到的like式查询,sql怎样写呢?我现在只能想到把所有的记录取出来,遍历这棵树,找到属于指定节点的所有子节点。
beckhambobo 2003-08-22
  • 打赏
  • 举报
回复
首先:本人不认为ID和Parent字段实现了一个树形结构性能差,oracle对这方面也做得挺多的。
其实:HelperCode这样实现一个树型结构,记录挺多的,而like操作符要进行全表检索,这样更不利于性能.
movingboy2 2003-08-22
  • 打赏
  • 举报
回复
to tiangou(阿木):
谢谢你的建议。
1.我的应用中999够用了。:)
2.我的客户端是通过DataSet来提交的,我希望如果没有其它原因(比如主键冲突,违反其它约束),提交总是成功的。对于Oracle数据库来讲,两个客户端A、B同时新增数据,A没提交之前,B看不到A操作的结果,即B可能取得与A相同的最大HelperCode。这样A提交后B再提交,事务就会失败。我希望有个好的方法来解决这个问题。

to zjhclf(寂寞撩人):
比如有如下节点的HelperCode
001
001001
001001001
001001002
001002
002
我用 HelperCode like '001%'就可以取出前4条记录,而没有该字段就比较麻烦了。
如果新增一个节点(假定它的HelperCode为001001003),我的Sql语句不变,仍能取到预期的结果。
zjhclf 2003-08-22
  • 打赏
  • 举报
回复
首先,seq是永远不存在并发,就算2个session几乎同时选择seq,也会分出先后。
如果只用id不会造成重复问题。我还是不明白为什么要用helpercode??
tiangou 2003-08-22
  • 打赏
  • 举报
回复
问题描述得很清楚,这种问题我也碰到过,不过是在SQL Server中
先钻一个牛角尖:

=======================================================================
现在我填写HelperCode的方法是:
1.用户在客户端为某个节点增加一个子节点时
2.取得该节点的直接子节点中HelperCode最大者
3.将该值增加1作为新增的子节点的HelperCode(如果最大数是999,怎么办?)
=======================================================================

我的一个办法:
1、将HelperCode列置为Unique列,不允许重复
2、写一个函数取最大HelperCode值,如:getMaxCode(id in number)
3、向t_area表中插数据,同时进行异常捕捉,如果违背了唯一性,即dup_val_on_index异常,则循环调用getMaxCode(id)函数,直到可插入为止

供参考:)



movingboy2 2003-08-22
  • 打赏
  • 举报
回复
to zjhclf(寂寞撩人):
ID是从一个Sequence里取出来的整数直接写到字段里的,Parent实际上也是一个整数。
如果ID和Parent改为HelperCode的编码方式,同样会遇到这样的问题啊

to hqwang77(haiqing):
加锁的语法是怎样的?可否按照你的思路给个例子?谢谢!
海清 2003-08-22
  • 打赏
  • 举报
回复
如果考虑并发那么,你要在“2.取得该节点的直接子节点中HelperCode最大者
”是加锁,这样就避免重复。

17,081

社区成员

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

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