MySQL 命令大全
DDL(数据定义语句)
CREATE TABLE/DATABASE
ALTER TABLE/DATABASE
DROP TABLE/DATABASE
DML(数据管理语句)
INSERT => 新增
DELETE => 删除
UPDATE => 更新
SELECT => 查询
创建数据库
—创建并使用数据库
CREATE DATABASE mydatabase;
创建数据库
USE mydatabase;
使用数据库
—查看已有的数据库
SHOW DATABASES;
建表
建表语句
<pre class="md-fences md-end-block" lang="sql" contenteditable="false" cid="n554" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">CREATE TABLE students
(
id
INT NOT NULL AUTO_INCREMENT,
name
VARCHAR(200) NOT NULL
);</pre>
常见类型
int,char,varchar,datetime
例子:
<pre class="md-fences md-end-block" lang="sql" contenteditable="false" cid="n580" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">-- 新建数据库
CREATE DATABASE school
;
-- 使用数据库
USE school
;
-- id : 学生的ID
-- name: 学生名称
-- nickname: 学生的昵称
-- sex: 性别
-- in_time: 入学的时间
CREATE TABLE students
(
id
INT NOT NULL AUTO_INCREMENT,
name
VARCHAR(20) NOT NULL,
nickname
VARCHAR(20) NULL,
sex
CHAR(1) NULL,
in_time
DATETIME(20) NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
-- 插入数据
INSERT INTO students
(1,'张三','san',now());
-- 删除表
DROP TABLE IF EXISTS students
;
-- 查询
SELECT * FROM students
;
-- 查询语句
SELECT
select_expr, ...
FROM table_references -- table_references 表来源
[WHERE where_definition] -- where_definition 条件
[GROUP BY {col_name | expr | position}]
[HAVING where_definition]
[ORDER BY {col_name | expr | position}
[ASC | DESC],...]
[LIMIT {[offset,] row_count}] -- LIMIT限制查询条数 offset(偏移量,从哪开始), row_count(查询的条数)
-- 条件查询
SELECT * FROM student
WHERE sex
='男';
SELECT id
,name
,nickname
FROM student
WHERE sex
='男' ORDER BY id
DESC;
-- 修改(更新)
UPDATE table_references
SET col_name1=expr1[, col_name2=expr2 ...]
[WHERE where_definition]
-- 更新操作
UPDATE student
SET sex
= '女' WHERE sex
= '男';
UPDATE student
SET sex
= '女' WHERE id
> 5;
-- 其他操作
CREATE INDEX -- 新建索引
ALTER TABLE -- 修改表
DROP -- 删除数据库、表、索引、视图等</pre>
<figure class="md-table-fig" contenteditable="false" cid="n307" mdtype="table" style="box-sizing: border-box; margin: -8px 0px 0px -8px; overflow-x: auto; max-width: calc(100% + 16px); padding: 8px;">
命令 | 说明 |
---|---|
net start mysql | 启动数据库 |
net stop mysql | 关闭数据库 |
mysql -u root -p | 根据用户名密码,登录数据库 |
mysql -u root | 如果数据库没有密码则使用 |
show databases; | 查看在当前服务器中有多少个数据库 |
drop database databaseName; | 删除某个数据库 |
commit; | 提交 |
CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; | 创建数据库 |
ALTER DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; | 更改数据库的字符编码 |
use databaseName; | 选择使用某个数据库 |
show tables; | 查看数据库中有多少的表 |
drop table tableName; | 删除表 |
describe tableName; | 显示表结构 |
SET PASSWORD FOR 'root'``@``'localhost' = ``PASSWORD``(``'newpass'``);
|
方法1: 用SET PASSWORD命令 |
方法2:用mysqladmin | |
</figure>
方法1: 用SET PASSWORD命令
MySQL -u root
mysql> ``SET
PASSWORD
FOR
'root'``@``'localhost'
= ``PASSWORD``(``'newpass'``);
方法2:用mysqladmin
mysqladmin -u root ``password
"newpass"
如果root已经设置过密码,采用如下方法
mysqladmin -u root ``password
oldpass ``"newpass"
方法3: 用UPDATE直接编辑user表
mysql -u root
mysql> use mysql;
mysql> ``UPDATE
user
SET
Password
= ``PASSWORD``(``'newpass'``) ``WHERE
user
= ``'root'``;
mysql> FLUSH ``PRIVILEGES``;
在丢失root密码的时候,可以这样
mysqld_safe ``--skip-grant-tables&
mysql -u root mysql
mysql> ``UPDATE
user
SET
password``=``PASSWORD``(``"new password"``) ``WHERE
user``=``'root'``;
mysql> FLUSH ``PRIVILEGES``;
快捷命令说明:
command + w 关闭标签command + 数字 command + 左右方向键 切换标签command + enter 切换全屏command + f 查找command + d 垂直分屏command + shift + d 水平分屏command + option + 方向键 command + [ 或 command + ] 切换屏幕command + ; 查看历史命令command + shift + h 查看剪贴板历史ctrl + u 清除当前行ctrl + l 清屏ctrl + a 到行首ctrl + e 到行尾ctrl + f/b 前进后退ctrl + p 上一条命令ctrl + r 搜索命令历史
新闻表设计
字段说明
<pre class="md-fences md-end-block" lang="sql" contenteditable="false" cid="n599" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">-- ID: 新闻的唯一标识
-- title: 新闻的标题
-- content: 新闻的内容
-- create_time: 新闻添加的时间
-- types: 新闻的类型
-- image: 新的缩略图
-- author: 作者
-- view_count: 浏览量
-- is_valid: 删除标记
CREATE TABLE news
(
id
INT NOT NULL AUTO_INCREMENT,
title
VARCHAR(200) NOT NULL,
content
VARCHAR(2000) NOT NULL,
types
VARCHAR(10) NOT NULL,
image
VARCHAR(300) NULL,
author
VARCHAR(20) NULL,
view_count
INT DEFAULT 0,
create_time
DATETIME NULL,
is_valid
SMALLINT DEFAULT 1,
PRIMARY KEY (id
)
) DEFAULT CHARSET = 'UTF8'
-- 任务
-- 1、创建一个数据库,然后设计一个新闻表(数据类型要使用合理)
-- 2、使用SQL语句向数据表写入十五条不同的数据
-- 3、使用SQL语句查询类别为"百家"的新闻数据
-- 4、使用SQL语句删除一条新闻数据
-- 5、使用SQL语句查询所有的新闻,以添加时间的倒序进行排列
-- 6、使用SQL语句查询第二页(每一页5条数据)</pre>
Flask-SQLAlchemy使用
Queck-Start快速上手
<pre class="md-fences md-end-block" lang="python" contenteditable="false" cid="n625" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">"""
"""
from flask import Flask
from flask-sqlachemy improt SQLAlchemy
app = Flask(name)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
class User(db.Model)
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nuallable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def repr(self):
return '<User %r>' % self.username</pre>
为了创建初始数据库,只需db
从交互式Python shell 导入对象并运行该SQLAlchemy.create_all()
方法来创建表和数据库:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n644" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> from yourapplication import db
db.create_all()</pre>
接着,需要给你的数据库添加一些数据,例如新增两个用户:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n655" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> from yourapplication import User
admin = User(username='admin', email='admin@example.com')
guest = User(username='guest', email='guest@example.com')</pre>
但是它们还没有真正地写入到数据库中,因此让我们来确保它们已经写入到数据库中:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n668" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> db.session.add(admin)
db.session.add(guest)
db.session.commit()</pre>
访问数据库中的数据很简单:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n679" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> User.query.all()
[<User u'admin'>, <User u'guest'>]
User.query.filter_by(username='admin').first()
<User u'admin'></pre>
最简单的关系型数据库
SQLAlchemy 连接到关系型数据库,关系型数据最擅长的东西就是关系。因此,我们将创建一个使用两张相互关联的表的应用作为例子:
<pre class="md-fences md-end-block" lang="python" contenteditable="false" cid="n721" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">from datetime import datetime
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
body = db.Column(db.Text)
pub_date = db.Column(db.DateTime)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category',
backref=db.backref('posts', lazy='dynamic'))
def init(self, title, body, category, pub_date=None):
self.title = title
self.body = body
if pub_date is None:
pub_date = datetime.utcnow()
self.pub_date = pub_date
self.category = category
def repr(self):
return '<Post %r>' % self.title
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
def init(self, name):
self.name = name
def repr(self):
return '<Category %r>' % self.name</pre>
首先让我们创建一些对象:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n739" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> py = Category('Python')
p = Post('Hello Python!', 'Python is pretty cool', py)
db.session.add(py)
db.session.add(p)</pre>
现在因为我们在 backref 中声明了 posts 作为动态关系,查询显示为:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n757" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> py.posts
<sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x1027d37d0></pre>
它的行为像一个普通的查询对象,因此我们可以查询与我们测试的 “Python” 分类相关的所有文章(posts):
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n775" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> py.posts.all()
[<Post 'Hello Python!'>]</pre>
启蒙之路
您仅需要知道与普通的 SQLAlchemy 不同之处:
-
SQLAlchemy
允许您访问下面的东西:-
sqlalchemy
和sqlalchemy.orm
下所有的函数和类 -
一个叫做 session 的预配置范围的会话(session)
-
metadata
属性 -
engine
属性 -
SQLAlchemy.create_all()
和SQLAlchemy.drop_all()
,根据模型用来创建以及删除表格的方法 -
一个
Model
基类,即是一个已配置的声明(declarative)的基础(base)
-
-
Model
声明基类行为类似一个常规的 Python 类,不过有个 query 属性,可以用来查询模型 (Model
和BaseQuery
) -
您必须提交会话,但是没有必要在每个请求后删除它(session),Flask-SQLAlchemy 会帮您完成删除操作。
配置
下面是 Flask-SQLAlchemy 中存在的配置值。Flask-SQLAlchemy 从您的 Flask 主配置中加载这些值。 注意其中的一些在引擎创建后不能修改,所以确保尽早配置且不在运行时修改它们。
配置键
Flask-SQLAlchemy 扩展能够识别的配置键的清单:
<figure class="md-table-fig" contenteditable="false" cid="n953" mdtype="table" style="box-sizing: border-box; margin: -8px 0px 0px -8px; overflow-x: auto; max-width: calc(100% + 16px); padding: 8px;">
SQLALCHEMY_DATABASE_URI |
用于连接数据的数据库。例如:sqlite:////tmp/test.db``mysql://username:password@server/db
|
---|---|
SQLALCHEMY_BINDS |
一个映射绑定 (bind) 键到 SQLAlchemy 连接 URIs 的字典。 更多的信息请参阅 绑定多个数据库。 |
SQLALCHEMY_ECHO |
如果设置成 True,SQLAlchemy 将会记录所有 发到标准输出(stderr)的语句,这对调试很有帮助。 |
SQLALCHEMY_RECORD_QUERIES |
可以用于显式地禁用或者启用查询记录。查询记录 在调试或者测试模式下自动启用。更多信息请参阅get_debug_queries() 。 |
SQLALCHEMY_NATIVE_UNICODE |
可以用于显式地禁用支持原生的 unicode。这是 某些数据库适配器必须的(像在 Ubuntu 某些版本上的 PostgreSQL),当使用不合适的指定无编码的数据库 默认值时。 |
SQLALCHEMY_POOL_SIZE |
数据库连接池的大小。默认是数据库引擎的默认值 (通常是 5)。 |
SQLALCHEMY_POOL_TIMEOUT |
指定数据库连接池的超时时间。默认是 10。 |
SQLALCHEMY_POOL_RECYCLE |
自动回收连接的秒数。这对 MySQL 是必须的,默认 情况下 MySQL 会自动移除闲置 8 小时或者以上的连接。 需要注意地是如果使用 MySQL 的话, Flask-SQLAlchemy 会自动地设置这个值为 2 小时。 |
SQLALCHEMY_MAX_OVERFLOW |
控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。 |
SQLALCHEMY_TRACK_MODIFICATIONS |
如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。 |
</figure>
连接 URI 格式
完整连接 URI 格式列表请跳转到 SQLAlchemy 下面的文档(支持的数据库)。这里展示了一些常见的连接字符串。
SQLAlchemy 把一个引擎的源表示为一个连同设定引擎选项的可选字符串参数的 URI。URI 的形式是:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1003" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">dialect+driver://username:password@host:port/database</pre>
该字符串中的许多部分是可选的。如果没有指定驱动器,会选择默认的(确保在这种情况下 不 包含 +
)。
Postgres:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1008" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">postgresql://scott:tiger@localhost/mydatabase</pre>
MySQL:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1011" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">mysql://scott:tiger@localhost/mydatabase</pre>
Oracle:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1014" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">oracle://scott:tiger@127.0.0.1:1521/sidname</pre>
SQLite (注意开头的四个斜线):
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1017" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">sqlite:////absolute/path/to/foo.db</pre>
声明模型
通常下,Flask-SQLAlchemy 的行为就像一个来自 declarative
扩展配置正确的 declarative 基类。因此,我们强烈建议您阅读 SQLAlchemy 文档以获取一个全面的参考。尽管如此,我们这里还是给出了最常用的示例。
需要牢记的事情:
-
您的所有模型的基类叫做 db.Model。它存储在您必须创建的 SQLAlchemy 实例上。 细节请参阅 快速入门。
-
有一些部分在 SQLAlchemy 上是必选的,但是在 Flask-SQLAlchemy 上是可选的。 比如表名是自动地为您设置好的,除非您想要覆盖它。它是从转成小写的类名派生出来的,即 “CamelCase” 转换为 “camel_case”。
简单示例
一个非常简单的例子:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1037" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def init(self, username, email):
self.username = username
self.email = email
def repr(self):
return '<User %r>' % self.username</pre>
用 Column
来定义一列。列名就是您赋值给那个变量的名称。如果您想要在表中使用不同的名称,您可以提供一个想要的列名的字符串作为可选第一个参数。主键用 primary_key=True
标记。可以把多个键标记为主键,此时它们作为复合主键。
列的类型是 Column
的第一个参数。您可以直接提供它们或进一步规定(比如提供一个长度)。下面的类型是最常用的:
<figure class="md-table-fig" contenteditable="false" cid="n1042" mdtype="table" style="box-sizing: border-box; margin: -8px 0px 0px -8px; overflow-x: auto; max-width: calc(100% + 16px); padding: 8px;">
Integer | 一个整数 |
---|---|
String (size) | 有长度限制的字符串 |
Text | 一些较长的 unicode 文本 |
DateTime | 表示为 Python datetime 对象的 时间和日期 |
Float | 存储浮点值 |
Boolean | 存储布尔值 |
PickleType | 存储为一个持久化的 Python 对象 |
LargeBinary | 存储一个任意大的二进制数据 |
</figure>
一对多(one-to-many)关系
最为常见的关系就是一对多的关系。因为关系在它们建立之前就已经声明,您可以使用 字符串来指代还没有创建的类(例如如果 Person 定义了一个到 Article 的关系,而 Article在文件的后面才会声明)。
关系使用 relationship()
函数表示。然而外键必须用类 sqlalchemy.schema.ForeignKey
来单独声明:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1072" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address', backref='person',
lazy='dynamic')
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))</pre>
db.relationship()
做了什么?这个函数返回一个可以做许多事情的新属性。在本案例中,我们让它指向 Address 类并加载多个地址。它如何知道会返回不止一个地址?因为 SQLALchemy 从您的声明中猜测了一个有用的默认值。 如果您想要一对一关系,您可以把 uselist=False
传给 relationship()
。
那么 backref 和 lazy 意味着什么了?backref 是一个在 Address 类上声明新属性的简单方法。您也可以使用 my_address.person
来获取使用该地址(address)的人(person)。lazy 决定了 SQLAlchemy 什么时候从数据库中加载数据:
-
'select'
(默认值) 就是说 SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据。 -
'joined'
告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系。 -
'subquery'
类似'joined'
,但是 SQLAlchemy 会使用子查询。 -
'dynamic'
在有多条数据的时候是特别有用的。不是直接加载这些数据,SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。
您如何为反向引用(backrefs)定义惰性(lazy)状态?使用 backref()
函数:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1092" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address',
backref=db.backref('person', lazy='joined'), lazy='dynamic')</pre>
多对多(many-to-many)关系
如果您想要用多对多关系,您需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议 不 使用模型,而是采用一个实际的表:
<pre class="md-fences md-end-block" lang="" contenteditable="false" cid="n1096" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">tags = db.Table('tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)
class Page(db.Model):
id = db.Column(db.Integer, primary_key=True)
tags = db.relationship('Tag', secondary=tags,
backref=db.backref('pages', lazy='dynamic'))
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)</pre>
这里我们配置 Page.tags 加载后作为标签的列表,因为我们并不期望每页出现太多的标签。而每个 tag 的页面列表( Tag.pages)是一个动态的反向引用。 正如上面提到的,这意味着您会得到一个可以发起 select 的查询对象。
选择(Select),插入(Insert), 删除(Delete)
现在您已经有了 declared models,是时候从数据库中查询数据。我们将会使用 快速入门章节中定义的数据模型。
插入记录
在查询数据之前我们必须先插入数据。您的所有模型都应该有一个构造函数,如果您 忘记了,请确保加上一个。只有您自己使用这些构造函数而 SQLAlchemy 在内部不会使用它, 所以如何定义这些构造函数完全取决与您。
向数据库插入数据分为三个步骤:
-
创建 Python 对象
-
把它添加到会话
-
提交会话
这里的会话不是 Flask 的会话,而是 Flask-SQLAlchemy 的会话。它本质上是一个 数据库事务的加强版本。它是这样工作的:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1133" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> from yourapp import User
me = User('admin', 'admin@example.com')
db.session.add(me)
db.session.commit()</pre>
好吧,这不是很难吧。但是在您把对象添加到会话之前, SQLAlchemy 基本不考虑把它加到事务中。这是好事,因为您仍然可以放弃更改。比如想象 在一个页面上创建文章,但是您只想把文章传递给模板来预览渲染,而不是把它存进数据库。
调用 add()
函数会添加对象。它会发出一个 INSERT 语句给数据库,但是由于事务仍然没有提交,您不会立即得到返回的 ID 。如果您提交,您的用户会有一个 ID:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1138" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> me.id
1</pre>
删除记录
删除记录是十分类似的,使用 delete()
代替 add()
:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1142" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> db.session.delete(me)
db.session.commit()</pre>
查询记录
那么我们怎么从数据库中查询数据?为此,Flask-SQLAlchemy 在您的 Model
类上提供了 query
属性。当您访问它时,您会得到一个新的所有记录的查询对象。在使用 all()
或者 first()
发起查询之前可以使用方法 filter()
来过滤记录。如果您想要用主键查询的话,也可以使用 get()
。
下面的查询假设数据库中有如下条目:
<figure class="md-table-fig" contenteditable="false" cid="n1148" mdtype="table" style="box-sizing: border-box; margin: -8px 0px 0px -8px; overflow-x: auto; max-width: calc(100% + 16px); padding: 8px;">
id | username | |
---|---|---|
1 | admin | admin@example.com |
2 | peter | peter@example.org |
3 | guest | guest@example.com |
</figure>
通过用户名查询用户:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1167" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> peter = User.query.filter_by(username='peter').first()
peter.id
1
peter.email
u'peter@example.org'</pre>
同上但是查询一个不存在的用户名返回 None:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1170" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> missing = User.query.filter_by(username='missing').first()
missing is None
True</pre>
使用更复杂的表达式查询一些用户:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1173" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> User.query.filter(User.email.endswith('@example.com')).all()
[<User u'admin'>, <User u'guest'>]</pre>
按某种规则对用户排序:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1176" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> User.query.order_by(User.username)
[<User u'admin'>, <User u'guest'>, <User u'peter'>]</pre>
限制返回用户的数量:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1179" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> User.query.limit(1).all()
[<User u'admin'>]</pre>
用主键查询用户:
<pre class="md-fences md-end-block" lang="shell" contenteditable="false" cid="n1182" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">>>> User.query.get(1)
<User u'admin'></pre>
在视图中查询
当您编写 Flask 视图函数,对于不存在的条目返回一个 404 错误是非常方便的。因为这是一个很常见的问题,Flask-SQLAlchemy 为了解决这个问题提供了一个帮助函数。可以使用 get_or_404()
来代替 get()
,使用 first_or_404()
来代替 first()
。这样会抛出一个 404 错误,而不是返回 None:
<pre class="md-fences md-end-block" lang="python" contenteditable="false" cid="n1186" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 0.9em; white-space: pre; text-align: left; break-inside: avoid; display: block; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; background-position: inherit inherit; background-repeat: inherit inherit;">@app.route('/user/<username>')
def show_user(username):
user = User.query.filter_by(username=username).first_or_404()
return render_template('show_user.html', user=user)</pre>
网友评论