目录
PostgreSQL 别名:重命名一张表或者一个字段的名称
PostgreSQL 触发器:数据库的回调函数
创建触发器:
列出触发器:
删除触发器:
PostgreSQL 索引:加速搜索引擎检索数据的一种特殊表查询
CREATE INDEX 语句:创建索引
索引类型
单列索引:是一个只基于表的一个列上创建的索引
组合索引:是基于表的多列上创建的索引
唯一索引:不允许任何重复的值插入到表中
局部索引:是在表的子集上构建的索引
隐式索引:是在创建对象时,由数据库服务器自动创建的索引
列出表中的所有索引:/d table_name
列出数据库中所有索引:/di
删除索引:DROP INDEX index_name;
我们可以用 SQL 重命名一张表或者一个字段的名称,这个名称就叫着该表或该字段的别名。
创建别名是为了让表名或列名的可读性更强。
SQL 中 使用 AS 来创建别名。
/*表的别名语法:*/
SELECT column1, column2....
FROM table_name AS alias_name
WHERE [condition];
/*列的别名语法:*/
SELECT column_name AS alias_name
FROM table_name
WHERE [condition];
实例:
mydb=# select * from company;
id | name | age | address | salary | join_date
----+-------+-----+----------------------------------------------------+--------+-----------
1 | Paul | 32 | California | 20000 |
2 | Allen | 25 | Texas | 15000 |
3 | Teddy | 23 | Norway | 20000 |
4 | Mark | 25 | Rich-Mond | 65000 |
5 | David | 27 | South-Hall | 85000 |
8 | Paul | 24 | Houston | 20000 |
9 | James | 44 | Norway | 5000 |
10 | James | 45 | Texas | 5000 |
6 | Kim | 22 | | |
7 | James | 24 | | |
(10 行记录)
mydb=# select * from department;
id | dept | emp_id
----+----------------------------------------------------+--------
1 | IT Billing | 1
2 | Engineering | 2
3 | Finance | 7
4 | Engineering | 3
5 | Finance | 4
6 | Engineering | 5
7 | Finance | 6
(7 行记录)
/*下面我们分别用 C 和 D 表示 COMPANY 表和 DEPAERMENT 表的别名:*/
mydb=# SELECT C.ID, C.NAME, C.AGE, D.DEPT FROM COMPANY AS C, DEPARTMENT AS D WHERE C.ID = D.EMP_ID;
id | name | age | dept
----+-------+-----+----------------------------------------------------
1 | Paul | 32 | IT Billing
2 | Allen | 25 | Engineering
7 | James | 24 | Finance
3 | Teddy | 23 | Engineering
4 | Mark | 25 | Finance
5 | David | 27 | Engineering
6 | Kim | 22 | Finance
(7 行记录)
/*下面,我们用 COMPANY_ID 表示 ID 列,COMPANY_NAME 表示 NAME 列,来展示列别名的用法:*/
mydb=# SELECT C.ID AS COMPANY_ID, C.NAME AS COMPANY_NAME, C.AGE, D.DEPT FROM COMPANY AS C, DEPARTMENT AS D WHERE C.ID = D.EMP_ID;
company_id | company_name | age | dept
------------+--------------+-----+----------------------------------------------------
1 | Paul | 32 | IT Billing
2 | Allen | 25 | Engineering
7 | James | 24 | Finance
3 | Teddy | 23 | Engineering
4 | Mark | 25 | Finance
5 | David | 27 | Engineering
6 | Kim | 22 | Finance
(7 行记录)
PostgreSQL 触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。
下面是关于 PostgreSQL 触发器几个比较重要的点:
PostgreSQL 触发器可以在下面几种情况下触发:
- 在执行操作之前(在检查约束并尝试插入、更新或删除之前)。
- 在执行操作之后(在检查约束并插入、更新或删除完成之后)。
- 更新操作(在对一个视图进行插入、更新、删除时)。
触发器的 FOR EACH ROW 属性是可选的,如果选中,当操作修改时每行调用一次;
相反,选中 FOR EACH STATEMENT,不管修改了多少行,每个语句标记的触发器执行一次。
WHEN 子句和触发器操作在引用 NEW.column-name 和 OLD.column-name 表单插入、删除或更新时可以访问每一行元素。其中 column-name 是与触发器关联的表中的列的名称。
如果存在 WHEN 子句,PostgreSQL 语句只会执行 WHEN 子句成立的那一行;
如果没有 WHEN 子句,PostgreSQL 语句会在每一行执行。
BEFORE 或 AFTER 关键字决定何时执行触发器动作,决定是在关联行的插入、修改或删除之前或者之后执行触发器动作。
要修改的表必须存在于同一数据库中,作为触发器被附加的表或视图,且必须只使用 tablename,而不是 database.tablename。
当创建约束触发器时会指定约束选项。这与常规触发器相同,只是可以使用这种约束来调整触发器触发的时间。当约束触发器实现的约束被违反时,它将抛出异常。
/*创建触发器时的基础语法如下:*/
CREATE TRIGGER trigger_name [BEFORE|AFTER|INSTEAD OF] event_name
ON table_name
[
-- 触发器逻辑....
];
/*event_name 可以是在所提到的表 table_name 上的 INSERT、DELETE 和 UPDATE 数据库操作。*/
/*您可以在表名后选择指定 FOR EACH ROW。*/
/*以下是在 UPDATE 操作上在表的一个或多个指定列上创建触发器的语法:*/
CREATE TRIGGER trigger_name [BEFORE|AFTER] UPDATE OF column_name
ON table_name
[
-- 触发器逻辑....
];
/*你可以把从 pg_trigger 表中把当前数据库所有触发器列举出来:*/
runoobdb=# SELECT * FROM pg_trigger;
/*列举出特定表的触发器,语法如下:*/
runoobdb=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';
/*基础语法如下:*
drop trigger ${trigger_name} on ${table_of_trigger_dependent};
/*删除本文上表 company 上的触发器 example_trigger 的指令为:*/
drop trigger example_trigger on company;
实例:
postgres=# \c learn
/*让我们假设一个情况,我们要为被插入到新创建的 COMPANY 表中的每一个记录保持审计试验:*/
learn=# CREATE TABLE COMPANY(
learn(# ID INT PRIMARY KEY NOT NULL,
learn(# NAME TEXT NOT NULL,
learn(# AGE INT NOT NULL,
learn(# ADDRESS CHAR(50),
learn(# SALARY REAL
learn(# );
CREATE TABLE
/*为了保持审计试验,我们将创建一个名为 AUDIT 的新表。每当 COMPANY 表中有一个新的记录项时,日志消息将被插入其中:*/
//EMP_ID 是来自 COMPANY 表的 ID,DATE 将保持 COMPANY 中记录被创建时的时间戳。
learn=# CREATE TABLE AUDIT(
learn(# EMP_ID INT NOT NULL,
learn(# ENTRY_DATE TEXT NOT NULL
learn(# );
CREATE TABLE
/*在 COMPANY 表上创建一个触发器,如下所示:*/
learn=# CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();
错误: 函数 auditlogfunc() 不存在
/*auditlogfunc() 是 PostgreSQL 一个程序,其定义如下:*/
learn=# CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
learn$# BEGIN
learn$# INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
learn$# RETURN NEW;
learn$# END;
learn$# $example_table$ LANGUAGE plpgsql;
CREATE FUNCTION
/*在 COMPANY 表上创建一个触发器,如下所示:*/
learn=# CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();
CREATE TRIGGER
/*往 COMPANY 表中插入数据:*/
learn=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00 );
INSERT 0 1
learn=# select * from company;
id | name | age | address | salary
----+------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
(1 行记录)
/*这时,COMPANY 表中插入了一条记录:*/
/*同时, AUDIT 表中也插入了一条记录,因为我们在插入 COMPANY 表时创建了一个触发器。*/
learn=# select * from audit;
emp_id | entry_date
--------+-------------------------------
1 | 2022-05-19 14:58:52.062211+08
(1 行记录)
/*从 pg_trigger 表中把当前数据库所有触发器列举出来:*/
learn=# select * from pg_trigger;
tgrelid | tgname | tgfoid | tgtype | tgenabled | tgisinternal | tgconstrrelid | tgconstrindid | tgconstraint | tgdeferrable | tginitdeferred | tgnargs | tgattr | tgargs | tgqual | tgoldtable | tgnewtable
---------+-----------------+--------+--------+-----------+--------------+---------------+---------------+--------------+--------------+----------------+---------+--------+--------+--------+------------+------------
17156 | example_trigger | 17170 | 5 | O | f | 0 | 0 | 0 | f | f | 0 | | \x | | |
(1 行记录)
/*列举出特定表的触发器,语法如下:*/
learn=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';
tgname
-----------------
example_trigger
(1 行记录)
/*删除上表 company 上的触发器 example_trigger 的指令为:*/
learn=# drop trigger example_trigger on company;
DROP TRIGGER
learn=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';
tgname
--------
(0 行记录)
索引是加速搜索引擎检索数据的一种特殊表查询。
简单地说,索引是一个指向表中数据的指针。
一个数据库中的索引与一本书的索引目录是非常相似的。
拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。
- 索引有助于加快 SELECT 查询和 WHERE 子句,但它会减慢使用 UPDATE 和 INSERT 语句时的数据输入。索引可以创建或删除,但不会影响数据。
- 使用 CREATE INDEX 语句创建索引,它允许命名索引,指定表及要索引的一列或多列,并指示索引是升序排列还是降序排列。
索引也可以是唯一的,与 UNIQUE 约束类似,在列上或列组合上防止重复条目。
/*CREATE INDEX (创建索引)的语法如下:*/
CREATE INDEX index_name ON table_name;
/*基本语法如下:*/
CREATE INDEX index_name
ON table_name (column_name);
/*基本语法如下:*/
CREATE INDEX index_name
ON table_name (column1_name, column2_name...);
不管是单列索引还是组合索引,该索引必须是在 WHERE 子句的过滤条件中使用非常频繁的列。
如果只有一列被使用到,就选择单列索引,如果有多列就使用组合索引。
使用唯一索引不仅是为了性能,同时也为了数据的完整性。
/*基本语法如下:*/
CREATE UNIQUE INDEX index_name
on table_name (column_name);
子集由一个条件表达式定义。索引只包含满足条件的行。
/*基本语法如下:*/
CREATE INDEX index_name
on table_name (conditional_expression);
索引自动创建为主键约束和唯一约束。
实例:
/*在 COMPANY 表的 SALARY 列上创建索引:*/
learn=# CREATE INDEX salary_index ON COMPANY (salary);
CREATE INDEX
/*用 \d company 命令列出 COMPANY 表的所有索引:*/
learn=# \d company
数据表 "public.company"
栏位 | 类型 | Collation | Nullable | Default
---------+---------------+-----------+----------+---------
id | integer | | not null |
name | text | | not null |
age | integer | | not null |
address | character(50) | | |
salary | real | | |
索引:
"company_pkey" PRIMARY KEY, btree (id) /*company_pkey 是隐式索引 ,是表创建表时创建的:*/
"salary_index" btree (salary)
/*用 \di 命令列出数据库中所有索引:*/
learn=# \di
关联列表
架构模式 | 名称 | 类型 | 拥有者 | 数据表
----------+--------------+------+----------+---------
public | company_pkey | 索引 | postgres | company
public | salary_index | 索引 | postgres | company
(2 行记录)
/*DROP INDEX (删除索引)————删除之前创建的索引:*/
learn=# DROP INDEX salary_index;
DROP INDEX
learn=# \di
关联列表
架构模式 | 名称 | 类型 | 拥有者 | 数据表
----------+--------------+------+----------+---------
public | company_pkey | 索引 | postgres | company
(1 行记录)
虽然索引的目的在于提高数据库的性能,但这里有几个情况需要避免使用索引。
使用索引时,需要考虑下列准则:
- 索引不应该使用在较小的表上。
- 索引不应该使用在有频繁的大批量的更新或插入操作的表上。
- 索引不应该使用在含有大量的 NULL 值的列上。
- 索引不应该使用在频繁操作的列上。