#python #sqlite #sqlalchemy
#python #sqlite #sqlalchemy
Вопрос:
У меня есть внешний ключ в PropertyChange
таблице, который находится id
в Run
таблице. Когда я запускаю и фиксирую данные для обеих таблиц, я получаю IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: PropertyChange.run_id
. Из того, что я прочитал, настройка autoincrement=True
в Run
таблице должна была решить эту проблему.
models.py
class Run(Base):
__tablename__ = 'Run'
id = Column(Integer, primary_key=True, autoincrement=True)
instance = Column(Integer, nullable=True)
name = Column(String, nullable=False)
host = Column(String, nullable=False)
config = Column(JSON, nullable=False)
property_change = relationship('PropertyChange', back_populates='run')
class PropertyChange(Base):
__tablename__ = 'PropertyChange'
id = Column(Integer, primary_key=True, autoincrement=True)
timestamp = Column(DateTime(timezone=True), nullable=False)
property_name = Column(String, nullable=True)
p_values = Column(JSON, nullable=False)
s_values = Column(JSON, nullable=False)
c_values = Column(JSON, nullable=True)
run_id = Column(Integer, ForeignKey('Run.id'), nullable=False)
run = relationship('Run', back_populates='property_change')
Добавление и фиксация данных, поскольку мои данные находятся в dataframe:
prod_run = models.Run
prop_change = models.PropertyChanges
pending_data = []
for row in run_df.itertuples():
pending_data.append(prod_run(instance =row.instance, name=row.name, host =row.host, config = row.config ))
for row in property_changes.itertuples():
pending_data.append(prop_change(timestamp=row.timestamp, property_name=row.property_name, p_values=row.p_values, s_values=row.s_values, c_values=row.c_values))
session.add_all(pending_data)
session.commit()
Комментарии:
1. Два примечания: (1) По умолчанию SQLite не применяет ограничения внешнего ключа. Подробности здесь . (2) Если у вас уже есть данные в двух отдельных фреймах данных, тогда зачем создавать объекты ORM и добавлять их в сеанс, когда вы можете просто загрузить данные непосредственно в базовые таблицы? Вы всегда можете получить определенные объекты ORM после обновления таблиц.
2. Мой вопрос при загрузке непосредственно из фрейма данных заключается в том, как мне сообщить
PropertyChange
таблице оrun_id
Run
таблице? Это генерируется после того, как я передаю данные вRun
таблицу.3. Если у вас уже есть данные в двух отдельных фреймах данных, то они уже должны иметь общее значение ключа для связывания строк. Если вы не можете использовать это общее (ключевое) значение в качестве первичного ключа для запуска (например, потому что оно уникально в этом подмножестве строк, но не уникально глобально), то вы могли бы, по крайней мере, использовать его для связывания строк в этом конкретном пакете.
4. Мне все еще нужно сгенерировать глобально уникальный идентификатор … на чем я и застрял с dataframe.to_sql(). Что, я думаю, может сработать, и это супер хакерство — сначала зафиксировать таблицу выполнения, а затем запросить БД и взять идентификатор последней добавленной строки и назначить его в качестве столбца run_id для каждой строки в property_changes dataframe. Затем зафиксируйте эту таблицу, чтобы она имела правильный глобально уникальный идентификатор. Однако это довольно хитрый обходной путь. Есть еще идеи?
5. Я недостаточно знаю о ваших данных, чтобы написать что-то большее, чем комментарий в форме ответа (который технически «не является ответом»). Если вы исправите подход ORM и опубликуете свое решение в качестве ответа (можно ответить на свой собственный вопрос), то, если вы хотите дополнительно изучить параметр DataFrame-to-table (например, если вы обнаружите, что подход ORM медленный, что может оказаться), тогда выможете задать это как отдельный вопрос.
Ответ №1:
Поскольку часть комментария слишком коротка для обсуждения решений, я перейду сюда:
Я упомяну некоторые моменты для проверки и решения:
(1)
проверьте данные в ваших фреймах данных, связанных со столбцами nullable=False
. есть ли в nan
значениях. ( name, host and config
в run_df
и timestamp, p_values, s_values
в PropertyChange )
(2)
Переопределение столбца ‘run_id in
PropertyChange , you make it
nullable=False , and you assigned neither a valid
Run.id nor a reference to the object of
Тип «Выполнить».
(3)
Наконец, вы устанавливаете связь run = relationship('Run', back_populates='property_change')
в модели PropertyChange
без связанного внешнего ключа в Run
модели, я столкнулся с неожиданными проблемами с SQLAlchemy для подобных случаев.
ищу либо решаемые, либо комментарии 🙂