PostgreSQL 入门

PostgreSQL 入门

简介:

1. 是一个免费的对象-关系数据库服务器(ORDBMS)
2. PostgreSQL 的 Slogan 是 "世界上最先进的开源关系型数据库"。

ORDBMS 术语

- 数据库: 数据库是一些关联表的集合。

- 数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。

- 列: 一列(数据元素) 包含了相同的数据, 例如邮政编码的数据。

- 行:一行(=元组,或记录)是一组相关的数据,例如一条用户订阅的数据。

- 冗余:存储两倍数据,冗余降低了性能,但提高了数据的安全性。

- 主键:主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。

- 外键:外键用于关联两个表。

- 复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。

- 索引:使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。

- 参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件,目的是保证数据的一致性。

PostgreSQL 特征

- 函数:通过函数,可以在数据库服务器端执行指令程序。

- 索引:用户可以自定义索引方法,或使用内置的 B 树,哈希表与 GiST 索引。

- 触发器:触发器是由SQL语句查询所触发的事件。如:一个INSERT语句可能触发一个检查数据完整性的触发器。触发器通常由INSERT或UPDATE语句触发。 多版本并发控制:PostgreSQL使用多版本并发控制(MVCC,Multiversion concurrency control)系统进行并发控制,该系统向每个用户提供了一个数据库的"快照",用户在事务内所作的每个修改,对于其他的用户都不可见,直到该事务成功提交。

- 规则:规则(RULE)允许一个查询能被重写,通常用来实现对视图(VIEW)的操作,如插入(INSERT)、更新(UPDATE)、删除(DELETE)。

- 数据类型:包括文本、任意精度的数值数组、JSON 数据、枚举类型、XML 数据

等。

- 全文检索:通过 Tsearch2 或 OpenFTS,8.3版本中内嵌 Tsearch2。

- NoSQL:JSON,JSONB,XML,HStore 原生支持,至 NoSQL 数据库的外部数据包装器。

- 数据仓库:能平滑迁移至同属 PostgreSQL 生态的 GreenPlum,DeepGreen,HAWK 等,使用 FDW 进行 ETL。

PSQL语法

#  Linux 操作系统连接数据库. 
	sudo -i -u postgres 
# 查看 帮助 \help
	\help <指令>
    # 例如: 
    	\help SELECT

PostgreSQL 命令

# abort 用于退出当前事务    
### alter 系列
# alter aggregate 修改 聚合函数的定义
# alter collation 修改 排序规则定义
# alter conversion 修改 编码转换的定义
# alter database  修改 数据库
# alter default privileges 定义 默认访问的权限
# alter domain 修改 域的定义
# alter function  修改 函数的定义
# alter group 修改 用户组
# alter index 修改 索引的定义。
# alter language 修改 过程语言的定义
# alter operator 修改 操作符的定义
# alter operator class 修改 操作符的定义
# alter schema 修改 模式的定义
# alter sequence 修改 序列生成器的定义
# alter table 修改 表的定义
# alter tablespace 修改 表空间的定义
# alter trigger 修改 触发器的定义
# alter type 修改 类型的定义
# alter user 修改 数据库帐号
### create 系列
# create aggregate 定义 新的聚合函数
# create cast 定义 用户定义的转换
# create constraint trigger 定义新的约束触发器
# create conversion 定义新的编码转换
# create database  创建新的数据库
# create domina 创建新域
# create function 定义一个新函数
# create group 定义一个用户组
# create index 定义一个新索引
# create language 定义新的过程语言
# create operator 定义 新的操作符
# 
### 其他系列
# analyze 收集 与数据库有关的统计
# begin 开始一个事务块
# checkpoint 强制 一个事务日志检查点
# close  关闭 游标
# cluster 根据 某个 索引对某个 表盘簇化排序
# comment 定义 或 改变 一个对象的注释
# commit 提交当前事务
# copy 在表 和 文件 之间拷贝数据

建库建表

# 建库
	- CREATE DATABASE dbname;
# 选择数据库
	- \c  dbname
# 建表
    CREATE TABLE table_name(
       column1 datatype,
       column2 datatype,
       column3 datatype,
       .....
       columnN datatype,
       PRIMARY KEY( 一个或多个列 )
    );

创建模式SCHEMA

# 模式schema 可以看成是一个表的集合
	- 一个模式可以包含视图/索引/数据类型/函数/操作符等
	- 相同对象名称可以被应用于不同模式不会冲突
   	- 模式的优势:
        1. 允许多个用户使用一个数据库,不会相互干扰
        2. 将数据库对象组织成逻辑组以便更容易管理
        3. 第三方应用的对象可以放在独立的模式中. 不会与其他对象的名称发生冲突

# 创建模式
	- create schema myschema;
# 建立模式表
    create table myschema.company(
       ID   INT              NOT NULL,
       NAME VARCHAR (20)     NOT NULL,
       AGE  INT              NOT NULL,
       ADDRESS  CHAR (25),
       SALARY   DECIMAL (18, 2),
       PRIMARY KEY (ID)
    );
# 删除模式
	- drop schema myschema;

psql 数据操作

# CRUD
	- 与 mysql无异
    
# where 条件语句

# and 且 & or 或 操作

# like 匹配
	- 两种通配符: %  和 _ (占位符)
    - like '%a' # 已a结尾
    - like 'a%' # 已a开头
    - like '%a%' # 包含a的数据
    - like 'a%%'  # 已a开头的字符,长度大于3的数据
    
    - like '_00%'  # 第二第三个位置是0的数据
    - like '2___3' # 2 开头 ,3 结尾长度为5的数据
    - like '_2%3'  # 第二个位置上为2,且已3结尾的数据

# limit 限制数据的数量
	- limit 1 # 取一条
    - limit 3 offset 2 # 偏移2条后,取3条

# order by 排序 
	- desc 降序
    - asc 升序 默认
    
# group by 分组 
	- ** 分组后, 只有分组的字段可以单独查询
    - ** 分组后, 可对非分组的数据进行聚合操作

# with 子句提供了一种编写辅助语句的方法
	- 解释: 两张不同的表(最好是有关联的表),相当于将一部分SQL语句固定,可在select中使用
    - 用法: 
        WITH RECURSIVE t(n) AS (
           VALUES (0)
           UNION ALL
           SELECT SALARY FROM COMPANY WHERE SALARY < 20000
        )
        SELECT sum(n) FROM t;
        
# having 
	- 分组后的条件语句
    - 例如: 
        SELECT NAME FROM COMPANY GROUP BY name HAVING count(name) > 1;
        
# distinct 去重

PostgreSQL 约束

# NOT NULL:
	- 指示某列不能存储 NULL 值。

# UNIQUE:
	- 确保某列的值都是唯一的。

# PRIMARY Key:
	- NOT NULL 和 UNIQUE 的结合。确保某列(或两个列
多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。

# FOREIGN Key:
	- 保证一个表中的数据匹配另一个表中的值的参照完整性。
	- 关键字 :references  表名(字段)
        
# CHECK:
	- 保证列中的值符合指定的条件。

# EXCLUSION :
	- 排他约束,保证如果将任何两行的指定列或表达式使用指定操作符进行比较,至少其中一个操作符比较将会返回 false 或空值。
    
    
    
# 删除约束
	ALTER TABLE table_name DROP CONSTRAINT some_name;

PostgreSQL 连接(JOIN)

# CROSS JOIN :交叉连接	
	- 数据大量冗余
    - 笛卡尔积

# INNER JOIN:内连接
	- 仅包含两个表都有的数据
    
# LEFT OUTER JOIN:左外连接
	- 以左侧表为主
    - 当左侧出现的数据,右侧未曾出现,则右侧空匹配
    
# RIGHT OUTER JOIN:右外连接
	- 以右侧表为主
    - 当右侧出现的数据,左侧未曾出现,则左侧空匹配.
    
# FULL OUTER JOIN:全外连接
	- 左右连接 合成表联合, 不同于内连接(会有空值出现)

PostgreSQL UNION 操作符

#  UNION 
	- 操作符合并两个或多个 SELECT 语句的结果
	- 操作符用于合并两个或多个 SELECT 语句的结果集。
	- 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型
	- 每个 SELECT 语句中的列的顺序必须相同
    
    
# NION 例子:
SELECT EMP_ID, NAME, DEPT FROM COMPANY INNER JOIN DEPARTMENT
   ON COMPANY.ID = DEPARTMENT.EMP_ID
    
   UNION

SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT
    ON COMPANY.ID = DEPARTMENT.EMP_ID;
    
    
# UNION ALL 子句
	- 可以连接两个有重复行的 SELECT 语句
    - 允许重复的值
    
# UNION ALL 例子:
SELECT EMP_ID, NAME, DEPT FROM COMPANY INNER JOIN DEPARTMENT
   ON COMPANY.ID = DEPARTMENT.EMP_ID
   UNION ALL
SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT
    ON COMPANY.ID = DEPARTMENT.EMP_ID;

PostgreSQL 别名

# AS 创建别名

PostgreSQL 触发器

# 触发器
	- 是数据库的回调函数
    - 会在指定事件发生时,自动执行/调用
    - 特点:
        1. 在执行之前触发(插入/更新/删除之前)
        2. 在执行之后触发(插入/更新/删除之后)
        3. 更新操作(对视图进行插入/更新/删除)
     	4. 触发器 for each row属性时可选的. 修改时每行调用一次
        5. 触发器 FOR EACH STATEMENT , 不管修改多少行.每个语句标记的触发器执行一次
        6. when子句和触发器在引用 NEW.columns-name 和 OLD.columns-name 表单插入,删除或更新时可以访问每一行元素.
其中columns-name是触发器关联的表中的列的名称
		7. 存在when 子句 ,PSQL语句只会执行 when子句成立的那一行,如果没有when子句,则每一行都执行
    	8. before 和 after 关键字决定何时执行触发器动作,决定是在关联行的插入/修改/删除. 之前或之后执行
        9. 修改表必须存在同一数据库中,作为触发器被附加的表或视图,且必须只使用tablename,而不是database.tablename
        10. 当创建约束触发器时会指定约束选选项,这与常规触发器相同. 只是可以使用这种约束来调整触发器的时间.
        11. 当触发器的实现的约束被违反,将跑出异常

触发器案例

# 1. 创建触发器函数 auditlogfunc
    CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
       BEGIN
          INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
          RETURN NEW;
       END;
    $example_table$ LANGUAGE plpgsql;

# 2. 创建触发器
	CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();
  
# 3. 执行 插入语句,将会在 AUDIT表中插入一条记录
	INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00 );
    
    
# 4. 查询触发器
	SELECT * FROM pg_trigger;
    
# 5. 删除触发器
	drop trigger example_trigger on company;

PostgreSQL 索引

# 索引
	- 加速搜索引擎检索
	- 加速 select 和 where 子句
	- 减慢 update 和 insert 语句数据的录入
	- create index 创建索引
	- 索引具有唯一性

索引类型

# 1. 单 索引
	CREATE INDEX index_name
ON table_name (column_name);

# 2. 组合索引(多列)
	CREATE INDEX index_name
ON table_name (column1_name, column2_name);

# 3. 唯一索引
	CREATE UNIQUE INDEX index_name
on table_name (column_name);

# 4. 局部索引
	- 局部索引 是在表的子集上构建的索引;子集由一个条件表达式上定义。索引只包含满足条件的行
    
	CREATE INDEX index_name
on table_name (conditional_expression);

# 5. 隐式索引
	隐式索引 是在创建对象时,由数据库服务器自动创建的索引。索引自动创建为主键约束和唯一约束。

什么情况下要避免使用索引?

索引不应该使用在较小的表上。
索引不应该使用在有频繁的大批量的更新或插入操作的表上。
索引不应该使用在含有大量的 NULL 值的列上。
索引不应该使用在频繁操作的列上。

PostgreSQL View(视图)

# 视图 
	- 预定义 查询形式存在的表组合
    - 可以查询一个所有行 或 从一个/多个表选定行
    - 可从一个 或 多个 表创建
# 视图 虚拟表特点
	- 用户/用户组更直观的查找方式
    - 限制数据访问,只能看到有限的数据,不是完整的表
    - 汇总各种表中的数据,可生成报告
   	- 视图 `只读` 无法进行读写操作. 可在视图上建立触发器,利用触发器执行读写操作

视图案例

# 1. 创建视图
	CREATE VIEW COMPANY_VIEW AS SELECT ID, NAME, AGE
FROM  COMPANY;

# 2. 使用视图查询
	SELECT * FROM COMPANY_VIEW;

# 3. 删除视图 
	drop view view_name

PostgreSQL TRANSACTION(事务)

# ACID 属性
	- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。

	- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
	
	- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
	
	- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

事务案例

# 1. 启动事务
	- BEGIN;
	- BEGIN TRANSACTION;

# 2. 提交事务
	- commit

# 3. 回滚
	- rollback 
	
# 例子🌰	
BEGIN;
DELETE FROM COMPANY WHERE AGE = 25;
COMMIT;

PostgreSQL 子查询

# 子查询
	- 内部查询,嵌套查询,在where子句种迁入查询语句
	- 一个select 查询的结果作为另外一个语句的输入值
	- 必须使用 花括号 () 括起来
	- 子查询 select子句中只能有一个列. 除非主查询多列,与子查询选中的列比较 
	- order by 不能在子查询种使用.
	- group by 可以再子查询种使用
	- 子查询返回很多行,只能与多值运算符一起使用.如IN
	- BETWEEN 运算符不能与子查询一起使用. between可以在子查询内部使用

# 案例:
	 SELECT * FROM COMPANY WHERE ID IN (SELECT ID FROM COMPANY  WHERE SALARY > 45000) ;

# 子查询 插入案例
	INSERT INTO COMPANY_BKP SELECT * FROM COMPANY  WHERE ID IN (SELECT ID FROM COMPANY) ;
    
# 子查询 更新案例
	UPDATE COMPANY SET SALARY = SALARY * 0.50 WHERE AGE IN (SELECT AGE FROM COMPANY_BKP WHERE AGE >= 27 );
    
# 子查询 删除案例
	DELETE FROM COMPANY WHERE AGE IN (SELECT AGE FROM COMPANY_BKP WHERE AGE > 27 );

PostgreSQL LOCK(锁)

# 锁 🔒
	- 为了保持数据库一致性,阻止用户修改一行/整表
	- 一般用于较高的并发
	- 排他锁和共享锁
	- 锁 只在事务下执行
	
# 语法:
	LOCK 表
	name in lock_mode
	
	- name : 锁的名称
	- lock_mode : 锁的模式: ACCESS SHARE,ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE,ACCESS EXCLUSIVE。
	
	
# 死锁
	两个事物彼此等待对方完成. 

# 咨询锁
	咨询锁
PostgreSQL 提供了创建具有应用程序定义含义的锁的方法。这些被称为咨询锁。由于系统不强制使用它们,所以正确使用它们取决于应用程序。咨询锁对于不适合 MVCC 模型的锁定策略非常有用。

例如,咨询锁的一个常见用途是模拟所谓"平面文件"数据管理系统中典型的悲观锁定策略。虽然存储在表中的标志可以用于相同的目的,但是通知锁更快,避免了表膨胀,并且在会话结束时由服务器自动清理。


# 案例
	BEGIN;
	LOCK TABLE company1 IN ACCESS EXCLUSIVE MODE;
posted @ 2021-06-10 17:04  染指未来  阅读(310)  评论(0编辑  收藏  举报