当前位置: 首页 > news >正文

PostgreSQL 修改字段类型但是存在视图依赖

其实视图的存在与否在数据库界一直是一个话题。用好视图可以简化程序的很多代码,用不好视图不仅会给维护带来很多的不便,也会造成很大的性能问题。下面我从维护方面给出案例,以及当存在这种问题的时候,如何去解决这个问题。

假设有如下的表和视图
CREATE TABLE view_test (id int,cname varchar(10),des text);
CREATE VIEW vw_view_testa AS SELECT * FROM view_test WHERE id > 2;
CREATE VIEW vw_view_testb AS SELECT * FROM view_test WHERE id < 3;
INSERT INTO view_test(id,cname,des) VALUES (1,'a','value a'),(2,'b','value b'),(3,'c','value c'),(4,'d','value d'),(5,'e','value e');

现在我想修改表的字段 cname 从 varchar(10) 到 varchar(50)
ALTER TABLE view_test ALTER COLUMN cname TYPE VARCHAR(50);

ERROR:  cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view vw_view_testa depends on column "cname"
说明:这个时候会提示存在视图依赖无法修改字段的长度。当视图依赖成为一种嵌套的时候,这种问题在系统升级的时候会严重的影响升级的速度。那么有没有更好的办法去兼容呢。好的架构师需要从根本上解决,一般的业务公司只能是考虑做兼容。

下面是解决视图依赖的解决方案和步骤以及操作案例

CREATE TABLE public.deps_saved_ddl (
  deps_id serial,
  deps_view_schema name,
  deps_view_name name,
  deps_ddl_to_run text,
  PRIMARY KEY (deps_id));
ALTER TABLE public.deps_saved_ddl OWNER TO postgres;

-- 将所有与表依赖的视图进行转储
CREATE OR REPLACE FUNCTION public.deps_save_and_drop_dependencies(p_view_schema name, p_view_name name)
  RETURNS pg_catalog.void AS $BODY$
  DECLARE v_curr record;
  BEGIN FOR v_curr IN (
            SELECT obj_schema,obj_name,obj_type
            FROM ( WITH recursive recursive_deps(obj_schema, obj_name, obj_type, depth) AS
                ( SELECT p_view_schema, p_view_name, null::char,0
                  UNION
                  SELECT dep_schema::name, dep_name::name, dep_type::char, recursive_deps.depth + 1
                  FROM ( SELECT ref_nsp.nspname ref_schema, ref_cl.relname ref_name, rwr_cl.relkind dep_type, rwr_nsp.nspname dep_schema, rwr_cl.relname dep_name
                 FROM pg_depend dep
                 INNER JOIN pg_class ref_cl ON dep.refobjid = ref_cl.oid
                 INNER JOIN pg_namespace ref_nsp ON ref_cl.relnamespace = ref_nsp.oid
                 INNER JOIN pg_rewrite rwr ON dep.objid = rwr.oid
                 INNER JOIN pg_class rwr_cl ON rwr.ev_class = rwr_cl.oid
                 INNER JOIN pg_namespace rwr_nsp ON rwr_cl.relnamespace = rwr_nsp.oid
                 WHERE dep.deptype = 'n' AND dep.classid = 'pg_rewrite'::regclass ) deps
          INNER JOIN recursive_deps ON deps.ref_schema = recursive_deps.obj_schema AND deps.ref_name = recursive_deps.obj_name
    WHERE (deps.ref_schema != deps.dep_schema or deps.ref_name != deps.dep_name) )  
    SELECT obj_schema, obj_name, obj_type, depth
        FROM recursive_deps
        WHERE depth > 0 ) t
    GROUP BY obj_schema, obj_name, obj_type
    ORDER BY max(depth) DESC ) LOOP
         
    INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
    SELECT DISTINCT p_view_schema, p_view_name, indexdef
    FROM pg_indexes
    WHERE schemaname = v_curr.obj_schema AND tablename = v_curr.obj_name;

    INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
    SELECT DISTINCT tablename, rulename, definition
    FROM pg_rules
    WHERE schemaname = v_curr.obj_schema AND tablename = v_curr.obj_name;

    INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
    SELECT p_view_schema,
               p_view_name,
                     'COMMENT ON ' || CASE WHEN c.relkind = 'v' THEN 'VIEW' WHEN c.relkind = 'm' THEN 'MATERIALIZED VIEW' ELSE '' END || ' ' || n.nspname || '.' || c.relname || ' IS ''' || replace(d.description, '''', '''''') || ''';'
    FROM pg_class c
    INNER JOIN pg_namespace n ON n.oid = c.relnamespace
    INNER JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = 0
    WHERE n.nspname = v_curr.obj_schema AND c.relname = v_curr.obj_name AND d.description is not null;

  INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
  SELECT p_view_schema,
           p_view_name,
                 'COMMENT ON COLUMN ' || n.nspname || '.' || c.relname || '.' || a.attname || ' IS ''' || replace(d.description, '''', '''''') || ''';'
  FROM pg_class c
  INNER JOIN pg_attribute a ON c.oid = a.attrelid
  INNER JOIN pg_namespace n ON n.oid = c.relnamespace
  INNER JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum
  WHERE n.nspname = v_curr.obj_schema AND c.relname = v_curr.obj_name AND d.description is not null;
 
  INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
  SELECT p_view_schema,
           p_view_name,
                 'GRANT ' || privilege_type || ' ON ' || table_schema || '.' || quote_ident(table_name) || ' TO ' || grantee
  FROM information_schema.role_table_grants
  WHERE table_schema = v_curr.obj_schema AND table_name = v_curr.obj_name;
 
  IF v_curr.obj_type = 'v' THEN
    INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
    SELECT p_view_schema,
               p_view_name,
                     'CREATE VIEW ' || v_curr.obj_schema || '.' || quote_ident(v_curr.obj_name) || ' AS ' || view_definition
    FROM information_schema.views
    WHERE table_schema = v_curr.obj_schema AND table_name = v_curr.obj_name;
  elsif v_curr.obj_type = 'm' THEN
    INSERT INTO deps_saved_ddl(deps_view_schema, deps_view_name, deps_ddl_to_run)
    SELECT p_view_schema,
               p_view_name,
                     'CREATE MATERIALIZED VIEW ' || v_curr.obj_schema || '.' || quote_ident(v_curr.obj_name) || ' AS ' || definition
    FROM pg_matviews
    WHERE schemaname = v_curr.obj_schema AND matviewname = v_curr.obj_name;
  END IF;
 
  EXECUTE 'DROP ' || CASE WHEN v_curr.obj_type = 'v' THEN 'VIEW' WHEN v_curr.obj_type = 'm' THEN 'MATERIALIZED VIEW' END || ' ' || v_curr.obj_schema || '.' || quote_ident(v_curr.obj_name);
 
END loop;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

ALTER FUNCTION public.deps_save_and_drop_dependencies(p_view_schema name, p_view_name name) OWNER TO postgres;

-- 对所有之前创建的视图进行重建
CREATE OR REPLACE FUNCTION "public"."deps_restore_dependencies"("p_view_schema" name, "p_view_name" name)
  RETURNS "pg_catalog"."void" AS $BODY$
  DECLARE   v_curr record;
  BEGIN
  FOR v_curr IN ( SELECT deps_ddl_to_run
                        FROM deps_saved_ddl
                        WHERE deps_view_schema = p_view_schema AND deps_view_name = p_view_name ORDER BY deps_id DESC )
        loop
        EXECUTE v_curr.deps_ddl_to_run;
      END loop;
        DELETE FROM deps_saved_ddl WHERE deps_view_schema = p_view_schema AND deps_view_name = p_view_name;
  END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
 
ALTER FUNCTION public.deps_restore_dependencies(p_view_schema name, p_view_name name) OWNER TO postgres;

操作案例
BEGIN;
SELECT deps_save_and_drop_dependencies('public', 'view_test');
ALTER TABLE view_test ALTER COLUMN cname TYPE VARCHAR(50);
SELECT deps_restore_dependencies('public', 'view_test');
COMMIT;

查看表的结构字段 cname 的长度是否是 50
[postgres@localhost data]$ psql
psql (12.8)
Type "help" for help.

postgres=# \c cloud_test
You are now connected to database "cloud_test" as user "postgres".
cloud_test=# \d view_test
                    Table "public.view_test"
 Column |         Type          | Collation | Nullable | Default
--------+-----------------------+-----------+----------+---------
 id     | integer               |           |          |
 cname  | character varying(50) |           |          |
 des    | text                  |           |          |

cloud_test=#

相关文章:

PostgreSQL 修改字段类型但是存在视图依赖

其实视图的存在与否在数据库界一直是一个话题。用好视图可以简化程序的很多代码&#xff0c;用不好视图不仅会给维护带来很多的不便&#xff0c;也会造成很大的性能问题。下面我从维护方面给出案例&#xff0c;以及当存在这种问题的时候&#xff0c;如何去解决这个问题。 假设…...

基于.NET 9实现实时进度条功能:前后端完整示例教程

要在基于.NET 9的应用中实现进度条功能&#xff0c;我们可以通过HttpContext.Response来发送实时的进度更新到前端。以下是一个简单的示例&#xff0c;展示了如何在ASP.NET Core应用中实现这一功能。 但是&#xff0c;我在.net framework4.7.2框架下&#xff0c;实际不了HttpC…...

力扣 LeetCode 19. 删除链表的倒数第N个结点(Day2:链表)

解题思路&#xff1a; 快慢指针 class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummy new ListNode(-1);dummy.next head;ListNode fast dummy;ListNode slow dummy;for (int i 0; i < n; i) {fast fast.next;}while (fast.ne…...

音频格式转换

一、场景 项目需求需要App实现声纹识别功能&#xff0c;调用科大讯飞接口&#xff1a; 声纹识别 API 文档 | 讯飞开放平台文档中心 其接口要求音频文件格式为mp3 二、问题产生 在安卓端根据官方文档说明&#xff0c;系统并不支持直接录制mp3格式音频&#xff0c;支持格式如…...

npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系

文章目录 作用示例常用选项示例命令注意事项 1、实战举例**解决方法**1. **锁定唯一的 types/node 版本**2. **清理依赖并重新安装**3. **设置 tsconfig.json 的 types**4. **验证 Promise 类型支持** **总结** npm list types/node 命令用于列出当前项目中 types/node 包及其…...

【Spring】Spring框架中有有哪些常见的设计模式

Spring 框架中广泛运用了多种设计模式&#xff0c;今天让我们来学习一下 1. 单例模式&#xff08;Singleton Pattern&#xff09; 用途&#xff1a;在Spring框架中&#xff0c;Bean默认是单例的&#xff0c;也就是说在容器中每种类型的Bean只有一个实例。这个设计可以节省资源…...

提升百度排名的有效策略与技巧解析

内容概要 提升百度排名对于网站的成功至关重要。首先&#xff0c;了解百度排名的基本原则&#xff0c;掌握搜索引擎是如何评估网页质量的&#xff0c;是优化过程中不可或缺的一部分。搜索引擎越来越倾向于将用户需求放在首位&#xff0c;因此提供高质量的内容和良好的用户体验…...

【Linux】Linux下查看cpu信息指令(top/mpstat/iostat/pidstat)说明

top命令 top(1) - Linux manual page (man7.org) top查看总的CPU利用率 us: 用户空间消耗的CPU资源占比&#xff0c;进程在用户态执行函数调用&#xff0c;编解码消耗的都是us sy: 内核空间消耗的CPU资源占比&#xff0c;进程调用系统调用达到内核后会增加sy的消耗 ni&…...

HDLBIts习题(3):使用冒号表示位宽时,冒号两端必须是常量

&#xff08;1&#xff09;易错习题1&#xff1a;Circuits - Combinational Logic - Multiplexers - 256-to-1 4bit multiplexer 使用冒号表示位宽时&#xff0c;冒号两端必须是常量&#xff0c;因此如果使用变量&#xff0c;可以使用位拼接的方法。 &#xff08;2&#xff09;…...

C++20协程详解

文章目录 什么是协程为什么需要协程什么时候使用协程协程的类别C20的协程协程的使用关键字co_wait框架一阶段完成数据交换co_yieldco_return 什么是协程 我们在学习编程的过程中&#xff0c;逐渐从单线程&#xff0c;到多线程&#xff0c;再到异步编程和并发处理 这些异步与并…...

Chromium 中chrome.system.display扩展接口定义c++

一、chrome.system.display 使用 system.display API 查询展示元数据。 权限 system.display 类型 ActiveState Chrome 117 及更高版本 用于指示系统是否检测到和使用显示屏的枚举。如果系统未检测到显示屏&#xff08;可能断开连接&#xff0c;或因睡眠模式等原因而被视…...

容器docker的ulimit

Ulimit 在linux里ulimit命令可以对shell生成的进程的资源进行限制。 常用的ulimit限制 打开文件句柄数core文件大小设置进程能够消耗的虚拟内存设置用户能够打开的进程数目 不太常用的ulimit限制 设置数据段的最大值.单位:kbytes 设置创建文件的最大值.单位:blocks 设置在…...

一、HTML

一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大&#xff0c;且都有自己的内核。 什么是内核&#xff1a; 内核是浏览器的核心&#xff0c;用于处理浏览器所得到的各种资源。 例如&#xff0c;服务器发送图片、视频、音频的资源&#xff0c;浏览…...

使用Geekbench6软件对真实和虚拟的苹果桌面系统(macOS)进行打分比较

前言 感觉VMWare安装的MacOS使用起来非常的慢&#xff0c;所以特意用打分软件GeekBench进行了评测。 一、Geekbench的安装 可以从官网直接进行下载&#xff0c; 链接是&#xff1a; 二、Geekbench的直接使用 2.1、真机的信息 2.2、虚拟机的信息 三、打分的比较 3.1、真机…...

lua入门教程:随机数

在Lua中&#xff0c;生成随机数是通过math库中的math.random函数来实现的。这个函数可以生成一个[0, 1)区间内的随机浮点数。如果你需要生成其他范围内的随机数&#xff0c;或者需要整数类型的随机数&#xff0c;可以通过一些简单的数学运算来调整math.random的输出。 以下是如…...

华为大咖说 | 浅谈智能运维技术

本文分享自华为云社区&#xff1a;华为大咖说 | 浅谈智能运维技术-云社区-华为云 本文作者&#xff1a;李文轩 &#xff08; 华为智能运维专家 &#xff09; 全文约2695字&#xff0c;阅读约需8分钟 在大数据、人工智能等新兴技术的加持下&#xff0c;智能运维&#xff08;AI…...

creo toolkit二次开发学习之获取任意选择模型作为元件,并进行获取约束等

获取任意选择模型作为元件进行操作前&#xff0c;先了解组件路径和程序集的构成&#xff1a;creo toolkit二次开发学习之程序集&#xff08;ProAsmcomp&#xff09;和装配体组件路径对象&#xff08;ProAsmcomppath&#xff09;-CSDN博客 代码如下 ProError test1() {ProError…...

sanitize-html 防止 XSS(跨站脚本攻击)

sanitize-html 是一个用于清理和验证 HTML 的 JavaScript 库&#xff0c;主要用于防止 XSS&#xff08;跨站脚本攻击&#xff09;。它允许你定义一套规则来决定哪些 HTML 标签和属性是可以被信任的&#xff0c;从而确保用户输入的内容不会包含潜在的恶意代码。 主要功能 HTML…...

【JavaEE】文件io

目录 文件类型 File概述 属性 构造方法 常用方法 Reader Writer InputStream OutputStream 字节流转字符流 通过Scanner读取InputStream 通过PrintWriter转换outputstream 示例 文件类型 从编程的角度看&#xff0c;文件类型主要就是两大类 文本&#xff08;文…...

FlinkPipelineComposer 详解

FlinkPipelineComposer 详解 原文 背景 在flink-cdc 3.0中引入了pipeline机制&#xff0c;提供了除Datastream api/flink sql以外的一种方式定义flink 任务 通过提供一个yaml文件&#xff0c;描述source sink transform等主要信息 由FlinkPipelineComposer解析&#xff0c…...

NVIDIA Profile Inspector实战手册:从参数调试到显卡性能全面优化

NVIDIA Profile Inspector实战手册&#xff1a;从参数调试到显卡性能全面优化 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 在PC硬件优化领域&#xff0c;专业工具与普通用户之间往往存在技术鸿沟。N…...

3步解锁魔兽争霸III最佳体验:WarcraftHelper全方位优化工具指南

3步解锁魔兽争霸III最佳体验&#xff1a;WarcraftHelper全方位优化工具指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为…...

如何快速配置TranslucentTB:Windows任务栏美化终极教程

如何快速配置TranslucentTB&#xff1a;Windows任务栏美化终极教程 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 想要让Windows任务栏变…...

超滤膜行业领先公司

《2026年超滤膜权威排名&#xff1a;深圳市洛哈斯水处理技术有限公司何以凭借AI智控技术领跑行业&#xff1f;》在2026年的深度测评中&#xff0c;深圳市洛哈斯水处理技术有限公司凭借其行业领先的“AIoT智能膜系统”与卓越的长期运行稳定性&#xff0c;综合表现排名第一&#…...

别只盯着时钟了!用Vivado的Set_Data_Check搞定FPGA里两个数据信号的时序检查(附工程源码)

FPGA时序约束进阶&#xff1a;用Set_Data_Check精准控制数据信号时序关系 在FPGA设计中&#xff0c;时序约束是确保电路功能正确性的关键环节。大多数工程师对时钟与数据信号之间的setup/hold约束已经驾轻就熟&#xff0c;但当面对两个数据信号之间的时序关系时&#xff0c;却常…...

重构PDF知识管理:Obsidian PDF++让文献处理效率提升300%的实战指南

重构PDF知识管理&#xff1a;Obsidian PDF让文献处理效率提升300%的实战指南 【免费下载链接】obsidian-pdf-plus PDF: the most Obsidian-native PDF annotation & viewing tool ever. Comes with optional Vim keybindings. 项目地址: https://gitcode.com/gh_mirrors/…...

SGMICRO圣邦微 SGM8740YC5G/TR SC70-5 比较器

特性 快速&#xff0c;45纳秒传播延迟(10毫伏过驱动)低功耗:在Vs3V时为155pA(典型值) 宽电源电压范围:2.7V至5.5V优化适用于3V和5V应用轨到轨输入电压范围低偏置电压:0.9mV(典型值)内部迟滞以实现干净开关 输出摆幅:在4mA输出电流下&#xff0c;从轨距内.200mV范围内 与CMOS/TT…...

期权到期日别慌!手把手教你搞定上交所股票期权的行权与交割(附避坑清单)

期权到期日实战指南&#xff1a;从行权准备到交割避坑全流程解析 手机屏幕上的红色倒计时提醒着期权合约即将到期&#xff0c;作为刚接触期权交易不久的新手&#xff0c;此刻最需要的不再是复杂的概念解释&#xff0c;而是一份能握在手中的应急操作清单。本文将用最直白的语言拆…...

从Solid模块到轨迹规划:一个完整机械臂SimMechanics仿真项目的保姆级拆解

从Solid模块到轨迹规划&#xff1a;一个完整机械臂SimMechanics仿真项目的保姆级拆解 机械臂仿真一直是工业自动化和机器人研究中的核心课题。不同于传统Adams等专业仿真软件&#xff0c;SimMechanics凭借其与Matlab/Simulink的无缝集成&#xff0c;为工程师提供了从建模到控制…...

Dramatron:AI驱动的剧本创作革命

Dramatron&#xff1a;AI驱动的剧本创作革命 【免费下载链接】dramatron Dramatron uses large language models to generate coherent scripts and screenplays. 项目地址: https://gitcode.com/gh_mirrors/dr/dramatron 价值定位&#xff1a;重新定义创意写作流程 在…...