当前位置:网站首页>PostgreSQL:无法更改视图或规则使用的列的类型
PostgreSQL:无法更改视图或规则使用的列的类型
2022-07-28 06:58:00 【欧晨eli】
在一次关于 PostgreSQL 的讲座中,一位参与者提出了一个令人费解的问题:如何将ALTER COLUMN一个表级联到一个视图?有两种主要方法:使用 DDL 可交易命令的强大功能或更改系统目录。在这篇文章中,我解释了如何做到这两点。
想象一下,您有一个表和一个在其上构建的视图(动态的或物化的):
> CREATE TABLE t( pk smallint, t char(2) );
> CREATE VIEW vw_t AS SELECT * FROM t;当然,视图和表格都反映了相同的字段结构
> \d t
Table "public.t"
Column | Type | Collation | Nullable | Default
--------|--------------|-----------|----------|---------
pk | smallint | | |
t | character(2) | | |
> \d vw_t
View "public.vw_t"
Column | Type | Collation | Nullable | Default
--------|--------------|-----------|----------|---------
pk | smallint | | |
t | character(2) | | | 如果t表改变结构会发生什么?PostgreSQL 不允许这样做,因为存在来自vw_tover的依赖t:
> ALTER TABLE t ALTER COLUMN t TYPE char(10);
ERROR: cannot alter type of a column used by a view or rule
DETAIL: rule _RETURN on view vw_t depends on column "t"
> ALTER TABLE t ALTER COLUMN pk TYPE bigint;
ERROR: cannot alter type of a column used by a view or rule
DETAIL: rule _RETURN on view vw_t depends on column "pk"该DETAIL消息提供了有关问题的提示:"_RETURN"规则是 PostgreSQL 处理视图的特殊方式:它确实将 `SELECT** 语句反弹到基础表。 只有一个正确的方法可以解决这个问题:由于 PostgreSQL 允许在事务中包含任何 DDL 命令,因此可以使用事务来删除视图、更改表并重新创建视图:
> BEGIN;
> DROP VIEW vw_t;
> ALTER TABLE t ALTER COLUMN pk TYPE bigint;
> ALTER TABLE t ALTER COLUMN t TYPE char(10);
> CREATE VIEW vw_t AS SELECT * FROM t;
> COMMIT;由于不需要像在其他数据库系统中那样编译视图,因此绝不应该在实时系统上不执行上述操作。在无法启动上述事务的极少数情况下,可以更改系统目录以反映所需的结构。检查pg_attribute系统目录显示表是如何定义的:
> SELECT attname, atttypmod, attlen
FROM pg_attribute
WHERE attname IN ( 'pk', 't' )
AND attrelid = 't'::regclass;
attname | atttypmod | attlen
---------|-----------|--------
pk | -1 | 2
t | 6 | -1简而言之,pk作为数字的列没有类型修饰符 ( atttypmod) 和总长度 ( attlen)2字节(它是 a smallint);另一方面,该t列没有特定的长度,但有一个修饰符6,特别是4由长度本身添加(在这种情况下,是 a char(2))2 + 4 = 6。
假设必须更改表以使pka 变为bigint列ta char(10):可以将其强制在目录本身上。虽然可以t直接在目录上修改列以增加类型修饰符长度,但这在pk列上是不可能的,因为pg_attribute.attlen它不是真实值,而是pg_type.typlen如图所示的副本在pg_attribute文档中。因此,t表的更新必须按如下方式进行: 1)改变数值列的类型pk;2) 更改列的类型修饰符长度t,将 PostgreSQL 预订所需的 4 个字节添加到所需值。
上述两步必须以超级用户身份执行,因此如果无法获得超级用户权限,则无法通过系统目录更新表结构。还需要注意的是,里面的名字pg_type不是 SQL 名字,而是 PostgreSQL 内部名字;换句话说,该bigint类型被命名int8。
让我们看看实际的过程:
# BEGIN;
# UPDATE pg_attribute
SET atttypid =
( SELECT oid
FROM pg_type
WHERE typname = 'int8' )
WHERE attname = 'pk'
AND attrelid = 't'::regclass;
# UPDATE pg_attribute SET atttypmod = 14
WHERE attname = 't'
AND attrelid = 't'::regclass;
# \d t
Table "public.t"
Column | Type | Collation | Nullable | Default
--------|---------------|-----------|----------|---------
pk | bigint | | |
t | character(10) | | |
# \d vw_t
View "public.vw_t"
Column | Type | Collation | Nullable | Default
--------|--------------|-----------|----------|---------
pk | smallint | | |
t | character(2) | | |
-- if ready commit changes ...当然,这不是必需的,所以我强烈反对提交上述事务。需要针对整个依赖对象(在这种情况下vw_t)重播相同的语句。如果视图保持其旧结构,则可能会出现奇怪的行为,因为可以定期读取提取的值(即,t列将受到基础表的限制,因此 a char(10))但是视图的更新可能会导致数据截断。
同样,在 PostgreSQL 中执行这种结构更改的正确方法是使用普通事务,一旦表发生更改,删除依赖对象并在同一事务中重新创建它们。
使用系统目录时要格外小心,并确保在更改数据之前对数据进行有效备份,因为这不是让 PostgreSQL 保护数据的预期方式!
边栏推荐
- Unity中队列(Queue)的简单使用
- 百度智能云九州区县大脑,描绘城乡新蓝图!
- Sparksql and flinksql create and link table records
- 2022 Niuke multi school first problem solving Report
- SQL Server查询结果导出到EXCEL表格
- What happens when you unplug the power? Gaussdb (for redis) dual life keeps you prepared
- CarSim simulation quick start (10) - Modeling of braking system
- [mindspire YiDianTong robot-01] you may have seen many Knowledge Q & A robots, but this is a little different
- Brief introduction to ThreadLocal class
- Prescan quick start to master the track editing path of Lecture 16
猜你喜欢

Find out whether the number exists from the matrix

Five screens, VR, projection, "Wei Xiaoli" rolled up on the intelligent cockpit

PMP practice once a day | don't get lost in the exam -7.13

2022牛客多校第一场解题报告

Prescan quick start to master the road elements of lecture 15

解决EMC、EMI传导干扰的八大方法

C#,入门教程——程序运行时的调试技巧与逻辑错误探针技术与源代码

SQL Server查询结果导出到EXCEL表格

EMC EMI磁珠的特性
![[pyqt] pyqt development experience_ How to find events and methods of controls](/img/40/7597d6413c88793e22276325d5f602.png)
[pyqt] pyqt development experience_ How to find events and methods of controls
随机推荐
How to set it to pop up the right-click menu
金属质感登录框样式
[pyqt] pyqt development experience_ How to find events and methods of controls
DCL singleton mode
JS cartoon English alphabet typing game source code
How to use QT help documents
5张图告诉你:同样是职场人,差距怎么这么大?
SQL注入 ----前置基础
Get the clicked line number in qtablewidget
‘全局事件总线’&‘消息订阅与发布’
微信小程序----微信小程序浏览pdf文件
MCU IO port controls 12V voltage on and off, MOS and triode circuit
[reprint] man Rsync translation (Chinese Manual of Rsync command)
Chairman tree review
Half bridge buck circuit - record
业务数字化飞速奔跑,管理数字化亟待出发
Matlab (3) matlab program flow control statement
Brief introduction to ThreadLocal class
File operation of QT
Tell you step by step what you need to do to apply for PMP? What should I do?