MySQL入门

-MySQL入门

学习步骤

1. 安装MySQL软件

2. 基本配置并启动服务

3. 创建数据库(类似于创建文件夹)

4. 创建表结构(类似于创建文件夹下的excle文件)

5. 创建账户并授权(让程序使用此账户访问数据库中的表)

 

6. 安装pymysql模块(python操作MySQL)

7. 基于pymysql模块连接MySQL

8. 基于pymysql模块发送指令

win系统安转

  1.下载官网:https://downloads.mysql.com/archives/community/

   免安装软件,只要解压即可。

  2.创建配置文件my.ini, 放在安装目录下

[mysqld]

#  port
port = 3306

# set basedir to your installation path
basedir = D:\\Program Files\\mysql-8.0.29-winx64   -安装目录

# set datadir to the location of yourdata directory
datadir = D:\\Program Files\\mysql-8.0.29-winx64\\data   -数据目录

  配置文件的查询机制

  cmd:>"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe" --help --verbose

图1 数据库配置查询

  3.初始化cmd

"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe" --initialize-insecure

初始化本质做了两件事:

  1)根据配置文件,创建data目录,在data目录里面初始化一些数据库必备的数据;

  2)除此以外还会帮助我们创建一些账户,比如root(没有密码)。

  如果报错:

    下载vcredist:https://www.mircrosoft.com/zh-cn/download/confirmation.aspx?id=40784  (主要)

    下载dirctx: https://www.mircrosoft.com/zh-CN/download/details.aspx?id=35 

  4.启动

   临时启动

"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe"

注意,这个地方的双引号的作用是将引号中的内容视为一个整体,避免出现空格时默认命令结束了。   

  制作服务管理(需要管理员权限)

"D:\Program Files\mysql-8.0.29-winx64\bin\mysqld.exe" --install mysql8029

    通过服务开启

net start mysql8029

   通过服务关闭

net stop mysql8029

   删除服务

"D:\Program Files\mysql-8.0.29-winx64\bin\mysqld.exe" --remove mysql8029 (可以不写名字,需要管理员权限)

  5.测试链接上服务

"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysql.exe" -h 127.0.0.1 -P 3307 -u root -p (如果是本机,可以不写-h和-P)

  6.加环境变量

指令学习

  1.查看数据库

show databases;

  2.退出

exit;

关于配置

关于密码

  1.设置密码(可登录的情况)

set password='root123'

  2.忘记密码

  修改配置文件

skip-grant-tables=1

  重启服务

net stop mysql8029
net start mysql8029

  重启后进入

mysql -u root -p

  进入后修改密码

use mysql;
updata user set authentication_string = '新密码',password_last_changed=now() whele user = 'root';

  退出修改配置文件

# skip-grant-tables=1

  再次重启。

数据库管理系统(DBMS)

  注意两个概念:

  数据库:相当于文件夹

  数据表:相当于文件夹下excel表格

数据库(文件夹)的操作指令

  数据库的操作指令必须以分号结尾,表示指令结束。

  show databases; 查看数据库。

show databases;

  create database 数据库名; 创建的数据库。

create database db25;

  但是这样是不够的,我们在创建文件的时候一般需要考虑它的编码。

create database db24 default charset utf8 collate utf8_general_ci;

  注意,数据库不区分大小写,包括文件名或者表格名等,默认小写字母。

  drop database 数据库名;删除数据库。

drop database db25;

   use 数据库名;进入数据库,相当于进入文件夹,可以不写分号。

use db24;

  基于python操作:

# 导入pymysql库
import pymysql
# 打开数据库连接(socket)
conn = pymysql.connect(host='localhost',port=3306,user='root',password='WENPENG1994325',charset='utf8')
# 使用cursor()方法获取操作游标
cursor = conn.cursor()
# 1.查看数据库
# 发送指令
cursor.execute('show databases')
# 获取指令的结果
result = cursor.fetchall()
print(result)  # (('day25',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',))

# 2. 创建数据库(新增、删除、修改)
# 发送指令
cursor.execute("create database db3 default charset utf8 collate utf8_general_ci")
# 执行
conn.commit()

# 3.查看数据库
cursor.execute('show databases')
result = cursor.fetchall()
print(result) # (('day25',), ('db3',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',))

# 4.删除数据库
cursor.execute('drop database db3')
conn.commit()

# 5.查看数据库
cursor.execute('show databases')
result = cursor.fetchall()
print(result) # (('day25',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',))

# 进入数据库
cursor.execute('use day25')
cursor.execute('show tables')
result = cursor.fetchall()
print(result)  # ()

# 关闭连接
cursor.close()
conn.close()

  运用python操作数据库,其根本和终端操作类似,python扮演着第三方模块的角色。需要掌握下面几个知识点。

  1)python和数据的链接需要通过pymysql库来实现;

  2)-.connect(host='localhost',user='root',password='WENPENG1994325',charset='utf8') 建立链接,相当于接口。host:表示id,如果是本机,可以写127.0.0.1或者localhost,port: 表示接口,默认3306; 如果是本机,上述两个参数均可以不写;user: 用户,主用户为root;password: 登陆密码;charset: 操作文件的编码,一般情况下都用utf8;database: 指定数据库(文件夹)。

  3)有了接口还不够,还需要一个游标,表示当前所在位置,作用相当于鼠标。游标直接通过接口生成conn.cursor()。默认游标在根目录下,如果链接时指定数据库(文件夹),则初始游标在该目录下。

  4)-.execute() 发送指令,这是python与数据库交流的桥梁,python可以通过它发送指令给数据库。

  5)发送增加,删除,修改数据库的命令时,需要用conn.commit()指示接口执行。

  6)发送查看数据库或者数据时,需要用-.fetchall(),-.fetchone()来解析数据。

  7)-.close()关闭游标或者数据库接口。

数据表(excle表格)的操作指令

表格的创建以及数据列操作

   0)进入数据库用use 数据库; 查看数据库下的数据表用show tables;

   1)创建数据表:

create table 表名(
    列名 类型,
    列名 类型,
    列名 类型
)default charset=utf8;

  注意:这里的编码不用字符串。

create table tb1(
    id int;
    name varchar(16)
)default charset=utf8;

  有的时候需要指定一些要求,比如是否运行数据为空。

create table tb2(
    id int,
    name varchar(16) not null,       --不允许为空
    email varchar(32) null,          --允许为空(默认)
    age int
)default charset=utf8;

  当然还有时需要默认值。

create table tb3(
    id int,
    name varchar(16) not null,       --不允许为空
    email varchar(32) null,          --允许为空(默认)
    age int default 3                --插入数据时,如果不给age列设置值,默认为:3
)default charset=utf8;

  注意:在mysql中双横线表示注释

  主键(用于区别数据条的列,不允许为空,也不能重复),一般用于当前数据的ID编号(类似于人的身份证),用于区分不同的数据。

create table tb4(
    id int primary key,                 --主键(不允许为空、不能重复)
    name varchar(16) not null,          --不允许为空
    email varchar(32) null,             --允许为空(默认)
    age int default 3                   --插入数据时,如果不给age列设置值,默认为:3
)default charset=utf8;

怎么样做到不重复呢?自增!

create table tb5(
    id int not null auto_increment primary key,                 --不允许为空 & 主键 & 自增
    name varchar(16) not null,                                  --不允许为空
    email varchar(32) null,                                     --允许为空(默认)
    age int default 3                                           --插入数据时,如果不给age列设置值,默认为:3
)default charset=utf8;

一般情况下,一张表里有且只有一个自增列,用于标识数据。

  2)删除表:drop table 表名;

  3)清空表:delete from 表名;或  truncate table 表名;

   两者的区别:truncate table 表名; 比 delete from 表名 的清空速度要快,但是用它清楚后的数据不可恢复。

    4)修改表

  • 添加列
    alter table 表名 add 列名 类型;
    alter table 表名 add 列名 类型 default 默认值;
    alter table 表名 add 列名 类型 not null default 默认值;
    alter table 表名 add 列名 类型 not null primary key auto_increment;
  • 删除列
    alter table 表名 drop column 列名;
  • 修改列  类型
    alter table 表名 modify column 列名 类型
  • 修改列  类型 +  名称
    alter table 表名 change 原列名 新列名 新类型;
    alter table tb1 change id id int not null;
    alter table tb1 change id id int not null default 5;
    alter table tb1 change id id int not null primary key auto_increment;
    alter table tb1 change id id int;
  • 修改列  默认值
    alter table 表名 alter 列名 set default 1000;
  • 删除列  默认值
    alter table 表名 alter 列名 drop default;
  • 添加主键
    alter table 表名 add primary key(列名)
  • 删除主键
    alter table 表名 drop primary key;

  注意:主键只能出现一个,故只能设置一次,重复设置会抛出异常:ERROR 1068 (42000): Multiple primary key defined,如果想修改需要先删除主键。 

   5) 查看表格的列(类型):desc 表名;

常见列类型

整形系列

int[(m)][unsigned][zerofill]

  m: 字符长度,有符号限制:-2147483648~2147483647,有符号限制:0~4294967295

  unsigned: 标识无符号

  zerofill: 是否填充零

mysql> create table L1(
    -> id int,
    -> uid int unsigned,
    -> zid int(5) zerofill
    -> )default charset=utf8;
Query OK, 0 rows affected, 3 warnings (0.02 sec)
mysql> insert into L1(id,uid,zid) values (1,2,3);
Query OK, 1 row affected (0.01 sec)
mysql> insert into L1(id,uid,zid) values (2147483641,4294967294,30000);
Query OK, 1 row affected (0.01 sec)
mysql> select * from L1;
+------------+------------+-------+
| id         | uid        | zid   |
+------------+------------+-------+
|          1 |          2 | 00003 |
| 2147483641 | 4294967294 | 30000 |
+------------+------------+-------+
2 rows in set (0.00 sec)
mysql> insert into L1(id,uid,zid) values (214748364100,4294967294,30000);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql> insert into L1(id,uid,zid) values (2147483641,4294967294,300000);
Query OK, 1 row affected (0.01 sec)

mysql> select * from L1;
+------------+------------+--------+
| id         | uid        | zid    |
+------------+------------+--------+
|          1 |          2 |  00003 |
| 2147483641 | 4294967294 |  30000 |
| 2147483641 | 4294967294 | 300000 |
+------------+------------+--------+
3 rows in set (0.00 sec)

  注意:严格模式和非严格模式,非严格模式会出现截断。

  另外,对于具体的使用,还有两种整形,tinyint和bigint。

tinyint [(m)][unsigned][zerofill]

有符号限制:-128~127,有符号限制:0~255

bigint[(m)][unsigned][zerofill]

有符号限制:-9223372036854775808~9223372036854775807,有符号限制:0~18446744073709551615

小数系列

decimal [(m[,d])][unsigned][zerofill]

  准确小数值。

  m: 数字总个数(负号不算)。

  d: 小数点后个数。

  m最大值为65,d的最大值为30。

mysql> create table L2(
    -> id int not null primary key auto_increment,
    -> salary decimal(8,2)
    -> )default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> insert into L2(salary) values(1.28);
Query OK, 1 row affected (0.01 sec)

mysql> insert into L2(salary) values(5.289);
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> insert into L2(salary) values(5.282);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into L2(salary) values(512132.28);
Query OK, 1 row affected (0.00 sec)

mysql> insert into L2(salary) values(512132.283);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from L2;
+----+-----------+
| id | salary    |
+----+-----------+
|  1 |      1.28 |
|  2 |      5.29 |
|  3 |      5.28 |
|  4 | 512132.28 |
|  5 | 512132.28 |
+----+-----------+
5 rows in set (0.00 sec)

mysql> insert into L2(salary) values(5121732.283);
ERROR 1264 (22003): Out of range value for column 'salary' at row 1

  需要注意的是,当小数点后的位数超出范围时,将发生四舍五入截断,不会报错,但是当整数部分超出范围时,严格意义下会报错。

  类似的,小数也有其他的函数。

float[(m,d)][unsigned][zerofill]

  单精浮点数,非准确小数值,32位存储。

double[(m,d)][unsigned][zerofill]

  双精度浮点数,非准确小数值,64位存储。

  非准确小数值,位数越多越不准确,所以不常用。

字符串系列

char(m)

  定长字符串,会占用相应的字符数,少于这个数系统会补齐,多于这个数,严格模式下会报错。非严格模式,进行截断。m具有限制最多可容纳255个字符。如果想查看补齐的元素,通过下面的语句修改配置文件即可。

sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH"

 

varchar(m)

  变长字符串,不同于char(m)的是,数据实际有多少就占多少,少于m时不会补齐,但是多于m的时候和char一样。不一样的是,varchar最多可容纳65535个字节

  严格模式和非严格模式。默认是严格模式,可以通过修改配置文件变成非严格模式。

sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

  除了char和varchar以为还有一些类型是存储字符串的。比如text,mediumtext,longtext。不同的是,它们可容纳的字符串长度是不一样的。

  text:用于保存变长的大字符串,最多可容纳65535(2**16-1)个字符。一般情况下,长文本会使用text,比如:新闻,文章等。

  nediumtext: 最多可容纳16,777,215(2**24-1)个字符。

  longtext: 最多可容纳4,294,967,295 或 4GB(2**32-1)个字符。

时间

datatime
YYYY-MM-DD HH:MM:SS (1000-01-01 00:00:00/9999-12-31 23:59:59)
timestamp
YYYY-MM-DD HH:MM:SS (1970-01-01 00:00:00/2037年)

  两者不同的地方是它们的范围不一样。另外timestamp还与时区有关系,具体看下面的实验。

mysql> create table L5(
    -> id int not null primary key auto_increment,
    -> dt datetime,
    -> tt timestamp
    -> )default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> insert into L5(dt,tt) values("2025-11-11 11:11:44","2025-11-11 11:11:44");
Query OK, 1 row affected (0.01 sec)

mysql> select * from L5;
+----+---------------------+---------------------+
| id | dt                  | tt                  |
+----+---------------------+---------------------+
|  1 | 2025-11-11 11:11:44 | 2025-11-11 11:11:44 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

mysql> show variables like '%time_zone%';     -- 查看时区设置
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set, 1 warning (0.04 sec)

mysql> set time_zone='+0:00';      -- 修改时区设置
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +00:00 |
+------------------+--------+
2 rows in set, 1 warning (0.00 sec)

mysql> select * from L5;
+----+---------------------+---------------------+
| id | dt                  | tt                  |
+----+---------------------+---------------------+
|  1 | 2025-11-11 11:11:44 | 2025-11-11 03:11:44 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

  系统默认的时区就是我们当前的时区,默认情况下,二者的区别就是范围,由于datatime的范围比较大,所以我们倾向于使用datatime。

  除此以外单独使用日期的时候,我们用date,单独使用时间的时候用time。

date
YYYY-MM-DD(1000-01-01/9999-12-31)
time
HH:MM:SS(-838:59:59/ 838:59:59)

小结

  MySQL还有很多其他的数据类型,例如:set、enum、TinyBlob、MediumBlob、LongBlob等,详见官方文档:https://dev.mysql.com/doc/refman/5.7/en/data-types.huml

python代码实现

import pymysql
# 连接数据库
conn = pymysql.connect(host='localhost',
                       port=3306,
                       user='root',
                       password='WENPENG1994325!',
                       charset='utf8'
                       )
cursor = conn.cursor()

# 1.创建数据库
cursor.execute('drop database db26')
cursor.execute('create database db26 default charset utf8 collate utf8_general_ci')
conn.commit()

# 2.进入数据库,查看数据表
cursor.execute('use db4')
cursor.execute('show tables')
result = cursor.fetchall()
print(result)

# 3.进入数据库创建表
cursor.execute('drop table L4')
sql = """
create table L4(
    id int not null primary key auto_increment,
    title varchar(128),
    content text,
    ctime datetime
)default charset=utf8;
"""
cursor.execute(sql)
conn.commit()

# 4. 查看数据库中的表
cursor.execute('show tables')
result = cursor.fetchall()
print(result)

# 5.其他drop table ... 略过

# 关闭连接
cursor.close()
conn.close()

数据行操作 *****

  1)新增数据

insert into 表名(列名,列名,列名) values(对应列的值,对应列的值,对应列的值)
mysql> insert into tb1(name,password) values('吴佩琪','123123');
Query OK, 1 row affected (0.01 sec)

mysql> insert into values('吴佩琪','123123'),('alex','123');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into tb1 values('吴佩琪','123123'),('alex','123'); --这种情况仅仅限于表中只有2列的情况
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

  2)删除数据

delete from 表名;
delete from 表名 where 条件;
delete from tb1;
delete from tb1 where name="wupeiqi";
delete from tb1 where name="wupeiqi" and password="123";
delete from tb1 where id>9;

  注意:这里的条件与其他地方的不一样,这个地方等于用的是等号,而不是双等号。

  3)修改数据

update 表名 set 列名=值;
update 表名 set 列名=where 条件;
update tb1 set name="wupeiqi";
update tb1 set name="wupeiqi" where id=1;
update tb1 set age=age+1 where id=2;  -- age必须是整形,字符串不可以直接相加,需要用到下面的concat函数
update users set name=concat(name,"123") where id=2;  --concat函数:可以拼接字符串

  4)查询数据

select * from 表名;
select 列名,列名,列名 from 表名;
select 列名,列名 as 列名,列名 from 表名;-- 查询的时候修改列名
select * from 表名 where 条件; 
select * from tb1;  --这里的*代指所有的列
select id,name,age from tb1;  -- select 选择列
select id,name as N from tb1;  --数据库采用的是就近原则,修改后面修改后面一个列的名字。
select id,name,111 as N from tb1; --额外显示一列111,值默认为111
select id,name,111 as age from tb1; --将111这一列的的列名改为age
select * from tb1 where id=1; --where条件选择行 select * from tb1 where id>1; select * from tb1 where id!=1; select * from tb1 where name="wupeiqi" and password="123";

python实现数据行增删改查

import pymysql
# 数据行的增删改查
# 连接mysql
conn = pymysql.connect(
    host='localhost',
    port=3306,
    user='root',
    password='WENPENG1994325',
    charset='utf8',
    database='db24'  # 自动执行use db24 --进入数据库
)
cursor = conn.cursor()

# 1.新增(需commit)
cursor.execute('insert into tb1(name,password) values("吴佩琪","123123")')
conn.commit()
# 增加id自增列主键
# cursor.execute('alter table tb1 add id int not null primary key auto_increment')


# 2.删除(需commit)
cursor.execute('delete from tb1 where id =1 ')
conn.commit()

# 3.修改(需commit)
cursor.execute('update tb1 set name = "wu" where id=2')
conn.commit()

# 4.查询
cursor.execute('select * from tb1')
data = cursor.fetchall()
print(data)

# 关闭连接
cursor.close()
conn.close()

应用案例

  其实真正做项目开发时,流程如下:

  第一步:根据项目的功能来设计相应的数据库&表结构(不会经常变动,在项目设计之初就确定好了)。

  第二步:操作表中的数据,已达到实现业务逻辑的目的。

  例子:实现一个用户管理系统。

  先使用MySQL自带的客户端创建相关数据库和表结构(相当于创建好Excel结构)。

mysql> create database userdb default charset utf8 collate utf8_general_ci;
Query OK, 1 row affected, 2 warnings (0.01 sec)
mysql> use userdb
Database changed
mysql> create table users(
    -> id int not null primary key auto_increment,
    -> name varchar(32),
    -> password varchar(64)
    -> )default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.02 sec)

  再在程序中执行编写相应的功能实现注册、登陆等功能。

import  pymysql
def register():
    print("用户注册")

    name = input("请输入用户名:")
    password = input("请输入密码:")

    # 连接指定的数据库
    conn = pymysql.connect(
        host='localhost',
        port=3306,
        user='root',
        password="WENPENG1994325",
        database='userdb',
        charset='utf8'
    )
    cursor = conn.cursor()

    # 发送命令保存用户名和密码
    # sql = insert into user(name,password) values("name","password")
    cursor.execute('insert into users(name,password) values("{name}","{password}")'.format(name=name,password=password))
    conn.commit()

    # 关闭数据库连接
    cursor.close()
    conn.close()

def login():
    print('用户登陆')

    name = input("请输入用户名:")
    password = input("请输入密码:")

    # 连接指定的数据库
    conn = pymysql.connect(
        host='localhost',
        port=3306,
        user='root',
        password="WENPENG1994325",
        database='userdb',
        charset='utf8'
    )
    cursor = conn.cursor()

    # 发送命令查询数据
    # sql = select * from users where name = "name" and password="password"
    cursor.execute('select * from users where name = "{name}" and password="{password}"'.format(name=name,password=password))
    result = cursor.fetchone()
    # fetchone, 如果指令(SQL语句)执行后获得了很多行数据,只拿第一行。
    # 没有:None
    # 有的话以元组的形式出现,表示第一行的数据
    # fetchall, 如果指令(SQL语句)执行后获得多行数据,所有的数据都获得到。
    # 没有 None
    # 有的话以元组套元组的形式出现,一个子元组代表一行数据。

    # 关闭数据库连接
    cursor.close()
    conn.close()

    # 判断是否登陆成功
    if result:
        print("登陆成功",result)
    else:
        print("登陆失败")


def run():
    choice = input("1.注册;2.登陆")
    if choice == '1':
        register()
    elif choice == '2':
        login()
    else:
        print('输入错误')


if __name__=="__main__":
    run()

  你会发现,在项目开发中,数据库&数据表的操作其实就做一次,最常写的还是对数据行的操作。

关于SQL注入

  登陆程序上述程序时,我只要输入用户名为" or 1=1 --,密码任意,就可以登入了。

  啊!那是为什么呢?

  问题出现在这儿。sql=select * from users where name = "" or 1=1 --" and password="password"

  哦!神奇的字符串拼接呀!

  明白了吧,所以不要用传统的字符串格式化。用pymysql提供的方法。

cursor.execute('select * from users where name = %s and password=%s',[name, password])

    或者

 cursor.execute('select * from users where name = %(name)s and password= %(password)s',{'name':name,'password':password})

  这样就可以实现,-.execute不但给我们实现转义,还会自动识别其中的引号等非法字符。

  哇!太神奇啦!

 

 参考视频

https://www.bilibili.com/video/BV1B34y1R7in?spm_id_from=333.337.search-card.all.click&vd_source=4a12138246864aafc0d59517830e26b6

 

 

 

 

 

 

 

 

 

 

 

  

  

  

 

posted @ 2022-08-10 16:59  动心成神  阅读(19)  评论(0)    收藏  举报