修改表字段类型长度_PG修改字段
今天又遇到一個需求,要把PG中的字段類型修改一下。本來以為是個很簡單的事情,畢竟Oracle就是一條指令就行了。但是在PG中改字段真的真的太難了。
當你修改表字段的時候,會報ERROR: cannot alter type of a column used by a view or rule.
這主要是因為這個表上存在視圖或者是rule,rule這里代表是觸發(fā)器。所以在PG中它不能像Oracle那樣修改字段。一般做法就是:
BEGIN; DROP VIEW view_name ALTER TABLE users ALTER COLUMN column_name TYPE character varying(500); CREATE VIEW view_name AS SELECT * FROM table_name; COMMIT; |
這樣干也沒什么問題,但是一旦上百個視圖依賴于一張表,或者視圖有多個嵌套,這問題就麻煩起來了,特別是有的視圖定義動輒上百上千行的,修改字段再創(chuàng)建視圖,一套弄下來就特別累。那么就沒有什么完美的解決辦法嗎?
通過研究,發(fā)現(xiàn)這個問題有兩種解決辦法,針對兩種不同的情況。
情況一:只修改長度
修改長度,是在日常維護中經常發(fā)生的。比如以前一個字段是20個長度,運行一段時間之后,發(fā)現(xiàn)長度不夠要擴成30。這個時候一般就會通知dba進行操作。我們可以通過修改pg_attribute基表的方式來繞開這個限制。
create table a(id int ,name varchar(20)); create view a_view as select id,name from a; alter table a alter name type varchar(30); ERROR: cannot alter type of a column used by a view or rule DETAIL: rule _RETURN on view a_view depends on column "name" SELECT atttypmod FROM pg_attribute WHERE attrelid = 'a'::regclass AND attname = 'name'; atttypmod ----------- 24 (1 row) update pg_attribute set atttypmod =34 WHERE attrelid ='a'::regclass AND attname = 'name'; UPDATE 1 SELECT atttypmod FROM pg_attribute WHERE attrelid = 'a'::regclass AND attname = 'name'; atttypmod ----------- 34 |
這里需要注意的一點是我設置的是varchar(20),查出來的是varchar(24),這是因為歷史原因,添加了4。我如果要改成30,這里就需要修改為34。
改完之后我們再來查詢我們的表和視圖,發(fā)現(xiàn)都是ok的。
postgres=# \d a Table "public.a" Column | ? ? ? ? Type ? ? ? ? ?| Collation | Nullable | Default --------+-----------------------+-----------+----------+--------- id ? ?| integer ? ? ? ? ? ? ? | ? ? ? ? ? | ? ? ? ? ?| name ?| character varying(30) | ? ? ? ? ? | ? ? ? ? ?| postgres=# insert into a values(1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'); INSERT 0 1 postgres=# select lengthb(name) from a; lengthb --------- 29 postgres=# select * from a_view; id | ? ? ? ? ? ? name ? ? ? ? ? ? ? ----+------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
雖然這樣修改能解決問題,但是確實有一定發(fā)生錯誤的風險,所以需要謹慎使用,最好要經過詳細的評審和測試之后再操作。
情況二:修改字段類型
修改字段類型這種情況多見于執(zhí)行SQL緩慢,通過執(zhí)行計劃發(fā)現(xiàn)是字段類型不匹配產生了隱式在轉換,而無法使用上索引。
這種情況就得通過我們之前的方法來實現(xiàn),把刪除視圖、修改字段、創(chuàng)建視圖放到一個事務下執(zhí)行,但是如果嵌套的視圖比較多就很麻煩。為了克服這個麻煩,就有一個大神級人物寫了兩個函數(shù)來輕松實現(xiàn)了這個問題。由于太多人受到這個“煩惱”問題的困擾,作者得到了極高的贊揚。
BEGIN; select deps_save_and_drop_dependencies('public', 'a'); alter table a alter name type varchar(30); select deps_restore_dependencies('public', 'a'); COMMIT |
以下是我在自己環(huán)境中進行的測試,非常簡單就搞定了。
函數(shù)可以在github上下載:
https://gist.github.com/mateuszwenus/11187288(PG12之前版本)
https://gist.github.com/briandignan/03ef42e78434658cf27f052e2f0798e8(PG12之后的版本)
如果讓我推薦,我還是推薦使用第二種方法,畢竟這個方法比較穩(wěn)妥一點。也基本上達到了比較完美的地步。就算遇到上百個視圖或者像俄羅斯套娃一樣的視圖你也不用擔心了。
參考文檔:
Problemwith Postgres ALTER TABLE
https://stackoverflow.com/questions/3243863/problem-with-postgres-alter-table/49000321
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的修改表字段类型长度_PG修改字段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 语言余一个负数_C语言学习日记(8)——
- 下一篇: 人声处理_10款免费的人声处理工具