SQL 是 Structured Query Language 的缩写,意为“结构化查询语言”,是一种专门用于管理关系型数据库的编程语言。它被广泛应用于数据库的查询、更新、删除和插入等操作,以及数据的统计、分析和报表生成等方面。SQL 语言具有简洁、灵活、强大和通用等特点,是数据库管理和数据分析的重要工具。
SQL 语言的主要功能包括:
1. 定义数据库结构:可以通过 CREATE TABLE 语句来创建表格、索引和视图等数据库对象。
2. 查询数据:可以使用 SELECT 语句来查询表格中的数据,并可以使用各种聚合函数、排序和分组等操作来对数据进行统计和分析。
3. 更新数据:可以使用 INSERT、UPDATE 和 DELETE 语句来插入、更新和删除表格中的数据。
4. 控制权限:可以使用 GRANT 和 REVOKE 语句来授权和回收权限,以保护数据的安全性。
5. 事务处理:可以使用 EGIN、COMMIT 和 ROLLBACK 语句来实现事务的开始、提交和回滚等操作。
SQL 语言的应用范围非常广泛,几乎所有的关系型数据库管理系统都支持 SQL 语言,如 MySQL、Oracle、SQL Server、PostgreSQL 等。同时,SQL 语言也成为了数据库开发和数据分析领域的标准语言,被广泛应用于各种企业、机构和组织的数据管理和分析工作。
Mysql应该是现在学习资料最为全面,而且八股文最多的数据库了。所以我们选择PostSQL进行学习。
PostgreSQL(简称 PostSQL)是一个自由的开源对象 - 关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。它提供了相对于其他开放源代码数据库系统(如 MySQL 和 SQLite)以及专有系统(如 Oracle、Microsoft SQL Server 和 IBM DB2)的一种选择。PostgreSQL 支持多种编程语言和应用程序,并且可以处理各种类型的数据,包括文本、图像、音频和视频等。它具有强大的功能和灵活性,可以处理大规模数据集,并且可以快速地添加新的功能和模块。PostgreSQL 拥有一个庞大的社区,这个社区提供了大量的文档、教程和解决方案,使得 PostgreSQL 成为一种非常容易学习和使用的数据库管理系统。PostgreSQL 可以在各种操作系统上运行,包括 Windows、Linux 和 macOS 等。由于其不寻常的名字,有些人可能会停下来尝试拼读它,特别是那些把 PostgreSQL 拼读为 "PostgreSQL"。
这边为了不对操作系统有啥负担,建议还是使用docker进行安装
docker run -itd --name postgres -e POSTGRES_PASSWORD=1234 -p 5432:5432 -d postgre
#如果要设置用户名的话加上参数
-e POSTGRES_USER=[用户名]
#如果要设置密码的话加上参数
-e POSTGRES_PASSWORD=[密码]
连接上docker里面的postgreSqL
docker exec -it postgres bash
切换到postgres账户,如果使用root的话无法进入
su postgres
进入到数据库中:
psql
#如果一开始写了用户名的话就
psql -U [username]
以下是一些常用的快捷键:
\q 退出 PostgreSQL。
\l 显示所有的数据库
\c 数据库名 从一个数据库切换到另一个数据库
\d 查看表结构
\di 查看索引
\ds: 显示当前数据库中的所有表的关系。
\dl: 显示当前数据库中的所有列。
\dt: 显示当前数据库中的所有表的详细信息。
\du: 显示当前数据库中的所有用户和其权限。
\lp: 列出当前数据库中的所有过程。
\lo: 列出当前数据库中的所有外键。
\mi: 显示当前数据库中的所有成员。
\mj: 显示当前数据库中的所有 Journal 日志。
\ms: 显示当前数据库中的所有存储过程。
\mt: 显示当前数据库中的所有触发器。
\mu: 显示当前数据库中的所有用户权限。
\mv: 显示当前数据库中的所有视图。
\ow: 显示当前数据库中的所有预定义函数。
\pat: 显示当前数据库中的所有派生类型。
\pgr: 显示当前数据库中的所有过程。
\pi: 显示当前数据库中的所有接口。
\ps: 显示当前数据库中的所有存储过程。
\pt: 显示当前数据库中的所有触发器。
创建用户:
create user test_user;
创建数据库:
create database testdb;
对应的删除数据库:
drop database testdb;
进入到数据库中:
\c testdb
建表:
create table mytable(id int, name varchar(255));
查看表:
\d mytable;
删除表格:
drop table mytable;
#如果要删除多个表
drop table table1, table2;
在 PostgreSQL 数据库中,schema 是指在一个数据库内部创建的逻辑上的数据库,每个 schema 都有自己的命名空间,可以在同一个数据库内部创建多个 schema,每个 schema 可以包含不同的表、视图、存储过程等数据库对象。使用 schema 可以对数据库对象进行更好的组织和管理,同时也可以提高数据库的安全性和稳定性。
如果懂得C#的话,可以默认Schema是namespace。
创建schema
create schema myschema;
创建好 schema 之后,就可以在其中创建数据库对象,例如:
create table myschema.table(id int primary key, name varchar(20));
可以通过sql指令来查看下列的表格:
select * from myschema.table;
这时候如果要删除这个Schema的话:
drop schema myschema;
会出现这样的结果:
ERROR: cannot drop schema myschema because other objects depend on it
DETAIL: table myschema."table" depends on schema myschema
HINT: Use DROP ... CASCADE to drop the dependent objects too.
因此我们需要级联地删除,也就是顺便删除schema里面的所有对象
drop schema myschema cascade;
为数据库新增数据,这边postgresql和其他的数据库差别不大,都是用的insert into
#先创建一个表
CREATE TABLE EMPLOYER(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL,
JOIN_DATE DATE
);
#插入数据
INSERT INTO EMPLOYER(ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (1, 'Bob', 32, 'Beijing', 20000.00,'2001-01-01');
#设置一些Default属性
INSERT INTO EMPLOYER(ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (2, 'CC', 23, 'Shanghai', 20000.00, DEFAULT );
#插入多行
INSERT INTO EMPLOYER(ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (3, 'Dod', 25, 'Guangzhou ', 65000.00, '2007-02-03' ), (4, 'Eoe', 27, 'Shenzhen', 85000.00, '2011-11-11');
我们可以用Select指令来查看一下刚才插入的数据:
testdb=# select * from EMPLOYER;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
1 | Bob | 32 | Beijing | 20000 | 2001-01-01
2 | CC | 23 | Shanghai | 20000 |
3 | Dod | 25 | Guangzhou | 65000 | 2007-02-03
4 | Eoe | 27 | Shenzhen | 85000 | 2011-11-11
(4 rows)
这时候可以注意,postgresql对于大小写是不敏感的,所以后续会使用小写。
#根据条件筛选,删除某一列
testdb=# delete from employer where id = 1;
DELETE 1
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
(3 rows)
这时候可以看待id为1的那一行已经被删除了。
#删除整张表
Delect from company
在 PostgreSQL 数据库中,使用 DELETE 命令删除表时,不会自动释放表所占用的存储空间。相反,删除表只会删除表中的数据,而表结构和相关的索引、约束等对象仍然会保留在数据库中。
如果需要释放表所占用的存储空间,可以使用 DROP TABLE 命令:
drop table employer;
另外,如果表中的数据量较大,使用 DELETE 命令删除数据可能会导致性能问题。在这种情况下,可以使用 TRUNCATE 命令替代 DELETE 命令,例如:
truncate table employer;
Drop 和 Truncate 都是用于删除表的命令,但它们的作用和使用方式有一些不同。
1. 删除数据的范围不同:
Drop 命令会删除整个表,包括表结构和所有数据。而 Truncate 命令只删除表中的数据,不删除表结构。
2. 执行方式不同:
Drop 和 Truncate 都是 DDL 语句,执行后会自动提交。但是,Drop 命令是立即生效的,而 Truncate 命令在执行时会将数据放入回收站中,回收站中的数据可以在需要时进行恢复。
3. 影响的对象不同:
Drop 命令会删除表结构和所有相关的约束、触发器、索引等对象。而 Truncate 命令只删除表中的数据,不删除表结构和相关的对象。
4. 安全性不同:
Drop 和 Truncate 命令都需要谨慎使用,尤其是在没有备份的情况下。但是,Truncate 命令比 Drop 命令更安全,因为它只删除表中的数据,而不会影响表结构和相关对象。
5. 执行速度不同:
一般来说,Drop 命令的执行速度比 Truncate 命令快,因为 Drop 命令只需要删除表结构和相关对象,而 Truncate 命令需要删除表中的所有数据。
总结起来,Drop 和 Truncate 命令都有各自的用途和优缺点,需要根据具体情况选择合适的命令来删除表。
修改的方法是通过Update实现的,用法也很简单,如下
#通过where选择某一行,更新某一项
testdb=# update employer set salary = 100 where id = 3;
UPDATE 1
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
1 | Bob | 32 | Beijing | 20000 | 2001-01-01
2 | CC | 23 | Shanghai | 20000 |
4 | Eoe | 27 | Shenzhen | 85000 | 2011-11-11
3 | Dod | 25 | Guangzhou | 100 | 2007-02-03
(4 rows)
#更新很多项,并且非空项全部更新(因为没有加上筛选条件),这边注意,CC原本就没有join_date,所以这边没更新
testdb=# update employer set address = 'BeiJing', salary=100000;
UPDATE 4
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
1 | Bob | 32 | BeiJing | 100000 | 2001-01-01
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
(4 rows)
查询大多是通过Select加各种条件实现的,这边给一些简单的Demo
#如果要全选,就select *,但是如果只想选择对应的列就得都列出来
select ID, NAME, ADDRESS from EMPLOYER;
testdb=# select ID, NAME, ADDRESS from EMPLOYER;
id | name | address
----+------+----------------------------------------------------
1 | Bob | Beijing
2 | CC | Shanghai
3 | Dod | Guangzhou
4 | Eoe | Shenzhen
(4 rows)
# Where条件
# 这边可以用算数运算符进行判定
testdb=# select * from EMPLOYER where SALARY > 20000;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
3 | Dod | 25 | Guangzhou | 65000 | 2007-02-03
4 | Eoe | 27 | Shenzhen | 85000 | 2011-11-11
(2 rows)
#也可以用And or 或者not作为逻辑运算符号,比如
testdb=# select * from EMPLOYER where SALARY > 20000 and SALARY < 80000;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
3 | Dod | 25 | Guangzhou | 65000 | 2007-02-03
(1 row)
#也可以嵌套查询
testdb=# select * from employer where age > (select age from employer where salary > 65000);
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
1 | Bob | 32 | Beijing | 20000 | 2001-01-01
(1 row)
上面讲过了select * from table_name where 条件,这时候就是我们要筛选的条件。
往往我们筛选的条件会挺复杂的,因此SQL也会提供很多复杂的选择。
Like条件筛选匹配两种符号,百分号%和下划线_
其中,百分号表示的是一个或者多个字符,而_表现的只有一个位置
#原始的表如下
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
(3 rows)
#比如我们想筛选数据库中20几岁的人,那么就用%
testdb=# select * from employer where age like '2%';
ERROR: operator does not exist: integer ~~ unknown
LINE 1: select * from employer where age like '2%';
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
#这边需要用::text转一下
#使用%的话可以这么写
testdb=# select * from employer where age::text like '2%';
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
(3 rows)
testdb=# select * from employer where age::text like '2_';
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
(3 rows)
这边主要是因为年龄就两位,如果有两百岁的员工,那就没法用下划线筛选出来了。
Limit顾名思义,就是用于限制查询的数量,主要用于内容多的时候分页。我们先插入一些内容
这时候顺便引入一个概念,offset,偏移量。
比如我们有200页的内容,第一页只显示10行,就是
select * from table where [条件] limit 10;
那么我们要显示第二页的话就是
select * from table where [条件] limit 10 offset 10;
这个offset就不包括前面的,从第11行开始。
#原本的表格扩张如下
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
(5 rows)
#我们只筛选3行,并且还要从第二行开始
testdb=# select * from employer limit 3 offset 1;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
(3 rows)
排序,这个大家都很清楚了。一般来讲默认是Asc(升序),如果要降序的话就要加上Desc,我们直接来个例子
#原始的表格长这样
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
(5 rows)
#来个错误的案例,大家要注意,这边的order by是分开的,合在一起就错了。
testdb=# select * from employer orderby age;
ERROR: syntax error at or near "age"
LINE 1: select * from employer orderby age;
^
#这边就按照年龄正序排序,和asc一样,但是不写默认就是asc,
testdb=# select * from employer order by age;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
(5 rows)
#这边加上desc就是倒序排序了
testdb=# select * from employer order by age desc;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
2 | CC | 23 | BeiJing | 100000 |
(5 rows)
#当然不止如此,我们倒序排序之后还要根据薪资正序排序,就用逗号隔开
testdb=# select * from employer order by age desc, salary asc;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
2 | CC | 23 | BeiJing | 100000 |
(5 rows)
去除重复,就有点像是set的操作,直接上
testdb=# select * from employer;
id | name | age | address | salary | join_date
----+------+-----+----------------------------------------------------+--------+------------
2 | CC | 23 | BeiJing | 100000 |
4 | Eoe | 27 | BeiJing | 100000 | 2011-11-11
3 | Dod | 25 | BeiJing | 100000 | 2007-02-03
5 | Fof | 25 | Guangzhou | 65000 | 2007-02-03
6 | Gog | 27 | Shenzhen | 85000 | 2011-11-11
(5 rows)
#对哪一列去重就写哪一列
testdb=# select distinct salary from employer;
salary
--------
85000
65000
100000
(3 rows)