Рекурсивное удаление элементов SQLite

#java #android #sqlite

#java #Android #sqlite

Вопрос:

Пример базы данных SQLite:

** Я не создаю базу данных, это база данных закладок Android, к которой я получаю доступ с помощью contentproviders.

** из того, что я понимаю после некоторых поисков, SQLite не поддерживает ограничения внешнего ключа, но возможны триггеры — http://www.sqlite.org/cvstrac/wiki?p=ForeignKeyTriggers

Столбец ПАПКИ -> 0 = не папка (false), 1 = папка (true)

РОДИТЕЛЬСКИЙ столбец -> содержит идентификатор его папки

 ID  TITLE     FOLDER   PARENT
1   folder1      1        0
2   item1        0        1
3   item2        0        1
4   folder2      1        1
5   item1        0        4
6   item2        0        4
7   folder3      1        4
8   item1        0        7
9   item2        0        7
  

…и так далее

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

Например, у меня есть ID = 1, поэтому я могу легко удалить идентификаторы 2 и 3, запросив запрос всех элементов, для которых их родительским является ID = 1, получить идентификаторы элементов, а затем удалить.

Проблема в том, что я не могу понять, как удалить ID = 4 и его внутренние элементы (item1, item2 и folder3), а затем внутренние элементы folder3.

Хотелось бы получить помощь в этом! пытался часами :

Спасибо!

Комментарии:

1. Как вы хотите (должны) решить проблему, в (одном) операторе SQL или в «Java»?

2. @home в Java (я изменю его позже с помощью какого-нибудь Android API, который я должен использовать).

Ответ №1:

Похоже, вы хотите использовать КАСКАД УДАЛЕНИЯ в своем «родительском» столбце. Таким образом, при удалении родительского элемента все папки и файлы, которые указывают его в качестве родительского, также будут удалены. Затем эти результаты будут «каскадироваться» через вашу базу данных.

Итак, вы бы создали свою таблицу следующим образом:

 CREATE TABLE files (id PRIMARY KEY AUTOINCREMENT, title TEXT, folder INTEGER CHECK(FOLDER EQUALS 0 OR FOLDER = 1), parent REFERENCES id);
  

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

PS Наличие логических атрибутов (например, столбца вашей папки в данном случае) обычно считается плохой практикой. В вашем случае было бы лучше иметь папки и файлы в разных таблицах, потому что это разные вещи. Это называется нормализацией. Тем не менее, я мог видеть, что выдвигается аргумент о том, что способ, которым вы сейчас настраиваете вещи, все еще в порядке, потому что технически папки — это просто файлы, для которых установлен специальный флаг. Тем не менее, вам все равно следует рассмотреть идею создания в разных таблицах.

Комментарии:

1. звучит как решение. Я действительно мог бы использовать пример того, как использовать это в запросе…

2. Удивительный ответ 🙂 проблема в том, что я не создаю таблицу, это таблица SQLite для Android (я обращаюсь к ней с помощью ContentProviders — managedQuery …). В любом случае, я могу использовать это при запросе базы данных?

3. О, таблица не ваша? Хм …. это решение тогда не будет работать для вас. Мне придется придумать что-нибудь еще.

Ответ №2:

Если в java, то что-то вроде этого, я думаю, такие функции, как findNextChildId , не должны быть проблемой:

  deleteFolderAndSub(int id){
        int childId = findNextChildId(id);
         //Let -1 be that there are no more children
        while (childId!=-1){
        if (checkIfFolder(childId)){
            deleteFolderAndSub(childId);
    //on exiting from above function folder should be empty so it can be deleted without problem
            deleteEmptyFolder(id);
        } else {
            deleteitem(id);
        }
//it should be while loop and we have to find another child inside the loop
        childId = findNextChildId(id)
      }
    }

findNextChildId(int parentId){
   Coursor yourCoursor;
  while(yourCoursor.moveToNext()){
    if (parentId==yourCoursor.getInt("PARENT")){
        yourCoursor.getInt("ID");
    }
  }
}
  

Комментарии:

1. Тестирование вашего кода с некоторыми изменениями. может сработать. moveToFirst() и moveToNext() заменят findNextChildId

2. да, просто понял это, пока вы это писали 🙂 Отлично! это должно сработать после некоторых изменений. Спасибо!