SQLAlchemy: इंजन, कनेक्शन और सत्र अंतर


134

मैं SQLAlchemy का उपयोग करें और वहाँ कम से कम तीन संस्थाओं हैं: engine, sessionऔर connection, जो है executeविधि है, इसलिए यदि मैं जैसे सभी रिकॉर्ड से चयन करना चाहते हैं tableमैं यह कर सकता

engine.execute(select([table])).fetchall()

और इस

connection.execute(select([table])).fetchall()

और यह भी

session.execute(select([table])).fetchall()

- परिणाम समान होंगे।

जैसा कि मैं इसे समझता हूं, अगर कोई engine.executeइसका उपयोग करता है connection, तो खोलता है session(कीमिया आपके लिए इसका ख्याल रखता है) और क्वेरी को निष्पादित करता है। लेकिन क्या इस तरह के कार्य करने के इन तीन तरीकों के बीच एक वैश्विक अंतर है?


मुझे लगता है कि आपका जवाब यहीं है: hackersandslackers.com/-
SeF

जवाबों:


123

एक-पंक्ति अवलोकन:

का व्यवहार execute()सभी मामलों में समान है, लेकिन वे 3 अलग-अलग विधियां हैं, इन Engine, इन Connection, और Sessionकक्षाएं।

वास्तव में क्या है execute():

व्यवहार को समझने के लिए execute()हमें Executableकक्षा में देखने की जरूरत है । Executableसभी "स्टेटमेंट" प्रकारों के लिए एक सुपरक्लास है, जिसमें सेलेक्ट (), डिलीट (), अपडेट (), इंसर्ट (), टेक्स्ट () - सरलतम शब्दों में संभव है, ExecutableSQLAlchemy में समर्थित SQL अभिव्यक्ति कंस्ट्रक्शन है।

सभी मामलों में execute()विधि SQL पाठ लेती है या SQL अभिव्यक्ति का निर्माण करती है अर्थात SQLAlchemy में समर्थित SQL अभिव्यक्ति निर्माणों की कोई भी विविधता और क्वेरी परिणाम लौटाती है ( ResultProxy- DB-APIपंक्ति स्तंभों तक आसान पहुँच प्रदान करने के लिए कर्सर ऑब्जेक्ट को लपेटता है ।)


इसे और स्पष्ट करने के लिए (केवल वैचारिक स्पष्टीकरण के लिए, अनुशंसित दृष्टिकोण नहीं) :

Engine.execute()(कनेक्शन रहित निष्पादन) के अलावा Connection.execute(), और Session.execute(), execute()किसी भी Executableनिर्माण पर सीधे उपयोग करना भी संभव है । Executableवर्ग के उसके अपने कार्यान्वयन है execute()- आधिकारिक दस्तावेज के अनुसार, किस बारे में एक पंक्ति का वर्णन execute()करता है "है संकलित करें और इस पर अमलExecutable "। इस मामले में हमें Executableकिसी Connectionवस्तु या वस्तु के साथ (एसक्यूएल एक्सप्रेशन कंस्ट्रक्शन) को स्पष्ट रूप से बांधने की जरूरत होती है , Engine(जिसे स्पष्ट रूप से एक Connectionवस्तु मिलती है ), इसलिए execute()वसीयत को पता चल जाएगा कि कहां निष्पादित करना है SQL

निम्न उदाहरण इसे अच्छी तरह से प्रदर्शित करता है - नीचे दी गई तालिका के अनुसार:

from sqlalchemy import MetaData, Table, Column, Integer

meta = MetaData()
users_table = Table('users', meta,
    Column('id', Integer, primary_key=True),
    Column('name', String(50)))

स्पष्ट निष्पादन यानी Connection.execute()- एसक्यूएल पाठ या निर्माण एसक्यूएल अभिव्यक्ति गुजर execute()की विधि Connection:

engine = create_engine('sqlite:///file.db')
connection = engine.connect()
result = connection.execute(users_table.select())
for row in result:
    # ....
connection.close()

स्पष्ट संयोजन निष्पादन यानी Engine.execute()- को सीधे एसक्यूएल पाठ या निर्माण एसक्यूएल अभिव्यक्ति गुजर execute()इंजन की विधि:

engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
    # ....
result.close()

निहित निष्पादन यानी Executable.execute()- भी कनेक्शन रहित है, और की execute()विधि को कॉल करता है Executable, अर्थात, यह execute()सीधे SQLअभिव्यक्ति निर्माण ( Executableस्वयं का एक उदाहरण ) पर विधि कहता है।

engine = create_engine('sqlite:///file.db')
meta.bind = engine
result = users_table.select().execute()
for row in result:
    # ....
result.close()

नोट: स्पष्टीकरण के उद्देश्य के लिए निहित निष्पादन का उदाहरण दिया गया - निष्पादन का यह तरीका अत्यधिक अनुशंसित नहीं है - डॉक्स के अनुसार :

"निहित निष्पादन" एक बहुत पुराना उपयोग पैटर्न है कि ज्यादातर मामलों में यह मददगार होने की तुलना में अधिक भ्रामक है, और इसके उपयोग को हतोत्साहित किया जाता है। दोनों पैटर्न एप्लिकेशन डिज़ाइन में समीचीन "शॉर्ट कट्स" के अति प्रयोग को प्रोत्साहित करते हैं जो आगे चलकर समस्याओं का कारण बनते हैं।


आपके सवाल:

जैसा कि मैं समझता हूं कि अगर कोई इंजन का उपयोग करता है। यह कनेक्शन बनाता है, सत्र खोलता है (कीमिया आपके बारे में परवाह करता है) और क्वेरी निष्पादित करता है।

आप इस भाग के लिए सही हैं "यदि कोई इसका उपयोग engine.executeकरता है connection" लेकिन नहीं खुलता है, तो "खुलता है session(कीमिया आपके बारे में परवाह करता है) और क्वेरी निष्पादित करता है" - का उपयोग करना Engine.execute()और Connection.execute()(लगभग) एक ही बात, औपचारिक रूप से, Connectionवस्तु अंतर्निहित रूप से निर्मित होती है , और बाद के मामले में हम स्पष्ट रूप से इसे तुरंत बताते हैं। वास्तव में इस मामले में क्या होता है:

`Engine` object (instantiated via `create_engine()`) -> `Connection` object (instantiated via `engine_instance.connect()`) -> `connection.execute({*SQL expression*})`

लेकिन क्या ऐसे कार्य करने के इन तीन तरीकों के बीच एक वैश्विक अंतर है?

DB लेयर पर यह बिल्कुल एक ही बात है, ये सभी SQL (टेक्स्ट एक्सप्रेशन या विभिन्न SQL एक्सप्रेशन कंस्ट्रक्शंस) को निष्पादित कर रहे हैं। आवेदन के दृष्टिकोण से दो विकल्प हैं:

  • प्रत्यक्ष निष्पादन - उपयोग करना Engine.execute()याConnection.execute()
  • का उपयोग करना sessions- कुशलता के माध्यम से आसानी से, एक इकाई के-कार्य के रूप में लेन-देन को संभालती है session.add(), session.rollback(),session.commit() , session.close()। यह ORM यानी मैप्ड टेबल के मामले में DB के साथ बातचीत करने का तरीका है। एकल अनुरोध के दौरान पहले से ही एक्सेस की गई या नई बनाई गई / जोड़ी गई वस्तुओं को तुरंत प्राप्त करने के लिए आइडेंटिटी_मैप प्रदान करता है ।

Session.execute()Connection.execute()SQL कथन निष्पादित करने के लिए अंततः कथन निष्पादन विधि का उपयोग करता है । Sessionऑब्जेक्ट का उपयोग करना SQLAlchemy ORM डेटाबेस के साथ बातचीत करने के लिए किसी एप्लिकेशन के लिए अनुशंसित तरीका है।

से एक अंश डॉक्स का :

यह नोट करना महत्वपूर्ण है कि SQLAlchemy ORM का उपयोग करते समय, इन वस्तुओं को आम तौर पर एक्सेस नहीं किया जाता है; इसके बजाय, सत्र ऑब्जेक्ट डेटाबेस के लिए इंटरफ़ेस के रूप में उपयोग किया जाता है। हालाँकि, उन अनुप्रयोगों के लिए, जिन्हें ORM के उच्च स्तरीय प्रबंधन सेवाओं में शामिल किए बिना शाब्दिक SQL कथनों और / या SQL अभिव्यक्ति के प्रत्यक्ष उपयोग के आसपास बनाया गया है, इंजन और कनेक्शन राजा (और रानी?) हैं - पर पढ़ें।


"कनेक्शन रहित" शब्द का अर्थ है कि कोई कनेक्शन नहीं बनाया जा रहा है, जो नील के उत्तर के अनुसार नहीं है।
परमाणु

111

नबील का जवाब बहुत सारे विवरणों को शामिल करता है और सहायक है, लेकिन मैंने पाया कि इसका पालन करना दूभर है। चूंकि वर्तमान में इस मुद्दे के लिए यह पहला Google परिणाम है, इस सवाल को खोजने वाले भविष्य के लोगों के लिए मेरी समझ को जोड़ना:

रनिंग .execute ()

जब ओपी और नबेल अहमद दोनों नोट करते हैं, तो एक सादे को निष्पादित करते समय SELECT * FROM tablename, प्रदान किए गए परिणाम में कोई अंतर नहीं होता है।

इन तीनों वस्तुओं के बीच के अंतर इस संदर्भ के आधार पर महत्वपूर्ण हो जाते हैं कि SELECTकथन का उपयोग इस तरह किया जाता है, और अधिक सामान्यतः, जब आप अन्य चीजें करना चाहते हैं INSERT, जैसे DELETE, आदि।

आम तौर पर इंजन, कनेक्शन, सत्र का उपयोग करने के लिए

  • इंजन SQLAlchemy द्वारा उपयोग की जाने वाली निम्नतम स्तर की वस्तु है। यह कनेक्शन की एक पूल का कहना उपयोग जब भी आवेदन डेटाबेस से बात करने की जरूरत है के लिए उपलब्ध। .execute()एक सुविधा विधि है जो पहले कॉल करती है conn = engine.connect(close_with_result=True)और फिर conn.execute()। Close_with_result पैरामीटर का अर्थ है कि कनेक्शन स्वचालित रूप से बंद हो गया है। (मैं स्रोत कोड थोड़ा सा paraphrasing, लेकिन अनिवार्य रूप से सच है)। संपादित करें: यहां engine.execute के लिए स्रोत कोड है

    आप कच्चे SQL को निष्पादित करने के लिए इंजन का उपयोग कर सकते हैं।

    result = engine.execute('SELECT * FROM tablename;')
    #what engine.execute() is doing under the hood
    conn = engine.connect(close_with_result=True)
    result = conn.execute('SELECT * FROM tablename;')
    
    #after you iterate over the results, the result and connection get closed
    for row in result:
        print(result['columnname']
    
    #or you can explicitly close the result, which also closes the connection
    result.close()

    यह बेसिक उपयोग के तहत डॉक्स में कवर किया गया है ।

  • संबंध है (जैसा कि हमने ऊपर देखा) वह चीज़ जो वास्तव में SQL क्वेरी को निष्पादित करने का काम करती है। आपको ऐसा तब करना चाहिए जब भी आप कनेक्शन की विशेषताओं पर अधिक नियंत्रण चाहते हैं, जब यह बंद हो जाता है, आदि। उदाहरण के लिए, इसका एक बहुत ही आयात उदाहरण एक लेन-देन है , जो आपको डेटाबेस में आपके परिवर्तन करने के लिए निर्णय लेने की सुविधा देता है। सामान्य उपयोग में, परिवर्तन स्वतः पूर्ण होते हैं। लेन-देन के उपयोग के साथ, आप (उदाहरण के लिए) कई अलग-अलग SQL कथन चला सकते हैं और यदि उनमें से कुछ के साथ कुछ गलत हो जाता है तो आप एक बार में सभी परिवर्तनों को पूर्ववत कर सकते हैं।

    connection = engine.connect()
    trans = connection.begin()
    try:
        connection.execute("INSERT INTO films VALUES ('Comedy', '82 minutes');")
        connection.execute("INSERT INTO datalog VALUES ('added a comedy');")
        trans.commit()
    except:
        trans.rollback()
        raise

    यह आपको दोनों परिवर्तनों को पूर्ववत् करने देता है यदि कोई विफल हो जाता है, जैसे यदि आप datalog तालिका बनाना भूल गए हैं।

    इसलिए यदि आप कच्चे SQL कोड को निष्पादित कर रहे हैं और नियंत्रण की आवश्यकता है, तो कनेक्शन का उपयोग करें

  • सत्रSQLAlchemy के ऑब्जेक्ट रिलेशनशिप मैनेजमेंट (ORM) पहलू के लिए का उपयोग किया जाता है (वास्तव में आप यह देख सकते हैं कि वे कैसे आयात किए जाते हैं:) from sqlalchemy.orm import sessionmaker। वे अपने स्वचालित रूप से उत्पन्न SQL स्टेटमेंट को चलाने के लिए हुड के तहत कनेक्शन और लेनदेन का उपयोग करते हैं। .execute()एक सुविधा फ़ंक्शन है जो सत्र के लिए बाध्य है (आमतौर पर एक इंजन है, लेकिन एक कनेक्शन हो सकता है) से गुजरता है।

    यदि आप ORM कार्यक्षमता का उपयोग कर रहे हैं, सत्र का उपयोग करें; यदि आप केवल सीधे एसक्यूएल प्रश्नों को ऑब्जेक्ट्स के लिए बाध्य नहीं कर रहे हैं, तो आप शायद सीधे कनेक्शन का उपयोग कर रहे हैं।


1
डालने के बयान दोहरे उद्धरण चिह्नों में संलग्न नहीं होना चाहिए ""?
मिंगचू

2
@mingchau हाँ, आप सही हैं मेरे एकल उद्धरण एक दूसरे के साथ हस्तक्षेप करेंगे, दोहरे उद्धरण उस मुद्दे से बचने के लिए बहुत आसान हैं। अपडेट किया गया।
नील

दिए गए सत्र को देखते हुए, मेरा सत्र मेरे PostgreSQL कनेक्शन के साथ कैसे जुड़ा है?
राजू आपका Raj

@RajuyourPepe my_session.connection()। डॉक्स: docs.sqlalchemy.org/en/13/orm/...
नील

गंभीरता से? 'सत्र' ऑब्जेक्ट में कोई विशेषता नहीं है 'कनेक्ट' ", क्या मैंने पाया है
राजू yourPepe

0

यहां GRL जैसे DCL (डेटा नियंत्रण भाषा) चलाने का एक उदाहरण है

def grantAccess(db, tb, user):
  import sqlalchemy as SA
  import psycopg2

  url = "{d}+{driver}://{u}:{p}@{h}:{port}/{db}".\
            format(d="redshift",
            driver='psycopg2',
            u=username,
            p=password,
            h=host,
            port=port,
            db=db)
  engine = SA.create_engine(url)
  cnn = engine.connect()
  trans = cnn.begin()
  strSQL = "GRANT SELECT on table " + tb + " to " + user + " ;"
  try:
      cnn.execute(strSQL)
      trans.commit()
  except:
      trans.rollback()
      raise
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.