2010-07-14 25 views
23

Tôi có một vấn đề với ALTER TABLE trong postgre. Tôi muốn thay đổi kích thước của cột VARCHAR. Khi tôi cố gắng làm điều này, Nó nói rằng khung nhìn phụ thuộc vào cột đó. Tôi không thể bỏ chế độ xem vì việc sao chổi khác phụ thuộc vào nó. Có cách nào khác hơn là bỏ mọi thứ và tái tạo lại không?Vấn đề với Postgres ALTER TABLE

Tôi chỉ tìm thấy một tùy chọn, đó là xóa bảng tham gia khỏi chế độ xem, khi tôi sẽ không thay đổi các cột được trả về, tôi có thể làm điều đó. Nhưng vẫn còn, có nhiều quan điểm tôi sẽ cần phải thay đổi. Không có bất cứ điều gì làm thế nào tôi có thể nói rằng nó nên được hoãn lại và kiểm tra với cam kết?

+1

sao chép truy vấn xem và xóa truy vấn đó và thực hiện các thay đổi đối với Bảng – TaherT

Trả lời

15

Tôi đã gặp sự cố này và không thể tìm thấy bất kỳ cách nào xung quanh nó. Thật không may, như tốt nhất tôi có thể nói, người ta phải thả các quan điểm, thay đổi loại cột trên bảng bên dưới, và sau đó tạo lại các khung nhìn. Điều này có thể xảy ra hoàn toàn trong một giao dịch duy nhất.

Hạn chế trì hoãn không áp dụng cho vấn đề này. Nói cách khác, ngay cả SET CONSTRAINTS ALL DEFERRED cũng không ảnh hưởng đến giới hạn này. Để cụ thể, hạn chế trì hoãn không áp dụng cho kiểm tra tính nhất quán in ERROR: cannot alter type of a column used by a view or rule khi người ta cố gắng thay đổi loại của một cột nằm dưới chế độ xem.

4

Tôi đã gặp sự cố này ngày hôm nay và đã tìm thấy một công việc xung quanh để tránh giảm và tạo lại VIEW. Tôi không thể chỉ thả VIEW vì nó là một VIEW chính có nhiều VIEWs phụ thuộc được xây dựng trên nó. Ngắn của việc có một kịch bản xây dựng lại để thả CASCADE và sau đó tạo lại tất cả các VIEWs của tôi đây là một công việc xung quanh.

Tôi thay đổi chế độ xem chính để sử dụng giá trị giả cho cột vi phạm, thay đổi cột trong bảng và chuyển VIEW của tôi trở lại cột. Sử dụng một thiết lập như thế này:

CREATE TABLE base_table 
(
    base_table_id integer, 
    base_table_field1 numeric(10,4) 
); 

CREATE OR REPLACE VIEW master_view AS 
    SELECT 
    base_table_id AS id, 
    (base_table_field1 * .01)::numeric AS field1 
    FROM base_table; 

CREATE OR REPLACE VIEW dependent_view AS 
    SELECT 
    id AS dependent_id, 
    field1 AS dependent_field1 
    FROM master_view; 

Đang cố gắng để thay đổi loại base_table_field1 như thế này:

ALTER TABLE base_table ALTER COLUMN base_table_field1 TYPE numeric(10,6); 

sẽ cung cấp cho bạn lỗi này:

ERROR: cannot alter type of a column used by a view or rule 
DETAIL: rule _RETURN on view master_view depends on column "base_table_field1" 

Nếu bạn thay đổi master_view sử dụng một giá trị giả cho cột như sau:

CREATE OR REPLACE VIEW master_view AS 
    SELECT 
    base_table_id AS id, 
    0.9999 AS field1 
    FROM base_table; 

Sau đó chạy ALTER của bạn:

ALTER TABLE base_table ALTER COLUMN base_table_field1 TYPE numeric(10,6); 

Và chuyển cái nhìn của bạn trở lại:

CREATE OR REPLACE VIEW master_view AS 
    SELECT 
    base_table_id AS id, 
    (base_table_field1 * .01)::numeric AS field1 
    FROM base_table; 

Tất cả đều phụ thuộc vào nếu master_view của bạn có một loại rõ ràng điều đó không thay đổi. Vì VIEW của tôi sử dụng '(base_table_field1 * .01) :: số AS field1' nó hoạt động, nhưng 'base_table_field1 AS field1' sẽ không phải vì loại cột thay đổi. Cách tiếp cận này có thể giúp trong một số trường hợp như tôi.

+4

Làm cách nào tốt hơn là giảm chế độ xem, thay đổi bảng và tạo lại chế độ xem? Tôi thấy rằng điều này là tồi tệ hơn, phải xem xét thông qua DDL của khung nhìn và tìm các trường hợp của cột. Khi bạn đang giảm, tất cả những gì bạn cần là giữ một bản sao DDL của chế độ xem ban đầu để bạn có thể tạo lại nó. – ADTC

+3

Làm cách nào tốt hơn là giảm chế độ xem? Dòng đầu tiên ... "nó là một VIEW chính có nhiều VIEWs phụ thuộc được xây dựng trên đầu trang của nó." Nghĩa là, thác thả xuống các khung nhìn phụ thuộc đó. –

7

Nếu bạn không cần phải thay đổi loại của lĩnh vực này, nhưng chỉ cần kích thước của nó, phương pháp này nên làm việc:

Bắt đầu với các bảng:

CREATE TABLE foo (id integer primary key, names varchar(10)); 
CREATE VIEW voo AS (SELECT id, names FROM foo); 

\d foo\d voo cả hai hiển thị chiều dài là 10:

id  | integer    | not null 
names | character varying(10) | 

Bây giờ thay đổi độ dài thành 20 trong pg_attribute bảng:

UPDATE pg_attribute SET atttypmod = 20+4 
WHERE attrelid IN ('foo'::regclass, 'voo'::regclass) 
AND attname = 'names'; 

(lưu ý: 20 + 4 là một số điên postgresql di sản điều, 4 là bắt buộc.)

Bây giờ \d foo show:

id  | integer    | not null 
names | character varying(10) | 

Bonus: đó là waaay nhanh hơn làm:

ALTER TABLE foo ALTER COLUMN names TYPE varchar(20); 

Về mặt kỹ thuật, bạn có thể thay đổi kích thước của bảng c olumn mà không thay đổi kích thước của cột xem, nhưng không đảm bảo về những tác dụng phụ sẽ có; có lẽ tốt nhất là nên thay đổi cả hai cùng một lúc.

nguồn và giải thích đầy đủ hơn: http://sniptools.com/databases/resize-a-column-in-a-postgresql-table-without-changing-data

+7

Bạn nên tránh thay đổi các danh mục (chẳng hạn như pg_attribute) theo cách thủ công bất cứ khi nào có thể. Có một nguy cơ thực sự của việc nhận được một cái gì đó sai và gây ra lỗi, bao gồm cả sự cố và dữ liệu tham nhũng, sau này khi bạn ít mong đợi nó. CHỈ làm điều đó như một phương sách cuối cùng, SAU KHI tư vấn mã nguồn để đảm bảo bạn không bỏ sót bất cứ điều gì.Đề xuất điều này mà không có bất kỳ tuyên bố từ chối trách nhiệm nào là vô trách nhiệm. – intgr

+0

Đó là cách mà công cụ dữ liệu thực sự làm sau hậu trường. Bạn không thay đổi TYPE, nhưng kích thước. Vì VARCHAR không gây hại cho dữ liệu. +1 –

2

Tôi là một chút muộn để đảng, nhưng năm sau khi câu hỏi này đã được đăng, một giải pháp tuyệt vời đã được đăng thông qua một bài báo tham khảo dưới đây (không phải của tôi - Tôi chỉ đơn giản là một người thụ hưởng biết ơn về sáng chói của anh ấy).

Tôi vừa thử nghiệm điều này trên một đối tượng được tham chiếu (ở cấp độ đầu tiên) trong 136 lượt xem riêng biệt và mỗi chế độ xem đó được tham chiếu trong các chế độ xem khác. Giải pháp chạy chỉ trong vài giây.

Vì vậy, đọc bài viết này và sao chép và dán bàn và hai chức năng được liệt kê: Ví dụ

http://mwenus.blogspot.com/2014/04/postgresql-how-to-handle-table-and-view.html

Thực hiện:

alter table mdm.global_item_master_swap 
alter column prod_id type varchar(128), 
alter column prod_nme type varchar(512); 

ERROR: cannot alter type of a column used by a view or rule DETAIL: rule _RETURN on view toolbox_reporting."Average_setcost" depends on column "prod_id" ********** Error **********

ERROR: cannot alter type of a column used by a view or rule

Và bây giờ cho phép thuật ninja của PostgreSQL:

select util.deps_save_and_drop_dependencies('mdm', 'global_item_master_swap'); 


alter table mdm.global_item_master_swap 
alter column prod_id type varchar(128), 
alter column prod_nme type varchar(512); 


select util.deps_restore_dependencies('mdm', 'global_item_master_swap'); 
+0

Bạn là một linh hồn tuyệt vời. – Vishnu

Các vấn đề liên quan