Змініть тип поля варшара на ціле число: "не можна автоматично передати на тип цілого"


154

У мене невелика таблиця, і певне поле містить тип " характер варіюється ". Я намагаюся змінити його на " Integer ", але це дає помилку, що кастинг неможливий.

Чи є спосіб обходити це чи мені просто створити іншу таблицю і внести до неї записи за допомогою запиту.

Поле містить лише цілі значення.


Яке конкретно ВИПУСКУ ТАБЛИЦІ ви спробували та яке саме повідомлення про помилку?
mu занадто короткий

@muistooshort Я спробував використовувати alter від phppgadmin. Вибрав стовпчик і спробував ввести новий тип поля. Помилка:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols

3
Спочатку - це резервне копіювання таблиці. Тоді ви можете створити інший стовпець (скажімо поле2) цілого типу в тій самій таблиці. Виберіть значення для відтворення цілого числа поля1 до поля2. Потім перейменуйте стовпець.
Ігор

@Igor, але новий стовпець потрапляє в кінці таблиці, правда? Не можу я мати його в тому ж положенні?
itsols

2
@itsols Догляд за положеннями стовпців зазвичай є ознакою iffy дизайну додатків. Ви майже завжди хочете використовувати чітко названі стовпці та 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посилання.

Дивіться також це пов'язане питання ; мова йде про міграцію Рейлів, але основна причина та сама, і відповідь стосується.

Якщо помилка все-таки виникає, вона може бути пов’язана не зі значеннями стовпців, але індекси над цим стовпцем або значеннями за замовчуванням стовпця можуть не вводити typecast. Індекси потрібно скинути перед ALTER COLUMN і відтворити після. Значення за замовчуванням слід відповідним чином змінити.


Дякую, що знайшли час. Але мені здається, що це не працює. Я спробував ваш рядок ALTER, і він видає мені помилку "Помилка синтаксису біля використання"
itsols

Мій вислів: ALTER TABLE "tblMenus" ALTER COLUMN "MID" ВИКОРИСТАННЯ (trim ("MID") :: integer);
itsols

1
@itsols Цілком моя помилка; Я виправив це саме тоді, коли побачив ваш коментар. Див. Переглянуте. Це було правильно в демо-коді, тільки не загальний приклад на початку.
Крейг Рінгер

Завдяки мільйонів! Ця відповідь врятувала мені багато клопоту та часу. Цікаво, чому niether phppgadmin, ні pgadmin мають це як особливість ...
itsols

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

70

це працювало для мене.

змінити колонку 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

3
доки те, що є у стовпці, є цілим числом, так
bibangamba

Це не працює зі мною. Я використовую рубін 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)'

Вищенаведене імітує те, що ви знаєте з інших адаптерів бази даних. Якщо у вас є нечислові дані, результати можуть бути несподіваними (але ви все-таки перетворюєтесь на ціле число).


Я просто хотів додати ще один момент, що будьте обережні зі зміною_колонки. це незворотно. Я пропоную використовувати міграцію вгору та вниз, щоб зробити це оборотним.
Мукеш Кумар Гупта

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""трапляється помилка
Шайг Халіглі

6

У мене така ж проблема. Тож я зрозумів, що для стовпця, який я намагався змінити, у мене є значення рядка за замовчуванням. Якщо видалити значення за замовчуванням, помилка зникла :)


Також можуть бути проблемою існуючі індекси цього стовпця. Їх потрібно скинути перед ALTER і відтворити після.
Енвек

1

Якщо ви випадково або не змішали цілі числа з текстовими даними, спочатку слід виконати команду оновлення нижче (якщо не вище таблиці alter не вдасться):

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.