เปลี่ยนประเภทของฟิลด์ varchar เป็นจำนวนเต็ม:“ ไม่สามารถแปลงโดยอัตโนมัติเพื่อพิมพ์จำนวนเต็ม”


154

ฉันมีตารางขนาดเล็กและเขตข้อมูลหนึ่งมีชนิด " ตัวอักษรเปลี่ยนแปลง " ฉันพยายามที่จะเปลี่ยนเป็น " จำนวนเต็ม " แต่มันทำให้เกิดข้อผิดพลาดที่ไม่สามารถทำการคัดเลือกนักแสดงได้

มีวิธีแก้ไขหรือไม่ฉันควรสร้างตารางอื่นและนำระเบียนไปใช้โดยใช้แบบสอบถาม

ฟิลด์มีค่าจำนวนเต็มเท่านั้น


คุณได้ลองแก้ไขตารางอะไรเฉพาะและข้อความแสดงข้อผิดพลาดเฉพาะคืออะไร
mu สั้นเกินไป

@muistooshort ฉันลองใช้การเปลี่ยนแปลงจาก phppgadmin เลือกคอลัมน์และพยายามป้อนประเภทฟิลด์ใหม่ ข้อผิดพลาดคือ:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols

3
แรกคือตารางสำรอง จากนั้นคุณอาจสร้างคอลัมน์อื่น (พูดฟิลด์ 2) ประเภทจำนวนเต็มในตารางเดียวกัน เลือกค่า cast เป็นจำนวนเต็มของ field1 ลงใน field2 จากนั้นเปลี่ยนชื่อคอลัมน์
Igor

@Igor แต่คอลัมน์ใหม่ตรงท้ายตารางใช่ไหม ฉันไม่สามารถอยู่ในตำแหน่งเดียวกันได้หรือไม่?
itsols

2
@itsols การดูแลเกี่ยวกับตำแหน่งของคอลัมน์มักเป็นสัญลักษณ์ของการออกแบบแอพพลิเคชั่นที่ไม่แน่นอน คุณเกือบจะต้องการใช้คอลัมน์และSELECTรายการที่มีชื่ออย่างชัดเจนโดยไม่ต้องอาศัยตำแหน่งอันดับของคอลัมน์ ที่กล่าวว่าวิธีการที่กำหนดในคำตอบจะรักษาตำแหน่งคอลัมน์
Craig Ringer

คำตอบ:


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 จะไม่แสดงข้อผิดพลาดทั้งหมด นี่คือสิ่งที่เกิดขึ้นถ้าฉันทดสอบในpsqlPostgreSQL 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 แต่สาเหตุสำคัญเหมือนกันและคำตอบนั้นถูกนำไปใช้

หากข้อผิดพลาดยังคงเกิดขึ้นแสดงว่าอาจไม่เกี่ยวข้องกับค่าคอลัมน์ แต่การจัดทำดัชนีเหนือค่าเริ่มต้นของคอลัมน์หรือคอลัมน์นี้อาจล้มเหลว typecast ดัชนีจะต้องลดลงก่อนที่จะเปลี่ยนคอลัมน์และสร้างขึ้นใหม่หลังจาก ควรเปลี่ยนค่าเริ่มต้นอย่างเหมาะสม


ขอบคุณที่สละเวลา แต่ฉันไม่สามารถทำงานนี้ได้ ฉันลองบรรทัด ALTER ของคุณแล้วมันทำให้ฉันมีข้อผิดพลาด "ข้อผิดพลาดทางไวยากรณ์ใกล้การใช้"
itsols

คำสั่งของฉัน: แก้ไขตาราง "tblMenus" คอลัมน์แก้ไข "MID" โดยใช้ (ตัด ("MID") :: จำนวนเต็ม);
itsols

1
@itsols ผิดทั้งหมดของฉัน; ฉันแก้ไขมันเมื่อฉันเห็นความคิดเห็นของคุณ ดูการแก้ไข มันถูกต้องในรหัสตัวอย่างไม่ใช่ตัวอย่างทั่วไปตอนเริ่มต้น
Craig Ringer

ขอบคุณหนึ่งล้าน! คำตอบนี้ช่วยให้ฉันมีปัญหาและเวลามาก ฉันสงสัยว่าเหตุใด niether phppgadmin และ pgadmin จึงมีคุณลักษณะนี้ ...
itsols

@itsols ทีมแกนหลักส่วนใหญ่ไม่สนใจ PgAdmin และบางคนใช้มัน มันมีหูดที่ใช้งานได้น่ารำคาญและข้อ จำกัด การทำงาน นี่เป็นเพียงหนึ่งในหลาย ๆ เนื่องจากผู้เชี่ยวชาญไม่กี่คนที่ใช้ PgAdmin พวกเขาไม่มีแรงจูงใจที่จะแก้ไขสิ่งต่าง ๆ ที่จะรบกวนพวกเขาเกี่ยวกับเรื่องนี้ ฉันไม่ได้ใช้ด้วยตัวเองเพราะฉันพบว่าpsqlเร็วกว่าและง่ายกว่ามาก ฉันเขียนเล็กน้อยเกี่ยวกับการใช้งาน PgAdmin เกี่ยวกับการสำรองข้อมูลและกู้คืนในขณะที่ผ่านมา: blog.ringerc.id.au/2012/05/05
Craig Ringer

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)'

คุณลองทำแบบฝึกหัดนี้กับข้อมูลและข้อมูลของคุณยังคงอยู่หรือไม่?
itsols

3
ตราบเท่าที่สิ่งที่อยู่ในคอลัมน์เป็นจำนวนเต็มใช่
bibangamba

มันไม่ทำงานกับฉัน ฉันใช้ทับทิม 2.2.3 กับราง 4.2.3
Thinh D. Bui

@ ThinhD.Bui - ทำงานให้ฉัน, 2.3.0, ราง 4.2.6
Philip

1
ระวังด้วยค่าเริ่มต้นเช่นกัน
Francisco Quintero

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 มันกลับไม่ได้ ฉันขอแนะนำให้ใช้การโยกย้ายขึ้นและลงเพื่อทำให้สิ่งนี้ย้อนกลับได้
Mukesh Kumar Gupta

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""ข้อผิดพลาดเกิดขึ้น
Shaig Khaligli

6

ฉันมีปัญหาเดียวกัน กว่าที่ฉันรู้ว่าฉันมีค่าสตริงเริ่มต้นสำหรับคอลัมน์ที่ฉันพยายามแก้ไข การลบค่าเริ่มต้นทำให้ข้อผิดพลาดหายไป :)


นอกจากนี้ดัชนีที่มีอยู่ในคอลัมน์นี้อาจเป็นปัญหา พวกเขาจะต้องลดลงก่อนที่จะแก้ไขและสร้างขึ้นมาใหม่หลังจาก
Envek

1

หากคุณบังเอิญจำนวนเต็มผสมกับข้อมูลตัวอักษรคุณควรดำเนินการด้านล่างคำสั่ง update ครั้งแรก (ถ้าไม่แก้ไขตารางข้างต้นจะล้มเหลว):

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

3
คุณจะรู้สึกดีขึ้นregexp_replace(col_name, '[^0-9.]','','g')ถ้าคุณพยายามที่จะดึงตัวละครที่ไม่ต้องการและ white-space คุณจะต้องบางบิตซับซ้อนมากขึ้นถ้าคุณต้องการที่จะรักษาNaNและInfและ10E42สัญกรณ์วิทยาศาสตร์แม้ว่า
Craig Ringer

1

หากคุณกำลังทำงานกับสภาพแวดล้อมการพัฒนา (หรือสำหรับ env การผลิตอาจเป็นการสำรองข้อมูลของคุณ) ก่อนอื่นให้ล้างข้อมูลจากฟิลด์ DB หรือตั้งค่าเป็น 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.