Sqlite3是Python3标准库不须要另外安装,只须要安装SQLAlchemy便可。本文sqlalchemy版本为1.2.12html
pip install sqlalchemy
除了第一步建立引擎时链接URL不同,其余操做其余mysql等数据库和sqlite都是差很少的。python
sqlite建立数据库链接就是建立数据库,而其余mysql等应该是须要数据库已存在才能建立数据库链接;创建数据库链接本文中有时会称为创建数据库引擎。mysql
以相对路径形式,在当前目录下建立数据库格式以下:sql
# sqlite://<nohostname>/<path> # where <path> is relative: engine = create_engine('sqlite:///foo.db')
以绝对路径形式建立数据库,格式以下:数据库
#Unix/Mac - 4 initial slashes in total engine = create_engine('sqlite:////absolute/path/to/foo.db') #Windows engine = create_engine('sqlite:///C:\\path\\to\\foo.db') #Windows alternative using raw string engine = create_engine(r'sqlite:///C:\path\to\foo.db')
sqlite能够建立内存数据库(其余数据库不能够),格式以下:flask
# format 1 engine = create_engine('sqlite://') # format 2 engine = create_engine('sqlite:///:memory:', echo=True)
PostgreSQL:session
# default engine = create_engine('postgresql://scott:tiger@localhost/mydatabase') # psycopg2 engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/mydatabase') # pg8000 engine = create_engine('postgresql+pg8000://scott:tiger@localhost/mydatabase')
MySQL:多线程
# default engine = create_engine('mysql://scott:tiger@localhost/foo') # mysql-python engine = create_engine('mysql+mysqldb://scott:tiger@localhost/foo') # MySQL-connector-python engine = create_engine('mysql+mysqlconnector://scott:tiger@localhost/foo') # OurSQL engine = create_engine('mysql+oursql://scott:tiger@localhost/foo')
Oracle:oracle
engine = create_engine('oracle://scott:tiger@127.0.0.1:1521/sidname') engine = create_engine('oracle+cx_oracle://scott:tiger@tnsname')
MSSQL:框架
# pyodbc engine = create_engine('mssql+pyodbc://scott:tiger@mydsn') # pymssql engine = create_engine('mssql+pymssql://scott:tiger@hostname:port/dbname')
咱们以在当前目录下建立foo.db为例,后续各步同使用此数据库。
在create_engine中咱们多加了两样东西,一个是echo=Ture,一个是check_same_thread=False。
echo=Ture----echo默认为False,表示不打印执行的SQL语句等较详细的执行信息,改成Ture表示让其打印。
check_same_thread=False----sqlite默认创建的对象只能让创建该对象的线程使用,而sqlalchemy是多线程的因此咱们须要指定check_same_thread=False来让创建的对象任意线程均可使用。不然不时就会报错:sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 35608 and this is thread id 34024. [SQL: 'SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password \nFROM users \nWHERE users.name = ?\n LIMIT ? OFFSET ?'] [parameters: [{}]] (Background on this error at: http://sqlalche.me/e/f405)
from sqlalchemy import create_engine engine = create_engine('sqlite:///foo.db?check_same_thread=False', echo=True)
先创建基本映射类,后边真正的映射类都要继承它
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
而后建立真正的映射类,咱们这里以一下User映射类为例,咱们设置它映射到users表。ORM中表是不须要先存在的,反而是后续要经过映射类来建立表,这一点是须要明确的。
from sqlalchemy import Column, Integer, String # 定义映射类User,其继承上一步建立的Base class User(Base): # 指定本类映射到users表 __tablename__ = 'users' # 指定id映射到id字段; id字段为整型,为主键 id = Column(Integer, primary_key=True) # 指定name映射到name字段; name字段为字符串类形, name = Column(String(20)) fullname = Column(String(32)) password = Column(String(32)) def __repr__(self): return "<User(name='%s', fullname='%s', password='%s')>" % ( self.name, self.fullname, self.password)
# 查看映射对应的表 User.__table__ # 建立数据表 Base.metadata.create_all(engine)
增查改删(CRUD)操做须要使用session进行操做
from sqlalchemy.orm import sessionmaker # engine是2.2中建立的链接 Session = sessionmaker(bind=engine) # 建立Session类实例 session = Session()
# 建立User类实例 ed_user = User(name='ed', fullname='Ed Jones', password='edspassword') # 将该实例插入到users表 session.add(ed_user) # 一次插入多条记录形式 session.add_all( [User(name='wendy', fullname='Wendy Williams', password='foobar'), User(name='mary', fullname='Mary Contrary', password='xxg527'), User(name='fred', fullname='Fred Flinstone', password='blah')] ) # 当前更改只是在session中,须要使用commit确认更改才会写入数据库 session.commit()
query至关前select xxx from xxx部分。
filter_by至关于where部分,外另可用filter。他们的区别是filter_by参数为sql形式,filter参数为python形式。
# 指定User类查询users表,查找name为'ed'的第一条数据 our_user = session.query(User).filter_by(name='ed').first() our_user # 比较ed_user与查询到的our_user是否为同一条记录 ed_user is our_user
更多查询语句见:https://docs.sqlalchemy.org/en/latest/orm/tutorial.html#querying
不过要注意该连接Common Filter Operators节中形如equals的query.filter(User.name == 'ed'),在真正使用时都得改为session.query(User).filter(User.name == 'ed')形式,否则只后看到报错“NameError: name 'query' is not defined”。
咱们上边的sql直接是our_user = session.query(User).filter_by(name='ed').first()形式,但到实际中时User部分和name=‘ed’这部分是经过参数传过来的,使用参数传递时就要注意如下两个问题。
首先,是参数不要使用引号括起来。好比以下形式是错误的(使用引号),将报错sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column
table_and_column_name = "User" filter = "name='ed'" our_user = session.query(table_and_column_name).filter_by(filter).first()
其次,对于有等号参数须要变换形式。以下去掉了引号,对table_and_column_name没问题,但filter = (name='ed')这种写法在python是不容许的
table_and_column_name = User # 下面这条语句不符合语法 filter = (name='ed') our_user = session.query(table_and_column_name).filter_by(filter).first()
对参数中带等号的这种形式,如今能想到的只有使用filter代替filter_by,即将sql语句中的=号转变为python语句中的==。正确写法以下:
table_and_column_name = User filter = (User.name=='ed') our_user = session.query(table_and_column_name).filter(filter).first()
# 要修改须要先将记录查出来 mod_user = session.query(User).filter_by(name='ed').first() # 将ed用户的密码修改成modify_paswd mod_user.password = 'modify_passwd' # 确认修改 session.commit()
# 要删除须要先将记录查出来 del_user = session.query(User).filter_by(name='ed').first() # 打印一下,确认未删除前记录存在 del_user # 将ed用户记录删除 session.delete(del_user) # 确认删除 session.commit() # 遍历查看,已无ed用户记录 for user in session.query(User): print(user)
虽然使用框架规定形式能够在必定程度上解决各数据库的SQL差别,好比获取前两条记录各数据库形式以下。
# mssql/access select top 2 * from table_name; # mysql select * from table_name limit 2; # oracle select * from table_name where rownum <= 2;
但框架存消除各数据库SQL差别的同时会引入各框架CRUD的差别,而开发人员每每就有必定的SQL基础,若是一个框架强制用户只能使用其规定的CRUD形式那反而增长用户的学习成本,这个框架注定不能成为成功的框架。直接地执行SQL而不是使用框架设定的CRUD不该当是一种低级的操做应当是一种被鼓厉的标准化行为。
# 正常的SQL语句 sql = "select * from users" # sqlalchemy使用execute方法直接执行SQL records = session.execute(sql)
参考: