admin管理员组文章数量:1315334
My SQLAlchemy ORM model is populated by a JSON file that occasionally changes. The JSON file does not provide an integer primary key but has a unique alphanumeric ProductCode. My model:
class ProductDescriptor(Base):
__tablename__ = 'product_descriptor'
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
ProductCode: Mapped[str] = mapped_column(String(50), unique=True)
DisplayName: Mapped[str] = mapped_column(String(50))
Description: Mapped[str] = mapped_column(String(1000))
...
This answer makes sense until this line:
on_duplicate_stmt = insert_stmt.on_duplicate_key_update(dict(txt=insert_stmt.inserted.txt))
Because the incoming data lacks a key I have nothing to compare. Do I need to change the ProductCode definition? I am using Unique=True
. My code:
product_list = []
for product in products:
# Create filtered list of dicts to be send to the DB
product_list.append({
'ProductName': product.get('ProductName'),
'DisplayName': product.get('DisplayName'),
'Description': product.get('Description'),
... more columns
})
insert_stmt = insert(ProductDescriptor).values(product_list)
# This is where it goes wrong
on_duplicate_stmt = insert_stmt.on_duplicate_key_update()
# Trying to deal with integrity errors and rollback requests
for product in product_list:
try:
self.session.add(resource)
self.sessionmit()
except IntegrityError:
pass
- How can I efficiently create an update or create function for bulk records?
- Do I need to turn my unique field into a key field?
- Can I keep an autoincrement key field as well?
In Django I would be using the update_or_create
method where I can specify the key field and provide a defaults
dictionary:
Profile.objects.update_or_create(custid=user_profile.custid, defaults=defaults)
My SQLAlchemy ORM model is populated by a JSON file that occasionally changes. The JSON file does not provide an integer primary key but has a unique alphanumeric ProductCode. My model:
class ProductDescriptor(Base):
__tablename__ = 'product_descriptor'
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
ProductCode: Mapped[str] = mapped_column(String(50), unique=True)
DisplayName: Mapped[str] = mapped_column(String(50))
Description: Mapped[str] = mapped_column(String(1000))
...
This answer makes sense until this line:
on_duplicate_stmt = insert_stmt.on_duplicate_key_update(dict(txt=insert_stmt.inserted.txt))
Because the incoming data lacks a key I have nothing to compare. Do I need to change the ProductCode definition? I am using Unique=True
. My code:
product_list = []
for product in products:
# Create filtered list of dicts to be send to the DB
product_list.append({
'ProductName': product.get('ProductName'),
'DisplayName': product.get('DisplayName'),
'Description': product.get('Description'),
... more columns
})
insert_stmt = insert(ProductDescriptor).values(product_list)
# This is where it goes wrong
on_duplicate_stmt = insert_stmt.on_duplicate_key_update()
# Trying to deal with integrity errors and rollback requests
for product in product_list:
try:
self.session.add(resource)
self.sessionmit()
except IntegrityError:
pass
- How can I efficiently create an update or create function for bulk records?
- Do I need to turn my unique field into a key field?
- Can I keep an autoincrement key field as well?
In Django I would be using the update_or_create
method where I can specify the key field and provide a defaults
dictionary:
Profile.objects.update_or_create(custid=user_profile.custid, defaults=defaults)
Share
Improve this question
edited Feb 5 at 20:26
user4157124
3,00214 gold badges31 silver badges46 bronze badges
asked Jan 30 at 9:20
Byte InsightByte Insight
1,1541 gold badge11 silver badges22 bronze badges
3
- 1 The answer you cited is for MySQL. Is that your database backend as well? – Gord Thompson Commented Jan 30 at 14:08
- @GordThompson SQLite. – Byte Insight Commented Jan 30 at 15:21
- 1 Have you checked the docs to see how SQLite differs from MySQL in this regard? – Gord Thompson Commented Jan 30 at 15:48
1 Answer
Reset to default 1SQLite lets us specify the matching columns for ON CONFLICT, like so:
from sqlalchemy.dialects.sqlite import insert
new_values = json.loads("""\
[
{"ProductCode": "code_1", "DisplayName": "display_1", "Description": "description_1"},
{"ProductCode": "code_2", "DisplayName": "display_2", "Description": "description_2"}
]
""")
insert_stmt = insert(ProductDescriptor).values(new_values)
do_update_stmt = insert_stmt.on_conflict_do_update(
index_elements=["ProductCode"],
set_=dict(
DisplayName=insert_stmt.excluded.DisplayName,
Description=insert_stmt.excluded.Description,
),
)
engine.echo = True
with engine.begin() as conn:
conn.execute(do_update_stmt)
"""
BEGIN (implicit)
INSERT INTO product_descriptor ("ProductCode", "DisplayName", "Description") VALUES (?, ?, ?), (?, ?, ?) ON CONFLICT ("ProductCode") DO UPDATE SET "DisplayName" = excluded."DisplayName", "Description" = excluded."Description"
[no key 0.00093s] ('code_1', 'display_1', 'description_1', 'code_2', 'display_2', 'description_2')
COMMIT
"""
Note that if "ProductCode" is a unique non-nullable column then it is in fact a natural primary key, so the autoincrement integer "id" column is not really necessary
本文标签: pythonInsert or update when importing from JSONStack Overflow
版权声明:本文标题:python - Insert or update when importing from JSON - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741976720a2408166.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论