Измените тип поля varchar на integer: «не может быть автоматически приведен к типу integer»


154

У меня есть небольшая таблица, и определенное поле содержит тип « символ меняется ». Я пытаюсь изменить его на " Integer ", но выдает ошибку, что приведение невозможно.

Есть ли способ обойти это или я должен просто создать другую таблицу и внести записи в нее с помощью запроса.

Поле содержит только целочисленные значения.


Какой конкретный ALTER TABLE вы пробовали и какое конкретное сообщение об ошибке?
мю слишком коротка

@muistooshort Я пытался использовать alter из phppgadmin. Выделил столбец и попытался ввести новый тип поля. Ошибка:SQL error: ERROR: column "MID" cannot be cast to type integer
itols

3
Во-первых, это резервная копия таблицы. Затем вы можете создать другой столбец (скажем, field2) целочисленного типа в той же таблице. Выберите приведение к целочисленному значению поля field1 в field2. Затем переименуйте столбец.
Игорь

@ Игорь, но новый столбец находится в конце таблицы, верно? Разве я не могу иметь его в той же позиции?
itols

2
@itsols Забота о позициях столбцов обычно является признаком неправильного дизайна приложения. Вы почти всегда хотите использовать явно именованные столбцы и SELECTсписки, не полагаясь на порядковые позиции столбцов. Тем не менее, подход, приведенный в ответах, сохранит положение столбца.
Крейг Рингер

Ответы:


264

Не существует неявного (автоматического) приведения из textили varcharв integer(т. Е. Вы не можете передатьvarchar в функцию, ожидающую integerили присвоить varcharполе integerодному), поэтому вы должны указать явное приведение, используя ALTER TABLE ... ALTER COLUMN ... TYPE. .. ИСПОЛЬЗОВАНИЕ :

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

Мое утверждение: ALTER TABLE "tblMenus" ALTER COLUMN "MID" USING (trim ("MID") :: integer);
itols

1
@itsols полностью моя ошибка; Я исправил это, как только увидел твой комментарий. См пересмотрено. Это было правильно в демонстрационном коде, но не в общем примере в начале.
Крейг Рингер

Бесконечно благодарен! Этот ответ спас мне много хлопот и времени. Интересно, почему ни phppgadmin, ни pgadmin не имеют этого в качестве функции ...
itols

@itsols Большая часть основной команды не так заинтересована в PgAdmin, и лишь немногие из них используют его. Он имеет некоторые раздражающие юзабилити и функциональные ограничения. Это только один из многих из них. Из-за того, что немногие эксперты используют PgAdmin, они не так мотивированы, чтобы исправлять то, что их раздражало. Я сам им не пользуюсь, потому что нахожу psqlнамного быстрее и проще. Некоторое время назад я написал несколько слов о юзабилити PgAdmin в отношении резервного копирования и восстановления: blog.ringerc.id.au/2012/05/…
Крейг Рингер

71

это сработало для меня.

изменить столбец 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)'

Вы пробовали это упражнение с данными и ваши данные были целы?
itols

3
до тех пор, пока в столбце есть целое число, да
bibangamba

Это не работает со мной. Я использую ruby ​​2.2.3 с рельсами 4.2.3
Thinh D. Bui

@ ThinhD.Bui - работает для меня, 2.3.0, рельсы 4.2.6
Филипп

1
Будьте осторожны с настройками по умолчанию
Франциско Кинтеро

17

Вы можете сделать это как:

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

или попробуйте это:

change_column :table_name, :column_name, :integer, using: 'column_name::integer'

Если вы хотите узнать больше об этой теме, прочитайте эту статью: https://kolosek.com/rails-change-database-column


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. это необратимо Я предлагаю использовать вверх и вниз при миграции, чтобы сделать это обратимым.
Мукеш Кумар Гупта

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""ошибка происходит
Шаиг Халигли

6

У меня та же проблема. Тогда я понял, что у меня есть значение по умолчанию для столбца, который я пытался изменить. Удаление значения по умолчанию сделало ошибку исчезла :)


Также существующие индексы в этом столбце могут быть проблемой. Их нужно сбросить до ALTER и воссоздать после.
Envek

1

Если вы случайно или не смешали целые числа с текстовыми данными, вам сначала нужно выполнить команду обновления ниже (если не выше, то изменить таблицу не удастся):

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

3
Вам было бы лучше с чем-то вроде, regexp_replace(col_name, '[^0-9.]','','g')если вы пытаетесь убрать ненужных персонажей и пробелы. Вы должны были бы что - то немного более сложным , если вы хотите сохранить NaNи Infи 10E42научную нотацию, хотя.
Крейг Рингер

1

Если вы работаете в среде разработки (или в производственной среде, то это может быть резервное копирование ваших данных), затем сначала удалите данные из поля БД или установите значение 0.

UPDATE table_mame SET field_name= 0;

После этого для запуска приведенного ниже запроса и после успешного выполнения запроса к схеме-миграции и после этого запустите сценарий миграции.

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

Я думаю, что это поможет вам.


1

Я была такая же проблема. Я начал сбрасывать настройки колонки по умолчанию.

change_column :users, :column_name, :boolean, default: nil
change_column :users, :column_name, :integer, using: 'column_name::integer', default: 0, null: false
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.