首页 文章

Postgresql - 更改varchar列的大小

提问于
浏览
118

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

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

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

任何线索将不胜感激!提前致谢,

注意:我使用PostgreSQL 9.0 .

8 回答

  • 42

    有关如何在Resize a column in a PostgreSQL table without changing data执行此操作的说明 . 您必须破解数据库目录数据 . 正式执行此操作的唯一方法是使用ALTER TABLE,并且正在运行_2957653 .

    在更改之前,请务必阅读文档的Character Types部分 . 这里有各种各样奇怪的案例需要注意 . 当值存储到行中时,将完成长度检查 . 如果您在那里破解下限,则根本不会减小现有值的大小 . 您最好在整个表格上进行扫描,查找在进行更改后字段长度> 40个字符的行 . 你只需要对超大型锁定一些锁定 - 因为如果有人试图更新该行上的任何内容,那么它现在会拒绝它,因为它会存储新版本的行 . 为用户提供欢闹 .

    VARCHAR是PostgreSQL中存在的一种可怕的类型,只是为了符合SQL标准中相关的可怕部分 . 如果您不关心多数据库兼容性,请考虑将数据存储为TEXT并添加约束以限制其长度 . 您可以在没有此表锁定/重写问题的情况下更改约束,并且它们可以执行更多完整性检查,而不仅仅是弱长度检查 .

  • 73

    在PostgreSQL 9.1中有一种更简单的方法

    http://www.postgresql.org/message-id/162867790801110710g3c686010qcdd852e721e7a559@mail.gmail.com

    CREATE TABLE foog(a varchar(10));
    
    ALTER TABLE foog ALTER COLUMN a TYPE varchar(30);
    
    postgres=# \d foog
    
     Table "public.foog"
     Column |         Type          | Modifiers
    --------+-----------------------+-----------
     a      | character varying(30) |
    
  • 27

    好吧,我可能迟到了派对,但......

    在你的情况下,没有必要调整柱子的大小!

    Postgres与其他一些数据库不同,它足够聪明,只能使用足够的空间来容纳字符串(即使使用压缩来处理更长的字符串),所以即使你的列被声明为VARCHAR(255) - 如果你存储了40个字符的字符串在列中,空间使用量将是40字节1字节的开销 .

    短字符串(最多126个字节)的存储要求是1个字节加上实际字符串,其中包括字符空间填充 . 较长的字符串有4个字节的开销而不是1.长字符串由系统自动压缩,因此磁盘上的物理要求可能更少 . 非常长的值也存储在后台表中,因此它们不会干扰对较短列值的快速访问 .

    http://www.postgresql.org/docs/9.0/interactive/datatype-character.html

    VARCHAR中的大小规范仅用于检查插入的值的大小,它不会影响磁盘布局 . 实际上,VARCHAR and TEXT fields are stored in the same way in Postgres .

  • 63

    我正面临同样的问题,试图将VARCHAR从32截断到8并获得 ERROR: value too long for type character varying(8) . 我希望尽可能接近SQL,因为我选择了(PostgreSQL是默认的) . 因此,我不想使用改变系统表的技巧 .

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

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

    正如@raylu所指出的那样, ALTER 获取了对表的独占锁定,因此所有其他操作将被延迟直到完成 .

  • 5

    这是Greg Smith描述的页面的the cache . 如果死亡,alter语句如下所示:

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

    如果您的表是TABLE1,则该列为COL1,您希望将其设置为35个字符(根据链接,遗留目的需要4个,可能是评论中A.H . 引用的开销) .

  • 1

    如果将alter放入事务中,则不应锁定表:

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

    这对我来说非常快速,在一张超过40万行的 table 上几秒钟 .

  • 7

    在redshift postgresql上添加新列并用旧版替换新列,请参阅此链接以获取更多详细信息https://gist.github.com/mmasashi/7107430

    BEGIN;
    LOCK users;
    ALTER TABLE users ADD COLUMN name_new varchar(512) DEFAULT NULL;
    UPDATE users SET name_new = name;
    ALTER TABLE users DROP name;
    ALTER TABLE users RENAME name_new TO name;
    END;
    
  • 6

    我找到了一种非常简单的方法来改变大小,即注释@Size(min = 1,max = 50),它是“import javax.validation.constraints”的一部分,即“import 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),
    
    .....
    
    )
    

相关问题