private void del(Connection conn, int id)
{
Statement stmt = null;
ResultSet rs = null;

try
{
stmt = conn.createStatement();
String sql = "select * from \"bbs\".\"article\" where pid = " + id;
rs = stmt.executeQuery(sql);

while(rs.next())
{
int sid = rs.getInt("id");
System.out.println("找到其子结点" + sid);
del(conn, sid);
}
stmt.executeUpdate("delete from \"bbs\".\"article\" where id = " + id);
System.out.println("删除此结点" + id);

Statement disIdSt = conn.createStatement();
ResultSet disIdRs = disIdSt.executeQuery
                 ( "select id from \"bbs\".\"article\" where id > " + id );
while(disIdRs.next())
{
int disId = disIdRs.getInt(1);
System.out.println("找到需要更改的结点" + disId);
disIdSt.executeUpdate
  ( "update \"bbs\".\"article\" set id = " + (disId - 1)
        + "where id = " + disId );
System.out.println("修改id " + disId + "为" + (disId - 1));
disIdSt.executeUpdate
  ( "update \"bbs\".\"article\" set pid = " + (disId - 1)
+ "where pid = " + disId );
System.out.println("修改pid " + disId + "为" + (disId - 1));
}
disIdSt.close();
disIdRs.close();
这是del方法的一部分,删除一个树形结构的结点
测试树形结构如下:id(结点号)  pid(根结点号)   结构图11            10             11
12            11               ---- 12
13            12                      ---- 13
14            13                             ---- 14
15            11               ---- 15
16            15                      ---- 16
17            11               ---- 17我测试将结点12删除,本预计应是12,13,14一并删除
并将15,16,17的ID号改为12,13,14但测试结果输出如下:此结点为12
确定树结点为11
找到其子结点13
找到其子结点14
删除此结点14
找到需要更改的结点15
修改id 15为14
修改pid 15为14
删除此结点13
找到需要更改的结点14
修改id 14为13
修改pid 14为13
删除此结点12
找到需要更改的结点13
修改id 13为12
修改pid 13为12
结点11仍然有子结点点
执行后树形结构如下:id(结点号)  pid(根结点号)   结构图11            10             11
12            11               ---- 15
16            12                      ---- 16
17            11               ---- 17也就是说,改结点时 select id .... where id > id传回的结果集
ResultSet 在while中只调用了一次好困惑 我在SQLPLUS中 执行该语句确实返回的是3个值啊 15,16,和17
然而实际只改了15
    
  求高手解答

解决方案 »

  1.   

    你的设计并不好:
      1)一般作为id(Primary Key)这样的字段是不要用来修改的
      2)一段函数完成一个功能(你的这个递归的函数又在删除,又在修改),分两个函数写就好了
      

  2.   

    稍微改了中间那部分, 用for做了Statement disIdSt = conn.createStatement();
    ResultSet disIdRs = disIdSt.executeQuery
                     ( "select count(*) from \"bbs\".\"article\" where id > " + id );

    disIdRs.next();
    int count = disIdRs.getInt(1);
    System.out.println("需要更改的结点数目为" + count);
    disIdRs = disIdSt.executeQuery( "select id from \"bbs\".\"article\" where id > " + id );
    for (int i=0; i<count; i++)
    {
    disIdRs.next();
    int disId = disIdRs.getInt(1);
    System.out.println("找到需要更改的结点" + disId);
    disIdSt.executeUpdate
      ( "update \"bbs\".\"article\" set id = " + (disId - 1)
            + "where id = " + disId );
    System.out.println("修改id " + disId + "为" + (disId - 1));
    disIdSt.executeUpdate
      ( "update \"bbs\".\"article\" set pid = " + (disId - 1)
    + "where pid = " + disId );
    System.out.println("修改pid " + disId + "为" + (disId - 1));
    }
    输出结果一部分:删除此结点14
    需要更改的结点数目为3
    找到需要更改的结点15
    修改id 15为14
    修改pid 15为14
    java.sql.SQLException: 用尽的 Resultset
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)。。表明
    确实用select count(*) ...能说明返回三条记录
    所以用for循环三次,然而实际只做了一次,然后抛出用尽Resultset的错误
    说明 select id ... 返回一条记录甚是奇怪。。在SQLPLUS执行里是没有问题的,返回三条啊``
    。当然用别的办法可以解决,但我想知道究竟ResultSet这个东西怎么用法
      

  3.   

    改成这样就没问题了,但为什么返回一条记录可以,三条就不行``Statement disIdSt = conn.createStatement();
    ResultSet disIdRs = disIdSt.executeQuery
                     ( "select count(*) from \"bbs\".\"article\" where id > " + id );

    disIdRs.next();
    int count = disIdRs.getInt(1);
    System.out.println("需要更改的结点数目为" + count);

    for (int i=1; i<=count; i++)
    {
    disIdRs = disIdSt.executeQuery( "select id from \"bbs\".\"article\" where id = " + (id+i));
    disIdRs.next();
    int disId = disIdRs.getInt(1);
    System.out.println("找到需要更改的结点" + disId);
    disIdSt.executeUpdate
      ( "update \"bbs\".\"article\" set id = " + (disId - 1)
            + "where id = " + disId );
    System.out.println("修改id " + disId + "为" + (disId - 1));
    disIdSt.executeUpdate
      ( "update \"bbs\".\"article\" set pid = " + (disId - 1)
    + "where pid = " + disId );
    System.out.println("修改pid " + disId + "为" + (disId - 1));
    }
      

  4.   

    oracle sql 有树遍历delete from bbs where rowid in (
    select rowid from bbs
    start with id=11
    connect by prior pid=id
    )start with id=11  开始遍历的起点
    connect by prior pid=id 遍历的方向 如果 id=pid则方向反一下这里pid=id 还是 id=pid 楼主自己试一下,好久没玩ORACLE 了
      

  5.   

    哈,做项目也碰上了个树的问题。遍历树还可以用 order by nodeId ,nodePid。
      

  6.   

    哦`` 谢谢楼上两位`看来是我SQL的基础太差`` 我学的一本ORACLE 应用与实例集锦,只讲了两章PL/SQL语言,我还以为这个语言很简单呢``~~   
    有没细一点的SQL书啊,最好把ORACLE,MYSQL,SQLSEVER 这些异同的地方都讲了的