Как реализовать таблицу в стиле базы данных в Python - PullRequest
6 голосов
/ 15 ноября 2010

Я реализую класс, который похож на типичную таблицу базы данных:

  • имеет именованные столбцы и безымянные строки
  • имеет первичный ключ, по которому я могу ссылаться на строки
  • поддерживает поиск и назначение по первичному ключу и заголовку столбца
  • можно попросить добавить уникальный или неуникальный индекс для любого из столбцов, что позволяет быстро получить строку (или набор строк), которые имеют заданное значение в этом столбце
  • удаление строки выполняется быстро и реализуется как «мягкое удаление»: строка сохраняется физически, но помечается для удаления и не будет отображаться при любых последующих операциях поиска
  • быстрое добавление столбца
  • редко добавляются строки
  • столбцы редко удаляются

Я решил реализовать класс напрямую, а не использовать оболочку вокруг sqlite.

Какую структуру данных использовать?


Например, один из подходов, о котором я думал, - это словарь. Его ключи - это значения в столбце первичного ключа таблицы; его значения - строки, реализованные одним из следующих способов:

  1. Как списки. Номера столбцов отображаются в заголовках столбцов (используя список для одного направления и карту для другого). Здесь операция поиска сначала преобразует заголовок столбца в номер столбца, а затем находит соответствующий элемент в списке.

  2. Как словари. Заголовки столбцов являются ключами этого словаря.

Не уверен насчет плюсов / минусов двух.


Причины, по которым я хочу написать свой собственный код:

  • Мне нужно отслеживать удаление строк. То есть в любое время я хочу иметь возможность сообщать, какие строки были удалены и по какой «причине» («причина» передается моему методу удаления).
  • Мне нужны некоторые отчеты во время индексации (например, когда создается неуникальный индекс, я хочу проверить определенные условия и сообщить, если они нарушены)

Ответы [ 3 ]

2 голосов
/ 16 ноября 2010

Возможно, вы захотите создать класс, использующий таблицу sqlite в памяти:

import sqlite3

class MyTable(object):
    def __init__(self):
        self.conn=sqlite3.connect(':memory:')
        self.cursor=self.conn.cursor()
        sql='''\
            CREATE TABLE foo ...
        '''
        self.execute(sql)
    def execute(self,sql,args):
        self.cursor.execute(sql,args)
    def delete(self,id,reason):
        sql='UPDATE table SET softdelete = 1, reason = %s where tableid = %s'
        self.cursor.execute(sql,(reason,id,))
    def verify(self):
        # Check that certain conditions are true
        # Report (or raise exception?) if violated
    def build_index(self):
        self.verify()
        ... 

Мягкое удаление может быть реализовано с помощью столбца softdelete (типа bool). Точно так же у вас может быть столбец для хранения причины удаления. Для удаления просто потребуется обновить строку и изменить значение softdelete. Выбор строк, которые не были удалены, можно выполнить с помощью условия SQL WHERE softdelete != 1.

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

Другой альтернативой является использование массива структурированных масок.

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

2 голосов
/ 15 ноября 2010

Я бы подумал о создании словаря с ключами, которые являются кортежами или списками.Например: my_dict(("col_2", "row_24")) даст вам этот элемент.Исходя из этого, было бы довольно легко (если не очень быстро для очень больших баз данных) написать методы get_col и get_row, а также get_row_slice и get_col_slice из двух предыдущих, чтобы получить доступ к вашемуметоды.

Использование такого словаря дает 2 преимущества.1) Получение одного элемента будет быстрее, чем ваши 2 предложенных метода;2) Если вы хотите, чтобы в ваших столбцах было разное количество элементов (или отсутствующих элементов), это сделает его чрезвычайно легким и эффективным для использования памяти.

Просто мысль :) Мне будет интересно посмотреть, какие пакетылюди предложат!

Ура

0 голосов
/ 20 ноября 2010

Вы действительно должны использовать SQLite.

По вашей первой причине (отслеживание причин удаления) вы можете легко реализовать это, имея вторую таблицу, в которую вы «перемещаете» строки при удалении. Причину можно отследить в дополнительном столбце этой таблицы или в другой таблице, к которой вы можете присоединиться. Если причина удаления не всегда требуется, вы можете даже использовать триггеры в исходной таблице для копирования строк, которые должны быть удалены, и / или иметь пользовательскую функцию, которая может получить причину.

Причина индексации несколько связана с ограничениями и т. Д., Но я не могу обратиться к ней напрямую без более подробной информации.

...