sqlalchemy core: an introduction
TRANSCRIPT
SQLALCHEMY COREAN INTRODUCTION
/ Jason Myers @jasonamyers
Background by maul555
DIFFERENCES BETWEEN CORE AND ORM
ORM - DOMAIN MODELclass User(Base): __tablename__ = 'users'
id = Column(Integer, primary_key=True) name = Column(String) fullname = Column(String) password = Column(String)
CORE - SCHEMA-CENTRIC MODELfrom sqlalchemy import Table, Column, Integer, String, MetaDatametadata = MetaData()users = Table('users', metadata, Column('id', Integer, primary_key=True), Column('name', String), Column('fullname', String),)
STRUCTURE
Copyright © 2014 Mochimochi Land
STRUCTURE
INSTALLINGpip install sqlalchemy
pip install flask-sqlalchemy
bin/paster create -t pyramid_alchemy tutorial
INITIALIZINGimport sqlalchemyfrom sqlalchemy import create_engineengine = create_engine('sqlite:///:memory:')
DEFINING A TABLEfrom sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKeymetadata = MetaData()actors = Table('actors', metadata, Column('id', Integer, primary_key=True), Column('name', String), Column('fullname', String), Column('body_count', Integer))roles = Table('roles', metadata, Column('id', Integer, primary_key=True), Column('actor_id', None, ForeignKey('actors.id')), Column('character_name', String, nullable=False))
CREATE THE TABLESmetadata.create_all(engine)
TABLE OBJECTSactors.columns.items()
[ ('id', Column('id', Integer(), table=actors, primary_key=True...)), ('name', Column('name', String(), table=actors)), ('fullname', Column('fullname', String(), table=actors)), ('body_count', Column('body_count', Integer(), table=actors))]
OPENING A CONNECTIONconn = engine.connect()
SINGLE INSERTins = actors.insert().values(name='Graham', fullname='Graham Chapman', body_count=3)result = conn.execute(ins)result.inserted_primary_key
[1]
LOOKING AT WHAT WAS EXECUTEDprint str(ins)ins.compile().params
INSERT INTO actors (name, fullname, body_count) VALUES (:name, :fullname, :body_count){'body_count': 3, 'fullname': 'Graham Chapman', 'name': 'Graham'}
MULTIPLE INSERTresults = conn.execute(roles.insert(), [ {'actor_id': 1, 'character_name' : 'King Arthur'}, {'actor_id': 1, 'character_name' : 'Voice of God'}, {'actor_id': 2, 'character_name' : 'Sir Lancelot'}, {'actor_id': 2, 'character_name' : 'Black Knight'}, {'actor_id': 3, 'character_name' : 'Patsy'}, {'actor_id': 3, 'character_name' : 'Sir Bors'},])results.rowcount
6
UPDATEstmt = actors.update().where(actors.c.name == 'Graham').values(name='Gram')result = conn.execute(stmt)result.rowcount
1
DELETEresult = conn.execute(actors.delete().where(actors.c.name == 'Terry'))result.rowcount
1
SELECTINGs = select([actors.c.name, actors.c.fullname])result = conn.execute(s)for row in result: print row
(u'Graham', u'Graham Chapman')(u'John', u'John Cleese')(u'Terry', u'Terry Gilliam')
ORDERINGstmt = select([actors.c.name]).order_by(actors.c.name.desc())conn.execute(stmt).fetchall()
[(u'Terry',), (u'John',), (u'Graham',)]
LIMITINGstmt = select([actors.c.name, actors.c.fullname]).limit(1).offset(1)conn.execute(stmt).first()
(u'John', u'John Cleese')
COUNTfrom sqlalchemy.sql import funcstmt = select([func.count(actors)])conn.execute(stmt).scalar()
2
SUMstmt = select([func.count(actors), func.sum(actors.c.body_count)])conn.execute(stmt).first()
(2, 5)
JOINSs = select([actors, roles]).where(actors.c.id == roles.c.actor_id)for row in conn.execute(s): print row
(1, u'Graham', u'Graham Chapman', 1, 1, u'King Arthur')(1, u'Graham', u'Graham Chapman', 2, 1, u'Voice of God')(2, u'John', u'John Cleese', 3, 2, u'Sir Lancelot')(2, u'John', u'John Cleese', 4, 2, u'Black Knight')(3, u'Terry', u'Terry Gilliam', 5, 3, u'Patsy')(3, u'Terry', u'Terry Gilliam', 6, 3, u'Sir Bors')
GROUPINGstmt = select([actors.c.name, func.count(roles.c.id)]).\ select_from(actors.join(roles)).\ group_by(actors.c.name)conn.execute(stmt).fetchall()
[(u'Graham', 2), (u'John', 2), (u'Terry', 2)]
FILTERINGfrom sqlalchemy.sql import and_, or_, not_stmt = select([actors.c.name, roles.c.character_name]).\ where( and_( actors.c.name.like('Gra%'), roles.c.character_name.like('Vo%'), actors.c.id == roles.c.actor_id ) )conn.execute(stmt).fetchall()
[(u'Graham', u'Voice of God')]
AND SO ON...
COMMON DIALECTSInformixMS SQLOraclePostgresSQLiteCustom
BUT WHAT IF...class UnloadFromSelect(Executable, ClauseElement):
def __init__(self, select, bucket, access_key, secret_key): self.select = select self.bucket = bucket self.access_key = access_key self.secret_key = secret_key
@compiles(UnloadFromSelect)def visit_unload_from_select(element, compiler, **kw): return "unload ('%(query)s') to '%(bucket)s' credentials 'aws_access_key_id=%(access_key)s; aws_secret_access_key=%(secret_key)s' delimiter ',' addquotes allowoverwrite" % { 'query': compiler.process(element.select, unload_select=True, literal_binds=True), 'bucket': element.bucket, 'access_key': element.access_key, 'secret_key': element.secret_key, }
EXAMPLE STATEMENTunload = UnloadFromSelect( select([fields]), '/'.join(['s3:/', BUCKET, filename]), ACCESS_KEY, SECRET_KEY)
EXAMPLE USAGEunload ( 'select * from venue where venueid in ( select venueid from venue order by venueid desc limit 10)')to 's3://mybucket/venue_pipe_'credentials 'aws_access_key_id=ACCESS_KEY; aws_secret_access_key=SECRET_KEY';
DYNAMIC TABLE INTROSPECTIONdef build_table(engine, table_name): return Table(table_name, metadata, autoload=True, autoload_with=engine)
CHECKING FOR NULL COLUMNSbuild_table(engine, 'census')unavailable_fields = [ c.name for c in t.c if isinstance(c.type, NullType)]
CHAININGs = select( [ t.c.race, t.c.factor, func.sum(g.t.c.value).label('summed') ], t.c.race > 0 ).where( and_( t.c.type == 'POVERTY', t.c.value != 0 ) ).group_by( t.c.race, t.c.factor ).order_by( t.c.race, t.c.factor)
CONDITIONALSs = select( [ table.c.discharge_year, func.count(1).label( 'patient_discharges'), table.c.zip_code, ], table.c.discharge_year.in_(years)).group_by(table.c.discharge_year)s = s.where(table.c.hospital_name == provider)
if 'total_charges' not in unavailable_fields: s = s.column( func.sum(table.c.total_charges ).label('patient_charges') )
s = s.group_by(table.c.zip_code)s = s.order_by('discharges DESC')
cases = conn.execute(s).fetchall()
QUESTIONS
THANK YOU / Jason Myers @jasonamyers