SQLAlchemy: motor, bağlantı ve oturum farkı


135

: Ben SQLAlchemy kullanmak ve en az üç firma vardır engine, sessionve connectionvar olan executeörneğin ben tüm kayıtları seçmek istediğiniz eğer öyleyse, yöntem tablebunu yapabilirim

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

ve bu

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

ve hatta bu

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

- sonuçlar aynı olacaktır.

Anladığım kadarıyla, birisi engine.executeonu kullanırsa oluşturur connection, açar session(Alchemy sizin için ilgilenir) ve sorguyu yürütür. Ancak böyle bir görevi yerine getirmenin bu üç yolu arasında küresel bir fark var mı?


Sanırım cevabınız tam burada: hackerandslackers.com/…
SeF

Yanıtlar:


123

Tek satırlık bir genel bakış:

Davranışı execute()her durumda aynı, ama onlar 3 farklı yöntem, içindedir Engine, Connectionve Sessionsınıflar.

Tam olarak nedir execute():

Davranışını anlamak execute()için Executablesınıfa bakmamız gerekir . Executableselect (), delete (), update (), insert (), text () dahil olmak üzere tüm "ifade" türleri için bir üst sınıftır - mümkün olan en basit sözcüklerle, ExecutableSQLAlchemy'de desteklenen bir SQL ifade yapısıdır.

Tüm durumlarda, execute()yöntem SQL metnini veya oluşturulmuş SQL ifadesini alır, yani SQLAlchemy'de desteklenen çeşitli SQL ifade yapılarından herhangi birini alır ve sorgu sonuçlarını döndürür (a ResultProxy- DB-APISatır sütunlarına daha kolay erişim sağlamak için bir imleç nesnesini sarar .)


Daha fazla açıklığa kavuşturmak için (yalnızca kavramsal açıklama için, önerilen bir yaklaşım değil) :

Engine.execute()(Bağlantısız yürütme) ' ye ek olarak Connection.execute()ve herhangi bir yapı üzerinde doğrudan Session.execute()kullanmak da mümkündür . Sınıf içinde, bu kendi uygulaması vardır - resmi belgeler başına As, peki ya bir satır açıklama yapar "dir Derleme ve bu yürütmek ". Bu durumda biz açıkça bağlamak gerekir bir ile (SQL İfade yapısı) nesne ya, nesne (ki örtük bir olsun nesnesi) bu yüzden, yürütmek için nereye bilecek .execute()ExecutableExecutableexecute()execute()ExecutableExecutableConnectionEngineConnectionexecute()SQL

Aşağıdaki örnek bunu iyi göstermektedir - Aşağıdaki gibi bir tablo verildiğinde:

from sqlalchemy import MetaData, Table, Column, Integer

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

Açık yürütme yani Connection.execute()- SQL metnini veya oluşturulmuş SQL ifadesini şu execute()yönteme geçirmek Connection:

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

Açık bağlantısız yürütme, yani Engine.execute()- SQL metnini veya oluşturulmuş SQL ifadesini doğrudan execute()Engine yöntemine geçirme :

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

Örtük yürütme ie Executable.execute()- ayrıca bağlantısızdır ve execute()yöntemini çağırır Executable, yani execute()yöntemi doğrudan SQLifade yapısı (bir örneği Executable) üzerinde çağırır .

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

Not: Açıklığa kavuşturmak amacıyla örtük yürütme örneğini belirtmiştir - bu tür bir yürütme kesinlikle önerilmez - belgelere göre :

"Örtük yürütme", çoğu durumda yardımcı olduğundan daha kafa karıştırıcı olan çok eski bir kullanım modelidir ve kullanımı tavsiye edilmez. Her iki model de, uygulama tasarımında daha sonra sorunlara yol açan uygun “kısa yolların” aşırı kullanımını teşvik ediyor gibi görünmektedir.


Sorularınız:

Anladığım kadarıyla birisi engine.execute kullanırsa bağlantı oluşturur, oturum açar (Alchemy sizin için önemser) ve sorgu çalıştırır.

"Birisi engine.executeonu kullanırsa connection" ama için değil " bölümü için haklısınız session(Simya sizin için önemser) ve sorgu yürütür" - Kullanmak Engine.execute()ve Connection.execute()(neredeyse) aynı şeydir, biçimsel olarak Connectionnesne örtük olarak oluşturulur ve sonraki durumda bunu açıkça somutlaştırırız. Bu durumda gerçekten olan şey şudur:

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

Ancak bu tür bir görevi yerine getirmenin bu üç yolu arasında küresel bir fark var mı?

DB katmanında bu tamamen aynı şey, hepsi SQL (metin ifadesi veya çeşitli SQL ifade yapıları) yürütüyor. Uygulamanın bakış açısından iki seçenek vardır:

  • Doğrudan yürütme - Kullanarak Engine.execute()veyaConnection.execute()
  • Kullanma sessions- etkili bir şekilde tek bir birim bölgesinin çalışması olarak hareket işleme kolaylıkla ile session.add(), session.rollback(), session.commit(), session.close(). ORM, yani eşlenmiş tablolar durumunda DB ile etkileşime girmenin yoludur. Tek bir istek sırasında halihazırda erişilen veya yeni oluşturulan / eklenen nesnelere anında ulaşmak için kimlik haritası sağlar .

Session.execute()sonuçta Connection.execute()SQL ifadesini yürütmek için ifade yürütme yöntemini kullanır . SessionNesne kullanmak , SQLAlchemy ORM'nin bir uygulamanın veritabanıyla etkileşime girmesi için önerdiği yoldur.

Dokümanlardan bir alıntı :

SQLAlchemy ORM kullanılırken bu nesnelere genel olarak erişilmediğine dikkat etmek önemlidir; bunun yerine, Session nesnesi veritabanına arabirim olarak kullanılır. Ancak, ORM'nin üst düzey yönetim hizmetlerinin müdahalesi olmadan metinsel SQL ifadelerinin ve / veya SQL ifade yapılarının doğrudan kullanımı etrafında inşa edilen uygulamalar için, Motor ve Bağlantı kraldır (ve kraliçedir?) - okumaya devam edin.


"bağlantısız" kelimesi, Neal'ın cevabına göre hiçbir bağlantının oluşturulmadığını ima eder.
Atom

111

Nabeel'in cevabı pek çok detayı kapsıyor ve yardımcı oluyor, ancak takip etmeyi kafa karıştırıcı buldum. Bu, şu anda bu sorun için ilk Google sonucu olduğundan, bu soruyu bulan gelecekteki insanlar için benim anlayışımı da ekleyerek:

.Execute () çalıştırılıyor

OP ve Nabell Ahmed'in her ikisinin de belirttiği gibi, bir düzlüğü uygularken SELECT * FROM tablename, sağlanan sonuçta bir fark yoktur.

Bu üç nesneler arasındaki farklar olduğunu bağlamına göre önemli hale do SELECTdeyimi ya da daha yaygın, yapmak istediğinizde gibi diğer şeyler kullanılır INSERT, DELETEvb

Motor, Bağlantı, Oturum ne zaman kullanılır?

  • Motor , SQLAlchemy tarafından kullanılan en düşük seviyeli nesnedir. Bu bağlantıların bir havuz tutar uygulama veritabanına konuşmaya ihtiyacı olduğunda kullanıma hazır. .execute()önce çağıran conn = engine.connect(close_with_result=True)ve ardından conn.execute(). Close_with_result parametresi, bağlantının otomatik olarak kapatıldığı anlamına gelir. (Kaynak kodunu biraz açıklıyorum, ama aslında doğru). edit: İşte engine.execute için kaynak kodu

    Ham SQL'i yürütmek için motoru kullanabilirsiniz.

    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()

    Bu, temel kullanım altındaki belgelerde ele alınmıştır .

  • Bağlantı , (yukarıda gördüğümüz gibi) aslında bir SQL sorgusu yürütme işini yapan şeydir. Eğer bağlantının nitelikleri üzerinde daha fazla kontrol istedikleri zaman kapalı alır zaman Örneğin, vb yapmalı bu çok ithalat örnek olduğunu İşlem veritabanına değişiklikleri işlemek için zaman karar vermesini sağlar. Normal kullanımda, değişiklikler otomatik olarak yapılır. İşlemlerin kullanımıyla, (örneğin) birkaç farklı SQL ifadesi çalıştırabilir ve bunlardan birinde bir şeyler ters giderse, tüm değişiklikleri aynı anda geri alabilirsiniz.

    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

    Bu, veri günlüğü tablosunu oluşturmayı unutmanız gibi, biri başarısız olursa, her iki değişikliği de geri almanıza izin verir.

    Dolayısıyla, ham SQL kodu çalıştırıyorsanız ve kontrole ihtiyacınız varsa, bağlantıları kullanın

  • Oturumlar , SQLAlchemy'nin Nesne İlişkileri Yönetimi (ORM) yönü için kullanılır (aslında bunu nasıl içe aktarıldıklarından görebilirsiniz :) from sqlalchemy.orm import sessionmaker. Otomatik olarak oluşturulan SQL ifadelerini çalıştırmak için başlık altındaki bağlantıları ve işlemleri kullanırlar. .execute()oturumun bağlı olduğu her şeye (genellikle bir motordur, ancak bir bağlantı olabilir) geçen bir kullanışlılık işlevidir.

    ORM işlevselliğini kullanıyorsanız, oturum kullanın; yalnızca nesnelere bağlı olmayan düz SQL sorguları yapıyorsanız, bağlantıları doğrudan kullanmak muhtemelen daha iyidir.


1
İfadelerin çift tırnak içine alınması gerekmez ""mi?
mingchau

2
@mingchau Evet, haklısın, benim tek alıntılarım birbirine karışırdı, çift tırnak bu sorunu önlemek çok daha kolay. Güncellenmiş.
Neal

Oluşturulan oturum verildiğinde, Oturumum PostgreSQL bağlantımla nasıl bağlantılı?
Raju yourPepe

@RajuyourPepe my_session.connection(). Dokümanlar: docs.sqlalchemy.org/en/13/orm/… .
Neal

Ciddi anlamda ? 'Oturum' nesnesinin 'bağlan' özniteliği yok, bulduğum şey buydu
Raju yourPepe

0

GRANT gibi DCL'yi (Veri Kontrol Dili) çalıştırmanın bir örneğini burada bulabilirsiniz.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.