Я пытаюсь использовать bulk_insert
Alembic в файле миграции, чтобы получить некоторые данные в мою базу данных для целей тестирования. Это мой код создания базы данных:
import sqlalchemy as sa
from alembic import op
def upgrade():
test_table = op.create_table(
"test",
sa.Column("id", sa.String, nullable=False),
sa.Column("item_id", sa.String, nullable=True),
sa.Column("object_id", sa.String, nullable=True),
sa.Column("article_id", sa.String, nullable=True),
sa.Column("active", sa.Boolean, nullable=False, default=True),
sa.Column("name", sa.String, nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.ForeignKeyConstraint("item_id"),
sa.ForeignKeyConstraint("object_id"),
sa.ForeignKeyConstraint("article_id"),
)
Данные могут иметь либо item_id
, object_id
, article_id
, либо все сразу. Если идентификатор существует, это внешний ключ, указывающий на другую таблицу.
Вот как я пытаюсь вставить некоторые тестовые данные в таблицу. Он отлично работает для первой строки, но следующая вызывает ошибку, например: A value is required for bind parameter 'item_id', in parameter group 1
, если у моего первого объекта есть item_id
, но нет других FK, а у второго объекта нет item_id
. Если в первой строке есть article_id
, а во второй нет, ошибка A value is required for bind parameter 'article_id'...
.
op.bulk_insert(
test_table,
[
{
"id": "test1",
"item_id": "item001",
"active": True,
"name" : "item 1",
"created_at": datetime.now(tz=timezone.utc),
"updated_at": datetime.now(tz=timezone.utc),
},
{
"id": "test2",
"article_id": "art001",
"active": True,
"name" : "article 1",
"created_at": datetime.now(tz=timezone.utc),
"updated_at": datetime.now(tz=timezone.utc),
}
],
)
Я не могу понять, почему это происходит, почему я не могу вставить две строки в базу данных, где у меня есть разные столбцы FK? Чего я хотел бы добиться, так это того, что все отсутствующие поля FK будут Null
.
Я думаю, проблема не в том, что они отсутствуют, а в том, что словари имеют разные ключи. Попробуйте установить параметры, которые иногда появляются, а иногда нет, на None
. Я думаю, что оператор компилируется, а затем повторно используется снова и снова, вероятно, он основан на первом наборе значений в списке. Поэтому более поздние вызовы терпят неудачу, когда словарь отличается. Я думаю, это объясняется здесь выполнение нескольких операторов
When executing multiple sets of parameters, each dictionary must have the same set of keys; i.e. you cant have fewer keys in some dictionaries than others. This is because the Insert statement is compiled against the first dictionary in the list, and it’s assumed that all subsequent argument dictionaries are compatible with that statement.
op.bulk_insert(
test_table,
[
{
"id": "test1",
"article_id": None,
"item_id": "item001",
"active": True,
"name" : "item 1",
"created_at": datetime.now(tz=timezone.utc),
"updated_at": datetime.now(tz=timezone.utc),
},
{
"id": "test2",
"item_id": None,
"article_id": "art001",
"active": True,
"name" : "article 1",
"created_at": datetime.now(tz=timezone.utc),
"updated_at": datetime.now(tz=timezone.utc),
}
])