概念
- 数据库表是一个二维表,包含多行多列。把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,如:
[
('1', 'Michael'),
('2', 'Bob'),
('3', 'Adam')
]
但是这样的数据结构不够直观,很难看出表的结构,这时候,ORM的概念就诞生了,即与对向相关的映射(Object-Relational Mapping),它是通过一个类的实例化来实现的:
class User(object):
def __init__(self, id, name):
self.id = id
self.name = name
[
User('1', 'Michael'),
User('2', 'Bob'),
User('3', 'Adam')
]
当我们需要获得id,或者name的时候,只需要通过循环获取到对象,直接通过user1.id或者user1.name就可以获取到id和name的属性。并且使得数据的存取非常的规范,这样ORM架构应用而生。
sqlalchemy的安装
-
进入终端输入:
pip install sqlalchemy
-
如果没有部署mysql环境,就需要在虚拟机上安装mysql服务
yum install -y mysql-server mysql;systemctl start mysql
-
进入mysql创建数据库:
create database sqlalchemy;
-
授权:
grant all privileges on *.* to 'alchemy'@'localhost' identified by '123456';
-
初始化连接,创建一个engine实例
from sqlalchemy import create_engine
engine = create_engine("mysql+pymysql://alchemy:123456@fishxq.gicp.netsqlalchemy",echo=True) # 默认的dbi时mysqldb,如果要用pymysql要用到mysql+pymysql这种形式,echo参数是可选参数,会显示每条执行的sql语句
print(engine)
#执行结果:
Engine(mysql+pymysql://alchemy:***@fishxq.gicp.net/sqlalchemy)
- 创建一个表,通过sql语句
cursor = engine.connect()
sql = """
create table if not exists student(
id int not null primary key,
name varchar(100),
age int,
address varchar(100)
)ENGINE=INNODB DEFAULT charset=utf8 auto_increment=1;
"""
cursor.execute(sql)
cursor.close()
-
通过ORM方法来创建
from sqlalchemy import create_engine, MetaData, Integer, Table, Column, String engine = create_engine("mysql+pymysql://alchemy:123456@fishxq.gicp.net/sqlalchemy",echo=True) metadata = MetaData(engine) user = Table("user",metadata, Column('id',Integer,primary_key=True), Column('name',String(100)), Column('age',Integer) ) metadata.create_all(engine)
- 通过上述两种方法创建了2个表格,回到mysql里查看结果如下:
mysql> show tables; +----------------------+ | Tables_in_sqlalchemy | +----------------------+ | student | | user | +----------------------+ 2 rows in set (0.01 sec) mysql> desc user; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(100) | YES | | NULL | | | age | int(11) | YES | | NULL | | +-------+--------------+------+-----+---------+----------------+ 3 rows in set (0.01 sec) mysql> desc student; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(100) | YES | | NULL | | | age | int(11) | YES | | NULL | | | address | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ 4 rows in set (0.00 sec)
-
MetaData类主要用于保存表结构,连接字符串等数据
-
metadata = MetaData(engine) 绑定一个数据源的metadata
-
metadata.create_all(engine) 创建一个表,这是一个安全操作,如果表存在就不会创建新的表字段,可以用于逻辑判断
-
Table类用于创建表,参数有:
- 例子:
mytable = Table("mytable", metadata, Column('mytable_id', Integer, primary_key=True), Column('value', String(50)) )
- mytable时表名,metadata是元数据,column代表创建表字段,mytable_id代表创建的字段
-
创建会话session
from sqlalchemy.orm import sessionmaker
engine = create_engine("mysql+pymysql://alchemy:123456@fishxq.gicp.netsqlalchemy",echo=True)
DBsession = sessionmaker(bind=engine)
session = DBsession()
print(session)
sqlalchemy.orm.session.Session object at 0x10fef9780>
这个定制的DBsession类将创建新的Session对象绑定到我们的数据库。 无论何时你需要与数据库连接,你实例化一个DBession:
- 往表里添加数据
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
address = Column(String(100))
engine = create_engine("mysql+pymysql://alchemy:123456@fishxq.gicp.net:6106/sqlalchemy",echo=True)
DBsession = sessionmaker(bind=engine)
session = DBsession()
new_student = Student(id=10001, name="Bill", age=18,address='Xumin Rd 111')
new_student2 = Student(id=10002, name="Tom", age=18,address='Xumin Rd 112')
new_student3 = Student(id=10003, name="Floria", age=18, address='Xumin Rd 113')
new_student4 = Student(id=10004, name="Carrie", age=18, address='Xumin Rd 114')
session.add(new_student)
session.add_all([new_student2, new_student3,new_student4]) # 可以把数据一次都插入但是参数为一个列表
session.commit()
session.close()
#########################回到数据库查看表:
mysql> select * from student;
+-------+--------+------+--------------+
| id | name | age | address |
+-------+--------+------+--------------+
| 10001 | Bill | 18 | Xumin Rd 111 |
| 10002 | Tom | 18 | Xumin Rd 112 |
| 10003 | Floria | 18 | Xumin Rd 113 |
| 10004 | Carrie | 18 | Xumin Rd 114 |
+-------+--------+------+--------------+
4 rows in set (0.00 sec)
#######插入数据成功
参数有点多,用法都是约定俗称的一定要多加练习熟悉起用法
- 查询数据
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, query
Base = declarative_base()
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
address = Column(String(100))
engine = create_engine("mysql+pymysql://alchemy:123456@fishxq.gicp.net:6106/sqlalchemy",echo=False)
DBsession = sessionmaker(bind=engine)
session = DBsession()
student1 = session.query(Student).filter_by(name='Tom').first() # first()返回第一个数据,如果不加first()就会返回sql查询语句,如果用all()就会返回一个列表,包含所有查询到的数据
print(student1.id,student1.name,student1.age,student1.address)
- 上面的查询用了filter_by的过滤,现在用filter,filter可以多重过滤,最后也要跟first(),one()或all()
student2 = session.query(Student).filter(Student.name.like('%o%').filter(Student.id==10001).first()
print(student2.name)
结果输出为Tom
- filter()和filter_by()的区别:
-
Filter: 可以像写 sql 的 where 条件那样写 > < 等条件,但引用列名时,需要通过 类名.属性名 的方式。
-
filter_by: 可以使用 python 的正常参数传递方法传递条件,指定列名时,不需要额外指定类名。,参数名对应名类中的属性名,但似乎不能使用 > < 等条件。
-
当使用filter的时候条件之间是使用“==",fitler_by使用的是"="。
user1 = session.query(User).filter_by(id=1).first()
user1 = session.query(User).filter(User.id==1).first()
-
filter不支持组合查询,只能连续调用filter来变相实现。
-
而filter_by的参数是**kwargs,直接支持组合查询。 比如: q = sess.query(IS).filter(IS.node == node and IS.password == password).all()
-