Postgresql约束用于规定表中的数据规则。
如果存在违反约束的数据行为,行为会被约束终止。
约束可以在创建表的时候就规定(通过CREATE TABLE 语句),或者在表创建之后规定(通过ALTER TABLE 语句)。
约束确保了数据库中数据的准确性和可靠性。
约束可以是列级或者表级。列级约束仅适用于列,表级约束被应用到整个表。
以下是在Postgresql中常用的约束:
名称 | 说明 |
---|---|
NOT NULL | 指示某列不能存储NULL值 |
UNIQUE | 确保某列的值都是唯一的 |
PRIMARY Key | NOT NULL和UNIQUE的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。 |
FOREIGN Key | 保证一个表中的数据匹配另一个表中的值的参照完整性。 |
CHECK | 保证列中的值符合指定的条件。 |
EXCLUSION | 排他约束,保证如果将任何两行的指定列或表达式使用指定操作符进行比较,至少其中一个操作符比较将返回false或空值。 |
语法实例
CREATE TABLE COMPANY3(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL UNIQUE,
ADDRESS CHAR(50),
SALARY REAL CHECK(SALARY > 0),
EXCLUDE USING gist
(NAME WITH =, -- 如果满足NAME相同,AGE不相同则允许插入,否则不允许插入。
AGE WITH <>) -- 其比较的结果是如果整个表达式返回true,则不允许插入,否则允许。
)
注意
删除约束
ALTER TABLE table_name DROP CONSTRAINT some_name;
UNION操作符用于合并两个或多个SELECT 语句的结果集。
UNION内部的每个SELECT语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个SELECT语句中的列的顺序必须相同。
基础语法
SELECT column1 [, column2 ]
FROM table1 [, table2 ]
[WHERE condition]
UNION
SELECT column1 [, column2 ]
FROM table1 [, table2 ]
[WHERE condition]
演示
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 join department on company.id=department.emp_id;
-- 若要连接有重复行的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 join department on company.id=department.emp_id;
触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。
关于触发器有几个比较重要的点:
语法
--创建触发器时的基础语法如下:
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
[
-- 触发器逻辑....
]
举例
--创建company表和audit表,company表用于生产表,audit表用于日志记录。
-- company表 --
CREATE TABLE COMPANY(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
-- audit表 --
CREATE TABLE AUDIT(
EMP_ID INT NOT NULL,
ENTRY_DATE TEXT NOT NULL
);
-- 在company表上创建一个触发器
create trigger example_trigger after insert on company for each row execute procedure auditlogfunc();
-- auditlogfunc()是postgresql一个程序,其定义如下:
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;
列出触发器
select * from pg_trigger;
删除触发器
drop trigger ${trigger_name} on ${table_of_trigger_dependent};
-- 举例 --
-- 删除本文上表company上的触发器example_trigger的指令为:
drop trigger example_trigger on company;
索引是加速搜索引擎检索数据的一种特殊表查询。简单地说,索引是一个指向表中数据的指针。
使用 CREATE INDEX 语句创建索引,它允许命名索引,指定表及要索引的一列或多列,并指示索引是升序排列还是降序排列。索引也可以是唯一的,与 UNIQUE 约束类似,在列上或列组合上防止重复条目。
语法
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) |
隐式索引 | 建表时由数据库服务器自动创建,一般为主键约束和唯一约束 |
注意
不管是单列索引还是组合索引,该索引必须是在WHERE子句的过滤条件中使用非常频繁的列。
唯一索引的使用,一方面提高了查询性能,同时也保护了数据的完整性,不允许任何重复的值插入到表中。
删除索引:
drop index index_name;
什么情况下避免使用索引?
在postgresql中,alter table命令用于添加、修改、删除一张已经存在表的列。
也可以使用alter table命令添加和删除约束。
语法
在一张已存在的表上添加列的语法:
-- table_name :表名 ; column_name:新列名; datatype:数据类型
ALTER TABLE table_name ADD column_name datatype;
在一张已存在的表上删除列的语法:
ALTER TABLE table_name DROP COLUMN coulumn_name;
修改表中某列的DATA_TYPE(数据类型)的语法:
ALTER TABLE table_name ALTER COLUMN column_name TYPE datatype;
给表中某列添加NOT NULL约束,语法如下:
ALTER TABLE table_name MODIFY column_name datatype NOT NULL;
给表中某列ADD UNIQUE CONSTRAINT(添加UNIQUE约束),语法如下:
ALTER TABLE table_name
ADD CONSTRAINT MyUniqueConstraint UNIQUE(column1,column2,...);
给表中 ADD CHECK CONSTRAINT(添加 CHECK 约束):
ALTER TABLE table_name
ADD CONSTRAINT MyUniqueConstraint CHECK (CONDITION);
给表ADD PRIMARY KEY(添加主键):
ALTER TABLE table_name
ADD CONSTRAINT MyPrimaryKey PRIMARY KEY (column1,column2,....);
删除约束:
ALTER TABLE table_name
DROP CONSTRAINT MyUniqueConstraint;
view(视图)是一张假表,只不过是通过相关的名称存储在数据库中的一个Postgresql语句。
view(视图)实际上是一个以预定义的postgresql查询形式存在的表的组合。
view(视图)可以包含一个表的所有行或从一个或多个表选定行。
view(视图)可以从一个或多个表创建,这取决于要创建视图的Postgresql查询。
view(视图)是一种虚拟表,允许用户实现以下几点:
PostgreSQL 视图是只读的,因此可能无法在视图上执行 DELETE、INSERT 或 UPDATE 语句。但是可以在视图上创建一个触发器,当尝试 DELETE、INSERT 或 UPDATE 视图时触发,需要做的动作在触发器内容中定义。
语法
-- 创建视图
CREATE [TEMP | TEMPORARY] VIEW view_name AS
SELECT column1, column2.....
FROM table_name
WHERE [condition];
-- 注意:可以在 SELECT 语句中包含多个表,这与在正常的 SQL SELECT 查询中的方式非常相似。如果使用了可选的 TEMP 或 TEMPORARY 关键字,则将在临时数据库中创建视图。
-- 实例:从表company创建视图 --
CREATE VIEW COMPANY_VIEW AS
SELECT ID, NAME, AGE
FROM COMPANY;
-- 查询视图
select * from view_name;
-- 实例
select * from company_view;
-- 删除视图
drop view view_name;
--实例
drop view company_view;
TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:
事务的属性:
事务控制
实例
--创建company表,并写入数据(已有)
-- 开始一个事务,并从表中删除 age = 25 的记录,最后,我们使用 ROLLBACK 命令撤消所有的更改
begin;
delete from company where age = 25;
rollback; --回滚
-- 此时表中数据不会被删除
-- 我们开始另一个事务,从表中删除 age = 25 的记录,最后我们使用 COMMIT 命令提交所有的更改
begin;
delete from company where age = 25;
commit; -- 提交
-- 再次检查数据,表中记录已被删除
锁主要是为了保持数据库数据的一致性,可以阻止用户修改一行或整个表,一般用在并发较高的数据库中。
锁的类型:
锁类型 | 说明 |
---|---|
排它锁(Exclusive Locks) | 如果数据对象加上排它锁,则其他的事务不能对它读取和修改 |
共享锁(Share Locks) | 如果加上共享锁,则该数据库对象可以被其他事务读取,但不能修改 |
语法
LOCK [TABLE]
name
IN
lock_mode
-- name:要锁定的现有表的名称(可选模式限定)。如果只在表名之前指定,则只锁定该表。如果未指定,则锁定该表及其所有子表(如果有)
-- lock_mode:锁定模式指定该锁与哪个锁冲突。如果没有指定锁定模式,则使用限制最大的访问独占模式。可能的值是:ACCESS SHARE,ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE,ACCESS EXCLUSIVE。
-- 实例
-- 将COMPANY表锁定为ACCESS EXCLUSIVE模式:
BEGIN;
LOCK TABLE COMPANY IN ACCESS EXCLUSIVE MODE;
子查询或称为内部查询、嵌套查询,指的是在 PostgreSQL 查询中的 WHERE 子句中嵌入查询语句。
一个 SELECT 语句的查询结果能够作为另一个语句的输入值。
子查询可以与 SELECT、INSERT、UPDATE 和 DELETE 语句一起使用,并可使用运算符如 =、<、>、>=、<=、IN、BETWEEN 等。
子查询必须遵循的几个规则:
SELECT语句中的子查询使用
SELECT column_name [, column_name ]
FROM table1 [, table2 ]
WHERE column_name OPERATOR
(SELECT column_name [, column_name ]
FROM table1 [, table2 ]
[WHERE])
-- 实例
SELECT * FROM COMPANY WHERE ID IN (SELECT ID FROM COMPANY WHERE SALARY > 45000) ;
INSERT 语句中的子查询使用
INSERT INTO table_name [ (column1 [, column2 ]) ]
SELECT [ *|column1 [, column2 ] ]
FROM table1 [, table2 ]
[ WHERE VALUE OPERATOR ]
-- 实例
--将具有相同结构的两个表进行数据的复制。
insert into company_bak select * from company where id in(select id from company);
UPDATE 语句中的子查询使用
UPDATE table
SET column_name = new_value
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME
FROM TABLE_NAME)
[ WHERE) ]
-- 实例
update company set salary = salary*0.5 where age in (select age from company_bak where age >= 27);
DELETE 语句中的子查询使用
DELETE FROM TABLE_NAME
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME
FROM TABLE_NAME)
[ WHERE) ]
-- 实例
DELETE FROM company where age in (select age from company_bak where age > 27);
AUTO INCREMENT(自动增长) 会在新记录插入表中时生成一个唯一的数字。
PostgreSQL 使用序列来标识字段的自增长,数据类型有smallserial、serial 和 bigserial 。这些属性类似于 MySQL 数据库支持的 AUTO_INCREMENT 属性。
使用Mysql设置自动增长的语句如下:
CREATE TABLE IF NOT EXISTS `runoob_tbl`(
`runoob_id` INT UNSIGNED AUTO_INCREMENT,
`runoob_title` VARCHAR(100) NOT NULL,
`runoob_author` VARCHAR(40) NOT NULL,
`submission_date` DATE,
PRIMARY KEY ( `runoob_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- mysql是使用AUTO_INCREMENT这个属性来标识字段的自增。
Postgresql是使用序列来标识字段的自增长:
CREATE TABLE runoob
(
id serial NOT NULL,
alttext text,
imgurl text
)
SMALLSERIAL,SERIAL,BIGSERIAL范围比较
序列名 | 存储大小 | 范围 |
---|---|---|
SMALLSERIAL | 2字节 | 1~32767 |
SERIAL | 4字节 | 1~2147483647 |
BIGSERIAL | 8字节 | 1~922 337 2036 854 775 807 |
举例
-- 现在向runoob表中插入几条数据
insert into runoob(alttext,imgurl) values('123','123');
insert into runoob(alttext,imgurl) values('45','45');
insert into runoob(alttext,imgurl) values('67','67');
insert into runoob(alttext,imgurl) values('89','89');
--通过select * from runoob发现ID从1开始自增长。
无论何时创建数据库对象,都会为其分配一个所有者,所有者通常是执行 create 语句的人。
对于大多数类型的对象,初始状态是只有所有者(或超级用户)才能修改或删除对象。要允许其他角色或用户使用它,必须为该用户设置权限。
在 PostgreSQL 中,权限分为以下几种:
SELECT INSERT UPDATE DELETE TRUNCATE REFERENCES TRIGGER CREATE CONNECT TEMPORARY EXECUTE USAGE
根据对象的类型(表、函数等),将制定权限应用于该对象。
要向用户分配权限,可以使用GRANT命令。
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命令取消权限,REVOKE语法 --
REVOKE privilege [, ...]
ON object [, ...]
FROM { PUBLIC | GROUP groupname | username }
实例
-- 创建一个用户:
CREATE USER runoob WITH PASSWORD '123456';
-- 给runoob分配(全部ALL)权限:
GRANT ALL ON COMPANY TO runoob;
-- 将runoob的权限撤销:
REVOKE ALL ON COMPANY FROM runoob;
-- 给runoob分配单个权限:
GRANT INSERT ON COMPANY TO runoob;
-- 将runoob的单个权限撤销:
REVOKE INSERT ON COMPANY FROM runoob;
-- 删除用户runoob:
DROP USER runoob;
日期类型的模糊查询是不能直接进行的,要先转换成字符串然后再查询。
通常使用to_char和to_date来进行日期转字符串和字符串转日期。
获取系统时间函数
-- 获取当前完整时间
select now();
select current_timestamp;
-- 获取当前日期
select current_date;
-- 获取当前时间
select current_time;
时间的计算
-- 当前时间节点的两年后
select now() + interval '2 years';
select now() + interval '2 year';
select now() + interval '2 y';
select now() + interval '2 Y';
select now() + interval '2Y';
-- 当前时间节点的一个月后
select now() + interval '1 month';
-- 当前时间节点的三周前
select now() - interval '3 week';
-- 当前时间节点的十分钟后
select now() + '10 min';
-- 计算两个时间差
select age(now(),timestamp '1998-04-08'); --精确到毫秒
select age(timestamp '1998-04-08'); --精确到天
时间字段的截取
在开发过程中,经常要取日期的年,月,日,小时等值,PostgreSQL 提供一个非常便利的EXTRACT函数。
EXTRACT(field FROM source)
-- field 表示取的时间对象,
-- source 表示取的日期来源,类型为 timestamp、time 或 interval。
-- 取年份
select extract(year from now());
-- 取月份
select extract(month from now());
-- 取天数
select extract(day from timestamp '2019-08-30');
select extract(DAY FROM INTERVAL '40 days 1 minute');
-- 查看现在剧1970-01-01 00:00:00 UTC的秒数
select extract(epoch from now());
-- 把epoch值转换回时间戳
select TIMESTAMP WITH TIME ZONE 'epoch' + 1567130417 * INTERVAL '1 second';