मेरे पास एक रिकॉर्ड है कि मैं डेटाबेस में मौजूद होना चाहता हूं यदि यह वहां नहीं है, और यदि यह पहले से मौजूद है (प्राथमिक कुंजी मौजूद है) मैं चाहता हूं कि फ़ील्ड वर्तमान स्थिति में अपडेट हो जाएं। इसे अक्सर upsert कहा जाता है।एसक्लएल्चेमी के साथ अपरर्ट कैसे करें?
निम्नलिखित अपूर्ण कोड स्निपेट दर्शाता है कि क्या काम करेगा, लेकिन यह अत्यधिक गुंजाइश लगता है (विशेष रूप से यदि बहुत अधिक कॉलम थे)। बेहतर/सर्वोत्तम तरीका क्या है?
Base = declarative_base()
class Template(Base):
__tablename__ = 'templates'
id = Column(Integer, primary_key = True)
name = Column(String(80), unique = True, index = True)
template = Column(String(80), unique = True)
description = Column(String(200))
def __init__(self, Name, Template, Desc):
self.name = Name
self.template = Template
self.description = Desc
def UpsertDefaultTemplate():
sess = Session()
desired_default = Template("default", "AABBCC", "This is the default template")
try:
q = sess.query(Template).filter_by(name = desiredDefault.name)
existing_default = q.one()
except sqlalchemy.orm.exc.NoResultFound:
#default does not exist yet, so add it...
sess.add(desired_default)
else:
#default already exists. Make sure the values are what we want...
assert isinstance(existing_default, Template)
existing_default.name = desired_default.name
existing_default.template = desired_default.template
existing_default.description = desired_default.description
sess.flush()
क्या ऐसा करने का कोई बेहतर या कम वर्बोज़ तरीका है? कुछ इस तरह बहुत अच्छा होगा:
sess.upsert_this(desired_default, unique_key = "name")
हालांकि unique_key
kwarg स्पष्ट रूप से अनावश्यक है मैं इसे जोड़ा सिर्फ इसलिए कि SQLAlchemy जाता है के लिए एक ही प्राथमिक कुंजी के साथ काम (ORM आसानी से यह पता लगा लिए सक्षम होना चाहिए)। उदाहरण: मैं देख रहा हूं कि Session.merge लागू होगा, लेकिन यह केवल प्राथमिक कुंजी पर काम करता है, जो इस मामले में एक ऑटोइनक्रिकमेंटिंग आईडी है जो इस उद्देश्य के लिए बहुत उपयोगी नहीं है।
इसके लिए एक नमूना उपयोग केस बस एक सर्वर अनुप्रयोग शुरू करते समय है जो अपने डिफ़ॉल्ट अपेक्षित डेटा को अपग्रेड कर सकता है। यानी: इस अपरिपक्वता के लिए कोई सहमति नहीं है।
क्यों आप 'name' क्षेत्र एक प्राथमिक कुंजी नहीं बना सकते अगर यह होता है अद्वितीय (और विलय इस मामले में काम करेगा)। आपको एक अलग प्राथमिक कुंजी की आवश्यकता क्यों है? – abbot
@abbot: मैं एक आईडी फ़ील्ड बहस में शामिल नहीं होना चाहता, लेकिन ... संक्षिप्त जवाब "विदेशी कुंजी" है। लंबा यह है कि यद्यपि नाम वास्तव में केवल एकमात्र आवश्यक कुंजी है, फिर भी दो समस्याएं हैं। 1) जब एक टेम्पलेट रिकॉर्ड को किसी अन्य तालिका में 50 मिलियन रिकॉर्ड द्वारा संदर्भित किया जाता है जिसमें एक स्ट्रिंग फ़ील्ड के रूप में एफके पागल होता है। एक अनुक्रमित पूर्णांक बेहतर है, इसलिए प्रतीत होता है कि बिंदुहीन आईडी कॉलम। और 2) उस पर विस्तार, यदि स्ट्रिंग * एफके के रूप में उपयोग किया गया था, तो नाम बदलने के लिए अब दो स्थान हैं, जब यह बदलता है, जो परेशान है और मृत रिश्तों के मुद्दों के साथ छेड़छाड़ कर रहा है। आईडी * कभी नहीं * बदलती है। – Russ
आप एक नया (बीटा) [पायथन के लिए अपर लाइब्रेरी] (https://github.com/seamusabshere/py-upsert) आज़मा सकते हैं ... यह psycopg2, sqlite3, MySQLdb –