ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2020-01-21 11:38:02  阅读:1070  来源: 互联网

标签:PostgreSQL bill 视图 修改 引用 test c1 id pg


在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"

不过这个情况在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语句封装在事务中处理,所以从删除依赖,到修改字段,再到重建依赖,都可以封装在一个事务中完成。

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

  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;  -- 结束事务  

除此之外我们还可以通过修改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)

在修改时,需要将这三个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

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"
foucus、 发布了101 篇原创文章 · 获赞 35 · 访问量 9504 私信 关注

标签:PostgreSQL,bill,视图,修改,引用,test,c1,id,pg
来源: https://blog.csdn.net/weixin_39540651/article/details/104060099

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有