当前位置:   article > 正文

PostgreSQL常用命令&常见错误_permission denied for schema public

permission denied for schema public

PostgreSQL常用命令

登录数据库shell命令
语法:psql -U User [[-d] DB]
不指定DB时默认登录用户名相同的DB
psql -U postgres -d postgres
psql -U postgres postgres
psql -U postgres
psql -U test -d testdb01
psql -U test testdb01

查看版本信息
show server_version;
show server_version_num;
psql --version
su - postgres
$ psql -version
select version();
 

创建数据库新用户
CREATE USER test WITH PASSWORD '1q2w3e';
注意:语句要以分号结尾,密码要用单引号括起来。

显示所有数据库(相当于show databases;)
\l

创建用户数据库
CREATE DATABASE testdb01 OWNER test;

将数据库的所有权限赋予用户
GRANT ALL PRIVILEGES ON DATABASE testdb01 TO test;

修改数据库的owner为test用户(如果创建时未指定owner、也可以通过alter命令指定)
alter database testdb01 owner to test;

将schema中all权限赋予给指定用户(管理员账号在对应DB中执行grant命令授权,授权给test用户为例)
\c testdb01
\c - postgres
grant all on schema public to test;

获取当前db中所有的表信息:
select * from pg_tables;

查看用户的所有表(用户自定义的表,如果未经特殊处理,默认都是放在名为public的schema下)
select tablename from pg_tables where schemaname='public';

切换数据库
\c testdb01

切换用户
\c - test

也可以登录时指定数据库
psql -U test testdb01

获取当前db中所有的表信息:
select * from pg_tables;

查看用户的所有表(用户自定义的表,如果未经特殊处理,默认都是放在名为public的schema下)
select tablename from pg_tables where schemaname='public';

创建表 & 插入数据
create table test01(
id integer not null,
name character(255) not null,
price decimal(8,2) not null,
primary key(id)
);

insert into test01(id,name,price) values (1,'a',11.5),(2,'b',20.3);

查看表结构
\d test01;
\d+ test01;

查看表的数据
select * from test01;

PostgreSQL查询表的实际数据存储类型:
SELECT 
    col.ordinal_position, 
    col.column_name , 
    col.udt_name , 
    col.character_maximum_length, 
    col.numeric_precision, 
    col.numeric_scale, 
    col.is_nullable, 
    des.description 
FROM  
    information_schema.columns col LEFT JOIN pg_description des 
    ON col.table_name::regclass = des.objoid 
    AND col.ordinal_position = des.objsubid 
WHERE  
    table_name = 'mytable' ;

PostGIS(geometry)时空数据类型相关
#geom_test01
CREATE TABLE geom_test01(id integer not null, name varchar(255), primary key(id));
SELECT AddGeometryColumn('geom_test01', 'zone_geom', 4326, 'POINT', 2);

INSERT INTO geom_test01(id, zone_geom, name) VALUES (1, ST_GeomFromText('POINT(-0.1250 52.500)',4326), 'test');
INSERT INTO geom_test01(id, zone_geom, name) VALUES (2, ST_GeomFromText('POINT(27.91162480 -33.01532)', 4326),'test');

SELECT * FROM geom_test01;
SELECT id, ST_AsText(zone_geom), ST_AsEwkt(zone_geom), ST_X(zone_geom), ST_Y(zone_geom) FROM geom_test01;

#geom_test02
CREATE TABLE geom_test02(
id integer not null,
zone_geom geometry(point, 4326),
name varchar(255),
primary key(id)
);

INSERT INTO geom_test02(id, zone_geom, name) values (1, st_geomfromtext('point(27.91162480 -33.01532)', 4326), 'aaa');
SELECT * FROM geom_test02;
SELECT id, ST_AsText(zone_geom), ST_AsEwkt(zone_geom), ST_X(zone_geom), ST_Y(zone_geom) FROM geom_test02;

修改密码
ALTER USER postgres with encrypted password '1q2w3e';
ALTER USER test with encrypted password '1q2w3e';

密码过期处理
远程连接提示密码过期报错:ERROR: Your password has expired, please alter password first
解决办法:
方法1)可以通过管理员postgres用户本地shell登录后修改指定用户的密码解决
psql -U postgres -d postgres
ALTER USER test with encrypted password '1q2w3e';

方法2)也可以通过过期用户本地shell登录后修改密码解决;
psql -U test -d testdb01
ALTER USER test with encrypted password '1q2w3e';

查看当前连接用户
select * from current_user;
select user;
如果在shell命令行下也可以执行 \conninfo 查看当前用户和数据库
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
postgres=# 

查看帮助:
postgres=# Help
You are using psql, the command-line interface to PostgreSQL.
Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit
postgres=# 

查看SQL命令帮助:

postgres=# \h
Available help:
  ABORT                            ALTER TEXT SEARCH TEMPLATE       CREATE PUBLICATION            ......
  ......

postgres=# \h show
Command:     SHOW
Description: show the value of a run-time parameter
Syntax:
SHOW name
SHOW ALL

URL: https://www.postgresql.org/docs/12/sql-show.html

查看所有参数的设置:
postgres=# show all;

等同于
postgres=# select *  from pg_settings;

所有参数配置可以通过 pg_settings 视图 select 查看

查看 pg_settings 视图结构:

testdb01=> \d pg_settings;
 name            | text    |           |          | 
 setting         | text    |           |          | 
 unit            | text    |           |          | 
 category        | text    |           |          | 
 short_desc      | text    |           |          | 
 extra_desc      | text    |           |          | 
 context         | text    |           |          | 
 vartype         | text    |           |          | 
 source          | text    |           |          | 
 min_val         | text    |           |          | 
 max_val         | text    |           |          | 
 enumvals        | text[]  |           |          | 
 boot_val        | text    |           |          | 
 reset_val       | text    |           |          | 
 sourcefile      | text    |           |          | 
 sourceline      | integer |           |          | 
 pending_restart | boolean |           |          | 
 

如果想要模糊查询,则通过 pg_settings 视图模糊查询:

testdb01=> select name, setting, short_desc from pg_settings where name like '%version%';

查看参数设置:
postgres=# show port;
postgres=# show max_connections;
postgres=# show max_wal_size;

查看参数配置文件的位置:
postgres=# show config_file;
postgres=# show hba_file;
postgres=# show ident_file;

        

查看psql命令帮助:
postgres=# \?
General
  \copyright             show PostgreSQL usage and distribution terms
  \crosstabview [COLUMNS] execute query and display results in crosstab
  \errverbose            show most recent error message at maximum verbosity
  \g [FILE] or ;         execute query (and send results to file or |pipe)
  \gdesc                 describe result of query, without executing it
  \gexec                 execute query, then execute each value in its result
  \gset [PREFIX]         execute query and store results in psql variables
  \gx [FILE]             as \g, but forces expanded output mode
  \q                     quit psql
  \watch [SEC]           execute query every SEC seconds
......
......

查看系统所有用户角色权限
\du[S+] [PATTERN]      list roles
\du
\du test*
\duS
\duS+

查看当前连接用户和数据库
\conninfo
postgres-# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".

\c[onnect] 也能达到类似效果
postgres-# \c
You are now connected to database "postgres" as user "postgres".
postgres-# 
postgres-# \connect
You are now connected to database "postgres" as user "postgres".

查看表结构
\d tableName


\d 命令
\d 命令可显示每个匹配关系(表,视图,索引,序列)的信息,包括对象所有的列,类型,表空间(如果不是默认的)和任何特殊属性(如NOT NULL或默认值等),以及表大小(Size)、表注释等。与唯一约束相关的索引,规则,约束,触发器也同样会显示出来。如果关系是一个视图,还会显示视图的定义。
如果\d命令什么都不带,将列出当前数据库中的所有表。

\d, \d+
\dt, \dt+
\dn, \dn+
\d pg_tables; ?#也可以通过select查询 select * from pg_tables;
\dt *.
\d public.*
\d public02.*
\d test01
\d public.test01
\dt public.*

\d 显示当前数据库中的所有的表
\d test01 显示test01表的详情
\dt 只显示匹配的表
\dt test* 只列出test开头的表
\dn 显示所有Schema
\dv 显示视图
\di 显示索引
\ds 显示序号
\df 显示函数
\du, \dg 列出数据库所有角色或用户
\dp, \z 显示所有表、视图、sequence的访问权限
\dRp[+] [PATTERN]      list replication publications
\dRs[+] [PATTERN]      list replication subscriptions

注意:
1)\d后面跟一个表名,表示显示这个表的结构定义,如果\d后面跟索引名则显示索引信息。
2)\d+:在显示表或索引等对象时,如果带+号可以显示比\d命令更详细的信息,除了前面介绍的那些,它还会显示任何与表列关联的注释,以及表中出现的ODI,如表大小(Size)等信息
3)\d后面支持通配符*或?

eg:
查看表结构
\d test01
\d geom_test01
\dt test*

显示SQL执行时间
可以执行 \timing on/off 命令后再执行SQL语句
testdb01=> \timing on
Timing is on.
testdb01=> select * from test01;
  1 | a  | 11.50
  2 | b  | 20.30
Time: 0.552 ms

查看schema/设置schema(如果不设置schema,查询时默认为 public)
show search_path;
set search_path to public;
set search_path to public, public02;
注意:仅当前会话生效,如果要数据库全局生效,则执行: alter database "testdb01" set search_path TO public, public02;

创建schema
创建schema public02并授权给test用户all权限
create schema public02;
grant all on schema public02 to test;
set search_path to public02;
注意:仅当前会话生效,如果要数据库全局生效,则执行: alter database "testdb01" set search_path TO public02;

创建索引
create index idx_name on table_name(column_name);

查看历史操作记录(命令行执行记录)
\s

查看字符集
\encoding

查看session信息:
select * from pg_stat_activity;

杀会话/杀进程(kill session):
select * from pg_stat_activity;
select pg_terminate_backend(pid);
 

显示当前默认模式
show search_path

更改默认模式
set search_path to myschema

切换显示模式(行显示|列显示)
\x
 

创建视图:
CREATE OR REPLACE VIEW v_test01 AS SELECT id,name from test01;

显示视图:
\dv

pg_hba.conf 配置文件修改后重载控制文件的方法(三种方法):

方法1. pg_ctl reload -D your_data_directory_here

例如:
先确认data目录,执行命令:
-bash-4.2$ ps aux |grep "\-D" |grep pgsql
postgres   945  0.0  2.5 1056000 202208 ?      Ss    2021 181:43 /usr/pgsql-12/bin/postmaster -D /var/lib/pgsql/12/data/

在重载生效配置(不能用root用户执行)
-bash-4.2$ pg_ctl reload -D /var/lib/pgsql/12/data/
server signaled


方法2. service postgresql-12 reload
postgresql-12 是服务名(ServiceName)

例如:
[root@pgmaster ~]# service postgresql-12 reload
Redirecting to /bin/systemctl reload postgresql-12.service
[root@pgmaster ~]# 

方法3. select pg_reload_conf();

例如:
[root@pgmaster ~]# psql -U postgres
psql (12.8)
Type "help" for help.

postgres=# select pg_reload_conf();
 pg_reload_conf 
----------------
 t
(1 row)

postgres=# 
 

PG常见错误:

> PG删除用户报错:
drop user test;

ERROR:  role "test" cannot be dropped because some objects depend on it
DETAIL:  privileges for schema public

解决方案:

先回收用户权限、再删除
revoke all on schema public from test;
drop user test;

> 新建的PG用户创建表报错:permission denied for schema public

CREATE USER test WITH PASSWORD '1q2w3e';
CREATE DATABASE testdb01 OWNER test;
GRANT ALL PRIVILEGES ON DATABASE testdb01 TO test;
\c testdb01
\c - test
create table test01( id integer not null, name character(255) not null, price decimal(8,2) not null, primary key(id) );
创建表报错:
ERROR:  permission denied for schema public

解决方案:
将schema(public)中all权限赋予给test用户(管理员账号在对应DB中执行grant schema 授权)
\c testdb01
\c - postgres
grant all on schema public to test;

切换用户重新创建表
\c - test
create table test01( id integer not null, name character(255) not null, price decimal(8,2) not null, primary key(id) );
insert into test01(id,name,price) values (1,'a',11.5),(2,'b',20.3);
执行成功

> 密码过期时,远程连接报错
远程连接提示密码过期报错:ERROR: Your password has expired, please alter password first
解决办法:
方法1)可以通过管理员postgres用户本地shell登录后修改指定用户的密码解决
psql -U postgres -d postgres
ALTER USER test with encrypted password '1q2w3e';

方法2)也可以通过过期用户本地shell登录后修改密码解决;
psql -U test -d testdb01
ALTER USER test with encrypted password '1q2w3e';

PostgreSQL中的序列自增

设置表字段的自增属性,PG有三种方式:serial、sequence、identity;

创建表时设置字段 serial 属性,系统会自动创建 sequence (系统自动命名、序列名包含表名)并关联到表对应的字段,drop表时也会自动删除对应的序列;

另外也可以单独创建sequence、再alter table 设置对应字段将序列值赋值给主键:

CREATE SEQUENCE table_xxx_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;

alter table_xxx alter column id set default nextval(table_xxx_seq');  -- 设置id字段自增

但这种方式删除表时不会自动删除sequence;


-- test
create table test52_serial (id serial primary key, info varchar null, cnt int null);
-- CREATE TABLE test52_serial (id int4 NOT NULL DEFAULT nextval('test52_serial_id_serial_seq'::regclass), info varchar NULL, cnt int4 NULL, CONSTRAINT test52_serial_pk PRIMARY KEY (id));  -- 等效

select * from test52_serial;
insert into test52_serial(info,cnt) values('aa',11), ('bb',22); -- 不显示插入自增值由系统自动维护
select * from test52_serial;
select * from pg_class where relkind='S' and relname like '%test52_serial%'; -- list all sequence like test
insert into test52_serial(id,info,cnt) values(3,'cc',33); -- 显示插入自增值
insert into test52_serial(info,cnt) values('dd',44); -- 再插入会报错,自增值已存在的冲突报错
select setval('test52_serial_id_seq', (select coalesce(max(id),1) from test52_serial)::BIGINT); -- 重置最大值,set sequenct to max(id), if null reset to 1
insert into test52_serial(info,cnt) values('dd',44); -- 再重新隐士插入,能够成功

delete from test52_serial where id=4;
update test52_serial set info='ssss' where id=3;
select * from test52_serial;

update test52_serial set id=100,info='ssssnnnn' where id=3;

delete from test52_serial;
select * from pg_class where relkind='S' and relname like '%test52_serial%'; -- list all sequence like test
alter sequence test52_serial_id_seq restart with 1; -- 重置 reset sequence after truncate or delete all;

identity

identity 本质是为了兼容标准sql中的语法而新加的,修复了一些 serial 的缺陷(例如:无法通过 alter table 方式实现增加/删除 serial 字段)。

identity 定义成 By Default 时,例如:id int8 NOT NULL GENERATED BY DEFAULT AS IDENTITY; 则也允许显式插入;

identity 定义成 Always 时,例如:id int8 NOT NULL GENERATED ALWAYS AS IDENTITY; 则申明用户不能显式赋值插入,否则会报错。但如果再加上 overriding system value,例如:insert into t1 (id) overriding system value values (1); 也可以实现显式不插入。

因此,identity 是 serial 的增强版,更适合作为自增列使用。

sequence,serial,identity 三者的共同的缺点是:在显式插入之后,无法将自增值更新为表中的最大id。

数据库oid和表oid查询:

\dS[+] 查看table, view, sequence列表(包括系统的和用户的)

查询database的oid(从 pg_catalog.pg_database 中查询):
pg_catalog.pg_database 系统表中记录了数据库的相关详细信息包括oid
\dS+ pg_database

postgres=> \c - test
postgres=> \c testdb01
testdb01=> select oid,datname,datdba,encoding,datcollate,datistemplate,dattablespace from pg_catalog.pg_database;
  oid  |  datname  | datdba | encoding | datcollate  | datistemplate | dattablespace 
-------+-----------+--------+----------+-------------+---------------+---------------
 14187 | postgres  |     10 |        6 | en_US.UTF-8 | f             |          1663
     1 | template1 |     10 |        6 | en_US.UTF-8 | t             |          1663
 14186 | template0 |     10 |        6 | en_US.UTF-8 | t             |          1663
 16437 | testdb01  |  16436 |        6 | en_US.UTF-8 | f             |          1663
 27237 | testdb02  |  16436 |        6 | en_US.UTF-8 | f             |          1663


database的oid对应了$PGDATA/base目录下的相应的目录:
-bash-4.2$ cd $PGDATA/base
-bash-4.2$ ls -l
total 76
drwx------. 2 postgres postgres  8192 Dec  6  2021 1
drwx------. 2 postgres postgres  8192 Dec  6  2021 14186
drwx------. 2 postgres postgres  8192 Feb 16 19:51 14187
drwx------. 2 postgres postgres 12288 Feb 17 12:33 16437
drwx------. 2 postgres postgres  8192 Feb 17 13:16 27237

testdb01(oid=16437)目录下存储了所有表对应的数据文件:
-bash-4.2$ ls -l $PGDATA/base/16437/  |more
total 2173548
-rw-------. 1 postgres postgres      16384 Feb  6 09:25 112
-rw-------. 1 postgres postgres       8192 Mar 16  2022 113
-rw-------. 1 postgres postgres     114688 Feb 17 13:18 1247
-rw-------. 1 postgres postgres      24576 Feb  6 09:25 1247_fsm
-rw-------. 1 postgres postgres       8192 Mar 16  2022 1247_vm
-rw-------. 1 postgres postgres     671744 Feb 17 12:35 1249
-rw-------. 1 postgres postgres      24576 Nov 18  2022 1249_fsm
-rw-------. 1 postgres postgres       8192 Nov 18  2022 1249_vm
-rw-------. 1 postgres postgres    1515520 Feb 17 09:15 1255
-rw-------. 1 postgres postgres      24576 Feb  6 09:25 1255_fsm
......
-rw-------. 1 postgres postgres       8192 Feb 16 19:44 27217
-rw-------. 1 postgres postgres       8192 Apr  3 10:10 27218
-rw-------. 1 postgres postgres      16384 Apr  3 10:10 27221
-rw-------. 1 postgres postgres       8192 Feb 17 12:36 27223
-rw-------. 1 postgres postgres      16384 Feb 17 12:36 27226
-rw-------. 1 postgres postgres       8192 Feb 17 12:40 27232
-rw-------. 1 postgres postgres      16384 Feb 17 12:40 27235
......
其中:27223 对应的是表 test02(relfilenode=oid=27223)

查询table的oid(从 pg_catalog.pg_class 中查询):
testdb01=> select oid,relname,relnamespace,relfilenode,relowner from pg_catalog.pg_class where relname='test02';
  oid  | relname | relnamespace | relfilenode | relowner 
-------+---------+--------------+-------------+----------
 27223 | test02  |         2200 |       27223 |    16436

其中 rolowner 是表的 owner (rolename) 的oid


查询role的oid(从 pg_catalog.pg_roles 中查询):
testdb01=> select rolname,oid from pg_catalog.pg_roles;
          rolname          |  oid  
---------------------------+-------
 pg_monitor                |  3373
 pg_read_all_settings      |  3374
 pg_read_all_stats         |  3375
 pg_stat_scan_tables       |  3377
 pg_read_server_files      |  4569
 pg_write_server_files     |  4570
 pg_execute_server_program |  4571
 pg_signal_backend         |  4200
 postgres                  |    10
 test                      | 16436
(10 rows)


查询当前数据库下的所有的表列表
testdb01=> \z

testdb01=> \dt[S+]

testdb01=> select tablename, schemaname, tableowner,tablespace from pg_catalog.pg_tables;
查询当前数据库下的用户表(不包含系统表):
testdb01=> select tablename, schemaname, tableowner,tablespace from pg_catalog.pg_tables where schemaname='public';
查询当前数据库下的指定表:
testdb01=> select tablename, schemaname, tableowner,tablespace from pg_catalog.pg_tables where schemaname='public' and tablename='test02';
 tablename | schemaname | tableowner | tablespace 
-----------+------------+------------+------------
 test02    | public     | test       | 
(1 row)
 

PostgreSQL/Greenplum 表复制和临时表合并到最终目的表

1,表复制(基于已有的表创建相同结构的新表)

建表语法官方详细介绍文档连接参考:
https://docs-cn.greenplum.org/v6/ref_guide/sql_commands/CREATE_TABLE.html

创建测试表:
drop table if exists public.test83;
create table public.test83 (
    id int not null,
    info varchar(255) null,
    cnt int null,
    uptime timestamp(6) not null default current_timestamp(6),
    constraint test83_pk primary key (id)
)
-- distributed by (id)
;

复制方式的建表语法: 
create table public.test83_tmp1 (like public.test83 {including | excluding} {defaults | constraints | indexes | storage | comments | all})

复制方式的建表示例(基于 test83 创建新表 test83_tmp1):
create table public.test83_tmp1 (like public.test83); 
或者
create table public.test83_tmp1 (like public.test83 including all); 

注意:如果不加 including all 选项的话,创建的新表不会包含主键和索引等信息的复制创建,加了该选项就会复制主键和索引等相关信息。


基于已有的表复制数据,执行命令:
insert into public.test83_tmp1 select * from public.test83;

2,Greenplum 临时表合并到最终目的表

-- 创建测试表:
drop table if exists public.test84;
create table public.test84 (
    id int not null,
    info varchar(255) null,
    cnt int null,
    uptime timestamp(6) not null default current_timestamp(6),
    constraint test84_pk primary key (id)
)
-- distributed by (id)
;

-- 生成测试数据
insert into public.test84 (id,info,cnt,uptime) values 
 (1,'a',2021,'2021-01-01 13:01:01.123456'), 
 (2,'b',2021,'2021-12-31 15:02:02.222333'),
 (3,'c',2022,'2022-01-01 13:01:01.123456');

select * from public.test84 order by uptime desc;

-- 基于源表创建目的表(表复制)
drop table if exists public.test84_dest;
create table public.test84_dest (like public.test84 including all);

-- 基于源表拷贝数据到目的表(数据复制)
insert into public.test84_dest select * from public.test84;

select * from public.test84_dest order by uptime desc;

-- 修改源表数据(update + insert)
delete from public.test84 where id<=2;
update public.test84 set info='c-02', uptime='2022-01-02 15:05:20.333444' where id=3;
insert into public.test84 (id,info,cnt,uptime) values 
 (4,'d',2023,'2023-01-01 13:01:01.123456'),
 (5,'e',2024, '2024-01-01 13:01:01.123456');
select * from public.test84 order by uptime desc;
 

-- 临时表合并到目的表(但忽略 delete,即 delete 不同步、仅同步 insert + update)
begin;

-- 基于目的表创建生成临时表(仅复制表结构、不含数据)
drop table if exists public.test84_tmp1;
create table public.test84_tmp1 (like public.test84_dest including all);

-- 源表数据拷贝到临时表
insert into public.test84_tmp1 select * from public.test84;
select * from public.test84_tmp1 order by uptime desc;


-- 临时表合并方案1

-- 临时表数据合并到目的表 merge-step1:  delete-from-dest for insert & update records
delete from public.test84_dest where id in (select id from public.test84_tmp1);
select * from public.test84_dest order by uptime desc;

-- 临时表数据合并到目的表 merge-step2:  insert-into-dest for insert & update records
insert into public.test84_dest select * from public.test84_tmp1;
select * from public.test84_dest order by uptime desc;

end;

注意:
1)其中的临时表合并方案也可以根据实际情况采用表重命名(rename)方案,SQL如下:
-- 临时表合并方案2(rename):
drop table if exists test84_old;
alter table public.test84 rename to test84_old;
alter table public.test84_tmp1 rename to test84;

2)用 begin/end 保证提交的SQL在同一个事务中;
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/606160
推荐阅读
相关标签
  

闽ICP备14008679号