06 | 关系型数据库入门 学习资源 无合适标签 原创

AI悦创 10月前 767

你好,我是悦创。

公众号:AI悦创

博客:www.aiyc.top

本篇,我将给你分享 Python 操作关系型数据库的入门,更多系列文章阅读我博客和公众号。

进入主题
1. MySql

MySql 是最流行的 关系型数据库管理系统 之一,在 web 应用,MySql 是最好的 RDBMS (关系型数据库管理系统)应用软件之一。

2. Flask

Python WEB 开发界主力——Flask。

使用 SQLAlchemy 进行数据库开发。

使用 ORM 是大势所趋。


1. MySql

数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。

每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据库。CURD。

数据库的三大范式

数据库

关系型数据库,是建立在关系关系模型的基础上的数据库,借助于集合、代数、等数学概念和方法来处理数据库中的数据。

特点:

  1. 数据以表格的形式出现

  2. 每行/为各种记录名称

  3. 每列/为记录名称所对应的数据域

  4. 许多的行和列组成一张表单

  5. 若干的表单组成 database

安装 MySql



https://www.runoob.com/mysql/mysql-install.html

检测是否安装成功:

运行程序命令:

 mysql -u root -p
 # Enter 后输入密码


接下来我们创建一个数据库,供我们接下来学习使用:

 create database test;
 # 输入上面的命令之后会给你返回:Query OK, 1 row affected (0.00 sec) 则创建成功
 # 如果返回:ERROR 1007 (HY000): Can't create database 'test'; database exists 则这个数据库已经存在
 
 
 # 查看我们的数据库是否成功创建:
 show databases;
 # 显示的数据库中有 test 表明创建成功;
 
 # 接下来我们来进简单的使用这个数据库:
 use test;
 # use 要使用的数据库的名称;
 # 输入之后会给你返回:Database changed
 
 # 我们可以使用以下命令查看数据库内容
 show tables;
 # 它会给你返回:
 Empty set (0.01 sec)


2. SQLAIchemy 操作 MySql
  • SQL alchemy 简介

SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

ORM方法论基于三个核心原则:

安装库:

 pip install sqlalchemy pymysql
 # sqlalchemy: 是我们的 ORM
 # pymysql:是我们能够执行这个 sqlalchemy 时候的相当于一个网关


根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

'数据库类型+数据库驱动名称://用户名:[email protected]:端口号/数据库名'

mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]

mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

 mysql+pymysql://:@/[?]
 # mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
 
 mysql+mysqldb://:@[:]/
 # mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>


2.7版本使用mysqldb 3.5版本使用pymysql

连接数据库

这里你要连接数据库前,请你创建好数据库(上面已经说明如何创建数据库 test


编写完上面的代码,我们需要运行程序,看程序是否报错,没有报错则代码无问题。如果报错,认真对比你和我的代码,按你实际数据库情况来写。

PS:上面的代码时样板代码,咱们连接数据库都是用上面的代码。

2.2. 基础知识

导入 DateTime 字段,default 传入的是函数 ,不是执行结果,不需要括号。

假如我们要创建一个表的话,需要导入一个 Table ,也就是这样写:

 from sqlalchemy import Table
 # 当然还需要其他的,例如:Column
 from sqlalchemy import Column
 # 这时,我们发现,我们导入 Table和Column来自于同一个库,所以我们可以直接写成这一句:
 from sqlalchemy import Table,Column
 # 接下来我把我们需要用到的库函数导入进来:
 from aqlalchemy import Table,Column,String,Integer,Boolean,MetaData
 from datetime import datetime

解析代码

 metadata = MetaData() # 取得元数据,介绍数据库
 # 获取元数据,这个元数据相当于你对这个数据库的一些描述,你也可以什么都不写。因为,我们没必要在里面写,直接在 sqlalchemy 里面导入 MetaData 就可以了。
 # Column:字段
 # default:默认
 test=Table('数据名称',元数据(metadata),
           Column('字段名称','字段类型',对这个字段的描述,比如说:第一个时主键,那就写(primary_key=True),自动增长也是 True(autoincrement=True)也就是说,),
            # 这个自动增长就是说,这个 id 作为主键,当表里面的内容不断增加,该 id 也自动增加。
           Column('name',String(255)),
            # 然后,第一个字段是我们的 名字(name),最长 255个字节
           Column('data',DateTime(),default=datetime.now,onupdate=datetime.now),
            # 第二个数据就是我们的时间('date'),数据类型时 Datetime(),default=datetime.now()也就是现在时间
           Column('main',Boolean(),default=False),
           # 是不是男性,类型就是布尔值,default=False 默认不是男性
           )
 

原代码

 from aqlalchemy import Table,Column,String,Integer,Boolean,MetaData
 from datetime import datetime
 
 metadata = MetaData() # 取得元数据,介绍数据库
 # 获取元数据,这个元数据相当于你对这个数据库的一些描述,你也可以什么都不写。因为,我们没必要在里面写,直接在 sqlalchemy 里面导入 MetaData 就可以了。
 test=Table('test',metadata,
           Column('id',Integer(),primary_key=True,autoincrement=True),
           Column('name',String(255)),
           Column('data',DateTime(),default=datetime.now,onupdate=datetime.now),
           Column('main',Boolean(),default=False),)

这时候有心急的小伙伴们就直接运行代码,然后会有疑问就直接来问老师我了。老师咋这个也没有创建呀,为什么呢?因为还差一个知识点没给你们讲呀,差一个事物。当然,这个接下来会讲到滴,我先给上面的代码加上一行代码执行以下看看哈:

 metadata.create_all(engine) # 创建数据表

如果运行正常,会输出一大堆信息:

 "C:\Program Files\Python37\python.exe" D:/daima/pycharm_daima/爬虫大师班/07-关系型数据库入门/Create_databases_Table.py
 2020-01-11 16:27:40,335 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
 2020-01-11 16:27:40,335 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,343 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
 2020-01-11 16:27:40,344 INFO sqlalchemy.engine.base.Engine {}
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 75")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6' for column 'VARIABLE_VALUE' at row 94")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 259")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 377")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 403")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 404")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 455")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column 'VARIABLE_VALUE' at row 484")
   result = self._query(query)
 2020-01-11 16:27:40,349 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
 2020-01-11 16:27:40,349 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,350 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
 2020-01-11 16:27:40,350 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,352 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
 2020-01-11 16:27:40,352 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,354 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
 2020-01-11 16:27:40,354 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,355 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
 2020-01-11 16:27:40,355 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,358 INFO sqlalchemy.engine.base.Engine DESCRIBE `test`
 2020-01-11 16:27:40,358 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,359 INFO sqlalchemy.engine.base.Engine ROLLBACK
 2020-01-11 16:27:40,360 INFO sqlalchemy.engine.base.Engine
 CREATE TABLE test (
  id INTEGER NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  date DATETIME,
  man BOOL,
  PRIMARY KEY (id),
  CHECK (man IN (0, 1))
 )
 
 
 2020-01-11 16:27:40,360 INFO sqlalchemy.engine.base.Engine {}
 2020-01-11 16:27:40,407 INFO sqlalchemy.engine.base.Engine COMMIT
 
 Process finished with exit code 0
 

扩展:使用 Python 操作之后原本的语句已经被转换为 MySql 的原生语句:

 # Python 中 sqlalchemy 的语句:
 test=Table('test',metadata,
           Column('id',Integer(),primary_key=True,autoincrement=True),
           Column('name',String(255)),
           Column('data',DateTime(),default=datetime.now,onupdate=datetime.now),
           Column('main',Boolean(),default=False),)
 
 # MySql 原生语句:
 CREATE TABLE test (
  id INTEGER NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  date DATETIME,
  man BOOL,
  PRIMARY KEY (id),
  CHECK (man IN (0, 1))
 )

一个学员的提问:

image-20200111221616658

学员:这个是不是得加括号?

我:default 传入是函数 ,不是执行结果,不需要括号。

我:内部会执行这个回调函数的

学员:括号,加和不加有什么区别呢?

我:default是一个函数,加了括号就是直接调用了,也就变成了一个值。

学员:不是特别理解

我:default需要的是一个函数,加了()就是执行了这个函数

学员:也就是说如果只需要一个函数就不加()如果要加括号就直接运行了?

我:执行函数会返回一个值, 如果加了()之后传入default就不是一个函数,而是datetime.now()的执行结果了。

我:这个函数传进去的目的就是内部会自己调用,程序在用到这个函数的时候会自己调用传入的这个函数,叫做回调函数。(他会自己调用的)

好,扩展之后我们继续:运行完代码之后,(也就是创建完我们的这个表之后)就可以在命令中(也就是已经启动 MySql)输入:

 # 按一下步骤操作,如果你在上面已经操作 MySql 则可以直接输入以下命令:
 desc test;
 # 当然,如果你不理解的话,请关掉控制台,让我们从头开始操作,检查刚刚所创建的数据库表
 (1)mysql -u root -p123456 (注意:-p后面所接的是你数据库的密码)
 (2)use test;
 (3)desc test;

操作图示:

image-20200111163333149

虽然,写的是 Python 代码,但是我们的 ORM 会帮我转换的。

2.3. 事物

一般来说,事物是必须满足4个条件(ACID)

  • 原子性

  • 一致性

  • 隔离性

  • 持久性

事物:事物就是我们没执行一个操作的时候的 会话(session)也就是我到ATM那里插卡存钱到退卡这就是一个Session。

接下来,我用在银行存一百块钱为例:

(1)原子性:我们的每一个事物,都是插入一条数据,都是很小的一个事件。

(2)一致性:类似我们存进去钱或者取出来钱,或者是中间有上面更改,都可以完完全全的展现在我的表上。(不会是,我存进去一百元而这个表没有任何的变动)也就是说,改动是一致的。

(3)隔离性:比方说两个不同的人,我存一百和你存一百是两个不同的事物,我取钱不会影响到你的资产变动,这就是我们所说的隔离性。

(4)持久性:持久性就是我们数据就一直在哪了,你没有操作的话,它就不会改变了。

事物用 BEGIN、ROLLBACK、COMMIT 来实现:

在上面我们创建了一个表,然后我们通过:conn=engine.connect() 获取一个连接。接下来我们开始一个事物:start=conn.begin()

扩展:提升数据库连接的安全性,使用嵌套函数。

 # 连接数据库的样板代码
 from sqlalchemy import create_engine,MetaData,Table
 
 
 def  my_dabase_big():
  def my_database():
   engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格
    # "mysql + pymysql://root:[email protected]/test",
    max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接
    pool_size = 10, # 连接池大小
    echo = True, # 调试信息展示
   )
  my_database()
 my_dabase_big()

 # 连接数据库的样板代码
 from sqlalchemy import create_engine,MetaData,Table
 
 
 def  my_dabase_big():
  def my_database():
   engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格
    # "mysql + pymysql://root:[email protected]/test",
    max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接
    pool_size = 10, # 连接池大小
    echo = True, # 调试信息展示
   )
  my_database()
 my_dabase_big()
 metadata = MetaData() # 取得元素据,介绍数据库
 # ------------当你上面创建好该表之后,就可以把这一个创建表的代码删除------------
 test=Table('test',metadata,
           Column('id',Integer(),primary_key=True,autoincrement=True),
           #  Column:字段,我们可以存储各种字段,
           #  第一个就是我们的字段名称(取个名字)
           #  第二个是类型(数据类型)
           #  第三个是对这个字段的描述(例如第一个是主键,我就 True,自动增长 autoincrement,也就是我每增加一条信息,他的 ID 就增加 1
           Column('name',String(255)),
            # 接下来就是我们的第一个字段, name,后面定义它最长 255 个字节
           Column('data',DateTime(),default=datetime.now,onupdate=datetime.now,)
           #  第二个我们存储日期,然后,使用 default 默认就是我们现在的时间
           Column('man',Boolean(),default=False),
            # man 是不是男性,(当然添加其他的也是可以的),使用了 布尔值(Bookean()) 默认不是男性 default=False
            )
 # ------------当你上面创建好该表之后,也可以不把创建的代码删除,把这一句删除即可:metadata.create_all(engine) # 创建数据表------------
 conn = engine.connect() # 获取一个连接
 a = conn.begin()  # 开始一个事物
 # 然后,接下来。我们就开始执行
 
 try:
  # 我们在这个事物中的表:test 插入入一个数据,也就是表中的 :name下面的数据插入 lol3
  conn.execute(test.insert(),{'name':'lol3'})
  print(1/0) # 这里我们故意让代码出错去执行 rollback()
  a.cmmit() # 最后提交即可
 
 except:
  a.rollback()
 #  我们来重点说一下这个事物回滚:
 # 在上面的 try:...except:...中的代码,在我们故意出错之前是正常执行了在数据库表中插入的操作。
 # 但这个代码出错的时候就回滚操作,那这个回顾就会撤销你刚刚所作出来的修改(或者说操作回退,就是类似于没有执行。譬如:文本操作中的 Control + Z)的操作。
 # 因为,我(程序)已经发生错误,保证数据库表的完整性,类似于文件的开启就要有关闭(保证文件数据的完整性一个意思)
 

常用数据类型

2.4. 索引

数据库创建索引能够大大提高系统性能。

 test = Table('host',metadata,
             Column('id',Integer(),primary_key=True),
             Column(('ip'),String(255),index=True),
 )

Ps:比如我们创建了一个 host 表,其中一个是 id 一个是 ip 。假如我们存入许多 id 与 ip ,其中有 120、127开头的,然后我假如要查询其中127开头的数据,但是查的时候我需要一条一条检索,这也时间速度上就会慢很多。

可是如果,我们在代码中添加 index=True 之后,就会建立索引。这是什么呢?就是当我们要查询 127 开头,它就只查询 127 的索引部分。这样可以加快速度。

但是需要注意的是,只有在这两种数据分类(区分)非常明显的(类似:男/女),你就可以用 indx=True。这个是一种优化手段,这个是你可以写也可以不写。前期,我们不需要写太多 index,index 写多了反而会造成系统性能下降。(这个是在数据库工程师后期,很深思熟虑的考量之后,才会添加这个 index 索引。但慎用!

接下来,我们来创建表结构,上面我们创建了 test 表,接下来我们创建一个 user 表:

 """
 # -*- coding: utf-8 -*-
 # @Author:AI悦创 @DateTime :2019/9/29  20:13 @Function :功能  Development_tool :PyCharm
 # code is far away from bugs with the god animal protecting
     I love animals. They taste delicious.
               ┏┓      ┏┓
             ┏┛┻━━━┛┻┓
             ┃      ☃      ┃
             ┃  ┳┛  ┗┳  ┃
             ┃      ┻      ┃
             ┗━┓      ┏━┛
                 ┃      ┗━━━┓
                 ┃  神兽保佑    ┣┓
                 ┃ 永无BUG!   ┏┛
                 ┗┓┓┏━┳┓┏┛
                   ┃┫┫  ┃┫┫
                   ┗┻┛  ┗┻┛
 """
 # 连接数据库的样板代码
 from sqlalchemy import create_engine,MetaData,Table,engine
 from sqlalchemy import Column,String,Integer,DateTime,Boolean
 
 
 engine = create_engine(
  "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格
  # "mysql + pymysql://root:[email protected]/test",
  max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接
  pool_size = 10, # 连接池大小
  echo = True, # 调试信息展示
 )
 
 
 metadata = MetaData() # 获得元数据,介绍数据库
 # 定义表
 user = Table('user',metadata,
              # 数据库表名称,元素据
              Column('id',Integer,primary_key=True,autoincrement=True),
              Column('name',String(10)))
 metadata.create_all(engine) # 创建数据表
 
 # ---------------------运行程序输出---------------------
 "C:\Program Files\Python37\python.exe" D:/daima/pycharm_daima/爬虫大师班/知识点/DataBase/database_2.py
 2019-09-29 20:32:31,984 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
 2019-09-29 20:32:31,984 INFO sqlalchemy.engine.base.Engine {}
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 75")
   result = self._query(query)
 [中间大部分省略......]
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 404")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 455")
   result = self._query(query)
 C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column 'VARIABLE_VALUE' at row 484")
   result = self._query(query)
 2019-09-29 20:32:31,990 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
 2019-09-29 20:32:31,990 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,993 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
 2019-09-29 20:32:31,993 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,994 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
 2019-09-29 20:32:31,994 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,996 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
 2019-09-29 20:32:31,996 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,996 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
 2019-09-29 20:32:31,996 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,997 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
 2019-09-29 20:32:31,997 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:31,998 INFO sqlalchemy.engine.base.Engine DESCRIBE `user`
 2019-09-29 20:32:31,998 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:32,000 INFO sqlalchemy.engine.base.Engine ROLLBACK
 2019-09-29 20:32:32,002 INFO sqlalchemy.engine.base.Engine
 CREATE TABLE user (
  id INTEGER NOT NULL AUTO_INCREMENT,
  name VARCHAR(10),
  PRIMARY KEY (id)
 )
 
 
 2019-09-29 20:32:32,002 INFO sqlalchemy.engine.base.Engine {}
 2019-09-29 20:32:32,055 INFO sqlalchemy.engine.base.Engine COMMIT
 
 Process finished with exit code 0
 

Ps:里面运行结果如果出现警告,这忽略就好编码问题,上古遗留问题。

注意:里面输出结果有一个语句,我们来看看

CREATE TABLE user ( id INTEGER NOT NULL AUTO_INCREMENT,  name VARCHAR(10),  PRIMARY KEY (id) )

我们的代码被转换成最原生的数据库代码,是可以直接使用的。

那我们在命令行中查看,表是否真的成功创建:

mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | test           | | user           | +----------------+ 2 rows in set (0.00 sec) mysql> # 零基础小白关怀 # 如果你是已经退出或者不知道为什么 show tables;结果不太对,那关闭数据库,按下面步骤操作查询: (1)mysql -u root -p123456 (2)use test; (3)show tables; # 操作过程演示: [email protected] D:\文字课程\GitChat 付费课程\Python 之站在高层框架下的SQLAIchemy 操作 MySql $ mysql -u root -p123456 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor.  Commands end with ; or \g. Your MySQL connection id is 11 Server version: 5.7.23 MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test; Database changed mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | test           | | user           | +----------------+ 2 rows in set (0.00 sec) mysql> # 输出结果和上面一样 mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | test           | | user           | +----------------+ 2 rows in set (0.00 sec) mysql>

我们还可以再看看,这个表的结构:

# 我们顺便看看, user 表的数据结构: mysql> desc user; +-------+-------------+------+-----+---------+----------------+ | Field | Type        | Null | Key | Default | Extra          | +-------+-------------+------+-----+---------+----------------+ | id    | int(11)     | NO   | PRI | NULL    | auto_increment | | name  | varchar(10) | YES  |     | NULL    |                | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.01 sec) mysql>

PRI:主键 >>> primary_key=True

我们先快速回顾一下,数据库命令行关键语句:

# 显示数据库 show databases; # 使用数据库 use test; # (test:你的数据库名称) # 查看表结构 desc user; # (user:你的表名称) # 查询语句 select * from user_table; # (user_table:你的数据库表名称) # 查看该数据库所有表 show tables;
2.5. 增加数据(原生语句)——方法一
# 连接数据库的样板代码 from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer,DateTime,Boolean engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) engine.execute("insert into user (name) values ('lyy')") engine.execute("insert into user (name) values ('AI悦创')") # 查看插入结果 mysql> select * from user; +----+--------+ | id | name   | +----+--------+ |  1 | lyy    | |  2 | AI悦创  | +----+--------+ 4 rows in set (0.00 sec) mysql>

INSERT INTO TABLE (KEY1,KEYA) VALUES (VALUE1,VALUE2);  # 增加语句

UPDATE TABLE SET KEY=VALUE, KEY=VALUE WHERE···;          # 修改语句

SELECT * FROM TABLE;   # 查询语句

DELETE FROM TABLE WHERE ···;     # 删除语句

完整操作示例:

""" # -*- coding: utf-8 -*- # @Author:AI悦创 @DateTime :2019/9/29  22:10 @Function :功能  Development_tool :PyCharm # code is far away from bugs with the god animal protecting     I love animals. They taste delicious.               ┏┓      ┏┓             ┏┛┻━━━┛┻┓             ┃      ☃      ┃             ┃  ┳┛  ┗┳  ┃             ┃      ┻      ┃             ┗━┓      ┏━┛                 ┃      ┗━━━┓                 ┃  神兽保佑    ┣┓                 ┃ 永无BUG!   ┏┛                 ┗┓┓┏━┳┓┏┛                   ┃┫┫  ┃┫┫                   ┗┻┛  ┗┻┛ """ # 连接数据库的样板代码 from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) # ---------创建表------------- metadata = MetaData() # 获得元数据,介绍数据库 # 定义表 user = Table('user',metadata,              # 数据库表名称,元素据              Column('id',Integer,primary_key=True,autoincrement=True),              Column('name',String(10))) metadata.create_all(engine) # 创建数据表 # ---------------实施增删查改的操作-------------- # 下面的代码请分开尝试,以免出现逻辑混乱 # 增加数据 engine.execute("insert into user (name) values ('AI悦创')") # 更新数据 engine.execute("update user set id=5,name='python' where id =5;") # 更新数据方法二 engine.execute("update user set name='python' where id =5;") # 更新数据方法三 engine.execute("update user set name='20191001'") # 删除数据 # engine.execute("delete from user") # 删除全部 # 删除指定位置 # engine.execute("delete from user where id=2") # 查看数据 a = engine.execute("select * from user") # print(a) for text in a: print(text) print(type(text))
2.5.1. 利用表结构增删改查——方法二

利用封装好的方法,避免写复杂的底层的 mysql 语句

我先看一下我们数据库中,有什么表:

mysql> show databases; +--------------------+ | Database           | +--------------------+ | information_schema | | bool               | | choose             | | lesson             | | look               | | look_1             | | mysql              | | p                  | | performance_schema | | pyspider           | | python_2019        | | runoob             | | sys                | | test               | | web_info           | +--------------------+ 15 rows in set (0.00 sec) mysql> use test; Database changed mysql> show tables; Empty set (0.00 sec) mysql>

我们可以看到,我们 test 数据库下面没有表,接下来我们来创建表。我们来创建一个user_table

from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) metadata = MetaData() # 获得元数据,介绍数据库 # 定义表 user_table = Table('user_table', metadata,                    Column("id", Integer, primary_key=True,autoincrement=True),                    Column("教学表",String(10))) metadata.create_all(engine) # 创建表 # 运行代码的结果 "C:\Program Files\Python37\python.exe" D:/daima/pycharm_daima/爬虫大师班/知识点/DataBase/database_num_4.py 2019-09-30 20:42:46,589 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode' 2019-09-30 20:42:46,589 INFO sqlalchemy.engine.base.Engine {} C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 75")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6' for column 'VARIABLE_VALUE' at row 94")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 259")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 377")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 403")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 404")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xBB\\xC6\\xBC\\xD2\\xB1\\xA6...' for column 'VARIABLE_VALUE' at row 455")   result = self._query(query) C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py:170: Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column 'VARIABLE_VALUE' at row 484")   result = self._query(query) 2019-09-30 20:42:46,594 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names' 2019-09-30 20:42:46,594 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,597 INFO sqlalchemy.engine.base.Engine SELECT DATABASE() 2019-09-30 20:42:46,597 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,597 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin' 2019-09-30 20:42:46,597 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,599 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1 2019-09-30 20:42:46,599 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,599 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1 2019-09-30 20:42:46,599 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,600 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1 2019-09-30 20:42:46,600 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,601 INFO sqlalchemy.engine.base.Engine DESCRIBE `user_table` 2019-09-30 20:42:46,601 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,602 INFO sqlalchemy.engine.base.Engine ROLLBACK 2019-09-30 20:42:46,605 INFO sqlalchemy.engine.base.Engine  CREATE TABLE user_table ( id INTEGER NOT NULL AUTO_INCREMENT,  `教学表` VARCHAR(10),  PRIMARY KEY (id) ) 2019-09-30 20:42:46,605 INFO sqlalchemy.engine.base.Engine {} 2019-09-30 20:42:46,650 INFO sqlalchemy.engine.base.Engine COMMIT Process finished with exit code 0 # 运行之后的数据库结果 mysql> use test; Database changed mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | user_table     | +----------------+ 1 row in set (0.00 sec) mysql>

我们成功创建了 user_table 数据表,接下来我先添加一个数据, hjb

# 修改表中数据 conn = engine.connect() # 获取一个连接 # # 增加数据 conn.execute(user_table.insert(),{"教学表":"hjb"}) # 关闭,防止内存溢出 conn.close()# 关闭连接 # 我们来查看一下,表中的数据 mysql> select * from user_table; +----+--------+ | id | 教学表  | +----+--------+ |  1 | hjb    | +----+--------+ 1 row in set (0.00 sec) mysql>

我们成功添加了数据:hjb

为了然接下来的教程更加直观,我们再添加一个数据 hjb_two

mysql> select * from user_table; +----+---------+ | id | 教学表  | +----+---------+ |  1 | hjb     | |  2 | hjb_two | +----+---------+ 2 rows in set (0.00 sec) mysql>
# 更新数据-更新全部数据 conn.execute(user_table.update(),{"教学表":"AI悦创"}) conn.close() # 运行程序数据库结果 mysql> select * from user_table; +----+--------+ | id | 教学表 | +----+--------+ |  1 | AI悦创 | |  2 | AI悦创 | +----+--------+ 2 rows in set (0.00 sec) mysql> # 全部更新成功 # 那如何指定修改一个数据呢? conn.execute(user_table.update().where(user_table.c.id==1).values(id=1000)) conn.close() # 我们把 id 为 1 的修改成 1000 # 数据库结果 mysql> select * from user_table; +------+--------+ | id   | 教学表 | +------+--------+ |    2 | AI悦创 | | 1000 | AI悦创 | +------+--------+ 2 rows in set (0.00 sec) mysql> # 修改数据 conn.execute(user_table.update().where(user_table.c.id==2).values(教学表='AIYC')) conn.close() # 运行之后数据库结果 mysql> select * from user_table; +------+--------+ | id   | 教学表 | +------+--------+ |    2 | AIYC   | | 1000 | AI悦创 | +------+--------+ 2 rows in set (0.00 sec) mysql>

方法二的完整代码:

from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) metadata = MetaData() # 获得元数据,介绍数据库 # 定义表 user_table = Table('user_table', metadata,                    Column("id", Integer, primary_key=True,autoincrement=True),                    Column("教学表",String(10))) metadata.create_all(engine) # 创建表 # 修改表中数据 conn = engine.connect() # 获取一个连接 # 增加数据 conn.execute(user_table.insert(),{"教学表":"hjb_two"}) # # 更新数据-更新全部数据 conn.execute(user_table.update(),{"教学表":"AI悦创"}) # # 更新指定数据 conn.execute(user_table.update().where(user_table.c.id==1).values(id=1000)) conn.execute(user_table.update().where(user_table.c.id==2).values(教学表='AIYC')) # # where(user.c.id==2) 查找的位置,或者说要修改的位置 conn.close()

接下来 就是查询语句了 ,查询语句,需要我们导入 select

from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer,select engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) metadata = MetaData() # 获得元数据,介绍数据库 # 定义表 user_table = Table('user_table', metadata,                    Column("id", Integer, primary_key=True,autoincrement=True),                    Column("教学表",String(10))) metadata.create_all(engine) # 创建表 # 修改表中数据 conn = engine.connect() # 获取一个连接 # 增加数据 conn.execute(user_table.insert(),{"教学表":"hjb_two"}) # # 更新数据-更新全部数据 conn.execute(user_table.update(),{"教学表":"AI悦创"}) # # 更新指定数据 conn.execute(user_table.update().where(user_table.c.id==1).values(id=1000)) data = input('Please you input data:>>>') conn.execute(user_table.update().where(user_table.c.id==1000).values(教学表=data)) # # where(user.c.id==2) 查找的位置,或者说要修改的位置 # 查询语句 # 找到 教学表的所有内容 res = conn.execute(select([user_table.c.教学表,])) print(res.fetchall()) # 输出 # [('AIYC',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',), ('AI悦创',)] for i in res: print(i) # 输出 """ ('AIYC',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) ('AI悦创',) """ # 删除数据 conn.execute(user_table.delete().where(user_table.c.id==2)) # id==2 删除指定的数据(id号所对应的数据 conn.close()
from sqlalchemy import create_engine,MetaData,Table,engine from sqlalchemy import Column,String,Integer engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) metadata = MetaData() # 获得元数据,介绍数据库 # 定义表 user = Table('mybank', metadata,    Column("id", Integer, primary_key=True,autoincrement=True),    Column("教学表",String(10))) metadata.create_all(engine) # 创建表 # ----------------------------插入数据---------------------------------- # 修改表中数据 conn = engine.connect() # 获取一个连接 # 增加数据 conn.execute(user.insert(),{"教学表":"hjb_two"}) conn.close() # ----------------------------更新数据---------------------------------- # # 更新数据-更新全部数据 conn.execute(user.update(),{"教学表":"AI悦创"}) # # 更新指定数据 conn.execute(user.update().where(user.c.id==1).values(id=1000)) conn.execute(user.update().where(user.c.id==2).values(教学表='AIYC')) # 同时更新多个数据 conn.execute(user.update().where(user.c.id==1).values(City="Beijing",name="AI悦创")) # # where(user.c.id==2) 查找的位置,或者说要修改的位置 conn.close() # ----------------------------查询数据---------------------------------- # 需要导入:select from sqlalchemy import select conn = engine.execute() res = conn.execute(select([user.c.name,])) # res = conn.execute(select([user.c.id==1, user.c.id==2])) print(res.fetchall()) conn.close() # ----------------------------删除数据---------------------------------- conn = engine.execute() conn.execute(user.delete().where(user.c.id==1)) conn.close()

2.5.2. 集成 ORM 类操纵数据——方法三(推荐学会)

Declarative_base:用于创建数据库表的基类

Sessionmaker:用于代替 conn ,执行数据库操作语句

from sqlalchemy import create_engine,Column,String,Integer from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import  declarative_base # 导入我们的基类,就是我们创建的类都是以他为基础 # sessionmaker 用于代替 conn 也就是 engine.connect() # conn = engine.connect() # 获取一个连接 # 连接数据库 engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) Base = declarative_base()# 创建一个基类 class Host(Base): # 表名为 hosts __tablename__='hosts' # 表结构 # primary_key 等于主键 # unique 唯一 # nullable 可为空 id = Column(Integer,primary_key=True,autoincrement=True) # unique 类似于微博后端或者其他名称不能重复的操作,也是实现增量式爬虫 # nullable 有些类似:用户搞怪,在注册页面填了空字符,写这个就是不允许为空 hostname = Column(String(64),unique=True,nullable=False) ip_addr = Column(String(128),unique=True,nullable=False) port = Column(Integer, default=22) title = Column(String(200)) Base.metadata.create_all(engine) # 创建表

首先用 sessionmaker 绑定 engine

之后实例化绑定 session

session 进行 CURD >>> Create、Update、Read、Delete

接下来就是 增删改查咯:

# -*- coding: utf-8 -*- # 写代码是热爱,写到世界充满爱! from sqlalchemy import create_engine,Column,String,Integer from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import  declarative_base # 导入我们的基类,就是我们创建的类都是以他为基础 # sessionmaker 用于代替 conn 也就是 engine.connect() # conn = engine.connect() # 获取一个连接 # 连接数据库 engine = create_engine( "mysql+pymysql://root:[email protected]:3306/test",# (里面的 root 要填写你的密码),注意:mysql+pymysql 之间不要加空格 # "mysql + pymysql://root:[email protected]/test", max_overflow = 5, # 超过连接池大小之后,外最多可以创建的链接 pool_size = 10, # 连接池大小 echo = True, # 调试信息展示 ) Base = declarative_base() class Host(Base): # 表名为 hosts __tablename__='hosts' # 表结构 # primary_key 等于主键 # unique 唯一 # unllable 非空 id = Column(Integer,primary_key=True,autoincrement=True) # unique 类似于微博后端或者其他名称不能重复的操作,也是实现增量式爬虫 # nullable 有些类似:用户搞怪,在注册页面填了空字符,写这个就是不允许为空 hostname = Column(String(64),unique=True,nullable=False) ip_addr = Column(String(128),unique=True,nullable=False) port = Column(Integer, default=22) # 表创建完成之后就注释掉 # Base.metadata.create_all(engine) # 创建表 if __name__ == '__main__': try: Session = sessionmaker(bind=engine) sess = Session() # 创建实例 h = Host(hostname='test1',ip_addr="127.0.0.1") h2 = Host(hostname='test2',ip_addr="192.168.0.1",port=8000) h3= Host(hostname='test3',ip_addr="192.168.1.1",port=8080) sess.add(h) # 每次添加一个 sess.add_all([h2,h3]) # 每次添加多个 sess.commit() # 事物提交,必须要有 except: print("Error!")
if __name__ == '__main__': try: Session = sessionmaker(bind=engine) sess = Session() # 创建实例 h = Host(hostname='test1',ip_addr="127.0.0.1") h2 = Host(hostname='test2',ip_addr="192.168.0.1",port=8000) h3= Host(hostname='test3',ip_addr="192.168.1.1",port=8080) sess.add(h) # 每次添加一个 sess.add_all([h2,h3]) # 每次添加多个 # 更新 sess.query(Host).filter(Host.id==1).update({"port":2019}) # Host 创建表的类名,filter 过滤(Host.id==1) # 删除 sess.query(Host).filter(Host.id==1).delete() # 查询 res = sess.query(Host).filter_by(id=1).all()         # res = sess.query(Host).filter(Host.id==1).all() # filter_by(id==1) 过滤,从Host表 for r in res: print(r.hostname) print(r.ip_addr) print(r.port) sess.commit() # 事物提交,必`须要有 except: print("Error!")
实战,多种方法存储数据


最新回复 (0)
返回