我正在尝试在Postgres中将类型为整数的列更新为数值(2)
ALTER TABLE employee_status
ALTER COLUMN status TYPE numeric(2);
但出现了错误信息 ERROR: 无法更改视图或规则使用的列的类型 DETAIL: 视图v_employee_details上的规则_RETURN依赖于列"status"
不删除数据的情况下,我该怎么做才能实现这个目标?有没有办法禁用规则或视图?
我正在尝试在Postgres中将类型为整数的列更新为数值(2)
ALTER TABLE employee_status
ALTER COLUMN status TYPE numeric(2);
但出现了错误信息 ERROR: 无法更改视图或规则使用的列的类型 DETAIL: 视图v_employee_details上的规则_RETURN依赖于列"status"
不删除数据的情况下,我该怎么做才能实现这个目标?有没有办法禁用规则或视图?
pg_get_viewdef
函数轻松获取视图定义。 如果您有很多相关视图,请参考这个答案以正确的顺序获取所有相关视图。不必担心 _RETURN
规则:这只是PostgreSQL中实现视图的一个实现细节,作为名为_RETURN
的ON SELECT DO INSTEAD
规则。do $$
declare v_employee_details_def text;
declare exec_text text;
begin
v_employee_details_def := pg_get_viewdef('v_employee_details');
drop view v_employee_details;
-- do your other stuff
exec_text := format('create view v_employee_details as %s',
v_employee_details_def);
execute exec_text;
end $$;
UPDATE pg_attribute SET atttypmod = 35+4 WHERE attrelid = 'TABLE1'::regclass AND attname = 'COL1';
您需要具有超级用户或类似权限才能更改Postgres系统表 - pg_attribute。这里有一个解释链接:链接!do $$
declare view_record record;
begin
drop table if exists public.__temp_views;
--at first create temporary table with all view definitions
create table public.__temp_views(schemaname text, viewname text, definition text, level float);
--then insert recursive views with levels
insert into public.__temp_views(schemaname, viewname, definition, level)
WITH RECURSIVE viewids AS (
/* all views that don't depend on other views */
SELECT t.oid, 1 as level
FROM pg_class t
JOIN pg_rewrite AS r ON r.ev_class = t.oid
WHERE r.rulename = '_RETURN'
AND t.relkind = 'v'
AND t.relnamespace NOT IN ('pg_catalog'::regnamespace,
'information_schema'::regnamespace,
'pg_toast'::regnamespace)
AND NOT EXISTS (
/* depends on a view */
SELECT 1
FROM pg_depend AS d
JOIN pg_class AS t2 ON d.refobjid = t2.oid
WHERE d.objid = r.oid
AND d.classid = 'pg_rewrite'::regclass
AND d.refclassid = 'pg_class'::regclass
AND d.deptype = 'n'
AND d.refobjsubid <> 0
AND t2.relkind = 'v'
)
AND NOT EXISTS (
/* depends on an extension */
SELECT 1
FROM pg_depend
WHERE objid = t.oid
AND classid = 'pg_class'::regclass
AND refclassid = 'pg_extension'::regclass
AND deptype = 'e'
)
UNION ALL
/* all views that depend on these views */
SELECT t.oid, viewids.level + 1
FROM pg_class AS t
JOIN pg_rewrite AS r ON r.ev_class = t.oid
JOIN pg_depend AS d ON d.objid = r.oid
JOIN viewids ON viewids.oid = d.refobjid
WHERE t.relkind = 'v'
AND r.rulename = '_RETURN'
AND d.classid = 'pg_rewrite'::regclass
AND d.refclassid = 'pg_class'::regclass
AND d.deptype = 'n'
AND d.refobjsubid <> 0
)
/* order the views by level, eliminating duplicates */
SELECT 'public', oid::regclass, pg_get_viewdef(oid::regclass), max(level)
FROM viewids
GROUP BY oid
ORDER BY max(level);
--then drop all views
FOR view_record IN SELECT * from public.__temp_views
LOOP
execute format('DROP VIEW IF EXISTS %s.%s CASCADE;', quote_ident(view_record.schemaname), quote_ident(view_record.viewname));
END LOOP;
-- then do your other stuff here
-- for example i'm changing column that depending by views
alter table public.connected_accounts
alter column provider TYPE text;
ALTER TABLE public.connected_accounts
ADD CONSTRAINT auth_providers_id_key
FOREIGN KEY (provider)
REFERENCES public.auth_providers (id) not valid;
--then recreate all the views recursively
FOR view_record IN SELECT * from public.__temp_views
LOOP
execute format('CREATE OR REPLACE VIEW %s.%s AS %s;', quote_ident(view_record.schemaname), quote_ident(view_record.viewname), view_record.definition);
END LOOP;
--finally drop temporary table
drop table public.__temp_views;
end $$;