侧边栏壁纸
博主头像
帮主の后花园博主等级

欢迎光临,开开心心每一天

  • 累计撰写 21 篇文章
  • 累计创建 5 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

PostgreSQL入门

Gxbalun
2022-03-07 / 0 评论 / 4 点赞 / 344 阅读 / 98688 字

PostgreSQL

PostgreSQL 是一个免费的对象-关系数据库服务器。

数据类型

  • 数值类型

    image-20220304112440001

  • 货币类型

    image-20220304112645879

  • 字符类型

    image-20220304112659721

  • 日期/时间类型

    image-20220304112713404

  • 布尔类型

    image-20220304112733491

  • 枚举类型

    #例如:
    CREATE TYPE mood AS ENUM('sad','happy','ok');
    #创建一周天数:
    CREATE TYPE week AS ENUM('Mon','Tue','Wed','Thu','Fri','Sat','Sun');
    
  • 几何类型

  • 网络地址类型

  • 位串类型

  • 文本搜索类型

  • UUID类型

Linux远程连接指令

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/postgreSQL/lib

/postgreSQL/bin/psql -h 127.0.0.1 -p 5432 -U root -d 123

数据库操作

  • 创建数据库:

CREATE DATABASE database_name;
  • 选择数据库:

#查看已经存在的数据库:
\l;

image-20220304131941212

#进入数据库:
\c database_name;

image-20220304132009338

  • 删除数据库:

#1.使用 DROP DATABASE SQL语句来删除;
DROP DATABASE [IF EXISTS] database_name;
#2.使用 dropdb 命令来删除;
# dropdb是 DROP DATABASE 的包装器,用于删除PostgreSQL数据库,只能有超级管理员或数据库拥有者执行
dropdb [option] [option] database_name;
#3.工具删除(pgAdmin、navicat等)

其中 option 为参数可选项,可以是以下值:

image-20220304124329617

表操作

  • 创建表:

CREATE TABLE table_name(
	column1 datatype,
    column2 datatype,
    ......
    columnN datatype,
    PRIMARY KEY(一个或多个列)
);

#例:
CREATE TABLE COMPANY(
   ID INT PRIMARY KEY     NOT NULL,
   NAME           TEXT    NOT NULL,
   AGE            INT     NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);
  • 查看表:

#查看表是否创建成功:
\d;

image-20220304131840620

#查看表信息:
\d table_name;

image-20220304131858701

  • 删除表:

DROP TABLE table_name;
  • 新增数据:

INSERT INTO table_name (column1,column2,column3,...,columnN) VALUES (value1,value2,value3,...,valueN);
#下面写法必须保证数据值与字段列数量和顺序相同
INSERT INTO table_name (value1,value2,value3,...,valueN);
下表列出执行插入后返回结果的说明:
image-20220304133858047

例:

#创建 company 表:
CREATE TABLE company(
	id INT PRIMARY KEY NOT NULL,
    name TEXT NOT NULL,
    age INT not NOT NULL,
    address CHAR(50),
    salary REAL,
    join_date DATE
);
#在 company 表中插入下列数据:
INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (1, 'Paul', 32, 'California', 20000.00,'2001-07-13');
INSERT 0 1
#以下插入语句忽略 salary 字段:
INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,JOIN_DATE) VALUES (2, 'Allen', 25, 'Texas', '2007-12-13');
INSERT 0 1
#以下插入语句 join_date 字段使用 default 子句来设置默认值,而不指定值:
INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (3, 'Teddy', 23, 'Norway', 20000.00, DEFAULT );
INSERT 0 1
#插入多行:
INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY,JOIN_DATE) VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00, '2007-12-13' ), (5, 'David', 27, 'Texas', 85000.00, '2007-12-13');
INSERT 0 2

查询表数据:

image-20220304141222969

  • 查询表中数据:

#例一
SELECT column1,column2,...columnN FROM table_name;
#例二
SELECT * FROM table_name;
#例三
SELECT id,name FROM table_name;
  • 修改表中数据:

update table_name set column1 = value1,column2 = values2...,columnN = valuesN where ...;
  • 删除表中数据:

delete from table_name where ...;

模式

PostgreSQL 模式可以看做是一个表的集合。

一个模式可以包含视图、索引、数据类型、函数和操作符等。

相同的对象名称可以被用于不同的模式而不会出现冲突,例如 schema1 和 myschema 都可以包含名为 mytable 的表。

使用模式的优势:

  • 允许多个用户使用一个数据库并且不会互相干扰。
  • 将数据库对象组织成逻辑组以便更容易管理。
  • 第三方应用的对象可以放在独立的模式中,这样它们就不会与其他对象的名称发生冲突。

模式类似操作系统层的目录,但模式不能嵌套。

语法

#创建模式:
CREATE SCHEMA myschema.mytable(
	...
);
#删除模式:
	#删除一个为空的模式(其中的所有对象以及被删除):
	drop shcema myschema
	#删除一个模式以及其中包含的所有对象:
	drop schema myschema cascade;

实例

#创建模式:
create schema myschema;

image-20220304142943024

#在此模式下创建一个表:
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)
);
查看表格是否创建:
image-20220304143345114
查看模式:
image-20220304144150489

运算符

  • 算数运算符

    image-20220304144422842

  • 比较运算符

image-20220304144516033

  • 逻辑运算符

image-20220304144539626

  • 按位运算符
p q p&q p|q
0 0 0 0
0 1 0 1
1 1 1 1
1 0 0 1

表达式

#where
select * from user where age > 20;
#and
select * from user where age > 18 and age <30;
#or
select * from user where age > 20 or sex = '男';
#not null
select * from user where age is not null;
#like  通配(% _) (其中_仅相当于一个位置)
select * from user where name like '王%';
#in
select * from user where age in (25,30);
#not in
select * from user where age not in (25,30);
#between
select * from user where age between 25 and 30;
  • 子查询:
select * from user where age > (select age from user where name = '王某');
  • LIMIT 语句:

limit 语句用于限制查询语句中查询数据的数量。

#查询满足条件的3条数据
select * from table_name where ... limit 3;
#从第3位开始提取3个记录
select * from table_name limit 3 offset 2;
  • ORDER BY 语句:

order by 语句用于对一列或多列数据进行升序(ASC)或降序(DESC)排列。

#例一:
select * from table_name where ... order by age ASC(DESC);
#例二:
select * from table_name where ... order by age,salary ASC(DESC);
  • GROUP BY 语句:

group by 语句和 select 一起使用,用于对相同的数据进行分组。

它的位置在 where 子句之后,order by 子句之前。

select * from table_name where ... group by column1,...,columnN order by column1,...,cloumnN ASC(DESC)
例-表company:
image-20220304153725524
#根据 name 字段值进行分组,找出每个人的工资总额:
SELECT NAME, SUM(SALARY) FROM COMPANY GROUP BY NAME ORDER BY NAME;
结果
image-20220304154135749
  • WITH 语句:

with 子句有助于将复杂的大型查询分解为更简单的表单,便于阅读。这些语句通常称为通用表表达式,也可以当做一个为查询而存在的临时表。

with 子句是在多次执行子查询时特别有用,允许我们在查询中通过它的名称(可以多次)引用它。

with 子句在使用前必须先定义。

语法:

# with 别名 as 子查询
with cte as (select * from company) select id,name from cte;

cte 是with子句的名称, cte 可以与现有的表名相同,并且具有优先级。

可以在 with 中使用数据 insert,update 或 delete 语句,允许在同一个查询中执行多个不同的操作。

  • HAVING 语句:

having 子句可以让我们筛选分组后的各组数据。

where 子句在所选列上设置条件,而 having 子句则在由 group by 子句创建的分组上设置条件。

语法:

# having 子句在查询语句中的位置
select
from
where
group by
having
order by
#例(找出根据 name 字段值进行分组,并且 name(名称) 字段的计数少于2的数据):
select name from company group by name having count(name) < 2;
  • DISTINCT 关键字:

distinct 关键字与 select 语句一起使用,用于去重记录,只获取唯一的记录。

语法:

select distinct column1,column2,...,columnN from table_name where ...;

PostgreSQL高级

约束

约束用于规定表中的数据规则。

如果存在违反约束的数据行为,行为会被约束终止。

约束可以在创建表时规定(通过 create 语句),或者在表创建之后规定(通过 alter 语句)。

约束确保了数据库中数据的准确性和可靠性。

约束可以是 列级 或 表级。列级约束仅适用于列,表级约束被应用到整个表。

常用的约束:

  • not null:保证某列不能存储 null 值。

create table table_name(
	id int not null
)
  • unique:保证某列的值都是唯一的。

create table table_name(
	id int not null,
    account varcahr(20) not null unique
)
  • primary key:not null 和 unique 的结合。确保某列(或两个列或多个列的结合)有唯一的标识。有助于更容易更快速地找出表中的某个特定记录。

primary key 称为主键,是数据表中每一条记录的唯一标识。设置 unique 的列可能有多个,但是一张表只有一列可以设置 primary key。

create table table_name(
	id int primary key not null
)
  • foreign key:保证一个表中的数据匹配到另一个表中的值的参照完整性。

foreign key 即外键约束,指定列(或一组列)中的值必须匹配另一个表中的某一行中出现的值。通常一个表中的 foreign key 指向另一个表中的 unique key(唯一约束的键),即维护了两个相关表之间的引用完整性。

#表一:
create table user(
	id int primary key
)
#表二:
create table stuff(
	id int primary key,
    user_id int references user(id)
)
  • check:保证列中的值复合指定的条件。

check 约束保证列中的所有值满足某一条件,即对输入一条记录进行检查。如果条件值为 false,则记录违反了约束,且不能输入到表。

#为 salary 列添加 check ,所以工资不能为 0:
create table company(
	id int primary key not null,
    name text not null,
    age int not null,
    address char(50),
    salary real check(salary > 0)
)
  • exclusion:排他约束,保证如果将任何两行的指定列或表达式使用指定操作符进行比较,至少其中一个操作符比较将会返回 false 或 空值。

exclision 约束确保如果使用指定的运算符在指定列或表达式上比较任意两行,至少其中一个运算符比较将返回 false 或null。

#如果满足 name 相同,age 不同则不允许插入,否则允许插入,其比较的结果是如果整个表达式返回 true,则不允许插入,否则允许
create table company(
	id int primary key not null,
    name text,
    age int,
    ...
    exclude using gist
    (name with =,
      age with <>)
);

删除约束:

删除约束必须知道约束名称,已经知道名称来删除约束很简单,如果不知道名称,可以使用 \d 表名 找到信息。

alter table 表名 drop constraint 约束名;

连接(JOIN)

join 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。

在 PostgreSQL 中,join 有 5 种连接方式:

  • cross join:交叉连接
  • inner join:内连接
  • left outer join:左外连接
  • reght outer join:右外连接
  • full outer join:全外连接

实例

表一 表二
image-20220304175502147

交叉连接

交叉连接把第一个表的每一行与第二个表的每一行进行匹配。如果两个输入表分别有x和y行,则结果表有x*y行。

由于交叉连接可能会产生非常大的表,使用时必须谨慎,只在适当的时候使用它们。

语法:

select ... from a cross join b ...

例:

select emp_id,name,dept from company cross join department;
结果

内连接

内连接根据连接谓词结合两个表(a 和 b)的列值来创建一个新的结果集。查询会把 a 中的每一行与 b 中的每一行进行比较,找到所有满足连接谓词的行的匹配对。

当满足连接谓词时,a 和 b 行的每个匹配对的列值会合并成一个结果行。

内连接是最常见的连接类型,是默认的连接类型。

语法:

select a.column1,b.column2...
from a
inner join b
on a.common_filed = b.common_filed;

例:

select emp_id,name,dept from company inner join department on company.id = department.emp_id;
结果
image-20220304183303713

左外连接

外部连接时内部连接的扩展。sql标准定义了三种类型的外部连接:left、right 和 full。

对于左外连接,首先执行一个内连接。然后,对于表 a 中不满足表 b 中连接条件的每一行,其中 b 的列中有 null 值也会添加一个连接行。因此,连接的表在 a 中的每一行至少有一行。

基础语法:

select ... from table1 left outer join table2 on ...;

例:

select emp_id,name,dept from company left outer join department on company.id = department.emp_id;
结果
image-20220307093030343

右外连接

首先执行内部连接。然后对表 b 中不满足表 a 中连接条件的每一行,其中 a 列中的值为空也会添加一个外连接。这与左连接相反;对于 b 中的每一行,结果表总有一行。

基本语法:

select ... from a right outer join b on ...;

例:

select emp_id,name,dept from company right outer join department on company.id = department.emp_id;
结果
image-20220307093715533

外连接

首先执行内连接。然后对表 a 中不满足表 b 中任何行连接条件的每一行,如果 b 的列中有 null 值也会添加一个到结果中。此外,对于 b 中不满足于 a 中的任何行连接条件的每一行,将会添加 a 列中包含 null 值的到结果中。

语法:

select ... from a full outer join b on ...;

例:

select emp_id,name,dept from company full outer join department on company.id = department.emp_id;
结果
image-20220307094255668

UNION 操作符

union 操作符合并两个或多个 select 语句的结果集。

需注意,union 内部的每个 select 语句必须有相同数量的列,列也必须有相似的数据类型。同时每个 select 语句中的列的顺序必须相同。

语法:

select column1,...,columnN from a where ... union select column1,...,columnN from a where ...;
表company 表department
image-20220307095606378 image-20220307095617257

例:

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
结果
image-20220307100022929

UNION ALL 子句

union all 操作符可以连接两个有重复行的 select 语句,默认的,union 操作符选取不同的值。如果允许重复的值,请使用 union all。

语法:

select column1,...,columnN from a where ... union all select column1,...,columnN from a where ...;

例:

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
结果
image-20220307101124118

NULL 值

语法:

#例一:
create tablea table_name(
	id int not null,
    ...
);
#例二:
update table_name set address = null,salary = null where id in(6,7);
#例三:
select * from table_name where salary is not null;
select * from table_name where address is null;

别名

我们可以用 SQL 重命名一张表或一个字段的名称,这个名称就叫做该表或该字段的别名。

创建别名是为了让表名或列名的可读性更强。

SQL 中使用 AS 来创建别名。

例:

select c.id,c.name,c.age,d.dept from company as c,department as d where c.id = d.emp_id;

触发器

触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行。

重要的点:

  • 触发器可在下面几种情况下触发:
    • 执行操作前(在检查约束并尝试插入、更新或删除之前)。
    • 在执行操作之后。
    • 更新操作(对一个视图进行插入、更新、删除时)。
  • 触发器的 for each row 属性是可选的,如果选中,当操作修改时每行调用一次;相反,选中 for each statement ,不管修改了多少行,每个语句标记的触发器执行一次。
  • when 子句和触发器操作在引用 new.column 和 old.colunn 表单插入、删除或更新时可以访问每一行元素。其中 column 是与触发器关联的表中列的名称。
  • 如果存在 when 子句,触发器只会执行 when 子句成立的哪一行,如果没有 when 子句,触发器会在每一行执行。
  • before 或 after 关键字决定何时执行触发器,决定是在关联行的插入、修改或删除之前或之后执行触发器。
  • 要修改的表必须必须存在于同一数据库中,作为触发器被附加的表或视图,且必须只使用 tablename,而不是 database.tablename。
  • 当创建约束触发器时会指定约束选项。这与常规触发器相同,只是可以是使用这种约束来调整触发器触发的时间。当约束触发器实现的约束被违反时,它将抛出异常。

语法:

create trigger trigger_name [before|after|instead of] event_name
on table_name
[
    --触发器逻辑...
];

例:

create trigger example_tigger after insert on company for each row execute procedure auditlogfunc();
#其中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;

列出触发器:

select * from pg_trigger;

image-20220307112707905

列出特定表的触发器:

select tgname from pg_trigger,pg_class where tgrelid=pg_class.oid and relname='company';

image-20220307112941823

删除触发器:

drop trigger ${trigger_name} on ${table_of_trigger_dependent};

#删除上表company上的触发器 example_trigger的指令为:
drop trigger example_trigger on company;

索引

索引是加速搜索引擎检索数据的一种特殊表查询。简单说,索引是一个指向表中数据的指针。一个数据库中的索引与一本书的索引目录是非常相似的。

索引有助于加快 select 查询和 where 子句,但会减慢使用 update 和 insert 语句时的数据输入。索引可以创建和删除,不会影响数据。

创建索引:

create index index_name on table_name;

删除索引:

drop index index_name;

索引类型

  • 单列索引

单例索引是一个只基于表的一个列上创建的索引,语法如下:

create index index_name on table_name(column1);
  • 组合索引

组合索引是基于表的多个列上创建的索引,语法如下:

create index index_name on table_name(column1,column2,...);

不管是单列索引还是组合索引,该索引必须在 where 子句的过滤条件中使用非常频繁的列。

  • 唯一索引

使用唯一索引不仅是为了性能,同时也是为了数据的完整性。唯一索引不允许任何重复的值插入到表中,语法如下:

create unique index index_name on table_name(column1);
  • 局部索引

局部索引是在表的子集上构建的索引,子集由一个条件表达式上定义。索引只包含满足条件的行,语法如下:

create index index_name on table_name(conditional_expression);
  • 隐式索引

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

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

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

ALTER TABLE 命令

alter table 命令用于添加,修改,删除一张已存在表的列。也可以用于添加和删除约束。

语法:

#添加列
alter table table_name add column_name datatype;
#删除列
alter table table_name drop column column_name;
#修改某列数据类型
alter table table_name alter column column_name type datatype;
#添加 not null 约束
alter table table_name alter column_name datatype not null;
#添加 unique 约束
alter table table_name add constraint myuniqueconstraint unique(column1,column2,...);
#添加 check 约束
alter table table_name add constraint myuniqueconstraint check(condition);
#添加主键
alter table table_name add constraint myprimarykey primary key(column1,column2...);
#删除约束
alter table table_name drop constraint myuniqueconstraint;
#删除主键
alter table table_name drop constraint myprimarykey;

TRUNCATE TABLE

PostgreSQL 中 truncate table 用于删除表的数据,但不删除表结构。

truncate table 与 delete 具有相同效果,但是由于它实际上不扫描表,所以速度快。此外,truncate table 可以立即释放表空间,而不需要后续的 vacuum 操作,这在大型表上非常有用。

语法:

truncate table table_name;

视图(VIEW)

视图是一张假表,只不过是通过相关的名称存储在数据库中的一个PostgreSQL语句。

实际上是一个以预定义的postgresql查询形式存在的表的组合。

可以包含一个表的所有行或从一个或多个表选定行。

可以从一个或多个表创建,这取决于要创建视图的查询。

是一种虚拟表,允许用户实现以下几点:

  • 用户或用户组认为更自然或直观查找结构数据的方式。
  • 限制数据访问,用户只能看到有限的数据,而不是完整的表。
  • 汇总各种表中的数据,用于生成报告。

视图是只读的,因此无法在视图上执行 delete、insert 或 update 语句。但可以在时涂上创建一个触发器,当尝试 delete、insert 或 update 视图时触发,需要做的动作在触发器内容中定义。

创建视图:

如果使用了可选的 temp 或 temporary 关键字,则将在临时数据库中创建视图。

create [temp | temporary] view view_name as
select column1,column2,...columnN
from table_name
where ...;

例:

create view company_view as
select id,name,age
from company;

创建好之后,可以查询视图,与实际查询表的方式类似:

select * from company_view;

删除视图:

drop view view_name;

事务

事务 是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。

数据库事务通常包含了一个序列的对数据库的 读/写 操作。包含以下两个目的:

  • 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

如果事务中有操作没有成完成,则事务中所有的操作都要回滚,回到事务执行前的状态。同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立运行。

事务的属性

事务具有以下四个标准属性,通常根据首字母缩写为ACID:

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

事务控制

使用以下命令来控制事务:

  • begin transaction:开始一个事务

事务可以使用 begin transaction 或简单的 begin 命令来启动。此类事务通常会持续执行下去,知道遇到下一个 commit 或 rollback 命令。不过在数据库关闭或发生错误时,事务处理也会回滚。以下是启动一个事务的简单语法:

begin;
或者
begin transaction;
  • commit:事务确认,或者可以使用 end transaction 命令

commit 命令是用于把事务调用的更改保存在数据库中的事务命令,即确认事务。

commit;
或者
end transaction;
  • rollback:事务回滚

rollback 命令是用于撤销尚未保存到数据库的事务命令,即回滚事务。

rollback;

例:

begin;
delete from company where age = 25;
rollback;
begin;
delete from company where age = 25;
commit;

锁(LOCK)

锁主要是为了保持数据库数据的一致性,可以阻止用户修改一行或整个表,一般用在并发较高的数据库中。

在多个用户访问数据库时,如果对并发操作不加控制就可能会读取和存储不准确的数据,破坏数据库的一致性。

数据库中有两种基本的锁:排它锁 和 共享锁。

如果数据对象加上排它锁,则其他的事务不能对它读取和修改。

如果加上共享锁,则该数据对象可以被其他事务读取,但不能修改。

LOCK 命令语法

lock [table]
table_name
in
lock_mode
  • table_name:要锁定的现有表的名称。如果只在表名之前指定,则只锁定该表。如果未指定,则锁定该表及所有子表。
  • lock_mode:锁定模式指定该锁与哪个锁冲突。如果没有指定锁定模式,则使用限制最大的访问独占模式。可能的值是:ACCESS SHARE,ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE,ACCESS EXCLUSIVE。

一旦获得了锁,锁将在当前事务的其余时间保持。没有解锁表命令;所总是在事务结束时释放。

死锁

当两个事务彼此等待对方完成其操作时,可能会发生死锁。尽管 postgresql 可以检测它们并以回滚结束它们,但死锁任然很不方便。为了防止应用程序遇到这个问题,请确保将应用程序设计为以相同的顺序锁定对象。

咨询锁

postgresql 提供了创建具有相同应用程序定义含义的锁的方法,被称为资讯锁。由于系统不强制使用它们,所以正确使用它们取决于应用程序。资讯锁对于不合适 mvcc 模型的锁定策略非常有用。

例:

#将 company 表锁定为 access exclusive 模式。
lock table company in access exclusive mode;

子查询

子查询又称内部查询、嵌套查询。指在查询中的 where 子句中嵌入查询语句。

一个 select 语句的查询结果可以作为另一个语句的输入值。

以下是子查询必须遵守的几个规则:

  • 子查询必须用括号括起来。
  • 子查询在 SELECT 子句中只能有一个列,除非在主查询中有多列,与子查询的所选列进行比较。
  • ORDER BY 不能用在子查询中,虽然主查询可以使用 ORDER BY。可以在子查询中使用GROUP BY,功能与 ORDER BY 相同。
  • 子查询返回多于一行,只能与多值运算符一起使用,如 IN 运算符。
  • BETWEEN 运算符不能与子查询一起使用,但是,BETWEEN 可在子查询内使用。

实例:

select * from company where id in (select id from company where salary > 45000);

insert into company select * from company where id in (select id from company);

update company set salary = salary * 0.5 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);

自动增长(AUTO INCREMENT)

auto increment 会在新纪录插入表中是生成一个唯一的数字。

postgresql 使用序列来表示字段的自增长,数据类型有 smallserial、serial 和 bigserial。这些属性类似于 mysql 数据库支持的 auto_increment 属性。

mysql 设置自增的语句:

create table if not exists t1(
	id int using auto_increment,
    name varchar(20) not null
);

mysql 是用 auto_increment 这个属性来标识字段的自增。

postgresql 使用序列来标识字段的自增长:

create table t1(
	id serial not null,
    alttext text
);

smallserial、serial 和 bigserial 范围:

伪类型 存储大小 范围
samllserial 2字节 1 - 32767
serial 4字节 1 - 2147483647
bigserial 8字节 1- 9223372036854775807

语法:

create table tablename(
	column serial
);

例:

create table company(
	id serial primary key,
    name text not null,
    age int not null
);

权限

无论何时创建数据库对象,都会为其分配一个所有者,所有者通常是执行 create 语句的人。

对于大对数类型的对象,初始状态时只有所有者(或超级用户)才能修改或删除。要允许其他角色或用户使用它,必须为该用户设置权限。

在 postgresql 中,权限被分为以下几种:

  • select
  • insert
  • update
  • delete
  • truncate
  • references
  • trigger
  • create
  • connect
  • temporary
  • execute
  • usage

根据对象的类型(表、函数等),将指定权限应用于该对象。

要向用户分配权限,可以使用 graint 命令。

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:要授予权限的用户名。

另外,可以使用 revoke 命令取消权限,语法:

revoke privilege
on object
from {public | GROUP group | username}

实例:

#为用户 runoob 分配权限
graint all on company to runoob;
#撤销用户 runoob 的权限
revoke all on company from runoob;
#删除用户
drop user runoob;

常用函数

postgresql 内置函数也称为聚合函数,用于对字符串或数字数据执行处理。

下面是所有通用 postgresql 内置函数的列表:

  • COUNT 函数:用于计算数据库表中的行数。
  • MAX 函数:用于查询某一特定列中最大值。
  • MIN 函数:用于查询某一特定列中最小值。
  • AVG 函数:用于计算某一特定列中平均值。
  • SUM 函数:用于计算数字列所有值的总和。
  • ARRAY 函数:用于输入值(包括null)添加到数组中。
  • Numeric 函数:完整列出一个 SQL 中所需的操作数的函数。
  • String 函数:完整列出一个 SQL 中所需的操作字符的函数。

数学函数

函数 返回类型 描述 例子 结果
abs(x) 绝对值 abs(-17.4) 17.4
cbrt(double) 立方根 cbrt(27.0) 3
ceil(double/numeric) 不小于参数的最小的整数 ceil(-42.8) -42
degrees(double) 把弧度转为角度 degrees(0.5) 28.6478897565412
exp(double/numeric) 自然指数 exp(1.0) 2.71828182845905
floor(double/numeric) 不大于参数的最大整数 floor(-42.8) -43
ln(double/numeric) 自然对数 ln(2.0) 0.693147180559945
log(double/numeric) 10为底的对数 log(100.0) 2
log(b numeric,x numeric) numeric 指定底数的对数 log(2.0, 64.0) 6.0000000000
mod(y, x) 取余数 mod(9,4) 1
pi() double "π"常量 pi() 3.14159265358979
power(a double, b double) double 求a的b次幂 power(9.0, 3.0) 729
power(a numeric, b numeric) numeric 求a的b次幂 power(9.0, 3.0) 729
radians(double) double 把角度转为弧度 radians(45.0) 0.785398163397448
random() double 0.0到1.0之间的随机数值 random()
round(double/numeric) 圆整为最接近的整数 round(42.4) 42
round(v numeric, s int) numeric 圆整为s位小数数字 round(42.438,2) 42.44
sign(double/numeric) 参数的符号(-1,0,+1) sign(-8.4) -1
sqrt(double/numeric) 平方根 sqrt(2.0) 1.4142135623731
trunc(double/numeric) 截断(向零靠近) trunc(42.8) 42
trunc(v numeric, s int) numeric 截断为s小数位置的数字 trunc(42.438,2) 42.43

三角函数

函数 描述
acos(x) 反余弦
asin(x) 反正弦
atan(x) 反正切
atan2(x, y) 正切 y/x 的反函数
cos(x) 余弦
cot(x) 余切
sin(x) 正弦
tan(x) 正切

字符串函数和操作符

函数 返回类型 描述 例子 结果
string 丨丨 string text 字串连接 ‘Post’ 丨丨 ‘greSQL’ PostgreSQL
bit_length(string) int 字串里二进制位的个数 bit_length(‘jose’) 32
char_length(string) int 字串中的字符个数 char_length(‘jose’) 4
convert(string using conversion_name) text 使用指定的转换名字改变编码。 convert(‘PostgreSQL’ using iso_8859_1_to_utf8) ‘PostgreSQL’
lower(string) text 把字串转化为小写 lower(‘TOM’) tom
octet_length(string) int 字串中的字节数 octet_length(‘jose’) 4
overlay(string placing string from int [for int]) text 替换子字串 overlay(‘Txxxxas’ placing ‘hom’ from 2 for 4) Thomas
position(substring in string) int 指定的子字串的位置 position(‘om’ in ‘Thomas’) 3
substring(string [from int] [for int]) text 抽取子字串 substring(‘Thomas’ from 2 for 3) hom
substring(string from pattern) text 抽取匹配 POSIX 正则表达式的子字串 substring(‘Thomas’ from ‘…$’) mas
substring(string from pattern for escape) text 抽取匹配SQL正则表达式的子字串 substring(‘Thomas’ from ‘%#“o_a#”_’ for ‘#’) oma
trim([leading丨trailing 丨 both] [characters] from string) text 从字串string的开头/结尾/两边/ 删除只包含characters(默认是一个空白)的最长的字串 trim(both ‘x’ from ‘xTomxx’) Tom
upper(string) text 把字串转化为大写。 upper(‘tom’) TOM
ascii(text) int 参数第一个字符的ASCII码 ascii(‘x’) 120
btrim(string text [, characters text]) text 从string开头和结尾删除只包含在characters里(默认是空白)的字符的最长字串 btrim(‘xyxtrimyyx’,‘xy’) trim
chr(int) text 给出ASCII码的字符 chr(65) A
convert(string text, [src_encoding name,] dest_encoding name) text 把字串转换为dest_encoding convert( ‘text_in_utf8’, ‘UTF8’, ‘LATIN1’) 以ISO 8859-1编码表示的text_in_utf8
initcap(text) text 把每个单词的第一个子母转为大写,其它的保留小写。单词是一系列字母数字组成的字符,用非字母数字分隔。 initcap(‘hi thomas’) Hi Thomas
length(string text) int string中字符的数目 length(‘jose’) 4
lpad(string text, length int [, fill text]) text 通过填充字符fill(默认为空白),把string填充为长度length。 如果string已经比length长则将其截断(在右边)。 lpad(‘hi’, 5, ‘xy’) xyxhi
ltrim(string text [, characters text]) text 从字串string的开头删除只包含characters(默认是一个空白)的最长的字串。 ltrim(‘zzzytrim’,‘xyz’) trim
md5(string text) text 计算给出string的MD5散列,以十六进制返回结果。 md5(‘abc’)
repeat(string text, number int) text 重复string number次。 repeat(‘Pg’, 4) PgPgPgPg
replace(string text, from text, to text) text 把字串string里出现地所有子字串from替换成子字串to。 replace(‘abcdefabcdef’, ‘cd’, ‘XX’) abXXefabXXef
rpad(string text, length int [, fill text]) text 通过填充字符fill(默认为空白),把string填充为长度length。如果string已经比length长则将其截断。 rpad(‘hi’, 5, ‘xy’) hixyx
rtrim(string text [, character text]) text 从字串string的结尾删除只包含character(默认是个空白)的最长的字 rtrim(‘trimxxxx’,‘x’) trim
split_part(string text, delimiter text, field int) text 根据delimiter分隔string返回生成的第field个子字串(1 Base)。 split_part(‘abc@def@ghi’, ‘@’, 2) def
strpos(string, substring) text 声明的子字串的位置。 strpos(‘high’,‘ig’) 2
substr(string, from [, count]) text 抽取子字串。 substr(‘alphabet’, 3, 2) ph
to_ascii(text [, encoding]) text 把text从其它编码转换为ASCII。 to_ascii(‘Karel’) Karel
to_hex(number int/bigint) text 把number转换成其对应地十六进制表现形式。 to_hex(9223372036854775807) 7fffffffffffffff
translate(string text, from text, to text) text 把在string中包含的任何匹配from中的字符的字符转化为对应的在to中的字符。 translate(‘12345’, ‘14’, ‘ax’) a23x5

类型转换相关函数

函数 返回类型 描述 实例
to_char(timestamp, text) text 将时间戳转换为字符串 to_char(current_timestamp, ‘HH12:MI:SS’)
to_char(interval, text) text 将时间间隔转换为字符串 to_char(interval ‘15h 2m 12s’, ‘HH24:MI:SS’)
to_char(int, text) text 整型转换为字符串 to_char(125, ‘999’)
to_char(double precision, text) text 双精度转换为字符串 to_char(125.8::real, ‘999D9’)
to_char(numeric, text) text 数字转换为字符串 to_char(-125.8, ‘999D99S’)
to_date(text, text) date 字符串转换为日期 to_date(‘05 Dec 2000’, ‘DD Mon YYYY’)
to_number(text, text) numeric 转换字符串为数字 to_number(‘12,454.8-’, ‘99G999D9S’)
to_timestamp(text, text) timestamp 转换为指定的时间格式 time zone convert string to time stamp to_timestamp(‘05 Dec 2000’, ‘DD Mon YYYY’)
to_timestamp(double precision) timestamp 把UNIX纪元转换成时间戳 to_timestamp(1284352323)
4

评论区