как удалить повторяющиеся строки из базы данных ms access (С#)

Я просматривал различные сайты и коды, но, похоже, ничто не положило конец моим страданиям. Либо они помогают найти и удалить дубликаты для определенного столбца, либо удаляют только из таблицы данных, а не из самой базовой базы данных. Я хочу удалить повторяющиеся строки из таблицы «table1» моего файла mdb.

Чтобы сделать мои требования более понятными:

  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??
    }

Заранее спасибо. Да я новичек..


person nawfal    schedule 08.04.2011    source источник
comment
Некоторые механизмы баз данных позволяют вам сделать что-то похожее на удаление первых 1 из .... Возможно, Access поддерживает это? О, и добавьте первичный ключ.   -  person Lasse V. Karlsen    schedule 08.04.2011
comment
Почему нельзя получить первичный ключ? Как вы получаете повторяющиеся строки в первую очередь?   -  person Lasse V. Karlsen    schedule 09.04.2011
comment
@Lasse, извини, я не знаю, откуда top1. У меня нет первичного ключа для моих столбцов, таких как Name1, Name2 или Name3. Поскольку это означает только уникальное значение для этих столбцов. У меня может быть уникальный идентификатор в качестве первичного ключа, но для какой цели это будет здесь? Если я установлю свой столбец 0 в качестве первичного ключа, то каким образом я могу обнаружить повторяющиеся строки, строки с одинаковым значением для столбца 1, столбца 2 и столбца 3?   -  person nawfal    schedule 09.04.2011
comment
Может ли кто-нибудь предоставить код, чтобы делать то, что я хочу? Я не могу сделать это, читая онлайн.   -  person nawfal    schedule 09.04.2011
comment
@nawfal: я не совсем понимаю, почему у вас не может быть первичного ключа. Вы говорите, что это не позволит дубликаты, но вы, кажется, тоже не хотите дубликатов. Вы понимаете, что первичный ключ может состоять из нескольких столбцов (так называемый составной первичный ключ), верно?   -  person Alek Davis    schedule 09.04.2011
comment
@ Алек, да, я хочу дубликаты в столбцах Имя1, Имя2 и Имя3. Вы можете увидеть их в моем примере. Я имел в виду, что не могу установить столбец Name1 в качестве основного столбца, так как мне нужны дубликаты. Мое требование состоит в том, что у меня не должно быть строки с одинаковым значением для Name1,2 и 3!. В противном случае нет проблем с столбцом уникального идентификатора в качестве столбца 0. Я думаю, что пояснил это в своем комментарии выше вашего. Во всяком случае, я получил это с ответом, который я дал. Да, я использовал там первичный столбец, но можно обойтись и без первичного ключа, используя ту же логику. Просто вопрос выбора.   -  person nawfal    schedule 09.04.2011
comment
Если ваше требование состоит в том, что [у вас] не должно быть строки с одинаковым значением для Name1,2 и 3, просто определите свой первичный ключ как составной ключ, состоящий из всех трех столбцов (как я уже сказал, ключ может быть сделан из несколько столбцов). См. раздел составных ключей по адресу office.microsoft.com/en-us/access-help/   -  person Alek Davis    schedule 09.04.2011
comment
@Алек, большое спасибо за этот совет. Я никогда не знал ничего подобного. Наверняка поможет мне в будущем. спасибо..   -  person nawfal    schedule 12.04.2011


Ответы (4)


Если вы еще не поняли, механизмы баз данных склонны мыслить абсолютными понятиями. Если вы хотите, чтобы он удалил строку, вы должны сообщить ему, как идентифицировать эту строку. Итак, первичные ключи.

Сказав это, обычно, но не всегда, есть два (2) способа сделать это:

  1. Узнайте, поддерживает ли Access синтаксис, чтобы указать DELETE учитывать только «первые N строк», как DELETE TOP 1 FROM ...
  2. Возьмите отдельный набор данных из своей таблицы, удалите в нем все строки и вставьте в него отдельные строки обратно.

Первое возможно, но это зависит от того, поддерживает ли Access какой-либо синтаксис, который делает это возможным. Например. Microsoft SQL Server поддерживает выполнение инструкции SET ROWCOUNT 1 перед DELETE, а затем DELETE удалит только 1 строку, а затем остановится. Я не знаю, сделает ли Access это.

Второе будет проблемой, если у вас есть внешние ключи, но я собираюсь пойти на риск и предположить, что, поскольку у вас нет первичных ключей, у вас нет внешних ключей, поэтому целостность данных не является проблемой. реальная проблема здесь.

person Lasse V. Karlsen    schedule 08.04.2011
comment
MS Access поддерживает предикат TOP. - person BrandonZeider; 09.04.2011

Вот статья, в которой обсуждаются несколько подходов к удалению повторяющихся строк в SQL Server, но я подозреваю, что это применимо и к MS Access: Удаление дубликатов из таблицы в SQL Server

person Alek Davis    schedule 08.04.2011
comment
Я не думаю, что MS Access будет поддерживать табличные переменные, не так ли? - person BrandonZeider; 09.04.2011
comment
@ Брэндон, наверное, это не имеет значения. В этой статье он используется только в демонстрационных целях. Настоящий вопрос заключается в том, есть ли в Access что-нибудь вроде SET ROWCOUNT 1 - person Lasse V. Karlsen; 09.04.2011

Хорошо, это полный взлом, но похоже, что это ваш единственный вариант...

Сделайте SELECT DISTINCTROW из своего стола. Удалите все записи из вашей таблицы. Вставьте отдельные строки обратно.

Синтаксис DISTINCTROW< /а>.

person BrandonZeider    schedule 08.04.2011

Поскольку ни один из ответов не был для меня удовлетворительным (я просто слишком новичок, чтобы понять краткий и слегка технический способ, которым здесь говорят более знающие и опытные люди), я попробовал свой собственный вариант, чтобы сделать это. Я не мог понять, что делать с такими командами, как distinct или set 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();
    }

Изменить: извините, я пропустил, чтобы сказать, что я использовал уникальный столбец с первичным ключом, чтобы сделать это. Тем не менее, это можно сделать и без этого. Просто вопрос выбора. И по неизвестным причинам этот метод тоже кажется таким быстрым.

person nawfal    schedule 08.04.2011
comment
Этот образец действительно может делать то, что вам нужно, но это не то, что вы хотели бы показать потенциальному работодателю или выпустить в реальной жизни. - person Alek Davis; 09.04.2011