我有一个关于一个非常大的表(几乎有3000万行)上的ALTER TABLE命令的问题。 其中一列是varchar(255),我想将其大小调整为varchar(40)。 基本上,我想通过运行以下命令来更改我的列:

ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);

如果进程很长,我没有问题,但似乎我的表在ALTER table命令期间不再可读。 有没有更聪明的办法?也许添加一个新列,从旧列复制值,删除旧列,最后重命名新列?

注意:我使用PostgreSQL 9.0。


当前回答

我正面临着同样的问题,试图将VARCHAR从32截断为8,并得到ERROR:值对于类型字符变化(8)太长。我希望尽可能地接近SQL,因为我使用的是自制的类似于jpa的结构,我们可能不得不根据客户的选择切换到不同的DBMS (PostgreSQL是默认的)。因此,我不想使用修改System表的技巧。

我结束了在ALTER TABLE中使用using语句:

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8)
USING substr("MyColumn", 1, 8)

正如@raylu指出的那样,ALTER在表上获得了一个排他锁,因此所有其他操作将被延迟,直到它完成。

其他回答

下面是Greg Smith描述的页面缓存。如果它也死了,alter语句看起来像这样:

UPDATE pg_attribute SET atttypmod = 35+4
WHERE attrelid = 'TABLE1'::regclass
AND attname = 'COL1';

您的表是TABLE1,列是COL1,您希望将其设置为35个字符(根据链接,+4是遗留目的所需要的,可能是注释中A.H.提到的开销)。

如果你把alter放到一个事务中,表不应该被锁定:

BEGIN;
  ALTER TABLE "public"."mytable" ALTER COLUMN "mycolumn" TYPE varchar(40);
COMMIT;

这对我来说非常有效,几秒钟就搞定了400,000多行。

试着运行下面的alter表:

ALTER TABLE public.users 
ALTER COLUMN "password" TYPE varchar(300) 
USING "password"::varchar;

我正面临着同样的问题,试图将VARCHAR从32截断为8,并得到ERROR:值对于类型字符变化(8)太长。我希望尽可能地接近SQL,因为我使用的是自制的类似于jpa的结构,我们可能不得不根据客户的选择切换到不同的DBMS (PostgreSQL是默认的)。因此,我不想使用修改System表的技巧。

我结束了在ALTER TABLE中使用using语句:

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8)
USING substr("MyColumn", 1, 8)

正如@raylu指出的那样,ALTER在表上获得了一个排他锁,因此所有其他操作将被延迟,直到它完成。

我发现了一个非常简单的方法来改变大小,即注释@Size(min = 1, max = 50),这是import javax.validation的一部分。约束”。 “进口javax.validation.constraints.Size;”

@Size(min = 1, max = 50)
private String country;


when executing  this is hibernate you get in pgAdmin III 


CREATE TABLE address
(
.....
  country character varying(50),

.....

)