SQL概念
- 什么是SQL
即Structured Query Language结构化查询语言,访问和处理关系型数据库的计算机语言
- 为什么需要数据库
程序运行时使用到的数据通常保存在内存中,一旦关闭就消失了
想要将数据保存下来只能存到文件里,带来很多重复性的保存、解析代码
数据库可以帮助持久化数据这一过程
也就是应用程序不需要知道数据底层的存储情况,只需要使用数据库提供的接口就可以实现
- 什么是关系型数据库
可以把每一类数据看成一个二维表格,每一行是一个记录,每一列是一个字段
不同的关系表之间可以用一对多、多对多等关系
每一个属性需要定义数据类型,比如INT、BIGINT、DOUBLE、CHAR(N)、DATETIME等
- 关系模型
字段定义:
- 数据类型
- 是否允许为NULL(NULL表示数据不存在)
- 关系表的主键
在关系表中,不能存在两条完全一样的记录,主键就是用于区分不同记录的字段
主键的几个特点:
- 主键一定是唯一的
- 主键(最好)不再被修改,通常用一个自增的ID或者GUID
联合主键就是同时存在多个主键,只需一个不重复即可
- 关系表的外键
外键用于维护表与表之间的关系
- 一对多:如果想在表A中关联表B,只需要在表A的字段中加上表B的主键作为外键
- 多对多:通过一个中间表,维护两个一对多的关系即可
- 一对一:和一对多类似,可以把一个大表中一些经常查询的信息拆分出来,并设置一对一关系,从而加快查询速度
- 关系表的索引
索引用于对记录进行预排序,从而加快查询速度
通过唯一索引可以增加唯一性约束
SQL语法
- 语法特点
不区分大小写
查询数据SELECT
- 查询表中的所有列
SELECT * FROM table_name;
SELECT表示一次查询,*表示所有字段
FROM [table_name]指出在哪个表中查询
- 条件查询
SELECT * FROM table_name WHERE condition;
SELECT * FROM table_name WHERE condition1 AND condition2;
SELECT * FROM table_name WHERE condition1 OR condition2;
SELECT * FROM table_name WHERE NOT condition;
优先级:NOT > AND > OR,可以加小括号改变条件运算顺序
条件表达式:
> | < | = | >= | <= | <> | LIKE |
---|---|---|---|---|---|---|
大于 | 小于 | 等于 | 大于等于 | 小于等于 | 不等于 | 使用通配符 |
- 投影查询
即只查询表中的特定列
SELECT col1, col2 FROM table_name;
SELECT col1, col2 id FROM table_name;
可以在列名后面加上一个别名
- 排序
默认从低到高,使用DESC反序
SELECT * FROM table_name ORDER BY col1, col2;
SELECT * FROM table_name ORDER BY col1, col2 DESC;
- 分页显示
从第i个记录开始取(i从1开始),最多取出n条(可能少于n或为空),(i, n+i]
SELECT * FROM table_name LIMIT n OFFSET i;
SELECT * FROM tbale_name LIMIT i, n;
- 聚合查询
可以用COUNT函数查询关系表的行数
SELECT COUNT(*) FROM table_name;
SELECT COUNT(*) num FROM table_name;
查询的结果仍然是一个表,只有一个字段"COUNT(*)"(一般加上别名),和一个记录N(行数)
聚合函数:
SUM() | AVG() | MAX() | MIN() |
---|---|---|---|
只能用于数值类型,和 | 只能用于数值类型,平均值 | 最大值 | 最小值 |
分组:
SELECT id, COUNT(*) num FROM table_name GROUP BY id;
可以先将记录分组,然后再做聚合统计(比如样例中每个id的记录数)
- 多表查询
SELECT * FROM table1 t1, table2 t2;
会产生M*N条查询
- 连接查询
也是一种多表的查询,但是是直接把另一个表的其中几个字段加入到当前的表中
SELECT *, t2.name FROM table1 t1
INNER JOIN talb2 t2
ON t2.id == t1.t2_id;
还有**[RIGHT/LEFT/FULL] OUT JOIN**等连接方式
插入数据INSERT
- 插入记录
INSERT INTO table_name (col1, col2) VALUES
(val1, val2),
(val3, val4);
更新数据UPDATE
- 更新记录
UPDATE table_name SET col1=val1, col2=val2 WHERE condition;
删除数据DELETE
- 删除记录
DELETE FROM table_name;
DELETE FROM table_name WHERE condition;
管理 MySQL
- 登录mysql-client
mysql -u[username] -p
- 退出myql
EXIT;
- 查看所有用户
其实就是mysql数据库user表的user和host字段
SELECT user, host FROM mysql.user;
- 设置初始root用户密码
- 创建用户
CREATE USER '[name]'@'[ip]' IDENTIFIED BY '[password]'
- 显示所有数据库
SHOW DATABASES;
- 创建数据库
CREATE DATABASE dbname;
- 删除数据库
DROP DATABASE dbname;
- 操作数据库
USE name;
- 显示所有关系表
SHOW TABLES;
- 查看表结构
DESC table_name;
- 创建表
CREATE TABLE table_name;
CREATE TABLE table_name(
col type features
);
- 删除表
DROP TABLE table_name;
- 在表中添加列
ALTER TABLE [table_name] ADD COLUMN [col_name] [type] [features]
- 在表中删除列
ALTER TABLE [table_name] DROP COLUMN [col_name]
GORM
- 什么是ORM
Object Relation Mapping对象关系映射,也就是将程序中送到的对象(类)映射到数据库的关系表上
-
什么是GORM
-
连接数据库
db, err := gorm.Open("mysql", "root:root@(localhost:3306)/db_name?charset=utf8mb4&parseTime=True&loc=Local")
- 关闭数据库
db.Close()
GORM增删查改
type Student struct{
Name string
Age int
}
var student Student
var students []Student
- 创建表
db.AutoMigrate(&Student{})
就可以在数据库中创建一个字段和Student中对应的表
- 插入记录
db.Create(&Student{Name: "name", Age: 18})
db.Create(&student)
db.Create(&students)
db.Model(&Student{}).Create([]map[string] interface{}{
{Name: "name", Age: 18},
})
- 查询记录
// 第一条记录(主键升序)
db.First(&student)
db.First(&student, 1) // id=1
db.First(&student, []int{1, 2, 3})
db.First(&student, "Age = ?", 18)
// 获取一条记录
db.Take(&student)
// 最后一条记录
db.Last(&student)
// 查询全部记录
db.Find(&students)
- 条件查询
Where可以加查询条件
- 可以加上IN、LIKE、AND、BETWEEN等
- 可以用struct和map查询
db.Where("Name = ?", "zhiyu").Find(&students)
Not和Or方法
db.Not("Age = ?", 18).Find(&students)
db.Where(...).Or(...).Find(&students)
Select只检索出特定字段
db.Select("name", "age").Find(&students)
Order方法指定排序方式
db.Order("age DESC, name").Find(&students)
同样支持Limit&Offset和Group By
- 更新记录
db.Model(&student).Update("Age", 19)
- 删除记录
db.Delete(&student)
GORM约定
- 主键
默认使用ID作为表的主键
如果需要设置其他的主键,就用primaryKey标签
type User struct {
ID string
UUID string `gorm:"primaryKey"`
Name string
Age int
}
- 表名
默认是蛇形命名法(小写+下划线)
通过实现Tabler接口可以自定义
type Tabler interface {
TableName() string
}
// user -> user_profile
func (User) TableName() stromg {
return "user_profile"
}
- 列名
默认也是蛇形命名法
type User struct {
ID string
UUID string `gorm:"column:universally_unique_identifier"`
Name string
Age int
}
- 时间戳
直接在结构体中加指定字段
CreatedAt:创建时间
UpdatedAt:更新时间
DeletedAt:删除时间
// gorm.Model
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
type User struct {
gorm.Model
ID string
UUID string
Name string
Age int
}
gorm.Model会直接将其中的字段嵌入到User中,也可以用embeded标签嵌入其他的结构体
- 权限控制
控制只读、只写、只创建、只更新或忽略等
- 字段标签
标签名 | 描述 |
---|---|
column | 列名 |
type | 列数据类型 |
primaryKey | 主键 |
unique | 唯一,不可重复 |
default | 默认值 |
not mull | 不为空 |
autoIncrement | 自动增长 |
embeded | 嵌入字段 |
index | 索引 |
check | 创建约束 |