SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
SQLAlchemy
доступ к реляционным данным
        в стиле Python


       Юревич Юрий, http://pyobject.ru

     Семинар Учебного центра Люксофт,
             16 сентября 2008
«SQLAlchemy — это
Python SQL тулкит и ORM,
 которые предоставляют
      разработчику
всю мощь и гибкость SQL»
                http://sqlalchemy.org


                                        2
Active Record (Django ORM, Storm)




                                3
Data Mapper (SQLAlchemy)




                           4
Архитектура SQLAlchemy




                         5
Про что будет




                6
Про что (почти) не будет




                           7
Управление схемой данных




                           8
Схема == метаданные




                      9
Создание таблиц: SQL
CREATE TABLE users (
     id INTEGER NOT NULL,
     name VARCHAR(255),
     PRIMARY KEY (id)
  );
CREATE TABLE creds (
     id INTEGER NOT NULL,
     user_id INTEGER,
     login VARCHAR(20),
     passwd VARCHAR(40),
     PRIMARY KEY (id),
     FOREIGN KEY(user_id)
      REFERENCES users (id)
  );



                                10
Создание таблиц: SQLAlchemy
meta = MetaData()
users = Table('users', meta,
    Column('id', Integer, primary_key=True),
    Column('name', Unicode(255)),
  )
creds = Table('creds', meta,
    Column('id', Integer, primary_key=True),
    Column('user_id', Integer, ForeignKey('users.id')),
    Column('login', String(20)),
    Column('passwd', String(40)),
  )




                                                          11
MetaData: что умеет
    Создавать/удалять:
●



        Всё сразу:
    –
            meta.create_all() / meta.drop_all()
        По отдельности:
    –
            users.create() / users.drop()
    Рефлексия:
●



        Потаблично:
    –
          users = Table('users', meta, autoload=True)
        Всё сразу:
    –
          meta.reflect()
    Интроспекция:
●


        meta.tables
    –
                                                        12
MetaData: пример из жизни

# ... описание схемы

def get_indexes():
    return [
        Index('ix_users_id', users.c.id, unique=True),
        Index('ix_creds_id', creds.c.id, unique=True),
        Index('ix_creds_user_id', creds.c.user_id),
    ]

def load():
    # ... загрузка данных
    pass

def postload():
    for ix in get_indexes():
        ix.create()
                                                         13
Язык SQL-выражений




                     14
Для любителей трехбуквенных
            сокращений
    DML (Data Managament Language):
●


        insert/update/delete
    –

    DQL (Data Query Language):
●


        select
    –




                                      15
Insert
    Данные указываются при создании
●

     ins = users.insert(values={'name': u'Jack'})
     ins.execute()

    Данные указываются при выполнении
●

     ins = users.insert()
     ins.execute(name=u'Jack')

    Несколько записей сразу
●

     ins = users.insert()
     ins.execute([{'name': u'Jack'}, {'name': u'Ed'}])

    Явно указывая соединение
●

     engine = create_engine('sqlite:///')
     ins = insert(users)
     engine.connect().execute(ins, {'name': u'Jack'})

                                                         16
Delete
    Условие — SQLAlchemy SQL expression
●

      del_ = users.delete(users.c.name==u'Jack')
      del_.execute()

    Условие — строка с SQL
●

      del_ = users.delete('users.name=:user')
      del_.params({'user': u'Jack'}).execute()




                                                   17
Select
SELECT *
FROM users


q = users.select()


SELECT users.id, users.name
FROM users


                              18
Select
SELECT id
FROM users
WHERE name='Jack'

q = users.select([users.c.id],
             users.c.name==u'Jack')

SELECT users.id
FROM users
WHERE users.name=:name

                                      19
Select
SELECT *
FROM users
JOIN creds ON
creds.user_id=users.id

q = users.join(creds).select()

SELECT users.id, users.name,
       creds.id, creds.user_id,
       creds.login, creds.passwd
JOIN creds ON
users.id=creds.user_id             20
Почему SA SQL Expr?
    Потому что Python круче SQL
●




                                  21
Почему SA SQL Expr?
    Потому что Python круче SQL
●


    Генерация SQL на лету:
●


        q = select([users, creds.c.login],
    –
                   from_obj=users.join(creds),
                   whereclause=users.c.name==u'Jack')
        q = users.select()
    –
        q = q.where(users.c.name==u'Jack')
        q = q.column(creds.c.login)
        q.append_from(join(users, creds))
        SELECT users.id, users.name, creds.login
    –
        FROM users
        JOIN creds ON creds.user_id = users.id
        WHERE users.name = 'Jack'

                                                        22
Object Relational Mapper (ORM)




                                 23
Data Mapper, снова




                     24
Рабочий пример:
 схема данных




                  25
Рабочий пример:
                    таблицы в SQL
CREATE TABLE users (              CREATE TABLE messages (
           id INTEGER NOT NULL,              id INTEGER NOT NULL,
           name VARCHAR(255),                subject VARCHAR(255),
           PRIMARY KEY (id)                  body TEXT,
   );                                        author_id INTEGER,
                                             PRIMARY KEY (id),
CREATE TABLE creds (                         FOREIGN KEY(author_id)
           id INTEGER NOT NULL,              REFERENCES users (id)
           user_id INTEGER,          );
           login VARCHAR(20),
           passwd VARCHAR(20),   CREATE TABLE message_recipients (
           PRIMARY KEY (id),                message_id INTEGER NOT NULL,
           FOREIGN KEY(user_id)             recipient_id INTEGER NOT NULL,
           REFERENCES users (id)            PRIMARY KEY (
                                                message_id, recipient_id),
);                                          FOREIGN KEY(message_id)
                                            REFERENCES messages (id),
                                            FOREIGN KEY(recipient_id)
                                            REFERENCES users (id)
                                    );


                                                                         26
Рабочий пример:
                   Данные
users = {
    u'Jack': ['jack', 'jack-rabbit'],
    u'Edvard': ['ed'],
    u'Mary': ['mary'],
}

messages = (
    {   'author': u'Jack', 'recipients': [u'Edvard', u'Mary'],
        'title': u'The first', 'body': u'Ha-ha, I'm the first!,
    },
    {   'author': u'Edvard', 'recipients': [u'Jack', u'Mary'],
        'title': u'Hey all', 'body': u'Hi, I'm here',
    },
    {
        'author': u'Edvard', 'recipients': [u'Mary'],
        'title': u'The silence', 'body': u'Why are you ignoring me?',
    },
    {
        'author': u'Mary', 'recipients': [u'Jack'],
        'title': u'Hi', 'body': u'Hi, Jack, how are you?',
    },
                                                                      27
)
Рабочий пример:
              таблицы в SA SQL Expr
users = Table('users', meta,
   Column('id', Integer, primary_key=True),
   Column('name', Unicode(255)),
   )

creds = Table('creds', meta,
   Column('id', Integer, primary_key=True),
   Column('user_id', Integer, ForeignKey('users.id')),
   Column('login', String(20)),
   Column('passwd', String(20)),
   )

messages = Table('messages', meta,
   Column('id', Integer, primary_key=True),
   Column('subject', Unicode(255)),
   Column('body', Text),
   Column('author_id', Integer, ForeignKey('users.id')),
   )

message_recipients = Table('message_recipients', meta,
   Column('message_id', Integer, ForeignKey('messages.id'), primary_key=True),
   Column('recipient_id', Integer, ForeignKey('users.id'), primary_key=True),
   )
                                                                           28
Рабочий пример:
                     Mappings
Session = scoped_session(sessionmaker(autoflush=False))

class Base(object):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

class User(Base):
    pass
class Cred(Base):
    pass
class Message(Base):
    pass

Session.mapper(User, users)                                 # (1)

Session.mapper(Cred, creds, properties={                    # (2)
    'user': relation(User, backref='credentials'),})

Session.mapper(Message, messages, properties={              # (3)
    'recipients': relation(User, backref='inbox',
                           secondary=message_recipients),
                                                                    29
    'author': relation(User, backref='outbox'),})
Рабочий пример:
                  готовность №1
[ 1]>>> import schema as sch
[ 2]>>> import mappings as m

[   3]>>>   engine = create_engine('sqlite:///example.sqlite')
[   4]>>>   sch.meta.bind = engine
[   5]>>>   sch.meta.create_all()
[   6]>>>   m.Session.bind = engine

[ 7]>>> u1 = m.User.query.get(1)
[ 8]>>> u1.id
<<< 1
[ 9]>>> u1.name
<<< u'Jack'
[10]>>> u1.credentials
<<< [<Cred: jack>, <Cred: jack-rabbit>]
[11]>>> u1.outbox
<<< [<Message: from Jack to Edvard, Mary (subj: The first)>]
                                                             30
Рабочий пример:
               выборки
[1]>>> q = m.User.query.filter(User.id>1)
[2]>>> print str(q)
SELECT users.id AS users_id, users.name AS users_name
FROM users
WHERE users.id > ?

[3]>>> q = q.filter(m.User.name!=None)
[4]>>> print str(q)
SELECT users.id AS users_id, users.name AS users_name
FROM users
WHERE users.id > ? AND users.name IS NOT NULL

[5]>>> list(q)
<<< [<User u'Edvard'>, <User u'Mary'>]

[6]>>> q.first()
<<< <User u'Edvard'>
                                                        31
Рабочий пример:
      выборки (продолжение)
[1]>>> rabbit = m.Cred.query.
           filter_by(login='jack-rabbit').one()

[2]>>> rabbit_user = m.User.query.
           filter(User.credentials.contains(rabbit)).
           one()


[3]>>> rabbit_messages = m.Message.query.
           filter(or_(
               Message.author==rabbit_user,
               Message.recipients.contains(rabbit_user)
       ))
[4]>>> list(rabbit_messages)
<<<
[<Message: from Jack to Edvard, Mary (subj: The first)>,
 <Message: from Edvard to Jack, Mary (subj: Hey all)>,
 <Message: from Mary to Jack (subj: Hi)>]              32
Рабочий пример:
          выборки (хардкор)
# Выбрать пользователей, у которых
# в исходящих больше одного сообщения
[1]>>> sess = m.Session()
[2]>>> q = sess.query(m.User, func.count('*')).
               join(m.Message).group_by(m.User).
               having(func.count('*')>1)
[3]>>> list(q)
<<< [(<User u'Edvard'>, 2)]

# Выбрать пользователей, у которых
# во входящих больше одного сообщения
[4]>>> sess = m.Session()
[5]>>> q = sess.query(m.User, func.count('*')).
         join(sch.message_recipients).group_by(m.User).
         having(func.count('*')>1)
[6]>>> list(q)
<<< [(<User u'Jack'>, 2), (<User u'Mary'>, 3)]
                                                      33
Рабочий пример:
                 сессия, unit of work
[   1]>>>   engine = create_engine('sqlite:///example.sqlite', echo=True)
[   2]>>>   sch.meta.bind = engine
[   3]>>>   m.Session.bind = engine
[   4]>>>   sess = m.Session()
[   5]>>>   jack = m.User.query.filter_by(name=u'Jack').one()
2008-09-14 14:19:11,504 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT...
[ 6]>>> ed = m.User.query.filter_by(name=u'Edvard').one()
2008-09-14 14:20:22,731 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT...
[ 7]>>> jack.name = u'Jack Daniels'
[ 8]>>> sess.dirty
<<< IdentitySet([<User u'Jack Daniels'>])
[ 9]>>> ed.name = u'Edvard Noringthon'
[10]>>> sess.dirty
<<< IdentitySet([<User u'Edvard Noringthon'>, <User u'Jack Daniels'>])
[11]>>> sess.flush()
2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c
UPDATE users SET name=? WHERE users.id = ?
2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c
['Jack Daniels', 1]
2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c
UPDATE users SET name=? WHERE users.id = ?
2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c
['Edvard Noringthon', 2]
                                                                                 34
users = Table(
    'users', meta, ...)

class User:
    pass

mapper(users, User)




 «user» 5 раз, скучно?
                          35
Elixir:
ActiveRecord поверх SQLAlchemy
    Elixir (http://elixir.ematia.de):
●


        Декларативное описание в стиле Django
    –

        События:
    –

             До (update, insert, delete)
         ●


             После (update, insert, delete)
         ●



        Плагины:
    –

             acts_as_versioned (автоматическое хранение истории)
         ●


             acts_as_encrypted (шифрование колонок)
         ●


             associable (аналог Django generic relations)
         ●


             ...
         ●



                                                               36
Еще вкусности SQLAlchemy
    «Хитрые» атрибуты:
●


          Отложенная/непосредственная подгрузка
     –

          SQL-выражение как атрибут
     –

    Партицирование:
●


          Вертикальное (часть таблиц в одной БД, часть в другой)
     –

          Горизонтальное (шардинг, содержимое одной таблицы
     –
                               «раскидано» по таблицам/БД)

    Нетривиальные маппинги:
●


          Несколько маппингов к одному классу
     –

          Маппинг классов к SQL-запросам
     –

    ...
●                                                                  37
Диагноз:
                нужна ли вам SA
    Используете другой           Используете DB
●                            ●

    ORM и счастливы?             API2 и «чистый»
                                 SQL?
        Нет, в SQLAlchemy
    –
        «много буков», нет           Да, SQLAlchemy
                                 –
        смысла                       даст вам это и много
                                     что еще




                                                        38
Вопросы?

 ... не успели задать? - шлите почтой: the.pythy@gmail.com



                                                       39

Weitere ähnliche Inhalte

Was ist angesagt?

Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation Specifications
Unmon Mukherjee
 

Was ist angesagt? (20)

Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - php[tek] 2016
 
Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死Play, Slick, play2-authの間で討死
Play, Slick, play2-authの間で討死
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
Automatically Spotting Cross-language Relations
Automatically Spotting Cross-language RelationsAutomatically Spotting Cross-language Relations
Automatically Spotting Cross-language Relations
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
 
Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation Specifications
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009
 
DOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript FrameworkDOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript Framework
 
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Daily notes
Daily notesDaily notes
Daily notes
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
MoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORMMoSQL: More than SQL, but less than ORM
MoSQL: More than SQL, but less than ORM
 
Dig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup CairoDig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup Cairo
 
jQuery introduction
jQuery introductionjQuery introduction
jQuery introduction
 
Final tagless and cats mtl
Final tagless and cats mtl Final tagless and cats mtl
Final tagless and cats mtl
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016
 
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
 
Sk.php
Sk.phpSk.php
Sk.php
 

Andere mochten auch

Scalable Monitoring & Alerting
Scalable Monitoring & AlertingScalable Monitoring & Alerting
Scalable Monitoring & Alerting
Franklin Angulo
 
PHP to Python with No Regrets
PHP to Python with No RegretsPHP to Python with No Regrets
PHP to Python with No Regrets
Alex Ezell
 

Andere mochten auch (20)

What is NetFlow?
What is NetFlow?What is NetFlow?
What is NetFlow?
 
Graphite
GraphiteGraphite
Graphite
 
Go with the flow
Go with the flowGo with the flow
Go with the flow
 
DPI Vas Experts Linkmeup
DPI Vas Experts LinkmeupDPI Vas Experts Linkmeup
DPI Vas Experts Linkmeup
 
Monitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafanaMonitoring pg with_graphite_grafana
Monitoring pg with_graphite_grafana
 
Will iPython replace bash?
Will iPython replace bash?Will iPython replace bash?
Will iPython replace bash?
 
MPLS-TE Fault Tolerance
MPLS-TE Fault ToleranceMPLS-TE Fault Tolerance
MPLS-TE Fault Tolerance
 
Scalable Monitoring & Alerting
Scalable Monitoring & AlertingScalable Monitoring & Alerting
Scalable Monitoring & Alerting
 
Programming Under Linux In Python
Programming Under Linux In PythonProgramming Under Linux In Python
Programming Under Linux In Python
 
DDoS-bdNOG
DDoS-bdNOGDDoS-bdNOG
DDoS-bdNOG
 
Introducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for GrafanaIntroducing wizzy - a CLI tool for Grafana
Introducing wizzy - a CLI tool for Grafana
 
Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016Мониторинг. Опять, rootconf 2016
Мониторинг. Опять, rootconf 2016
 
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLONTorkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
Torkel Ödegaard (Creator of Grafana) - Grafana at #DOXLON
 
Hacking Cisco
Hacking CiscoHacking Cisco
Hacking Cisco
 
Python for Linux System Administration
Python for Linux System AdministrationPython for Linux System Administration
Python for Linux System Administration
 
Metrics: where and how
Metrics: where and howMetrics: where and how
Metrics: where and how
 
PHP to Python with No Regrets
PHP to Python with No RegretsPHP to Python with No Regrets
PHP to Python with No Regrets
 
Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)Real programmers use programming languages (Not shell scripts)
Real programmers use programming languages (Not shell scripts)
 
ZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 ConferenceZFS Tutorial USENIX LISA09 Conference
ZFS Tutorial USENIX LISA09 Conference
 
MPLS (Multi-Protocol Label Switching)
MPLS  (Multi-Protocol Label Switching)MPLS  (Multi-Protocol Label Switching)
MPLS (Multi-Protocol Label Switching)
 

Ähnlich wie SQLAlchemy Seminar

Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
Joao Lucas Santana
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
Louie Zhao
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
ActsAsCon
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)
shubhamvcs
 

Ähnlich wie SQLAlchemy Seminar (20)

Achilles presentation
Achilles presentationAchilles presentation
Achilles presentation
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
 
Montreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lakeMontreal Sql saturday: moving data from no sql db to azure data lake
Montreal Sql saturday: moving data from no sql db to azure data lake
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007
 
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de DadosUma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
Uma Abordagem Orientada a Modelos para Modelagem Conceitual de Banco de Dados
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
greenDAO
greenDAOgreenDAO
greenDAO
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.Miniproject on Employee Management using Perl/Database.
Miniproject on Employee Management using Perl/Database.
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
 
Relaxing With CouchDB
Relaxing With CouchDBRelaxing With CouchDB
Relaxing With CouchDB
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6How to leverage what's new in MongoDB 3.6
How to leverage what's new in MongoDB 3.6
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)
 

Mehr von Yury Yurevich

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST API
Yury Yurevich
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of Python
Yury Yurevich
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JS
Yury Yurevich
 

Mehr von Yury Yurevich (12)

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST API
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of Python
 
PyCon UA 2011: Test Infected
PyCon UA 2011: Test InfectedPyCon UA 2011: Test Infected
PyCon UA 2011: Test Infected
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JS
 
Лев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про ErlangЛев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про Erlang
 
Ильшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBreamИльшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBream
 
Иван Иноземцев — Fantom
Иван Иноземцев — FantomИван Иноземцев — Fantom
Иван Иноземцев — Fantom
 
Александр Гладыш — Lua
Александр Гладыш — LuaАлександр Гладыш — Lua
Александр Гладыш — Lua
 
Decorators' recipes
Decorators' recipesDecorators' recipes
Decorators' recipes
 
About Python
About PythonAbout Python
About Python
 
About (unit) testing
About (unit) testingAbout (unit) testing
About (unit) testing
 
Almost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migrationAlmost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migration
 

Kürzlich hochgeladen

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 

SQLAlchemy Seminar

  • 1. SQLAlchemy доступ к реляционным данным в стиле Python Юревич Юрий, http://pyobject.ru Семинар Учебного центра Люксофт, 16 сентября 2008
  • 2. «SQLAlchemy — это Python SQL тулкит и ORM, которые предоставляют разработчику всю мощь и гибкость SQL» http://sqlalchemy.org 2
  • 3. Active Record (Django ORM, Storm) 3
  • 7. Про что (почти) не будет 7
  • 10. Создание таблиц: SQL CREATE TABLE users ( id INTEGER NOT NULL, name VARCHAR(255), PRIMARY KEY (id) ); CREATE TABLE creds ( id INTEGER NOT NULL, user_id INTEGER, login VARCHAR(20), passwd VARCHAR(40), PRIMARY KEY (id), FOREIGN KEY(user_id) REFERENCES users (id) ); 10
  • 11. Создание таблиц: SQLAlchemy meta = MetaData() users = Table('users', meta, Column('id', Integer, primary_key=True), Column('name', Unicode(255)), ) creds = Table('creds', meta, Column('id', Integer, primary_key=True), Column('user_id', Integer, ForeignKey('users.id')), Column('login', String(20)), Column('passwd', String(40)), ) 11
  • 12. MetaData: что умеет Создавать/удалять: ● Всё сразу: – meta.create_all() / meta.drop_all() По отдельности: – users.create() / users.drop() Рефлексия: ● Потаблично: – users = Table('users', meta, autoload=True) Всё сразу: – meta.reflect() Интроспекция: ● meta.tables – 12
  • 13. MetaData: пример из жизни # ... описание схемы def get_indexes(): return [ Index('ix_users_id', users.c.id, unique=True), Index('ix_creds_id', creds.c.id, unique=True), Index('ix_creds_user_id', creds.c.user_id), ] def load(): # ... загрузка данных pass def postload(): for ix in get_indexes(): ix.create() 13
  • 15. Для любителей трехбуквенных сокращений DML (Data Managament Language): ● insert/update/delete – DQL (Data Query Language): ● select – 15
  • 16. Insert Данные указываются при создании ● ins = users.insert(values={'name': u'Jack'}) ins.execute() Данные указываются при выполнении ● ins = users.insert() ins.execute(name=u'Jack') Несколько записей сразу ● ins = users.insert() ins.execute([{'name': u'Jack'}, {'name': u'Ed'}]) Явно указывая соединение ● engine = create_engine('sqlite:///') ins = insert(users) engine.connect().execute(ins, {'name': u'Jack'}) 16
  • 17. Delete Условие — SQLAlchemy SQL expression ● del_ = users.delete(users.c.name==u'Jack') del_.execute() Условие — строка с SQL ● del_ = users.delete('users.name=:user') del_.params({'user': u'Jack'}).execute() 17
  • 18. Select SELECT * FROM users q = users.select() SELECT users.id, users.name FROM users 18
  • 19. Select SELECT id FROM users WHERE name='Jack' q = users.select([users.c.id], users.c.name==u'Jack') SELECT users.id FROM users WHERE users.name=:name 19
  • 20. Select SELECT * FROM users JOIN creds ON creds.user_id=users.id q = users.join(creds).select() SELECT users.id, users.name, creds.id, creds.user_id, creds.login, creds.passwd JOIN creds ON users.id=creds.user_id 20
  • 21. Почему SA SQL Expr? Потому что Python круче SQL ● 21
  • 22. Почему SA SQL Expr? Потому что Python круче SQL ● Генерация SQL на лету: ● q = select([users, creds.c.login], – from_obj=users.join(creds), whereclause=users.c.name==u'Jack') q = users.select() – q = q.where(users.c.name==u'Jack') q = q.column(creds.c.login) q.append_from(join(users, creds)) SELECT users.id, users.name, creds.login – FROM users JOIN creds ON creds.user_id = users.id WHERE users.name = 'Jack' 22
  • 26. Рабочий пример: таблицы в SQL CREATE TABLE users ( CREATE TABLE messages ( id INTEGER NOT NULL, id INTEGER NOT NULL, name VARCHAR(255), subject VARCHAR(255), PRIMARY KEY (id) body TEXT, ); author_id INTEGER, PRIMARY KEY (id), CREATE TABLE creds ( FOREIGN KEY(author_id) id INTEGER NOT NULL, REFERENCES users (id) user_id INTEGER, ); login VARCHAR(20), passwd VARCHAR(20), CREATE TABLE message_recipients ( PRIMARY KEY (id), message_id INTEGER NOT NULL, FOREIGN KEY(user_id) recipient_id INTEGER NOT NULL, REFERENCES users (id) PRIMARY KEY ( message_id, recipient_id), ); FOREIGN KEY(message_id) REFERENCES messages (id), FOREIGN KEY(recipient_id) REFERENCES users (id) ); 26
  • 27. Рабочий пример: Данные users = { u'Jack': ['jack', 'jack-rabbit'], u'Edvard': ['ed'], u'Mary': ['mary'], } messages = ( { 'author': u'Jack', 'recipients': [u'Edvard', u'Mary'], 'title': u'The first', 'body': u'Ha-ha, I'm the first!, }, { 'author': u'Edvard', 'recipients': [u'Jack', u'Mary'], 'title': u'Hey all', 'body': u'Hi, I'm here', }, { 'author': u'Edvard', 'recipients': [u'Mary'], 'title': u'The silence', 'body': u'Why are you ignoring me?', }, { 'author': u'Mary', 'recipients': [u'Jack'], 'title': u'Hi', 'body': u'Hi, Jack, how are you?', }, 27 )
  • 28. Рабочий пример: таблицы в SA SQL Expr users = Table('users', meta, Column('id', Integer, primary_key=True), Column('name', Unicode(255)), ) creds = Table('creds', meta, Column('id', Integer, primary_key=True), Column('user_id', Integer, ForeignKey('users.id')), Column('login', String(20)), Column('passwd', String(20)), ) messages = Table('messages', meta, Column('id', Integer, primary_key=True), Column('subject', Unicode(255)), Column('body', Text), Column('author_id', Integer, ForeignKey('users.id')), ) message_recipients = Table('message_recipients', meta, Column('message_id', Integer, ForeignKey('messages.id'), primary_key=True), Column('recipient_id', Integer, ForeignKey('users.id'), primary_key=True), ) 28
  • 29. Рабочий пример: Mappings Session = scoped_session(sessionmaker(autoflush=False)) class Base(object): def __init__(self, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) class User(Base): pass class Cred(Base): pass class Message(Base): pass Session.mapper(User, users) # (1) Session.mapper(Cred, creds, properties={ # (2) 'user': relation(User, backref='credentials'),}) Session.mapper(Message, messages, properties={ # (3) 'recipients': relation(User, backref='inbox', secondary=message_recipients), 29 'author': relation(User, backref='outbox'),})
  • 30. Рабочий пример: готовность №1 [ 1]>>> import schema as sch [ 2]>>> import mappings as m [ 3]>>> engine = create_engine('sqlite:///example.sqlite') [ 4]>>> sch.meta.bind = engine [ 5]>>> sch.meta.create_all() [ 6]>>> m.Session.bind = engine [ 7]>>> u1 = m.User.query.get(1) [ 8]>>> u1.id <<< 1 [ 9]>>> u1.name <<< u'Jack' [10]>>> u1.credentials <<< [<Cred: jack>, <Cred: jack-rabbit>] [11]>>> u1.outbox <<< [<Message: from Jack to Edvard, Mary (subj: The first)>] 30
  • 31. Рабочий пример: выборки [1]>>> q = m.User.query.filter(User.id>1) [2]>>> print str(q) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.id > ? [3]>>> q = q.filter(m.User.name!=None) [4]>>> print str(q) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.id > ? AND users.name IS NOT NULL [5]>>> list(q) <<< [<User u'Edvard'>, <User u'Mary'>] [6]>>> q.first() <<< <User u'Edvard'> 31
  • 32. Рабочий пример: выборки (продолжение) [1]>>> rabbit = m.Cred.query. filter_by(login='jack-rabbit').one() [2]>>> rabbit_user = m.User.query. filter(User.credentials.contains(rabbit)). one() [3]>>> rabbit_messages = m.Message.query. filter(or_( Message.author==rabbit_user, Message.recipients.contains(rabbit_user) )) [4]>>> list(rabbit_messages) <<< [<Message: from Jack to Edvard, Mary (subj: The first)>, <Message: from Edvard to Jack, Mary (subj: Hey all)>, <Message: from Mary to Jack (subj: Hi)>] 32
  • 33. Рабочий пример: выборки (хардкор) # Выбрать пользователей, у которых # в исходящих больше одного сообщения [1]>>> sess = m.Session() [2]>>> q = sess.query(m.User, func.count('*')). join(m.Message).group_by(m.User). having(func.count('*')>1) [3]>>> list(q) <<< [(<User u'Edvard'>, 2)] # Выбрать пользователей, у которых # во входящих больше одного сообщения [4]>>> sess = m.Session() [5]>>> q = sess.query(m.User, func.count('*')). join(sch.message_recipients).group_by(m.User). having(func.count('*')>1) [6]>>> list(q) <<< [(<User u'Jack'>, 2), (<User u'Mary'>, 3)] 33
  • 34. Рабочий пример: сессия, unit of work [ 1]>>> engine = create_engine('sqlite:///example.sqlite', echo=True) [ 2]>>> sch.meta.bind = engine [ 3]>>> m.Session.bind = engine [ 4]>>> sess = m.Session() [ 5]>>> jack = m.User.query.filter_by(name=u'Jack').one() 2008-09-14 14:19:11,504 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT... [ 6]>>> ed = m.User.query.filter_by(name=u'Edvard').one() 2008-09-14 14:20:22,731 INFO sqlalchemy.engine.base.Engine.0x...ca2c SELECT... [ 7]>>> jack.name = u'Jack Daniels' [ 8]>>> sess.dirty <<< IdentitySet([<User u'Jack Daniels'>]) [ 9]>>> ed.name = u'Edvard Noringthon' [10]>>> sess.dirty <<< IdentitySet([<User u'Edvard Noringthon'>, <User u'Jack Daniels'>]) [11]>>> sess.flush() 2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c UPDATE users SET name=? WHERE users.id = ? 2008-09-14 14:21:00,535 INFO sqlalchemy.engine.base.Engine.0x...ca2c ['Jack Daniels', 1] 2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c UPDATE users SET name=? WHERE users.id = ? 2008-09-14 14:21:00,604 INFO sqlalchemy.engine.base.Engine.0x...ca2c ['Edvard Noringthon', 2] 34
  • 35. users = Table( 'users', meta, ...) class User: pass mapper(users, User) «user» 5 раз, скучно? 35
  • 36. Elixir: ActiveRecord поверх SQLAlchemy Elixir (http://elixir.ematia.de): ● Декларативное описание в стиле Django – События: – До (update, insert, delete) ● После (update, insert, delete) ● Плагины: – acts_as_versioned (автоматическое хранение истории) ● acts_as_encrypted (шифрование колонок) ● associable (аналог Django generic relations) ● ... ● 36
  • 37. Еще вкусности SQLAlchemy «Хитрые» атрибуты: ● Отложенная/непосредственная подгрузка – SQL-выражение как атрибут – Партицирование: ● Вертикальное (часть таблиц в одной БД, часть в другой) – Горизонтальное (шардинг, содержимое одной таблицы – «раскидано» по таблицам/БД) Нетривиальные маппинги: ● Несколько маппингов к одному классу – Маппинг классов к SQL-запросам – ... ● 37
  • 38. Диагноз: нужна ли вам SA Используете другой Используете DB ● ● ORM и счастливы? API2 и «чистый» SQL? Нет, в SQLAlchemy – «много буков», нет Да, SQLAlchemy – смысла даст вам это и много что еще 38
  • 39. Вопросы? ... не успели задать? - шлите почтой: the.pythy@gmail.com 39