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 修改字段类型但是存在视图依赖
其实视图的存在与否在数据库界一直是一个话题。用好视图可以简化程序的很多代码,用不好视图不仅会给维护带来很多的不便,也会造成很大的性能问题。下面我从维护方面给出案例,以及当存在这种问题的时候,如何去解决这个问题。 假设…...
基于.NET 9实现实时进度条功能:前后端完整示例教程
要在基于.NET 9的应用中实现进度条功能,我们可以通过HttpContext.Response来发送实时的进度更新到前端。以下是一个简单的示例,展示了如何在ASP.NET Core应用中实现这一功能。 但是,我在.net framework4.7.2框架下,实际不了HttpC…...
力扣 LeetCode 19. 删除链表的倒数第N个结点(Day2:链表)
解题思路: 快慢指针 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实现声纹识别功能,调用科大讯飞接口: 声纹识别 API 文档 | 讯飞开放平台文档中心 其接口要求音频文件格式为mp3 二、问题产生 在安卓端根据官方文档说明,系统并不支持直接录制mp3格式音频,支持格式如…...
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 框架中广泛运用了多种设计模式,今天让我们来学习一下 1. 单例模式(Singleton Pattern) 用途:在Spring框架中,Bean默认是单例的,也就是说在容器中每种类型的Bean只有一个实例。这个设计可以节省资源…...
提升百度排名的有效策略与技巧解析
内容概要 提升百度排名对于网站的成功至关重要。首先,了解百度排名的基本原则,掌握搜索引擎是如何评估网页质量的,是优化过程中不可或缺的一部分。搜索引擎越来越倾向于将用户需求放在首位,因此提供高质量的内容和良好的用户体验…...
【Linux】Linux下查看cpu信息指令(top/mpstat/iostat/pidstat)说明
top命令 top(1) - Linux manual page (man7.org) top查看总的CPU利用率 us: 用户空间消耗的CPU资源占比,进程在用户态执行函数调用,编解码消耗的都是us sy: 内核空间消耗的CPU资源占比,进程调用系统调用达到内核后会增加sy的消耗 ni&…...
HDLBIts习题(3):使用冒号表示位宽时,冒号两端必须是常量
(1)易错习题1:Circuits - Combinational Logic - Multiplexers - 256-to-1 4bit multiplexer 使用冒号表示位宽时,冒号两端必须是常量,因此如果使用变量,可以使用位拼接的方法。 (2)…...
C++20协程详解
文章目录 什么是协程为什么需要协程什么时候使用协程协程的类别C20的协程协程的使用关键字co_wait框架一阶段完成数据交换co_yieldco_return 什么是协程 我们在学习编程的过程中,逐渐从单线程,到多线程,再到异步编程和并发处理 这些异步与并…...
Chromium 中chrome.system.display扩展接口定义c++
一、chrome.system.display 使用 system.display API 查询展示元数据。 权限 system.display 类型 ActiveState Chrome 117 及更高版本 用于指示系统是否检测到和使用显示屏的枚举。如果系统未检测到显示屏(可能断开连接,或因睡眠模式等原因而被视…...
容器docker的ulimit
Ulimit 在linux里ulimit命令可以对shell生成的进程的资源进行限制。 常用的ulimit限制 打开文件句柄数core文件大小设置进程能够消耗的虚拟内存设置用户能够打开的进程数目 不太常用的ulimit限制 设置数据段的最大值.单位:kbytes 设置创建文件的最大值.单位:blocks 设置在…...
一、HTML
一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大,且都有自己的内核。 什么是内核: 内核是浏览器的核心,用于处理浏览器所得到的各种资源。 例如,服务器发送图片、视频、音频的资源,浏览…...
使用Geekbench6软件对真实和虚拟的苹果桌面系统(macOS)进行打分比较
前言 感觉VMWare安装的MacOS使用起来非常的慢,所以特意用打分软件GeekBench进行了评测。 一、Geekbench的安装 可以从官网直接进行下载, 链接是: 二、Geekbench的直接使用 2.1、真机的信息 2.2、虚拟机的信息 三、打分的比较 3.1、真机…...
lua入门教程:随机数
在Lua中,生成随机数是通过math库中的math.random函数来实现的。这个函数可以生成一个[0, 1)区间内的随机浮点数。如果你需要生成其他范围内的随机数,或者需要整数类型的随机数,可以通过一些简单的数学运算来调整math.random的输出。 以下是如…...
华为大咖说 | 浅谈智能运维技术
本文分享自华为云社区:华为大咖说 | 浅谈智能运维技术-云社区-华为云 本文作者:李文轩 ( 华为智能运维专家 ) 全文约2695字,阅读约需8分钟 在大数据、人工智能等新兴技术的加持下,智能运维(AI…...
creo toolkit二次开发学习之获取任意选择模型作为元件,并进行获取约束等
获取任意选择模型作为元件进行操作前,先了解组件路径和程序集的构成:creo toolkit二次开发学习之程序集(ProAsmcomp)和装配体组件路径对象(ProAsmcomppath)-CSDN博客 代码如下 ProError test1() {ProError…...
sanitize-html 防止 XSS(跨站脚本攻击)
sanitize-html 是一个用于清理和验证 HTML 的 JavaScript 库,主要用于防止 XSS(跨站脚本攻击)。它允许你定义一套规则来决定哪些 HTML 标签和属性是可以被信任的,从而确保用户输入的内容不会包含潜在的恶意代码。 主要功能 HTML…...
【JavaEE】文件io
目录 文件类型 File概述 属性 构造方法 常用方法 Reader Writer InputStream OutputStream 字节流转字符流 通过Scanner读取InputStream 通过PrintWriter转换outputstream 示例 文件类型 从编程的角度看,文件类型主要就是两大类 文本(文…...
FlinkPipelineComposer 详解
FlinkPipelineComposer 详解 原文 背景 在flink-cdc 3.0中引入了pipeline机制,提供了除Datastream api/flink sql以外的一种方式定义flink 任务 通过提供一个yaml文件,描述source sink transform等主要信息 由FlinkPipelineComposer解析,…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
