In [23]:
from sqlalchemy import create_engine
engine = create_engine('sqlite:///:memory:')
It’s not like a normal class definition, but a more list a list of table columns. The metadata is used as a catalog to provide a mapping between the actual tables and our pythonic representation of them.
This doesn't do us much good since there is not association between the engine we established above, and the tables objects we created.
In [24]:
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
metadata = 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)
)
We take the MetaData object we created early, and bind it to the engine as see below. This will create our tables in the actually database. This is conditional by default, will not attempt to recreate tables already present in the target database. NOTE: It doesn't check to make sure they are the same just that an existing table is already present.
In [25]:
metadata.create_all(engine)
In [26]:
actors.columns.items()
Out[26]:
In [27]:
conn = engine.connect()
In [28]:
ins = actors.insert().values(name='Graham', fullname='Graham Chapman', body_count=3)
result = conn.execute(ins)
In [29]:
result.inserted_primary_key
Out[29]:
In [30]:
print str(ins)
ins.compile().params
Out[30]:
In [31]:
ins = actors.insert().values(name='John', fullname='John Cleese', body_count=2)
result = conn.execute(ins)
ins = actors.insert().values(name='Terry', fullname='Terry Gilliam', body_count=6)
result = conn.execute(ins)
In [32]:
results = 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'},
])
In [33]:
results.rowcount
Out[33]:
In [34]:
stmt = actors.update().where(actors.c.name == 'Graham').values(name='Gram')
result = conn.execute(stmt)
In [35]:
result.rowcount
Out[35]:
In [36]:
result = conn.execute(actors.delete().where(actors.c.name == 'Terry'))
result.rowcount
Out[36]:
So unlike the other statements that were clauses off of the table object, this time we're going to use a new select stmt and operate on the table that way. You can use a clause off the table object; however, this is more commonly used as you'll normally be joining data and doing other things.
In [37]:
from sqlalchemy.sql import select
s = select([actors.c.name, actors.c.fullname])
result = conn.execute(s)
for row in result:
print row
In [45]:
stmt = select([actors.c.name]).order_by(actors.c.name.desc())
conn.execute(stmt).fetchall()
Out[45]:
In [46]:
stmt = select([actors.c.name, actors.c.fullname]).limit(1).offset(1)
conn.execute(stmt).first()
Out[46]:
In [51]:
from sqlalchemy.sql import func
stmt = select([func.count(actors)])
conn.execute(stmt).scalar()
Out[51]:
In [55]:
stmt = select([func.count(actors), func.sum(actors.c.body_count)])
conn.execute(stmt).first()
Out[55]:
In [56]:
s = select([actors, roles]).where(actors.c.id == roles.c.actor_id)
for row in conn.execute(s):
print row
In [57]:
stmt = select([actors.c.name, func.count(roles.c.id)]).\
select_from(actors.join(roles)).\
group_by(actors.c.name)
conn.execute(stmt).fetchall()
Out[57]:
In [22]:
from 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()
Out[22]:
In [53]: