数据库知识入门
pg 数据库的模式 schema
可以看成是一个数据表的集合,不同的模式中可以存在相同的数据表名, 默认情况下的 schema 是 public
create schema my_schema;
create table my_schema.test(id int, name varchar(10));
drop table my_schema.test;
drop schema my_schema;
pg 数据库支持创建用户,但是创建用户后需要给用户分配权限
控制台常用命令总结:
什么是数据库
数据库是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。
. 保管数据的仓库
. 数据管理的方法和技术
总结: 是一个计算机软件,用来存储和管理数据的
数据表的概念
是一系列二维数组的集合,纵向的列(字段、属性、列),横向的行(记录、行 )
数据库类型的概念
数据类型决定了数据在计算机中的存储格式和方式
数据库系统的构成
1、数据库
2、数据库管理系统
3、 数据库应用程序
三者之间的关系: 
SQL 语言
SQL是对数据库进行查询和修改的操作语言
SQL语言包含4个部分:
DDL: DROP、CREATE、ALTER 等语句, 数据库定义语言, 一般用来定义删除 数据库等
DML: INSERT、UPDATE、DELETE 等语句, 数据库操作语言, 一般用来操作数据库
DQL: SELECT 语句, 数据库查询语言, 一般用来查询数据库
DCL: GRANT(授权)、REVOKE(移除权限)、COMMIT、ROLLBACK 等语
数据库控制语言,一般用来授权、撤销授权,分配角色、控制事物提交等
常用的数据库访问技术
1、JDBC:Java 数据库连接,Java 程序通过 JDBC 访问数据库,JDBC 是 Java 语言访问数据库的标准接口,它定义了一组用于执行 SQL 语句并返回结果集的接口。
2、ODBC:Open Database Connectivity,开放数据库连接,ODBC 是一个跨平台数据库接口,它定义了一组用于执行 SQL 语句并返回结果集的接口。
3、PDO:PHP 数据对象,PDO 是 PHP 语言访问数据库的标准接口,它定义了一组用于执行 SQL 语句并返回结果集的接口。
4、ADO.NET:.NET 框架中用于和数据库交互的类库
POSTGREASSQL 历史
数据库的创建和删除、更新
注意所有的SQL语句都要以 ; 结尾
数据库的创建
create database 数据库名;
如果要添加约束条件
create database 数据库名 with owner = postgres encoding = 'UTF8' connection limit = -1; (-1代表没有限制)
修改数据库
alert database 数据库名 rename to 新数据库名;
如果想修改数据库的其他的信息,只需要指定修改的 参数名 和 修改的名称
删除数据库
drop database 数据库名;
- 注意点: 如果删除或更新数据的时候遇到其他地方有活动连接,可以使用一下命令查出数据
SELECT pid, usename, datname, query
FROM pg_stat_activity
WHERE datname = '数据库名';
这个命令可以查出是谁在连接数据库
可以通过命令将其杀死
SELECT pg_terminate_backend (pid);
随后再执行删除或更新数据库命令
具体含义: blog.csdn.net/hezuijiudex…
数据表的修改
数据表对象的创建
create table 表名( 列名 数据类型 ,)
create table student (
id int,
name varchar(30),
birthday date,
score numeric(5,2)
);
- 注意: 创建表是通过 create table 语句实现的,字段名后面接上类型, 如果有长度的话可以要写在()中
修改数据表的名称
alter table 数据表名 rename to 新表名;
alter table student rename to student1;
修改数据表的字段名称
alter table 数据表名 rename column 旧字段名 to 新字段名;
alter table student1 rename column name to stu_name;
向表中添加字段
alter table 数据表名 add column 字段名称 int;
alter table student1 add column address varchar(200);
删除表中的字段
alter table 数据表名 drop column 字段名称;
alter table student1 drop column birthday;
修改表中数据的类型
alter table 数据表名 alter column 字段名称 type 新类型;
alter table student1 alter column name type varchar(40);
删除一个数据表
drop table 数据表名; // 这种方式如果数据表不存在或则已经被删除,会报错
drop table if exists 数据表名; // 这种方式会先判断是否存在
操作数据库
create database db_xiao;
create database db_xiao1 with owner = postgres encoding = 'utf-8';
alter database db_xiao1 rename to db_1;
alter database db_xiao2 connection limit 20;
drop database db_xiao;
-- 查询数据的活动连接的pid
SELECT pid, usename, datname, query
FROM pg_stat_activity
WHERE datname = 'db_xiao';
-- 删除数据的连接
SELECT pg_terminate_backend (3185);
操作数据库表
create table student (
id int,
name varchar(30),
birthday date,
score numeric(5,2)
);
-- 修改表的名称
alter table student rename to student1;
-- 修改表中列的名称
alter table student1 column rename id to bh;
-- 修改数据表中数据的类型
alter table student1 alter column name type varchar(40);
-- 删除一个字段
alter table student1 drop column birthday;
-- 添加一个字段
alter table student1 add column address varchar(200);
-- 删除一个数据表, 这种方式删除,如果数据表不存在或则已经被删除会报错
drop table student1;
-- 可以使用下面的方式删除, 他会先判断数据表是否存在
drop table if exists student1;
postgresql 常用的数据类型介绍
数值类型
- 整数类型
SMALLINT // 小范围整数, 取值范围: -32768 ~ 32767
INT // 普通大小整数 -2147483648 ~ 2147483647
bigint
...
- 浮点数类型
REAL // 6位十进制数字精度
NUMERIC(m, n) // 任意精度类型, 这种类型需要两个参数(5, 2),可以存储的数值长度为5位, 保留两位小数点,注意小数点(.)是不占长度的,在使用 numeric 时,注意如果数值长度超过了数据精度,数据库会进行四舍五入
float
...
日期与时间类型
在 postgresql 中,常用日期类型有:
TIME : 只用于一日内时间, 8个字节, 举例: 10:05:05 , 只记录了时分秒
DATE : 只用于日期, 4个字节, 举例: 2018-01-01 , 只用于日期
TIMESTAMP : 用于日期和时间, 8个字节, 举例: 2018-01-01 10:05:05 , 日期和时间
insert into temp1 values ('10:05:05', '2015-06-02', '2016-09-08 10:49:00');
字符串类型
CHAR(n) / CHARACTER(n): 固定长度字符串, 不足补空白
VARCHAR(n) / CHARACTER VARYING(n): 可变长度字符串,有长度的限制, 长度不够不会补足空白
TEXT: 不限制长度, 变长字符串
create table temp(
x smallint,
y int,
z real,
n numeric(5,2)
);
insert into temp values (2, 3, 2.55, 6.88);
alter table temp rename x to a;
insert into temp values (3, 4, 3.333, 6.998); -- 会四舍五入
select * from temp;
create table temp1(
t time,
d date,
tm timestamp
);
select * from temp1;
insert into temp1 values ('10:05:05', '2015-06-02', '2016-09-08 10:49:00');
create table temp3(
ch char(10),
vch varchar(30),
t text
);
insert into temp3 values ('事事如意', '事事顺心', '万事可乐');
select concat('(', ch ,')') , concat('(', vch , ')'), concat('(', t, ')') from temp3;
postgreSql 运算符的介绍
算术运算符
加 + 减 - 乘 * 除 / 求余 %
select 3+2, 3-1, 3*8, 4/1, 5%3;
比较运算符
= : 等于
<>(!=) : 不等于
= : 等于
<>(!=) : 不等于
> : 大于
< :小于
>= : 大于等于
<= : 小于等于
LEAST : 在有两个或则多个参数时, 返回最小值
GREATEST : 在有两个或则多个参数时, 返回最大值
BETWEEN AND : 判断一个值是否在两个值之间
IN : 判断一个值是否在指定的值列表中, 也有 not in 这种写法,判断一个数不在一个数中
LIKE : 通配符匹配, 主要用来做一个模糊匹配 , 也有 not like 这种写法
在 postgersql 数据库中 null 值与任何一个数比较都为null , 字符串与字符串比较会默认为字符串比较, 如果一个字符串和一个数字比较, 则会默认将字符串转换为数字进行比较。
select 3+2, 3-1, 3*8, 4/1, 5%3;
select 1= 0, '2'=2, 'b'='b', null = null, null =1;
select 'good'<>'god', 1<>2, 2>1, 4!=4, 2>=1, 1>=1;
select 2 between 1 and 3, 3 between 1 and 6, 2 between 7 and 9;
select 2 in (2,3,4), 3 in (5,6,7), 2 not in (4,5);
-- % 通配符代表 0 - 任意个字符, 下划线通配符通常代表匹配一个字符
select 'abc' like '%a', 'abc' like '_b_', 'abc' not like '%d';
create table times (
id int primary key,
time1 time,
time2 time,
time3 time
);
insert into times values(1, '10:20:33', '10:20:40', '10:20:50');
select * from times;
-- 使用 greatest(查询数据中最大的值) 和 least(查询数据中最小的值) 方法
select id ,greatest(time1, time2, time3) as maxval, least(time1, time2, time3) as minval from times;
逻辑运算符
NOT (逻辑非) 取反操作:
AND (逻辑与) 并且的关系:
OR (逻辑或)或的关系:
-- 数据库中的 1 和 y 是真, 0 和 n 是假
-- not 操作运算符
select not 'n', not '1', not 'n', not 'y';
-- and 操作运算符 (且的关系)
select '1' and 'y', '1' and '0', '0' and 'n';
-- or 操作运算符 (或的关系)
select '1' or 'y', '1' or '0', '0' or 'n';
运算符的优先级
加上 () 会提升优先级
PostgreSQL 函数、索引和视图
在工作中我们会经常遇到这些函数, 但并不是只有这些函数,如果需要查看其他方法,可以查找资料
PostgreSQL 常用函数介绍
-
函数的作用 封装一些方法,方便我们使用
-
常用的数值函数
- AVG() 返回某列的平均值
- COUNT() 返回某列的行数
- MAX() 返回某列的最大值
- MIN() 返回某列的最小值
- SUM() 返回某列值的和
create table employee(
id int primary key,
gender varchar(6),
salary real,
hiredate date
);
insert into employee values (1, 'female', 2000.11, '2023-01-21');
insert into employee values (2, 'male', 9000.11, '2023-01-21');
insert into employee values (3, 'male', 8000.11, '2023-01-21');
insert into employee values (4, 'female', 1000.11, '2023-01-21');
select * from employee;
-- 查询某列的最大值和最小值
select max(salary), min(salary) from employee;
-- 返回某列的平均值
select avg(salary) from employee;
-- 返回某列的行数
select count(salary) from employee;
-- 返回某列值的和
select sum(salary) from employee;
- 常用的字符串函数
- LENGTH() 返回字符串长度
- CONCAT(S1, S2, ...) 字符串合并函数
- LTRIM(S)/ RTRIM(S) / TRIM(S) 去除字符串空格空格函数
- REPLACE(S, S1, S2) 字符串替换函数
- SUBSTRING(S, n, LEN) 字符串截取函数, 获取子串函数
- UPPER(S)/ LOWER(S) 字符串大小写转换函数
create table employee(
id int primary key,
gender varchar(6),
salary real,
hiredate date
);
insert into employee values (1, 'female', 2000.11, '2023-01-21');
insert into employee values (2, 'male', 9000.11, '2023-01-21');
insert into employee values (3, 'male', 8000.11, '2023-01-21');
insert into employee values (4, 'female', 1000.11, '2023-01-21');
alter table employee add column name varchar;
update employee set name = '张三' where id =1;
update employee set name = '德里不饶' where id =2;
update employee set name = '张三疯' where id = 3;
update employee set name = '不回人' where id =4;
select * from employee;
-- 查询某列的最大值和最小值
select max(salary), min(salary) from employee;
-- 返回某列的平均值
select avg(salary) from employee;
-- 返回某列的行数
select count(salary) from employee;
-- 返回某列值的和
select sum(salary) from employee;
-- 字符串常用函数
-- length
select name , length(name) from employee;
-- concat, 可以将多个字段的值连接到一起展示
select name, salary, gender, concat(name , salary, gender) from employee;
- 常用的日期和时间函数
- EXTRACT (type FROM d) : 获取日期指定值函数
- CURRENT_DATE : 获取当前日期函数
- CURRENT_TIME : 获取当前时间函数
- NOW() : 获取当前日期和时间函数
-- current_date 当前日期, current_time 当前时间, now 当前日期和时间
select current_date, current_time, now();
-- extract(type from d) 获取日期中的指定值
select name, gender, extract(year from hiredate), extract(month from hiredate),
extract(day from hiredate) from employee;
PostgreSQL 自定义函数
- 创建函数的语法
基本语法格式:
CREATE FUNCTION // 声明创建函数
add(integer, integer) // 定义函数名称,参数类型
RETURNS integer // 定义函数返回值类型
AS 'select $1 + $2;' // 定义函数体
LANGUAGE SQL // 定义函数使用的语言名字
RETURNS NULL ON NULL INPUT; // 定义参数为null 时处理情况
- 函数的创建
create function add(integer, integer) returns integer
as ' select $1 + $2' -- 函数体, 在函数体中引用参数的形式是用 $, $1 代表第一个参数
language sql
returns null on null input;
select add(1, 2);
create or replace function concat_test(real, varchar, date) returns varchar
as ' select $1 || $2 || $3;' -- 在postgresql 数据库中 || 就代表将两个拼接到一起的意思
language sql
returns null on null input; -- 处理为null时的情况
select * from employee;
select concat_test(salary, name, hiredate) from employee;
-
注意: or replace 的含义是, 如果数据库中存在同名的自定义函数,会进行覆盖
-
函数的删除
// 删除一个函数的时候要带上这个函数名和函数的参数类型,就是你声明的时候怎样就是怎样
drop function concat_test(real, varchar, date);
PostgreSQL 数据库索引介绍
- 索引的作用
提高数据的检索速度, 类似于目录的作用,当数据非常大的时候,很有用
-
索引的分类
- B-tree索引 : 适合处理那些能够按顺序存储数据
- Hash 索引: 只能处理简单的等于比较, 性能不是特别好
- GiST索引: 一种索引架构
- GIN索引: 反转索引, 处理包含多个值的键,数据表中的某一个列上有一个值是数组类型
-
索引的创建和删除
通过 create on 这种语法创建的索引默认是b-tree索引,如果需要其他类型的索引,需要使用其他语法
- 创建: create index 索引名称 on 表名(列名) -- 在某个表中的某个字段上添加索引
- 删除: drop index 索引名称;
-- 创建一个索引
create index name_index on employee(name); -- 默认是 B-tree索引
-- 删除一个索引
drop index name_index;
- 使用索引的优点和缺点
- 优点: 提高数据的查询速度,加速表与表之间的连接
- 缺点: 创建和维护索引需要耗费时间,在实际开发中不能过多也不能过少,需要占用磁盘空间
PostgreSQL 数据库视图介绍
-
视图的含义
数据库中,视图的作用和表的作用很类似, 视图是从一张表或多张表中导出的数据内容, 数据库中视图是与一张表或多张表相关联的, 但是在数据库中并没有为视图存数据,只是存储了视图的定义, 只有在使用视图的时候,视图内部会去查询关联表中的数据,将查询出来的数据为我们展示
简单的理解: 就是把查询语句封装成另一个类似表(视图), 后期查询这个表就和得出这个封装的查询语句内容
-
视图的创建
-- 创建一个视图
create view v_temp_dev as select name, gender, salary, hiredate from employee where id = 4 order by salary desc;
-- 查询视图, 视图和表类似
select * from v_temp_dev;
- 视图的删除
drop view v_temp_dev;
-
视图的作用
-
简单化
将复杂的查询语句封装起来,只需要查询视图,不需要再写一堆查询语句。
-
安全性
视图可以屏蔽关键的表名等, 比如在和其他公司合作的时候,只需要提供视图,其他公司可以获取数据,但是不能够获取到真实的表名,字段等。
-
逻辑数据独立性
当查询逻辑发生该改变的时候,只需要改变视图的结构就行,对于上层的业务系统不需要改变
-
postgresql 数据库操作和数据表约束介绍
简单数据插入操作
-
向单表中插入数据
insert into 数据表名 values ();
-
向指定字段插入数据
insert into 数据表名 (字段1, 字段2, 字段3) values ();
-- 向数据库中添加指定的值
create table student(
id integer,
name varchar(10),
age integer,
sex varchar(2)
);
select * from student;
-- 用这种方式插入值要和字段的顺序相对应,否者会插入null值
insert into student values (1, '张三', 10, '男');
-- 向指定的字段中添加值
insert into student (id, age, name) values (2, 20, '牛马');
批量数据插入操作
- 使用 insert into 语句向数据表中批量添加数据,写法和插入一样,在后面写上多个数据组
-- 批量向数据表中添加数据
insert into student values (5, '张三', 10, '男'), (6, '张三', 10, '男'),(7, '张三', 10, '男');
insert into student (id, name, age, sex) values (8, '里斯', 30, '女'),(9, '琼斯', 30, '女');
- 使用 select 查询批量向数据表中添加数据
- 注意: 这种方式,查询出来的数据字段一定要在插入表中有字段存在,否者会报错
-- 使用select向表中插入数据,就是通过select查询出数据后再插入表中
create table student_new(
id integer,
name varchar(10),
age integer,
sex varchar(2)
);
select * from student_new;
delete from student_new;
-- 向表中添加数据, 将student表中的值查询出来后插入新表
insert into student_new select * from student;
insert into student_new (id, name) select id, name from student;
数据更新操作
语法: update 数据表名 set 字段名 = 值 where 条件;
update student set birthday = '2023-04-09' where name = '张三';
-- 将指定结果更新到对应字段中
update student set age = '50' + 50 where id = 2;
注意: 如果不用where指定条件,则会批量更新数据表中的数据, ⭐️ 这个操作非常危险,⚠️, 使用前注意是否需要
数据删除操作
⚠️ 数据库的删除操作是很危险的,实际操作过程中谨慎使用
- 数据删除操作
-- 根据条件删除数据
delete from student where id = 8;
delete from student where age between 10 and 20; // 可以换成其他的表达式
-- 删除所有的数据
delete from student;
- truncate 数据清空操作
truncate table 表名;
- delete 与 truncate 之间的区别
pg数据表主键和外键的介绍
主键就是数据表中唯一标识一条记录的主要方式, 主键是唯一值, 不可能重复
- 如何定义主键约束
两种方式:
1、 在定义的时候直接在字段后面添加 primary key
2、 使用 constraint 定义主键约束
方式一: 列级约束, 不能指定主键的名称
create table emp(
id int primary key, -- 创建主键的方式 1, 直接在定义的时候写
name varchar(10),
salary numeric(5,2)
);
方式二: 表级约束, 可以指定主键的名称
create table emp1 (
id int,
name varchar(10),
salary numeric(9, 2),
constraint 主键名称 primary key(主键字段)
);
create table emp1 (
id int,
name varchar(10),
salary numeric(9, 2),
constraint pk_emp1 primary key(id)
);
- 如何定义外键约束
⭐️ 注意: 外键创建的时候, 必须先创建被引用的表, 否则会报错
语法: constraint 外键名称 foreign key (外键字段) references 被引用表(被引用字段), 注意这个被引用的表中的字段一定要是主表中的主键
-- 创建外键约束
create table dependent(
id int primary key,
name varchar(10)
);
insert into dependent values (1, '测试部');
insert into dependent values (2, '开发部');
select * from dependent;
create table empl3(
id int primary key,
name varchar(10),
salary numeric(9, 2),
deptId int,
constraint fk_emp3_dept foreign key (deptId) references dependent(id)
);
insert into empl3 values (1, '张三', 2000, 1);
insert into empl3 values (2, '李四', 3000, 3); -- 会报错, 原表中不存在ID等于3
insert into empl3 values (2, '李四', 3000, 2);
select * from empl3;
⭐️ 注意: 如果删除有外键引用的数据(可以理解为该数据(部门)下有数据)不能随意删除, 会报错
delete from dependent where id = 1; -- empl3 表中有数据引用了 id = 1 的数据, 所以会报错
- 主键约束和外键约束的作用
- 主键约束: 唯一标识一条记录, 提高检索效率
- 外键约束: 保证数据完整性(不能随意删除主表数据,如果有引用会报错), 提高检索效率
pg数据表非空约束、默认值约束、唯一值约束介绍
-
如何定义非空约束
-
如何定义唯一约束
-
如何定义默认值约束
-- 非空约束
create table emp4 (
id int primary key,
name varchar(10) not null,
salary numeric(9, 2)
);
-- 唯一约束
create table emp5(
id int,
name varchar(10) not null,
phone varchar(11) unique,
salary numeric(9, 2),
constraint emp_pk primary key(id)
);
-- 唯一约束和主键的区别: 主键不能为空也是唯一值,并且只有一个, 唯一值可以为空,并且一个表中可以有多个
-- 默认值约束
create table emp6(
id int,
name varchar(10) not null,
phone varchar(11) unique,
salary numeric(9, 2) default 2000,
constraint emp_pk2 primary key(id)
);
insert into emp6 values (2, 'zh', '12222222822'); -- 最后的salary 会默认补上 2000
select * from emp6;
- 非空约束、 唯一约束、 默认值约束的作用
- 维护数据的完整性 (有些值可能就需要有默认值)
- 在业务层面保证数据正确性 (有些值不能为空)
数据查询操作
前提条件,初始化数据:
create table dept (
d_no int primary key, -- 部门编号
d_name varchar(30), -- 部门名称
d_location varchar(300) -- 部门地址
);
insert into dept values (10, '开发部', '北京市海淀');
insert into dept values (20, '测试部', '北京市东城');
insert into dept values (30, '销售部', '上海市');
insert into dept values (40, '财务部', '武汉市');
insert into dept values (50, '运维部', '广州市');
insert into dept values (60, '集成部', '南京市');
create table employee(
e_no int primary key,
e_name varchar(30) not null,
e_danger char(2) not null,
dept_no int, -- 所在部门编号
e_job varchar(50) not null,
e_salary numeric(9, 2),
e_hireDate date,
constraint fk_emp_deptno foreign key(dept_no) references dept(d_no)
);
insert into employee values (100, '赵德刚', 'f', 10, '开发工程师', 5000, '2001-01-09');
insert into employee values (101, '大宝', 'f', 10, '开发工程师', 5000, '2004-07-09');
insert into employee values (102, '牛皮鲜', 'f', 10, '开发经理', 5000, '2001-01-09');
insert into employee values (103, '花枝', 'f', 20, '测试工程师', 5000, '2013-01-09');
insert into employee values (104, '的船', 'm', 20, '测试工程师', 5000, '2004-01-09');
insert into employee values (105, '牛二', 'f', 20, '测试经理', 5000, '2001-01-09');
insert into employee values (106, '赵三', 'm', 30, '销售人员', 5000, '2003-01-09');
insert into employee values (107, '马平', 'f', 30, '销售人员', 5000, '2001-01-09');
insert into employee values (108, '刘合', 'm', 30, '销售经理', 5000, '2004-01-09');
insert into employee values (109, '李刚', 'f', 30, '销售高级经理', 5000, '2013-01-09');
insert into employee values (110, '闻中', 'f', 40, '财务人员', 5000, '2013-01-09');
insert into employee values (111, '钱莫', 'm', 40, '财务人员', 5000, '2012-01-09');
insert into employee values (112, '林工', 'f', 40, '财务经理', 5000, '2012-01-09');
insert into employee values (113, '刘川枫', 'f', 10, '实习工程师', null, '2023-05-09');
insert into employee values (114, '秋名山', 'f', null, '实习工程师', null, '2023-06-09');
insert into employee values (115, '爆炸头', 'f', null, '实习工程师', null, '2023-01-09');
简单查询操作
- sql 查询语言介绍
-
简单数据查询操作
-
为表和字段指定别名
select * from dept;
select d_no, d_name, d_location from dept; -- 通过穷举的方式来进行查询
-- 也可以通过表名.字段名的方式来查询, 在真实查询中,from 后面可能跟了很多的表,通过这种饭方式可以区分
select dept.d_no, dept.d_name from dept;
-- 如果表名太长我们可以为他指定别名, 通过 as 来建立别名, 在指定表别名的时候 as 不是必须的,可以省略
select d.d_no, d.d_name from dept as d;
-- 也可以为字段取别名, 通过 as 关键字,as 关键字也可以省略, 取了别名,查询出来的名字也随之改变
select d.d_no as a, d.d_name b from dept d;
单表指定查询操作
- 查询指定记录
- in 关键字查询
- between and 关键字范围查询
- like 模糊查询
-- 查询指定记录
select e_no, e_name, e_salary from employee where e_salary < 5000;
select e_no, e_name, e_salary from employee where e_salary = 5000;
select e_no, e_name, e_salary from employee where e_salary > 5000;
-- 使用 in 关键字
select e_no, e_name, dept_no from employee where dept_no in (20, 30);
select e_no, e_name, dept_no from employee where dept_no not in (20, 30);
-- between 关键字
select e_no, e_name, e_salary from employee where e_salary between 5000 and 8000;
-- like 关键字 % 代表一个或多个字符, _代表一个字符
select e_name from employee where e_name like '赵%';
单表指定条件复杂查询
-- 检索 null 值, 在数据库中使用 is null 来检索null
select * from employee where e_salary is null;
-- 也可以使用 is not null 来检索 非null值
select * from employee where e_salary is not null;
-- 注意以下写法是错误的,在数据库中 null 不与任何值相等
select * from employee where e_salary = null;
-- 使用 and 和 or 实现多条件的查询
select e_no, e_name, e_danger, dept_no from employee where e_danger = 'f' and dept_no =10;
select e_no, e_name, e_danger, dept_no from employee where e_danger = 'f' and dept_no in (10, 20);
select e_no, e_name, e_danger, dept_no from employee where e_danger = 'f' or dept_no =10;
-- order by 排序操作
select * from employee order by e_salary; -- 默认是升序 asc
select * from employee order by e_salary desc;
-- 以下的含义是,如果第一个排序值是一样的,则按第二个字段排序
select * from employee order by e_salary, e_hiredate desc;
-- 注意: 如果我们排序时字段值有null值,数据库默认时 nulls last, 也可以改成 nulls first;
select * from employee order by e_salary nulls first;
-- 限制查询条数
select * from employee limit 5;
-- 对查询值中间一部分数据感兴趣,可以使用 offset (代表前面忽略多少条数据)用于分页展示操作
select * from employee limit 5 offset 5; -- 从第6条开始
多表连接查询操作
⭐️ 注意: 内连接查询不会将匹配为null的值查询出来
- inner join 查询操作
- left join 查询操作
- right join 查询操作
select * from dept;
select * from employee;
-- 当我们查询 employee 时,关联的外键,只能看到关联的字段值,不直观
-- 简单的内连接查询操作,这种方式称为隐式内连接查询
select e_no, e_name, dept_no, d_no, d_name, d_location from employee, dept where dept_no = d_no;
-- inner join on 内连接查询操作, 这种方式和上面的查询结果一致, 这种方式称为显示内连接查询
select e_no, e_name, dept_no, d_no, d_name, d_location from employee
inner join dept on dept_no = d_no;
-- 以上两种方式不会匹配出为 null 的数据, 如果要查询部门详细信息同时查出为 null 的数据,使用 left join on
select e_no, e_name, dept_no, d_no, d_name, d_location from employee
left join dept on dept_no = d_no;
-- left join on 方式会将左表中匹配和不匹配的都查询出来, 如果不匹配会将右表中的数据展示为 null
-- left outer join on 和 left join on 作用是一样的,只是写法不同
select e_no, e_name, dept_no, d_no, d_name, d_location from employee
left outer join dept on dept_no = d_no;
-- 同时也可以拼接其他的条件
select e_no, e_name, dept_no, d_no, d_name, d_location from employee
left join dept on dept_no = d_no where d_no = 10;
-- 右连接查询和左连接查询是一样的
子查询操作
子查询是一个查询语句嵌套在另一个查询语句内部的查询,会将内部的查询叫做子查询,将外部查询叫做主查询, 计算这条查询的时候,数据库会将子查询先执行,然后把结果返回给主查询作为过滤条件,主查询再计算。
还存在其他的子查询操作符, 需查资料
- exists 子查询操作
- in 子查询操作
- 标量子查询操作
select * from employee;
select * from dept;
-- exists 有点像 js 中的 if 判断中的条件
select * from employee where exists (
select d_no from dept where d_name = '开发部'
);
-- 上面的含义是, 如果()中查询的数据值为 true 那他就会执行外部的查询语句
select * from employee where exists (
select d_no from dept where d_name = '开发部' and d_no = dept_no
);
-- 上面执行逻辑是前面一部分查询为true后,exists 会将循环查询找到 d_no = dept_no 的数据, 可以使用 not exists
select * from employee where not exists (
select d_no from dept where d_name = '开发部' and d_no = dept_no
);
-- in 子查询中 in 判断字段值是否在某些固定值中,这里的固定值集合改变成查询语句
select * from employee where dept_no in (
select d_no from dept where d_name = '开发部'
); -- 会查出所有 dept_no 在 查询出来的 d_no 中的数据
select * from dept;
-- 标量子查询 , || 作用是拼接两个数据
select e_no, e_name, (select d_name || ' ' || d_location from dept
where dept_no = d_no
) as address from employee;
-- 标量子查询:将子查询的内容作为查询结果展示
查询结果集合并操作
⭐️ 注意: 在工作中我们要判断是否有有重复的情况,如果评估多表连接没有重复的情况,如果有,那么我们尽量使用 union all 否则尽量使用 union, 同时union和union all 连接的两张表查询结果字段要保持一致,如果不一致会报错(工作中可能会从多张表中查询出数据),如果一张表多出了字段,另一张表没有,我们可以使用 null 占位
- union all 对查询结果进行合并
- union 对查询结果进行合并
-- 使用 union all 操作符进行合并操作, 这种方式只是简单的将两条查询语句的结果进行拼接
select e_no, e_name, dept_no, e_salary from employee where dept_no in (10, 20)
union all
select e_no, e_name, dept_no, e_salary from employee where e_salary < 7000;
-- 使用 union 操作符进行合并操作,这种方式可以去重
select e_no, e_name, dept_no, e_salary from employee where dept_no in (10, 20)
union
select e_no, e_name, dept_no, e_salary from employee where e_salary < 7000;
- 两者的区别
- union : 可以去重, 查询速度比 union all 慢
- union all : 不去重, 查询速度比 union 快, 只是简单的将查询的结果拼接在一起
用户权限管理
pg 中没有严格的区分 用户和角色的概念
创建用户
使用 命令
create user 用户名称 with password '密码';
注意: 刚创建好的用户是没有权限的,我们需要切换到管理员的用户,一般是 postgres , 我们在进入数据库时候 如果不指定数据库,他默认会找和用户名一样名字的数据库,如果没有会报错
psql -U 用户名 -d 数据库名
分配权限
1、 先进入管理员用户
数据库授权,赋予指定用户指定数据库的权限
语法:
grant all privileges on database 数据库名 to 用户名;
grant all privileges on database mydb to test;
上面操作执行后,用户还是没有读写数据库的权限,需要给用户授权, 需要进入到指定数据中分配权限
语法:
grant all privileges on all tables in schema 模式 to 用户名;
grant all privileges on all tables in schema public to test;
REVOKE ALL PRIVILEGES ON TABLE table_name FROM role_name; (单个表权限)
通过以上不的步骤,test 用户就可以读写数据库了, 但是并没有其他的权限, 如果要有创建或则删除数据库或表的能力需要分配角色
-
删除用户和移除权限都要在管理员用户下操作
- 删除用户: drop user 用户名; -- 在删除前需要将分配的权限移除(需要在分配的数据库下操作)
- 移除权限: revoke all privileges on database 数据库名 from test;
分配角色
语法: alter role 用户名/角色名 with 角色属性;
如果要修改角色的属性,需要使用 alter role 角色名 with 角色属性; (同理用户也可以这样)
- pg 数据库中没有严格区分用户和角色的概念, 有一点注意,创建的角色是不具备登录的, 创建的用户是可以登录的
- 创建角色
语法: create role 角色名;
- 查询角色和用户
-- 查询角色
select * from pg_roles;
-- 查询用户
select * from pg_user;
删除角色和用户
⭐️ 注意: 删除角色和用户的时候, 一定要将该角色或用户身上绑定过的权限移除(包括一些属性、创建的表等), 否则会报错
// 语法
drop role 角色名;
drop user 用户名;