将varchar字段的类型更改为整数:“无法自动强制转换为整数”


153

我有一张小桌子,并且某个字段包含“ 字符变化 ” 类型。我正在尝试将其更改为“ Integer ”,但它给出了无法进行强制转换的错误。

有没有解决的办法,还是应该只创建另一个表并使用查询将记录带入其中。

该字段仅包含整数值。


您尝试了什么特定的ALTER TABLE,具体的错误消息是什么?
亩太短了

@muistooshort我尝试使用phppgadmin中的alter。选择该列并尝试输入新的字段类型。错误是:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols 2012年

3
首先是要备份表。然后,您可以在同一表中创建另一个整数类型的列(例如field2)。选择将field1的整数转换为field2。然后重命名该列。
伊戈尔(Igor)2012年

@Igor,但是新列位于表的末尾,对吗?我不能放在同一位置吗?
itsols 2012年

2
@itsols关心列的位置通常是应用程序设计困难的标志。您几乎总是希望使用显式命名的列和SELECT列表,而不依赖于列序位置。也就是说,答案中给出的方法将保留列的位置。
Craig Ringer

Answers:


264

没有隐含的(自动)从铸铁textvarcharinteger(即你不能传递varchar给函数期望integer或分配varchar领域的integer一个),所以你必须指定使用显式类型转换ALTER TABLE ... ALTER COLUMN ...类型。 ..使用

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (col_name::integer);

请注意,您的文本字段中可能会有空格;在这种情况下,请使用:

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (trim(col_name)::integer);

在转换之前去除空格。

如果该命令在中运行,则从错误消息中可以明显看出这一点psql,但是PgAdmin-III可能没有向您显示完整的错误。如果psql在PostgreSQL 9.2上进行测试,会发生以下情况:

=> CREATE TABLE test( x varchar );
CREATE TABLE
=> insert into test(x) values ('14'), (' 42  ');
INSERT 0 2
=> ALTER TABLE test ALTER COLUMN x TYPE integer;
ERROR:  column "x" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion. 
=> ALTER TABLE test ALTER COLUMN x TYPE integer USING (trim(x)::integer);
ALTER TABLE        

感谢@muistooshort添加USING链接。

参见这个相关问题 ; 这是关于Rails迁移的,但根本原因是相同的,答案也适用。

如果错误仍然存​​在,则可能与列值无关,但是此列或列默认值上的索引可能无法进行类型转换。索引需要在ALTER COLUMN之前删除,并在之后重新创建。默认值应适当更改。


感谢您抽出宝贵的时间。但是我似乎无法正常工作。我尝试了您的ALTER行,它给了我一个错误“使用附近的语法错误”
itsols 2012年

我的声明:ALTER TABLE“ tblMenus” ALTER COLUMN“ MID”使用(trim(“ MID”):: integer);
itsols 2012年

1
@itsols完全是我的错误;就像您看到的评论一样,我已对其进行了更正。见修订。演示代码中是正确的,只是开头没有通用示例。
Craig Ringer

太感谢了!这个答案为我节省了很多麻烦和时间。我想知道为什么niether phppgadmin和pgadmin都具有此功能...
itsols 2012年

@itsols大多数核心团队对PgAdmin并不感兴趣,很少有人使用它。它具有一些烦人的可用性缺陷和功能限制。这只是其中许多之一。因为很少有专家使用PgAdmin,所以他们没有动力去解决可能使他们烦恼的事情。我自己不使用它,因为我发现psql它变得越来越快。我写了一点关于pgAdmin的可用性咆哮与问候备份和恢复前一阵子:blog.ringerc.id.au/2012/05/...
克雷格林格

69

对我有用。

将varchar列更改为int

change_column :table_name, :column_name, :integer

得到:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

更改为

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

您是否尝试过使用数据进行此练习,并且您的数据是完整的吗?
itsols 2014年

3
只要列中的内容是整数,就可以
bibangamba 2014年

它对我不起作用。我使用Ruby 2.2.3与4.2.3的轨道
Thinh的D.裴

@ ThinhD.Bui-为我工作,2.3.0,导轨4.2.6
Philip

1
也要注意默认设置
Francisco Quintero


8

试试这个,它肯定会起作用。

在编写Rails迁移以将字符串列转换为整数时,您通常会说:

change_column :table_name, :column_name, :integer

但是,PostgreSQL将抱怨:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

“提示”基本上告诉您,您需要确认您希望这种情况发生,以及如何转换数据。只需在迁移中说一下:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

上面的内容将模仿您从其他数据库适配器知道的内容。如果您有非数字数据,结果可能会出乎意料(毕竟您要转换为整数)。


我只想补充一点,请注意change_column。这是不可逆的。我建议在迁移过程中上下使用,以使其可逆。
Mukesh Kumar Gupta

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""错误发生
Shaig Khaligli

6

我遇到了同样的问题。后来我意识到我要更改的列具有默认的字符串值。删除默认值会使错误消失:)


此列上的现有索引也可能是一个问题。它们需要在ALTER之前删除,然后在之后重新创建。
Envek

1

如果您不小心将整数与文本数据混合在一起,则应首先在以下update命令下执行(如果不在以上,则alter table将失败):

UPDATE the_table SET col_name = replace(col_name, 'some_string', '');

3
如果要去除regexp_replace(col_name, '[^0-9.]','','g')不需要的字符和空格,最好使用类似的方法。你需要一些更复杂一点,如果你想保留NaNInf10E42科学记数法,虽然。
Craig Ringer 2013年

1

如果您在开发环境中工作(或用于生产环境,则可能会备份您的数据),那么首先要清除DB字段中的数据或将值设置为0。

UPDATE table_mame SET field_name= 0;

之后,运行以下查询,并在成功运行查询之后,运行到schemamigration,然后运行迁移脚本。

ALTER TABLE table_mame ALTER COLUMN field_name TYPE numeric(10,0) USING field_name::numeric;

我认为它将为您提供帮助。


0

我遇到过同样的问题。我开始重置列的默认值。

change_column :users, :column_name, :boolean, default: nil
change_column :users, :column_name, :integer, using: 'column_name::integer', default: 0, null: false
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.