在pg中,当我们需要修改表的某个字段时,如果该字段刚好被视图引用,必须先将引用的对象删除,才能修改对应的字段。
bill=
CREATE TABLE
bill=
CREATE INDEX
bill=
CREATE VIEW
bill=
psql: ERROR: cannot alter type of a column used by a view or rule
DETAIL: rule _RETURN on view v_test_t depends on column "c1"
不过这个情况在oracle中并不存在:
SQL> create table test_t (id int, info varchar2(100), crt_time timestamp, c1 varchar(10));
Table created.
SQL> create index idx_test_t on test_t(c1);
Index created.
SQL> create view v_test_t as select id,c1 from test_t;
View created.
SQL> alter table test_t modify(c1 varchar(32));
Table altered.
那么我们在pg中该如何去修改被视图引用的表的字段呢?
pg中支持将DDL语句封装在事务中处理,所以从删除依赖,到修改字段,再到重建依赖,都可以封装在一个事务中完成。
例子:
不过这种方法需要注意:
- DDL是需要对表加排它锁的,排它锁与所有其他锁冲突,因此建议在事务开始时设置锁超时参数,避免问题。
- 如果修改字段涉及到rewrite table(例如int改到text),那么表很大时间会很久。如果需要很久,意味着需要长时间持有排它锁(堵塞也是比较严重的)。
begin;
set local lock_timeout = '1s';
drop view v_test_t;
alter table test_t alter column c1 type varchar(32);
create view v_test_t as select id,c1 from test_t;
end;
除此之外我们还可以通过修改pg中元数据表的方式去实现。
因为pg的定义都记录在元数据中,所以某些操作,可以直接修改元数据来实现。比如从numeric低精度修改到高精度,从字符串短长度修改到长长度。
但是不建议这么做,直接修改元数据存在隐患,甚至可能对数据库造成不可修复的伤害。
例子:
1、首先查看将要修改的C1字段的pg_attribute元信息
bill=
attrelid | attrelid | attname | atttypid | attstattarget | attlen | attnum | attndims | attcacheoff | atttypmod | attbyval | attstorage | attalign | attnotnull | atthasdef | atthasmissing | attiden
tity | attgenerated | attisdropped | attislocal | attinhcount | attcollation | attacl | attoptions | attfdwoptions | attmissingval
test_t | 200125 | c1 | 1043 | -1 | -1 | 4 | 0 | -1 | 36 | f | x | i | f | f | f |
| | f | t | 0 | 100 | | | |
idx_test_t | 200136 | c1 | 1043 | -1 | -1 | 1 | 0 | -1 | 36 | f | x | i | f | f | f |
| | f | t | 0 | 100 | | | |
v_test_t | 200137 | c1 | 1043 | -1 | -1 | 2 | 0 | -1 | 36 | f | x | i | f | f | f |
| | f | t | 0 | 100 | | | |
(3 rows)
在修改时,需要将这三个atttypmod一起修改掉。
变长字段的长度为4字节头+实际长度,所以36表示可以存储32个字符。
2、修改为varchar(64)这样操作
bill=
UPDATE 3
3、查看更新后的结构
bill=
Table "public.test_t"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
id | integer | | | | plain | |
info | text | | | | extended | |
crt_time | timestamp without time zone | | | | plain | |
c1 | character varying(64) | | | | extended | |
Indexes:
"idx_test_t" btree (c1)
Access method: heap
bill=
View "public.v_test_t"
Column | Type | Collation | Nullable | Default | Storage | Description
id | integer | | | | plain |
c1 | character varying(64) | | | | extended |
View definition:
SELECT test_t.id,
test_t.c1
FROM test_t;
bill=
Index "public.idx_test_t"
Column | Type | Key? | Definition | Storage | Stats target
c1 | character varying(64) | yes | c1 | extended |
btree, for table "public.test_t"
在pg中,当我们需要修改表的某个字段时,如果该字段刚好被视图引用,必须先将引用的对象删除,才能修改对应的字段。例如:bill=# create table test_t (id int, info text, crt_time timestamp, c1 varchar(10)); CREATE TABLEbill=# create index idx_test_t on test_t(...
这是视图内容: SELECT *
FROM students
WHERE Sex = 'M';修改视图CREATE OR REPLACE VIEW studentBySexAndClass
SELECT *
FROM students
WHERE Sex = 'M' and class='一年级';
ERROR: cannot alter type of a column used by a view or rule.
rule _RETURN on view 相关依赖视图 depends on column "字段名
执行sql
alter table tbname alter COLUMN 字段名 type varchar(500) ;
找了几个大佬博客,有大佬做出相关方
PostgreSQL强制删除正在被使用的库
轰炸大鱿鱼:
PostgreSQL修改被视图引用的表的字段
xiaoyu3538:
PostgreSQL修改被视图引用的表的字段
p&f°: