遞規刪除一整棵樹 我自己的想法

來源:互聯網
上載者:User
 

一、樹型資料庫結構 及 樹的一些基礎知識

首先我們來看一個簡單的應用樹….資料庫設計如下圖:

表名: testTree

欄位:
id (主鍵 自動遞增1) username (這個任意了。只是一個資料欄位) parentid (父節點的ID值)


id username parentid
1 A 0
2 B 1
3 C 2
4 D 1
5 E 2
6 F 5

如果按樹來排列這些資料  應該產生如下狀態:
A
|____B
|   |____C
|   |____E
|        |____F
|
|____D

如果按我們一般的習慣我們要從A開始刪除整棵樹的話 有多種演算法 例: A-》B-》C-》E-》F-》D 或者 A-》B-》D-》C-》E-》F 演算法多樣。。但由於是刪除一整棵(注意 是刪除) 如果不出意外的情況。。上面的演算法都能滿足於。但由於是刪除 我們要從樹的子結點刪除。。為什麼呢?因為從前端節點刪除的話。意外一出現。。前端節點刪除了。。但子節點卻未刪除 往後卻查詢不到這些子節點。產生了過多的垃圾的資料。。如果從子節點刪除的話。如有萬一。子節點刪除。而父節點未刪除。父節點也能再詢查詢到,再進行刪除操作?
這便是為什麼要從尾部開始刪除的原因了。

二、刪除過程(代碼)
按照傳統的思維 我們可能立即想到遞規刪除操作。。我想討論的也是這個?
使用VS.NET 建立一個C# 項目的 WINFORM 工程, 拖拉兩個Button控制項
和一個label 控制項 
然後在開頭的引用中 using System.Data.SqlClient;  因為這是拿來操作資料庫的類 ?
然後我們要構建幾個方法來實現我們的目標。。即遞規刪除!
變數:
static string connstring="server=192.100.100.135;database=jay;uid=sa;pwd=;"; //SQL SERVER 串連串
方法:
sqlCommandShell(string sql): 方法 用來操作SQL語句
getDataSet(string sql):方法 通過SQL語句來獲得一個DATASET(它相當於是在斷開資料庫後。。躲在記憶體中的資料庫表  ? 我是這麼認為的)
sqlDeleteID(string id) 指定要刪除的ID資料
deleteChildId(string id) 通過這個ID號查詢出它的孩子的ID值

方法的具體實現過程:
  /// <summary>
  /// 獲得一個sql語句執行
  /// </summary>
  /// <param name="sql">SQL語句</param>
  /// <returns>返回所影響的資料行數 </returns>
  public static int sqlCommandShell(string sql)
  {
   SqlConnection conn=new SqlConnection(connstring);
   conn.Open();
   SqlCommand cm=new SqlCommand(sql,conn);
   int i=cm.ExecuteNonQuery();
   conn.Close();
   return i;
  }

  /// <summary>
  /// 獲得一個DataSet
  /// </summary>
  /// <param name="sql">SQL語句</param>
  /// <returns>通過SQL語句返回一個DATASET</returns>
  public static DataSet getDataSet(string sql)
  {
   using(SqlConnection conn=new SqlConnection(connstring))
   {
    SqlDataAdapter dp=new SqlDataAdapter(sql,conn);
    DataSet ds=new DataSet();
    dp.Fill(ds);
    return ds;
   }
  }
 
上面兩個方法是對資料庫的操作  按照一般的思路 接下來的方法是
/// <summary>
  /// 要刪除的ID
  /// </summary>
  /// <param name="id"></param>
  void sqlDeleteID(string id)
  {
   string sql="delete [testTree] where id='"+id+"'";
   sqlCommandShell(sql);
  }


  /// <summary>
  /// 平時的刪除
  /// </summary>
  /// <param name="id">父ID</param>
  void deleteChildId(string id)
  {
   string sql="select * from [testTree] where parentid='"+id+"'";
   DataSet ds=getDataSet(sql);
   for(int i=0;i<ds.Tables[0].Rows.Count;i++)
   {
    string i_d=ds.Tables[0].Rows[i]["id"].ToString();
    deleteChildId(i_d); //(使用遞規刪除一顆樹)
    sqlDeleteID(i_d); //刪除過程
   }
  }


這樣就可以實現一樹的操作了。。。雙擊一個按鈕在裡面添加如下代碼
private void button2_Click(object sender, System.EventArgs e)
{
   deleteChildId("0");  //這個0即為你將要刪除的父節點的ID
}

這樣就實現了上述的描述。。即從尾到頭的刪除一棵樹
然而這樣的執行效率卻是不令滿意的。。操作小棵的樹還好。。只有幾個節點。。然後操作大棵的樹。。比如說有上萬個節點的時候 每次的資料連結。。刪除 這個操作 便要花費很多時間~~~
然後今天早上我便開始想有沒有更好的方法來操作呢?


三、自己的一些想法大家討論看行不行得通

在同一個共程中
資料庫連結串旁邊聲明一個 ArrayList al=new ArrayList(); //聲明一個記錄ID的數組
然後添加兩個方法如下:
 #region getDeleteSql
  /// <summary>
  /// 獲得要刪除的SQL語句
  /// </summary>
  /// <param name="id">要刪除的起始ID</param>
  /// <returns>返回一個SQL語句</returns>
  string getDeleteSql(string id)
  {
   string str=string.Empty;
   al.Clear();
   ArrayList aa=getId(id);
   for(int i=0;i<aa.Count;i++)
   {
    str=str+"id="+aa[i].ToString() +" or ";
   }
   str=str.Substring(0,str.Length-3);
   string sql="delete from [testTree] where " +str;
   return sql;

  }
  #endregion
 
  #region getIdList
  /// <summary>
  /// 獲得要刪除的ID列表
  /// </summary>
  /// <param name="id">父 ID</param>
  /// <returns>返回要刪除的ID列表數組</returns>
  ArrayList getId(string id)
  {
   string sql="select * from [testTree] where parentid='"+id+"'";
   DataSet ds=getDataSet(sql);
   for(int i=0;i<ds.Tables[0].Rows.Count;i++)
   {
    string i_d=ds.Tables[0].Rows[i]["id"].ToString();
    getId(i_d);
    al.Add(i_d);
    
   }
   return al;

  }
  #endregion
這樣通過例 getDeleteSql("0"); 方法構造出一個刪除的SQL語句
前面不是拖了兩個按鈕嗎  然後 雙擊另一個按鈕 代碼如下
private void button1_Click(object sender, System.EventArgs e)
{
  this.label1.Text=getDeleteSql("0");  //label1.Text為要操作的SQL語句。為方便我把它顯示出來了
  sqlCommandShell(this.label1.Text);
}

這樣產生了這麼一個SQL語句  然後資料庫連接一次。。執行一個SQL語句即可 我沒有那麼多的資料來測試。。不過我想這樣在大資料量的情況下 效率是不是能夠高出很多呢 。。。請大家討論下這種方法的可行性啊~

所有代碼如下:
/* ************************************************************************
 * 設計人員: upshania    email:uv51@sina.com
 * 設計時間: 2005.05.31
 * 功能描述: 遞規刪除整棵樹
 * 著作權: Copyright (c) 2005, Fujian upshania
 * 版本號碼:   1.0
***************************************************************************/

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;

namespace testTree
{
 /// <summary>
 /// Form1 的摘要說明。
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  #region 變數 屬性等
  static string connstring="server=192.100.100.135;database=jay;uid=sa;pwd=;"; //SQL SERVER 串連串
  ArrayList al=new ArrayList(); //聲明一個記錄ID的數組
  private System.Windows.Forms.Label label1;
  private System.Windows.Forms.Button button1;
  private System.Windows.Forms.Button button2;
  /// <summary>
  /// 必需的設計器變數。
  /// </summary>
  private System.ComponentModel.Container components = null;

  public Form1()
  {
   //
   // Windows 表單設計器支援所必需的
   //
   InitializeComponent();

   //
   // TODO: 在 InitializeComponent 調用後添加任何建構函式代碼
   //
  }

  /// <summary>
  /// 清理所有正在使用的資源。
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows 表單設計器產生的程式碼
  /// <summary>
  /// 設計器支援所需的方法 - 不要使用代碼編輯器修改
  /// 此方法的內容。
  /// </summary>
  private void InitializeComponent()
  {
   this.label1 = new System.Windows.Forms.Label();
   this.button1 = new System.Windows.Forms.Button();
   this.button2 = new System.Windows.Forms.Button();
   this.SuspendLayout();
   //
   // label1
   //
   this.label1.Location = new System.Drawing.Point(88, 32);
   this.label1.Name = "label1";
   this.label1.Size = new System.Drawing.Size(400, 48);
   this.label1.TabIndex = 0;
   this.label1.Click += new System.EventHandler(this.label1_Click);
   //
   // button1
   //
   this.button1.Location = new System.Drawing.Point(48, 144);
   this.button1.Name = "button1";
   this.button1.Size = new System.Drawing.Size(104, 32);
   this.button1.TabIndex = 1;
   this.button1.Text = "button1";
   this.button1.Click += new System.EventHandler(this.button1_Click);
   //
   // button2
   //
   this.button2.Location = new System.Drawing.Point(288, 144);
   this.button2.Name = "button2";
   this.button2.Size = new System.Drawing.Size(104, 40);
   this.button2.TabIndex = 2;
   this.button2.Text = "button2";
   this.button2.Click += new System.EventHandler(this.button2_Click);
   //
   // Form1
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
   this.ClientSize = new System.Drawing.Size(528, 309);
   this.Controls.Add(this.button2);
   this.Controls.Add(this.button1);
   this.Controls.Add(this.label1);
   this.Name = "Form1";
   this.Text = "Form1";
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// 應用程式的主進入點。
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new Form1());
  }
  #endregion

  #region 方法

  #region 共用的方法

  #region SqlCommandShell
  /// <summary>
  /// 獲得一個sql語句執行
  /// </summary>
  /// <param name="sql">SQL語句</param>
  /// <returns>返回所影響的資料行數 </returns>
  public static int sqlCommandShell(string sql)
  {
   SqlConnection conn=new SqlConnection(connstring);
   conn.Open();
   SqlCommand cm=new SqlCommand(sql,conn);
   int i=cm.ExecuteNonQuery();
   conn.Close();
   return i;

   
  }
  #endregion

  #region getdataset
  /// <summary>
  /// 獲得一個DataSet
  /// </summary>
  /// <param name="sql">SQL語句</param>
  /// <returns>通過SQL語句返回一個DATASET</returns>
  public static DataSet getDataSet(string sql)
  {
   using(SqlConnection conn=new SqlConnection(connstring))
   {
    SqlDataAdapter dp=new SqlDataAdapter(sql,conn);
    DataSet ds=new DataSet();
    dp.Fill(ds);
    return ds;
   }
  }
  #endregion

  #endregion

  #region 自己的想法

  #region getDeleteSql
  /// <summary>
  /// 獲得要刪除的SQL語句
  /// </summary>
  /// <param name="id">要刪除的起始ID</param>
  /// <returns>返回一個SQL語句</returns>
  string getDeleteSql(string id)
  {
   string str=string.Empty;
   al.Clear();
   ArrayList aa=getId(id);
   for(int i=0;i<aa.Count;i++)
   {
    str=str+"id="+aa[i].ToString() +" or ";
   }
   str=str.Substring(0,str.Length-3);
   string sql="delete from [testTree] where " +str;
   return sql;

  }
  #endregion
 
  #region getIdList
  /// <summary>
  /// 獲得要刪除的ID列表
  /// </summary>
  /// <param name="id">父 ID</param>
  /// <returns>返回要刪除的ID列表數組</returns>
  ArrayList getId(string id)
  {
   string sql="select * from [testTree] where parentid='"+id+"'";
   DataSet ds=getDataSet(sql);
   for(int i=0;i<ds.Tables[0].Rows.Count;i++)
   {
    string i_d=ds.Tables[0].Rows[i]["id"].ToString();
    getId(i_d);
    al.Add(i_d);
    
   }
   return al;

  }
  #endregion

  #endregion

  #region 平時遞規的刪除
  /// <summary>
  /// 要刪除的ID
  /// </summary>
  /// <param name="id"></param>
  void sqlDeleteID(string id)
  {
   string sql="delete [testTree] where id='"+id+"'";
   sqlCommandShell(sql);
  }


  /// <summary>
  /// 平時的刪除
  /// </summary>
  /// <param name="id">父ID</param>
  void deleteChildId(string id)
  {
   string sql="select * from [testTree] where parentid='"+id+"'";
   DataSet ds=getDataSet(sql);
   for(int i=0;i<ds.Tables[0].Rows.Count;i++)
   {
    string i_d=ds.Tables[0].Rows[i]["id"].ToString();
    deleteChildId(i_d);
    sqlDeleteID(i_d);
   }
  }
  #endregion

  #endregion

  
  private void button1_Click(object sender, System.EventArgs e)
  {
   this.label1.Text=getDeleteSql("0");
   sqlCommandShell(this.label1.Text);
  }

  private void label1_Click(object sender, System.EventArgs e)
  {
  
  }

  private void button2_Click(object sender, System.EventArgs e)
  {
   deleteChildId("0");
  }
 }
}




相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。