PostgreSQL 约束用于规定表中的数据规则。
如果存在违反约束的数据行为,行为会被约束终止。
规定约束时机:
创建表时规定(通过 CREATE TABLE 语句);
表创建之后规定(通过 ALTER TABLE 语句)。
约束确保了数据库中数据的准确性和可靠性。
约束可以是列级或表级。列级约束仅适用于列,表级约束被应用到整个表。
约束名 | 描述 |
---|---|
NOT NULL | 指示某列不能存储 NULL 值。 |
UNIQUE | 确保某列的值都是唯一的。 |
PRIMARY KEY | NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。 |
FOREIGN KEY | 保证一个表中的数据匹配另一个表中的值的参照完整性。 |
CHECK | 保证列中的值符合指定的条件。 |
EXCLUSION | 排他约束,保证如果将任何两行的指定列或表达式使用指定操作符进行比较,至少其中一个操作符比较将会返回 false 或空值。 |
pgtestdb=# CREATE TABLE COMPANY(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL,
pgtestdb(# PRIMARY KEY(ID)
pgtestdb(# );
CREATE TABLE
pgtestdb=# CREATE TABLE COMPANY3(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# SALARY REAL DEFAULT 50000.00,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# PRIMARY KEY(ID),
pgtestdb(# UNIQUE(AGE)
pgtestdb(# );
CREATE TABLE
pgtestdb=# CREATE TABLE COMPANY6(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL,
pgtestdb(# PRIMARY KEY(ID)
pgtestdb(# );
CREATE TABLE
pgtestdb=# CREATE TABLE DEPARTMENT1(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# DEPT CHAR(50) NOT NULL,
pgtestdb(# EMP_ID INT REFERENCES COMPANY6(ID)
pgtestdb(# );
CREATE TABLE
pgtestdb=# CREATE TABLE COMPANY5(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL CHECK(SALARY >0),
pgtestdb(# PRIMARY KEY(ID)
pgtestdb(# );
CREATE TABLE
CREATE TABLE circles(
c circle,
EXCLUDE USING gist (c WITH &&)
);
pgtestdb=# CREATE EXTENSION btree_gist;
错误: 无法打开扩展控制文件 "/usr/pgsql-13/share/extension/btree_gist.control": 没有那个文件或目录
删除约束必须知道约束名称:
已经知道名称来删除约束很简单;
如果不知道名称,则需要找到系统生成的名称,使用 \d 表名
可以找到这些信息。
语法:
ALTER TABLE table_name DROP CONSTRAINT some_name;
pgtestdb=# \d company
数据表 "public.company"
栏位 | 类型 | 校对规则 | 可空的 | 预设
---------+---------------+----------+----------+------
id | integer | | not null |
name | text | | not null |
age | integer | | not null |
address | character(50) | | |
salary | real | | |
索引:
"company_pkey" PRIMARY KEY, btree (id)
pgtestdb=# ALTER TABLE COMPANY DROP CONSTRAINT company_pkey;
ALTER TABLE
pgtestdb=# \d company
数据表 "public.company"
栏位 | 类型 | 校对规则 | 可空的 | 预设
---------+---------------+----------+----------+------
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
就为语法中的 some_name
。连接类型 | 描述 |
---|---|
CROSS JOIN | 交叉连接 |
INNER JOIN | 内连接 |
LEFT OUTER JOIN | 左外连接 |
RIGHT OUTER JOIN | 右外连接 |
FULL OUTER JOIN | 全外连接 |
pgtestdb=# CREATE TABLE COMPANY(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL,
pgtestdb(# PRIMARY KEY(ID)
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (1, 'Paul', 32, 'California', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (2, 'Allen', 25, 'Texas', 15000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (5, 'David', 27, 'Texas', 85000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (6, 'Kim', 22, 'South-Hall', 45000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (7, 'James', 24, 'Houston', 10000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (8, 'Paul', 24, 'Houston', 20000.00);
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (9, 'James', 44, 'Norway', 5000.00);
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (10, 'James', 45, 'Texas', 5000.00);
INSERT 0 1
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
8 | Paul | 24 | Houston | 20000
9 | James | 44 | Norway | 5000
10 | James | 45 | Texas | 5000
(10 行记录)
pgtestdb=# CREATE TABLE DEPARTMENT(
pgtestdb(# ID INT NOT NULL,
pgtestdb(# DEPT CHAR(50) NOT NULL,
pgtestdb(# EMP_ID INT NOT NULL,
pgtestdb(# PRIMARY KEY(ID)
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID) VALUES (1, 'IT Billing', 1 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID) VALUES (2, 'Engineering', 2 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID) VALUES (3, 'Finance', 7 );
INSERT 0 1
pgtestdb=# SELECT * FROM DEPARTMENT;
id | dept | emp_id
----+----------------------------------------------------+--------
1 | IT Billing | 1
2 | Engineering | 2
3 | Finance | 7
(3 行记录)
SELECT ... FROM table1 CROSS JOIN table2 ...
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY CROSS JOIN DEPARTMENT;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
1 | Allen | IT Billing
1 | Teddy | IT Billing
1 | Mark | IT Billing
1 | David | IT Billing
1 | Kim | IT Billing
1 | James | IT Billing
1 | Paul | IT Billing
1 | James | IT Billing
1 | James | IT Billing
2 | Paul | Engineering
2 | Allen | Engineering
2 | Teddy | Engineering
2 | Mark | Engineering
2 | David | Engineering
2 | Kim | Engineering
2 | James | Engineering
2 | Paul | Engineering
2 | James | Engineering
2 | James | Engineering
7 | Paul | Finance
7 | Allen | Finance
7 | Teddy | Finance
7 | Mark | Finance
7 | David | Finance
7 | Kim | Finance
7 | James | Finance
7 | Paul | Finance
7 | James | Finance
7 | James | Finance
(30 行记录)
根据连接谓词结合两个表(table1 和 table2)的列值来创建一个新的结果表。
*
查询会把 table1 中的每一行与 table2 中的每一行进行比较,找到所有满足连接谓词的行的匹配对。
*
当满足连接谓词时,A 和 B 行的每个匹配对的列值会合并成一个结果行。
*
内连接(INNER JOIN)是最常见的连接类型,是默认的连接类型。
语法:
SELECT table1.column1, table2.column2...
FROM table1
INNER JOIN table2
ON table1.common_filed = table2.common_field;
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY INNER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
(3 行记录)
外部连接是内部连接的扩展。
*
左外连接:
语法:
SELECT ... FROM table1 LEFT OUTER JOIN table2 ON conditional_expression ...
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
| James |
| David |
| Paul |
| Kim |
| Mark |
| Teddy |
| James |
(10 行记录)
首先,执行内部连接。
*
然后,对于表 T2 中不满足表 T1 中连接条件的每一行添加一个连接行,其中 T1 列中的值为空也会添加一个连接行。
*
这与左联接相反。
*
对于T2中的每一行,结果表总是有一行。
语法:
SELECT ... FROM table1 RIGHT OUTER JOIN table2 ON conditional_expression ...
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY RIGHT OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
(3 行记录)
首先,执行内部连接。
*
然后,对于表 T1 中不满足表 T2 中任何行连接条件的每一行,如果 T2 的列中有 null 值也会添加一个到结果中。
*
此外,对于 T2 中不满足与 T1 中的任何行连接条件的每一行,将会添加 T1 列中包含 null 值的到结果中。
语法:
SELECT ... FROM table1 FULL OUTER JOIN table2 ON conditional_expression ...
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY FULL OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
| James |
| David |
| Paul |
| Kim |
| Mark |
| Teddy |
| James |
(10 行记录)
总结:
SELECT column1 [, column2 ]
FROM table1 [, table2 ]
[WHERE condition]
UNION
SELECT column1 [, column2 ]
FROM table1 [, table2 ]
[WHERE condition]
pgtestdb=# CREATE TABLE COMPANY(
pgtestdb(# ID INT PRIMARY KEY NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (1, 'Paul', 32, 'California', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (2, 'Allen', 25, 'Texas', 15000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (5, 'David', 27, 'Texas', 85000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (6, 'Kim', 22, 'South-Hall', 45000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (7, 'James', 24, 'Houston', 10000.00 );
INSERT 0 1
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
pgtestdb=# CREATE TABLE DEPARTMENT(
pgtestdb(# ID INT PRIMARY KEY NOT NULL,
pgtestdb(# DEPT CHAR(50) NOT NULL,
pgtestdb(# EMP_ID INT NOT NULL
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (1, 'IT Billing', 1 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (2, 'Engineering', 2 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (3, 'Finance', 7 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (4, 'Engineering', 3 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (5, 'Finance', 4 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (6, 'Engineering', 5 );
INSERT 0 1
pgtestdb=# INSERT INTO DEPARTMENT (ID, DEPT, EMP_ID)
pgtestdb-# VALUES (7, 'Finance', 6 );
INSERT 0 1
pgtestdb=# 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 行记录)
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY INNER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID
pgtestdb-# UNION
pgtestdb-# SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID
pgtestdb-# ;
emp_id | name | dept
--------+-------+----------------------------------------------------
7 | James | Finance
6 | Kim | Finance
2 | Allen | Engineering
3 | Teddy | Engineering
5 | David | Engineering
4 | Mark | Finance
1 | Paul | IT Billing
(7 行记录)
pgtestdb=# SELECT EMP_ID, NAME, DEPT FROM COMPANY INNER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID
pgtestdb-# UNION ALL
pgtestdb-# SELECT EMP_ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID
pgtestdb-# ;
emp_id | name | dept
--------+-------+----------------------------------------------------
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
3 | Teddy | Engineering
4 | Mark | Finance
5 | David | Engineering
6 | Kim | Finance
1 | Paul | IT Billing
2 | Allen | Engineering
7 | James | Finance
3 | Teddy | Engineering
4 | Mark | Finance
5 | David | Engineering
6 | Kim | Finance
(14 行记录)
pgtestdb=# SELECT * FROM COMPANY WHERE SALARY IS NOT NULL;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
SELECT column1, column2....
FROM table_name AS alias_name
WHERE [condition];
SELECT column_name AS alias_name
FROM table_name
WHERE [condition];
pgtestdb=# 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 行记录)
pgtestdb=# 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 行记录)
触发器是数据库的回调函数,它会在指定的数据库事件(即,INSERT,UPDATE,DELETE或TRUNCATE语句)发生时自动执行/调用。
*
触发器用于验证输入数据,执行业务规则,保持审计跟踪等。
*
触发器触发情况:
对于操作修改的每一行,都会调用一个标记为FOR EACH ROWS的触发器。 另一方面,标记为FOR EACH STATEMENT的触发器只对任何给定的操作执行一次,而不管它修改多少行。
*
可以为同一事件定义同一类型的多个触发器,但条件是按名称按字母顺序触发。
*
当与它们相关联的表被删除时,触发器被自动删除。
*
详细内容在这里:Free AI-Hub 触发器
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); |
唯一索引 | 不仅是为了性能,同时也为了数据的完整性,唯一索引不允许任何重复的值插入到表中。 | CREATE UNIQUE INDEX index_name on table_name (column_name); |
局部索引 | 在表的子集上构建的索引;子集由一个条件表达式上定义。索引只包含满足条件的行。 | CREATE INDEX index_name on table_name (conditional_expression); |
隐式索引 | 在创建对象时,由数据库服务器自动创建的索引。索引自动创建为主键约束和唯一约束。 |
pgtestdb=# CREATE INDEX salary_index ON COMPANY (SALARY);
CREATE INDEX
pgtestdb=# \d COMPANY
数据表 "public.company"
栏位 | 类型 | 校对规则 | 可空的 | 预设
---------+---------------+----------+----------+------
id | integer | | not null |
name | text | | not null |
age | integer | | not null |
address | character(50) | | |
salary | real | | |
索引:
"company_pkey" PRIMARY KEY, btree (id)
"salary_index" btree (salary)
\di
命令列出数据库中所有索引:pgtestdb=# \di
关联列表
架构模式 | 名称 | 类型 | 拥有者 | 数据表
----------+-----------------+------+----------+------------
public | company_pkey | 索引 | postgres | company
public | department_pkey | 索引 | postgres | department
public | salary_index | 索引 | postgres | company
(3 行记录)
DROP INDEX index_name;
pgtestdb=# \di
关联列表
架构模式 | 名称 | 类型 | 拥有者 | 数据表
----------+-----------------+------+----------+------------
public | company_pkey | 索引 | postgres | company
public | department_pkey | 索引 | postgres | department
public | salary_index | 索引 | postgres | company
(3 行记录)
pgtestdb=# DROP INDEX salary_index;
DROP INDEX
pgtestdb=# \di
关联列表
架构模式 | 名称 | 类型 | 拥有者 | 数据表
----------+-----------------+------+----------+------------
public | company_pkey | 索引 | postgres | company
public | department_pkey | 索引 | postgres | department
(2 行记录)
操作 | 描述 | 语法 |
---|---|---|
ADD | 在一张已存在的表上添加列 | ALTER TABLE table_name ADD column_name datatype; |
DROP COLUMN | 在一张已存在的表上删除列 | ALTER TABLE table_name DROP COLUMN column_name; |
ALTER COLUMN … TYPE | 修改表中某列的数据类型 | ALTER TABLE table_name ALTER COLUMN column_name TYPE datatype; |
ALTER … NOT NULL | 给表中某列添加 NOT NULL 约束 | ALTER TABLE table_name ALTER column_name datatype NOT NULL; |
ADD CONSTRAINT … UNIQUE | 给表中某列添加 UNIQUE 约束 | ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint UNIQUE(column1, column2...); |
ADD CONSTRAINT … CHECK | 给表中添加 CHECK 约束 | ALTER TABLE table_name ADD CONSTRAINT MyUniqueConstraint CHECK (CONDITION); |
ADD CONSTRAINT … PRIMARY KEY | 给表添加主键 | ALTER TABLE table_name ADD CONSTRAINT MyPrimaryKey PRIMARY KEY (column1, column2...); |
DROP CONSTRAINT | 删除约束 | ALTER TABLE table_name DROP CONSTRAINT MyUniqueConstraint; |
DROP INDEX | MYSQL 删除约束 | ALTER TABLE table_name DROP INDEX MyUniqueConstraint; |
DROP CONSTRAINT … | 删除主键 | ALTER TABLE table_name DROP CONSTRAINT MyPrimaryKey; |
DROP PRIMARY KEY | MySQL 删除主键 | ALTER TABLE table_name DROP PRIMARY KEY; |
pgtestdb=# ALTER TABLE COMPANY ADD GENDER char(1);
ALTER TABLE
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary | gender
----+-------+-----+----------------------------------------------------+--------+--------
1 | Paul | 32 | California | 20000 |
2 | Allen | 25 | Texas | 15000 |
3 | Teddy | 23 | Norway | 20000 |
4 | Mark | 25 | Rich-Mond | 65000 |
5 | David | 27 | Texas | 85000 |
6 | Kim | 22 | South-Hall | 45000 |
7 | James | 24 | Houston | 10000 |
(7 行记录)
pgtestdb=# ALTER TABLE COMPANY DROP GENDER;
ALTER TABLE
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
TRUNCATE TABLE 用于删除表的数据,但不删除表结构。
*
DROP TABLE 删除表,但是这个命令会连表的结构一起删除,如果想插入数据,需要重新建立这张表。
*
TRUNCATE TABLE 与 DELETE 具有相同的效果,但是由于它实际上并不扫描表,所以速度更快。
*
RUNCATE TABLE 可以立即释放表空间,而不需要后续 VACUUM 操作,这在大型表上非常有用。
*
VACUUM 操作用于释放、再利用更新/删除行所占据的磁盘空间。
*
语法:
TRUNCATE TABLE table_name;
pgtestdb=# TRUNCATE TABLE COMPANY;
TRUNCATE TABLE
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+------+-----+---------+--------
(0 行记录)
View(视图)是一张假表,只不过是通过相关的名称存储在数据库中的一个 PostgreSQL 语句。
*
View(视图)实际上是一个以预定义的 PostgreSQL 查询形式存在的表的组合。
*
View(视图)可以包含一个表的所有行或从一个或多个表选定行。
*
View(视图)可以从一个或多个表创建,这取决于要创建视图的 PostgreSQL 查询。
*
View(视图)是一种虚拟表,允许用户实现以下几点:
视图是只读的,无法在视图上执行 DELETE、INSERT 或 UPDATE 语句。
*
语法:
CREATE [TEMP | TEMPORARY] VIEW view_name AS
SELECT column1, column2.....
FROM table_name
WHERE [condition];
pgtestdb=# CREATE TABLE COMPANY(
pgtestdb(# ID INT PRIMARY KEY NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (1, 'Paul', 32, 'California', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (2, 'Allen', 25, 'Texas', 15000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (5, 'David', 27, 'Texas', 85000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES (6, 'Kim', 22, 'South-Hall', 45000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY VALUES (7, 'James', 24, 'Houston', 10000.00 );
INSERT 0 1
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
pgtestdb=# CREATE VIEW COMPANY_VIEW AS
pgtestdb-# SELECT ID, NAME, AGE
pgtestdb-# FROM COMPANY;
CREATE VIEW
pgtestdb=# SELECT * FROM COMPANY_VIEW;
id | name | age
----+-------+-----
1 | Paul | 32
2 | Allen | 25
3 | Teddy | 23
4 | Mark | 25
5 | David | 27
6 | Kim | 22
7 | James | 24
(7 行记录)
pgtestdb=# \d
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+--------------+--------+----------
public | company | 数据表 | postgres
public | company_view | 视图 | postgres
public | department | 数据表 | postgres
(3 行记录)
pgtestdb=# DROP VIEW company_view;
DROP VIEW
pgtestdb=# \d
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+------------+--------+----------
public | company | 数据表 | postgres
public | department | 数据表 | postgres
(2 行记录)
TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
数据库事务通常包含了一个序列的对数据库的读/写操作。
事务包含有以下两个目的:
为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
当事务被提交给了数据库管理系统(DBMS):
则 DBMS 需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中;
如果事务中有的操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的状态;
同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行。
属性 | 描述 |
---|---|
原子性(Atomicity) | 事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。 |
一致性(Consistency) | 事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。 |
隔离性(Isolation) | 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 |
持久性(Durability) | 已被提交的事务对数据库的修改应该永久保存在数据库中。 |
某人要在商店使用电子货币购买100元的东西,当中至少包括两个操作:
该人账户减少 100 元。
商店账户增加100元。
支持事务的数据库管理系统就是要确保以上两个操作(整个"事务")都能完成,或一起取消,否则就会出现 100 元平白消失或出现的情况。
使用以下命令来控制事务:
事务控制命令只与 INSERT、UPDATE 和 DELETE 一起使用。他们不能在创建表或删除表时使用,因为这些操作在数据库中是自动提交的。
*
开始一个事务,并从表中删除 age = 25 的记录,最后,我们使用 ROLLBACK 命令撤消所有的更改。
pgtestdb=# BEGIN;
BEGIN
pgtestdb=*# DELETE FROM COMPANY WHERE AGE = 25;
DELETE 2
pgtestdb=*# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
3 | Teddy | 23 | Norway | 20000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(5 行记录)
pgtestdb=*# ROLLBACK;
ROLLBACK
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
pgtestdb=# BEGIN;
BEGIN
pgtestdb=*# DELETE FROM COMPANY WHERE AGE = 25;
DELETE 2
pgtestdb=*# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
3 | Teddy | 23 | Norway | 20000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(5 行记录)
pgtestdb=*# COMMIT;
COMMIT
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
3 | Teddy | 23 | Norway | 20000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(5 行记录)
锁主要是为了保持数据库数据的一致性,可以阻止用户修改一行或整个表,一般用在并发较高的数据库中。
在多个用户访问数据库的时候若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
数据库中有两种基本的锁:
排它锁(Exclusive Locks):如果数据对象加上排它锁,则其他的事务不能对它读取和修改。
共享锁(Share Locks):如果加上共享锁,则该数据库对象可以被其他事务读取,但不能修改。
LOCK 语句只在事务模式下工作。
LOCK 命令基础语法如下:
LOCK [ TABLE ]
name
IN
lock_mode
子查询或称为内部查询、嵌套查询,指的是在 PostgreSQL 查询中的 WHERE 子句中嵌入查询语句。
一个 SELECT 语句的查询结果能够作为另一个语句的输入值。
子查询可以与 SELECT、INSERT、UPDATE 和 DELETE 语句一起使用,并可使用运算符如 =、<、>、>=、<=、IN、BETWEEN 等。
以下是子查询必须遵循的几个规则:
子查询必须用括号括起来。
子查询在 SELECT 子句中只能有一个列,除非在主查询中有多列,与子查询的所选列进行比较。
ORDER BY 不能用在子查询中,虽然主查询可以使用 ORDER BY。可以在子查询中使用 GROUP BY,功能与 ORDER BY 相同。
子查询返回多于一行,只能与多值运算符一起使用,如 IN 运算符。
BETWEEN 运算符不能与子查询一起使用,但是,BETWEEN 可在子查询内使用。
SELECT column_name [, column_name ]
FROM table1 [, table2 ]
WHERE column_name OPERATOR
(SELECT column_name [, column_name ]
FROM table1 [, table2 ]
[WHERE])
pgtestdb=# SELECT * FROM COMPANY WHERE ID IN (SELECT ID FROM COMPANY WHERE SALARY > 45000);
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
5 | David | 27 | Texas | 85000
4 | Mark | 25 | Rich-Mond | 65000
(2 行记录)
INSERT INTO table_name [ (column1 [, column2 ]) ]
SELECT [ *|column1 [, column2 ] ]
FROM table1 [, table2 ]
[ WHERE VALUE OPERATOR ]
pgtestdb=# CREATE TABLE COMPANY_COPY(
pgtestdb(# ID INT PRIMARY KEY NOT NULL,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL
pgtestdb(# );
CREATE TABLE
pgtestdb=# SELECT * FROM COMPANY_COPY;
id | name | age | address | salary
----+------+-----+---------+--------
(0 行记录)
pgtestdb=# INSERT INTO COMPANY_COPY SELECT * FROM COMPANY WHERE ID IN (SELECT ID FROM COMPANY);
INSERT 0 7
pgtestdb=# SELECT * FROM COMPANY_COPY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
3 | Teddy | 23 | Norway | 20000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
2 | Allen | 25 | Texas | 15000
4 | Mark | 25 | Rich-Mond | 65000
(7 行记录)
UPDATE table
SET column_name = new_value
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME
FROM TABLE_NAME)
[ WHERE) ]
pgtestdb=# UPDATE COMPANY_COPY SET SALARY = SALARY * 0.50 WHERE AGE IN (SELECT AGE FROM COMPANY WHERE AGE >= 27);
UPDATE 2
pgtestdb=# SELECT * FROM COMPANY_COPY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
3 | Teddy | 23 | Norway | 20000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
2 | Allen | 25 | Texas | 15000
4 | Mark | 25 | Rich-Mond | 65000
1 | Paul | 32 | California | 10000
5 | David | 27 | Texas | 42500
(7 行记录)
DELETE FROM TABLE_NAME
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME
FROM TABLE_NAME)
[ WHERE) ]
pgtestdb=# DELETE FROM COMPANY_COPY WHERE AGE IN (SELECT AGE FROM COMPANY WHERE AGE >= 27);
DELETE 2
pgtestdb=# SELECT * FROM COMPANY_COPY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
3 | Teddy | 23 | Norway | 20000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
2 | Allen | 25 | Texas | 15000
4 | Mark | 25 | Rich-Mond | 65000
(5 行记录)
CREATE TABLE runoob
(
id serial NOT NULL,
alttext text,
imgurl text
)
伪类型 | 存储大小 | 范围 |
---|---|---|
SMALLSERIAL | 2字节 | 1 到 32,767 |
SERIAL | 4字节 | 1 到 2,147,483,647 |
BIGSERIAL | 8字节 | 1 到 922,337,2036,854,775,807 |
pgtestdb=# CREATE TABLE COMPANY(
pgtestdb(# ID SERIAL PRIMARY KEY,
pgtestdb(# NAME TEXT NOT NULL,
pgtestdb(# AGE INT NOT NULL,
pgtestdb(# ADDRESS CHAR(50),
pgtestdb(# SALARY REAL
pgtestdb(# );
CREATE TABLE
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ( 'Paul', 32, 'California', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ('Allen', 25, 'Texas', 15000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ('Teddy', 23, 'Norway', 20000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ( 'Mark', 25, 'Rich-Mond ', 65000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ( 'David', 27, 'Texas', 85000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ( 'Kim', 22, 'South-Hall', 45000.00 );
INSERT 0 1
pgtestdb=# INSERT INTO COMPANY (NAME,AGE,ADDRESS,SALARY)
pgtestdb-# VALUES ( 'James', 24, 'Houston', 10000.00 );
INSERT 0 1
pgtestdb=# SELECT * FROM COMPANY;
id | name | age | address | salary
----+-------+-----+----------------------------------------------------+--------
1 | Paul | 32 | California | 20000
2 | Allen | 25 | Texas | 15000
3 | Teddy | 23 | Norway | 20000
4 | Mark | 25 | Rich-Mond | 65000
5 | David | 27 | Texas | 85000
6 | Kim | 22 | South-Hall | 45000
7 | James | 24 | Houston | 10000
(7 行记录)
无论何时创建数据库对象,都会为其分配一个所有者,所有者通常是执行 create 语句的人。
对于大多数类型的对象,初始状态是只有所有者(或超级用户)才能修改或删除对象。
要允许其他角色或用户使用它,必须为该用户设置权限。
在 PostgreSQL 中,权限分为以下几种:
SELECT;
INSERT;
UPDATE;
DELETE;
TRUNCATE;
REFERENCES;
TRIGGER;
CREATE;
CONNECT;
TEMPORARY;
EXECUTE;
USAGE;
根据对象的类型(表、函数等),将指定权限应用于该对象。
要向用户分配权限,可以使用 GRANT 命令。
语法:
GRANT privilege [, ...]
ON object [, ...]
TO { PUBLIC | GROUP group | username }
- privilege − 值可以为:SELECT,INSERT,UPDATE,DELETE, RULE,ALL。
- object − 要授予访问权限的对象名称。可能的对象有: table, view,sequence。
- PUBLIC − 表示所有用户。
- GROUP group − 为用户组授予权限。
- username − 要授予权限的用户名。PUBLIC 是代表所有用户的简短形式。
REVOKE privilege [, ...]
ON object [, ...]
FROM { PUBLIC | GROUP groupname | username }
pgtestdb=# CREATE USER test_privileges WITH PASSWORD '123456';
CREATE ROLE
pgtestdb=# GRANT ALL ON COMPANY TO test_privileges;
GRANT
pgtestdb=# REVOKE ALL ON COMPANY FROM test_privileges;
REVOKE
pgtestdb=# DROP USER test_privileges;
DROP ROLE
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/S_numb/article/details/120655213
内容来源于网络,如有侵权,请联系作者删除!