2

我一直在浏览各种网站和代码,但似乎没有什么能结束我的痛苦。它们要么帮助查找和删除特定列的重复项,要么仅从数据表中删除,而不是从底层数据库本身中删除。我想从我的 mdb 文件的表“table1”中删除重复的行。

为了使我的要求更清楚:

  1. 表中的任何列都没有设置主键(我负担不起)
  2. 我想删除所有重复的行,但一个!(顺序没有意义)
  3. 我更喜欢从数据库中删除重复项,而不是在更新数据库本身之前首先检查是否存在这样的行(如果这是最后的手段,那是不受欢迎的)
  4. 重复行是指不明显的行。例如,在以下示例中,只有第 3 行和第 5 行是重复的。我想删除其中的任何一个。

          Name1  Name2    Name3
          tom    dick   harry
          tom    dick   mike
          ann    sara   mike
          sara   ann    mike
          ann    sara   mike
    

应通过单击按钮从数据库中删除重复的行,如下所示

     private void button1_Click(object sender, EventArgs e)
     {
         deletedupes();
     }

    private void deletedupes()
    {
        OleDbConnection con = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=C:\\hi.mdb");

        DataSet ds = new DataSet();
        OleDbDataAdapter da = new OleDbDataAdapter("select * from table1", con);
        con.Open();
        da.Fill(ds, "table1");

        // what could be rest of the code??
    }

提前致谢。是的,我是新手。。

4

4 回答 4

3

如果您还没有意识到这一点,那么数据库引擎往往会以绝对的方式思考。如果您希望它删除一行,您必须告诉它如何识别该行。因此,主键。

话虽如此,通常但并非总是有两 (2) 种方法可以做到这一点:

  1. 找出 Access 是否支持语法来告诉DELETE只考虑“前 N 行”,类似于DELETE TOP 1 FROM ...
  2. 从表中获取不同的数据集,删除其中的所有行,然后将不同的行重新插入其中

第一个可能是可能的,但这取决于 Access 是否支持任何使其成为可能的语法。例如。Microsoft SQL Server 支持SET ROWCOUNT 1在 a 之前执行一条语句DELETE,然后DELETE将只删除 1 行,然后停止。我不知道 Access 是否会这样做。

如果你有外键,第二个会很痛苦,但我要在这里冒个险,假设你没有主键,你没有外键,所以数据完整性不是真正的问题在这里。

于 2011-04-08T20:03:13.907 回答
2

这是一篇讨论在 SQL Server 中删除重复行的几种方法的文章,但我怀疑它也适用于 MS Access:Removing Duplicates from a Table in SQL Server

于 2011-04-08T20:00:07.737 回答
2

好的,这是一个完整的 hack,但听起来这是你唯一的选择......

SELECT DISTINCTROW从你的桌子上做一个。从您的表中删除所有记录。将不同的行重新插入。

DISTINCTROW 语法

于 2011-04-08T20:12:57.460 回答
0

由于没有一个答案对我来说是令人满意的(我只是有点太新手,无法理解更多知识渊博和经验丰富的人在这里所说的简洁和稍微技术化的方式),我尝试了自己的变体来完成这项工作。distinct我无法理解使用orset rowcount或等命令要做什么delete from。在示例中我找不到完全部署的代码。所以我尝试了这个。从头开始。

    int id, k;
    private void button2_Click(object sender, EventArgs e)
    {
        OleDbConnection con = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=C:\\hi.mdb");

        DataSet ds = new DataSet();

        OleDbDataAdapter da = new OleDbDataAdapter("select * from table2", con);
        con.Open();
        da.Fill(ds, "table2");


        for (int i = 0; i < ds.Tables["table2"].Rows.Count; i++)
        {
            DataRow row = ds.Tables["table2"].Rows[i];
            k++;
            for (int j = k; j < ds.Tables["table2"].Rows.Count; j++)
            {
                DataRow row2 = ds.Tables["table2"].Rows[j];
                if (row.ItemArray.GetValue(1).ToString() == row2.ItemArray.GetValue(1).ToString())
                {
                    if (row.ItemArray.GetValue(3).ToString() == row2.ItemArray.GetValue(3).ToString())
                    {
                        id = int.Parse(row2.ItemArray.GetValue(0).ToString());
                        deletedupes(id);
                    }
                }
            }
        }

        con.Close();
    }


    private void deletedupes(int num)
    {
        OleDbConnection con = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=C:\\hi.mdb");

        con.Open();

        OleDbCommand c = new OleDbCommand("Delete from table2 where id =?", con);
        c.Parameters.AddWithValue("id", num);
        c.ExecuteNonQuery();

        con.Close();
    }

编辑:对不起,我错过了说我确实使用了一个具有主键的唯一列来完成这项工作。尽管如此,这也可以在没有它的情况下完成。只是选择问题。而且不知什么原因,这个方法似乎也太快了..

于 2011-04-08T23:54:08.860 回答