当前位置:   article > 正文

PostgreSQL修改被视图引用的表的字段_postgres 修改字段 影响视图

postgres 修改字段 影响视图

在pg中,当我们需要修改表的某个字段时,如果该字段刚好被视图引用,必须先将引用的对象删除,才能修改对应的字段。

例如:

bill=# create table test_t (id int, info text, crt_time timestamp, c1 varchar(10));  
CREATE TABLE
bill=# create index idx_test_t on test_t(c1);  
CREATE INDEX
bill=# create view v_test_t as select id,c1 from test_t;
CREATE VIEW
bill=# alter table test_t alter column c1 type varchar(32); 
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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

不过这个情况在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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

那么我们在pg中该如何去修改被视图引用的表的字段呢?
pg中支持将DDL语句封装在事务中处理,所以从删除依赖,到修改字段,再到重建依赖,都可以封装在一个事务中完成。

例子:
不过这种方法需要注意:

  1. DDL是需要对表加排它锁的,排它锁与所有其他锁冲突,因此建议在事务开始时设置锁超时参数,避免问题。
  2. 如果修改字段涉及到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;  -- 结束事务  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

除此之外我们还可以通过修改pg中元数据表的方式去实现。
因为pg的定义都记录在元数据中,所以某些操作,可以直接修改元数据来实现。比如从numeric低精度修改到高精度,从字符串短长度修改到长长度。
但是不建议这么做,直接修改元数据存在隐患,甚至可能对数据库造成不可修复的伤害。

例子:
1、首先查看将要修改的C1字段的pg_attribute元信息

bill=# select attrelid::regclass,* from pg_attribute where attname='c1'; 
  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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在修改时,需要将这三个atttypmod一起修改掉。
变长字段的长度为4字节头+实际长度,所以36表示可以存储32个字符。

2、修改为varchar(64)这样操作

bill=# update pg_attribute set atttypmod=68 where attname='c1' and attrelid in (200125,200136,200137);  
UPDATE 3
  • 1
  • 2

3、查看更新后的结构

bill=# \d+ test_t 
                                              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=# \d+ v_test_t  
                                  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=# \d+ idx_test_t
                          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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/755080
推荐阅读
相关标签
  

闽ICP备14008679号