删除列不会完全删除列引用 - postgresql

时间:2017-03-27 15:04:57

标签: postgresql postgresql-9.1 alter-table

我有一个包含1600列的表,并希望在其中添加更多字段,但根据数据库规则,由于达到了更高的限制,因此不允许创建更多字段。

所以我决定从表中删除一些不需要的字段,然后我就这样做了。我再次试图在该表中添加几个字段,但它引发的相同错误是1600列,你不能添加更多。

我浏览了postgresql的其他表" pg_attribute "并且所有这些字段都在那里,并且删除参数= True。

  

到目前为止我尝试了什么

     

Drop Constraints将表数据带入另一个表Truncate Table   重新创建约束将数据重新复制到主表。

     

但是pg_attributes表中仍有删除的列。

     

我还尝试从 pg_attribute 删除该记录,但随后删除了   给我这样的错误。

ERROR:  catalog is missing 1 attribute(s) for relid 208996

********** Error **********

ERROR: catalog is missing 1 attribute(s) for relid 208996
SQL state: XX000
     

为什么我们有这么多列的原因是

     

我们有odoo-magento(odoo使用的postgresql db)集成和   在magento有超过60000种产品,拥有3000个独特的产品   属性,因此在连接器中,所有这些属性都创建为字段   在产品表中,我已经同步了magento - > odoo产品和   达到1600限制。现在它不允许我放弃那里的字段   表。

     

我已经在magento-odoo连接器中解决了这个问题,它只会   同步所需的属性,但我应该为已同步的属性做什么   字段如何删除它????

     

即使丢桌也不是一个正确的方法,因为它很大而且非常   重要的表格,所以我可以冒任何风险。

     

我想做什么

     

我想简单地从表中删除这些列并且需要   而是添加其他几列。

     

这个问题还有其他可能的解决方案吗?

任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:2)

永远不要直接混淆pg_attribute。如果您已经这样做了,那么可能是从备份恢复的时候了。

当删除一列时,PostgreSQL实际上并没有将其删除,而是更改名称并将其标记为已删除。

CREATE TABLE testtab (
   id integer PRIMARY KEY,
   dropme text NOT NULL,
   val text NOT NULL
);

ALTER TABLE testtab DROP dropme;

SELECT attname, attnum, attisdropped
FROM pg_attribute
WHERE attrelid = 'testtab'::regclass
   AND attnum > 0
ORDER BY attnum;

┌──────────────────────────────┬────────┬──────────────┐
│           attname            │ attnum │ attisdropped │
├──────────────────────────────┼────────┼──────────────┤
│ id                           │      1 │ f            │
│ ........pg.dropped.2........ │      2 │ t            │
│ val                          │      3 │ f            │
└──────────────────────────────┴────────┴──────────────┘
(3 rows)

所以我猜这个删除的列仍然会计入列限制。

我可以想到一种,不是很舒服,摆脱它的方法:

BEGIN;
CREATE TABLE testtab_2 (LIKE testtab INCLUDING ALL);
INSERT INTO testtab_2 SELECT * FROM testtab;
DROP TABLE testtab;
ALTER TABLE testtab_2 RENAME TO testtab;
COMMIT;

答案 1 :(得分:1)

As documented in the manual

  

DROP COLUMN表单没有物理删除列,只是使它对SQL操作不可见。表中的后续插入和更新操作将为列存储空值。因此,删除列很快,但不会立即减少表的磁盘大小,因为已删除列所占用的空间不会被回收。随着现有行的更新,该空间将随着时间的推移而被回收   
  要强制立即回收已删除列占用的空间,可以执行ALTER TABLE的一种形式,以执行整个表的重写。这导致重建每一行,并将删除的列替换为空值。