Rails กำหนดรหัสอัตโนมัติที่มีอยู่แล้ว


93

ฉันสร้างสถิติใหม่ดังนี้:

truck = Truck.create(:name=>name, :user_id=>2)

ขณะนี้ฐานข้อมูลของฉันมีเอนทิตีสำหรับรถบรรทุกหลายพันรายการ แต่ฉันกำหนดรหัสให้กับหลาย ๆ รายการในลักษณะที่ทำให้มี ID บางส่วน สิ่งที่เกิดขึ้นคือรางสร้างรายการที่มี id = 150 และใช้งานได้ดี แต่มันพยายามสร้างไอเท็มและกำหนด id = 151 แต่ id นั้นอาจมีอยู่แล้วดังนั้นฉันจึงเห็นข้อผิดพลาดนี้:

ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey" DETAIL: Key (id)=(151) already exists.

และในครั้งต่อไปที่ฉันเรียกใช้แอคชันมันจะกำหนด id 152 ซึ่งจะทำงานได้ดีหากยังไม่ได้ใช้ค่านั้น ฉันจะรับรางเพื่อตรวจสอบว่ามี ID อยู่แล้วก่อนกำหนดได้อย่างไร

ขอบคุณ!

แก้ไข

รหัสรถบรรทุกคือสิ่งที่ถูกทำซ้ำ มีผู้ใช้อยู่แล้วและเป็นค่าคงที่ในกรณีนี้ จริงๆแล้วมันเป็นปัญหาเดิมที่ฉันต้องจัดการ ทางเลือกหนึ่งคือการสร้างตารางขึ้นมาใหม่โดยให้รางอัตโนมัติกำหนดทุก id ในครั้งนี้ ฉันเริ่มคิดว่านี่อาจเป็นทางเลือกที่ดีที่สุดเพราะฉันมีปัญหาอื่น ๆ อีกเล็กน้อย แต่การย้ายข้อมูลเพื่อทำสิ่งนี้จะซับซ้อนมากเพราะ Truck เป็นคีย์ต่างประเทศในตารางอื่น ๆ จะมีวิธีง่ายๆในการสร้างรางสร้างตารางใหม่ด้วยข้อมูลเดิมที่เก็บไว้แล้วใน Truck โดยใช้ ID ที่กำหนดอัตโนมัติและรักษาความสัมพันธ์ที่มีอยู่ทั้งหมดหรือไม่?


ทำไมคุณไม่ปล่อยให้รางกำหนด ID โดยอัตโนมัติ? นั่นจะช่วยขจัดอันตรายจากการทำซ้ำ - หรือนี่คือปัญหาข้อมูลเดิมที่คุณต้องเก็บ ID เก่าไว้? เพียงต้องการทำความเข้าใจกรณีธุรกิจเล็กน้อยเนื่องจากนี่ไม่ใช่ธุรกิจเหมือนปกติเมื่อสร้างออบเจ็กต์ใหม่
MBHNYC

@MBHNYC ฉันคิดว่า D-Nice กำลังกำหนด user_id ในขณะที่สร้าง บริษัท ไม่ใช่ id อย่างที่คุณคิด (และฉันก็ทำไปสักพักแล้วด้วย)
Anil

Ooo จับ Anil ได้ดี - คุณพูดถูกทั้งหมด @ D-Nice อาจเพิ่มการย้ายข้อมูลสำหรับตารางนี้ในโพสต์ของคุณในกรณีที่มีอะไรแปลก ๆ ? อยากให้แก้ไข user_id นั้นเพื่อขจัดความสับสน ..
MBHNYC

ไม่ขออภัยมันไม่ชัดเจนรหัส บริษัท คือสิ่งที่ซ้ำกัน มีผู้ใช้อยู่แล้วและเป็นค่าคงที่ในกรณีนี้ จริงๆแล้วมันเป็นปัญหาเดิมที่ฉันต้องจัดการ จะแก้ไขโพสต์พร้อมข้อมูลเพิ่มเติม
D-Nice

คุณไม่จำเป็นต้องสร้างตารางใหม่ เพียงแค่ดูคำตอบของฉันเพื่อรีเซ็ตลำดับ
Dondi Michael Stroma

คำตอบ:


88

Rails อาจใช้ลำดับ PostgreSQL ในตัว ความคิดของลำดับคือใช้เพียงครั้งเดียว

วิธีแก้ปัญหาที่ง่ายที่สุดคือตั้งค่าลำดับสำหรับคอลัมน์ company.id ของคุณเป็นค่าสูงสุดในตารางด้วยแบบสอบถามดังนี้:

SELECT setval('company_id_seq', (SELECT max(id) FROM company));

ฉันเดาชื่อลำดับของคุณ "company_id_seq" ชื่อตาราง "บริษัท " และชื่อคอลัมน์ "id" ... โปรดแทนที่ด้วยชื่อที่ถูกต้อง คุณสามารถรับชื่อลำดับที่มีSELECT pg_get_serial_sequence('tablename', 'columname');หรือดูนิยามตารางด้วย\d tablenameหรือดูที่ความละเอียดตารางที่มี

ทางเลือกอื่นคือการแทนที่เมธอด save () ในคลาส บริษัท ของคุณเพื่อตั้งค่ารหัส บริษัท สำหรับแถวใหม่ด้วยตนเองก่อนทำการบันทึก


ฉันเดาว่าสิ่งที่จะทำคือให้การกำหนดอัตโนมัติเริ่มต้นด้วยค่าสูงสุด + 1 ในปัจจุบัน?
D-Nice

ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุดสำหรับคำถามของฉันอย่างไรก็ตามด้วยเหตุผลที่ไม่เกี่ยวข้องฉันจะต้องหาวิธีใช้กลยุทธ์ที่ฉันอธิบายไว้ในการแก้ไข OP
D-Nice

ฉันไม่เข้าใจว่าทำไมสิ่งนี้ถึงเริ่มต้นด้วย? สิ่งนี้เกิดขึ้นกับฉันและฉันอยากจะเข้าใจว่ามันเป็นไปได้อย่างไร
Hunt Burdick

2
@Websitescenes หากมีคอลัมน์ SERIAL ใน PostgreSQL (คอลัมน์อนุกรมคือคอลัมน์ที่ค่าเริ่มต้นคือค่าถัดไปในลำดับ) จากนั้นเติมข้อมูลในตารางด้วยค่าฮาร์ดในคอลัมน์นั้นลำดับจะไม่ถูกอัปเดตโดยอัตโนมัติ ตัวอย่าง: create table t (id serial not null primary key); insert into t values (1); insert into t values (default); ERROR: duplicate key value violates unique constraint "t_pkey" DETAIL: Key (id)=(1) already exists.
Dondi Michael Stroma

207

ฉันทำสิ่งนี้ซึ่งช่วยแก้ปัญหาให้ฉันได้

ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end

ฉันพบ reset_pk_sequence! จากกระทู้นี้ http://www.ruby-forum.com/topic/64428


4
ขอบคุณทางออกที่ดีที่สุด หลังจากการถ่ายโอนฐานข้อมูลฉันมีปัญหาเดียวกัน
Oleg Pasko

63
หรือเทียบเท่าซับเดียว (สำหรับวัตถุประสงค์ในการคัดลอก / วางคอนโซลราง):ActiveRecord::Base.connection.tables.each { |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) }
Raf

มีความคิดอย่างไรที่จะไม่ซิงค์กัน
Tall Paul

26

ขึ้นอยู่กับคำตอบของ @Apieคำตอบ

คุณสามารถทำงานและเรียกใช้เมื่อคุณต้องการด้วย:

rake database:correction_seq_id

คุณสร้างงานเช่นนี้:

rails g task database correction_seq_id

และในไฟล์ที่สร้าง ( lib/tasks/database.rake) ใส่:

namespace :database do
    desc "Correction of sequences id"
    task correction_seq_id: :environment do
        ActiveRecord::Base.connection.tables.each do |t|
            ActiveRecord::Base.connection.reset_pk_sequence!(t)
        end
    end
end

4

สำหรับฉันดูเหมือนปัญหาฐานข้อมูลไม่ใช่ปัญหา Rails เป็นไปได้ไหมว่าฐานข้อมูลของคุณมีเมล็ดพันธุ์ข้อมูลประจำตัวที่ไม่เหมาะสมในidคอลัมน์ของคุณ หากต้องการทดสอบให้ลองแทรกสองสามรายการลงในฐานข้อมูลของคุณโดยตรงและดูว่ามีพฤติกรรมเดียวกันหรือไม่


3
ทำไมต้องโหวตลง? นี่คือลักษณะการทำงานที่แน่นอนที่เกิดขึ้นหากคุณตั้งค่าลำดับการเพิ่มของคุณเป็นสิ่งที่ต่ำกว่าค่าอื่น ๆ ที่มีอยู่และทำให้บางครั้งเกิดการชนกันเมื่อแทรกข้อมูล ผู้โพสต์บอกแล้วว่ามีข้อมูลที่เข้าข่ายกรณีนี้
mynameiscoffey

ฉันสามารถแทรกได้ดี หลังจากที่ฉันได้รับข้อผิดพลาดนี้ฉันสามารถเรียกใช้การกระทำเดิมอีกครั้งและทำให้มันใช้งานได้หากยังไม่ได้ใช้รหัสถัดไปในลำดับ
D-Nice

ดูเหมือนว่านี่จะเป็นสถานการณ์ของฉัน - ฉันประสบปัญหา แต่บันทึกถัดไปที่ฉันใส่นั้นใช้งานได้ดีดังนั้นจึงต้องได้รับเมล็ดพันธุ์ในสถานที่ที่เหมาะสม
Ben Wheeler

4

ฉันแก้ไขปัญหานี้โดยทำตามคำสั่ง

เรียกใช้สิ่งนี้ในคอนโซลรางของคุณ

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.