मैं एक कॉलम को कैसे अद्वितीय बना सकता हूं और इसे रूबी माइग्रेशन पर रूबी में अनुक्रमित कर सकता हूं?


416

मैं uniqueरूबी माइग्रेशन स्क्रिप्ट पर रूबी में एक कॉलम बनाना चाहूंगा । यह करने के लिए सबसे अच्छा तरीका क्या है? इसके अलावा एक तालिका में एक स्तंभ को अनुक्रमित करने का एक तरीका है?

मैं uniqueएक डेटाबेस में स्तंभों को लागू करना चाहूंगा, जैसा कि सिर्फ उपयोग करने के लिए :validate_uniqueness_of

जवाबों:


686

रेल के पुराने संस्करणों के लिए संक्षिप्त उत्तर (रेल के लिए अन्य उत्तर देखें 4+):

add_index :table_name, :column_name, unique: true

कई कॉलमों को एक साथ अनुक्रमित करने के लिए, आप एकल कॉलम नाम के बजाय कॉलम नामों की एक सरणी पास करते हैं,

add_index :table_name, [:column_name_a, :column_name_b], unique: true

यदि आपको "सूचकांक नाम ... बहुत लंबा है", तो आप name: "whatever"नाम को छोटा करने के लिए add_index विधि में जोड़ सकते हैं ।

ठीक-ठीक नियंत्रण के लिए, एक " execute" विधि है जो सीधे SQL निष्पादित करती है।

बस!

यदि आप इसे नियमित पुराने मॉडल सत्यापन के प्रतिस्थापन के रूप में कर रहे हैं, तो यह देखने के लिए जांचें कि यह कैसे काम करता है। उपयोगकर्ता को रिपोर्ट करने में त्रुटि की संभावना मॉडल-स्तरीय सत्यापन के बिना उतनी अच्छी नहीं होगी। आप हमेशा दोनों कर सकते हैं।


36
+1 का उपयोग करने के लिए जारी रखने के सुझाव के लिए validates_uniqueness_of। त्रुटि हैंडलिंग एक एकल अनुक्रमित क्वेरी की लागत के लिए इस पद्धति का उपयोग करके बहुत अधिक स्वच्छ है, मैं सुझाव
दूंगा

1
मैंने कोशिश की कि यह काम न करे! मैं उस कॉलम_नाम के साथ दो रिकॉर्ड सम्मिलित कर सकता हूं जिसे मैंने अद्वितीय के रूप में परिभाषित किया है! मैं रेल का उपयोग कर रहा हूँ 2.3.4 और किसी भी विचार MySql?
ताम

मैंने आपको निष्पादन का उपयोग करके दूसरा सुझाव दिया: "पहले से उपयोग किए जाने वाले उपयोगकर्ताओं को जोड़ें (ईमेल)" और यह काम करता है! यकीन नहीं होता कि पहले वाले को जानने में दिलचस्पी क्यों नहीं होगी
टैम

1
यदि आपको indexed columns are not uniqueएक अद्वितीय सूचकांक बनाने की कोशिश करते समय कोई त्रुटि मिलती है , तो यह हो सकता है क्योंकि तालिका के डेटा में पहले से ही डुप्लिकेट हैं। डुप्लिकेट डेटा को हटाने और माइग्रेशन को फिर से चलाने का प्रयास करें।
हार्टले ब्रॉडी

5
यदि आपको "इंडेक्स नाम ... बहुत लंबा है", तो आप नाम छोटा , :name => "whatever"करने के लिए add_indexविधि में जोड़ सकते हैं ।
रिक स्मिथ

129

रेल से माइग्रेशन add_index_to_table_name column_name: uniq उत्पन्न होता है

या

रेल से माइग्रेशन add_column_name_to_table_name कॉलम_name: string: uniq: index उत्पन्न होता है

उत्पन्न करता है

class AddIndexToModerators < ActiveRecord::Migration
  def change
    add_column :moderators, :username, :string
    add_index :moderators, :username, unique: true
  end
end

यदि आप किसी मौजूदा कॉलम में इंडेक्स जोड़ रहे हैं, तो add_columnलाइन को हटाएं या टिप्पणी करें , या चेक में रखें

add_column :moderators, :username, :string unless column_exists? :moderators, :username

5
मैंने इसे अपडाउन किया क्योंकि मुझे कमांड लाइन फॉर्म चाहिए था। लेकिन यह मूर्खतापूर्ण है कि यह कॉलम को तब भी जोड़ता है जब मैं निर्दिष्ट करता हूं add_index...और नहीं add_column...
टायलर कोलियर

1
हां, शायद अगले संस्करण में।
d .anailov

49

चूँकि इसका उल्लेख अभी तक नहीं किया गया है, लेकिन जब मुझे यह पृष्ठ मिला तो मेरे द्वारा पूछे गए प्रश्न का उत्तर दिया गया है, आप यह भी निर्दिष्ट कर सकते हैं कि एक इंडेक्स अद्वितीय होना चाहिए जब इसे t.referencesया उसके साथ जोड़ रहे हों t.belongs_to:

create_table :accounts do |t|
  t.references :user, index: { unique: true } # or t.belongs_to

  # other columns...
end

(कम से कम रेल के रूप में 4.2.7)


42

यदि आप एक नई तालिका बना रहे हैं, तो आप इनलाइन शॉर्टकट का उपयोग कर सकते हैं:

  def change
    create_table :posts do |t|
      t.string :title, null: false, index: { unique: true }
      t.timestamps
    end
  end

14

मैं रेल्स 5 का उपयोग कर रहा हूं और ऊपर दिए गए उत्तर बहुत अच्छे हैं; यहाँ एक और तरीका है जो मेरे लिए भी काम करता है (तालिका का नाम है :peopleऔर स्तंभ का नाम है :email_address)

class AddIndexToEmailAddress < ActiveRecord::Migration[5.0]
  def change
    change_table :people do |t|
      t.index :email_address, unique: true
    end
  end
end

1

आप अद्वितीय कुंजी के लिए नाम जोड़ना चाह सकते हैं क्योंकि कई बार रेल द्वारा डिफ़ॉल्ट अनूठे_की नाम बहुत लंबा हो सकता है जिसके लिए DB त्रुटि फेंक सकता है।

अपने इंडेक्स के लिए नाम जोड़ने के लिए बस name:विकल्प का उपयोग करें । माइग्रेशन क्वेरी कुछ इस तरह दिख सकती है -

add_index :table_name, [:column_name_a, :column_name_b, ... :column_name_n], unique: true, name: 'my_custom_index_name'

अधिक जानकारी - http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index


1
add_index :table_name, :column_name, unique: true

कई कॉलमों को एक साथ अनुक्रमित करने के लिए, आप एकल कॉलम नाम के बजाय कॉलम नामों की एक सरणी पास करते हैं।


0

यदि आप DB कॉलम में अद्वितीय जोड़ने से चूक गए हैं, तो यह जाँचने के लिए कि क्या क्षेत्र अद्वितीय है, मॉडल में यह मान्यता जोड़ें:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name
end

यहाँ देखें ऊपर केवल परीक्षण के उद्देश्य से है, कृपया @Nate द्वारा सुझाए गए DB कॉलम को बदलकर सूचकांक जोड़ें

अधिक जानकारी के लिए कृपया इसे इंडेक्स के साथ देखें


2
मैं केवल अनुक्रमणिका के बिना सत्यापन जोड़ने की सिफारिश नहीं करूंगा। बेहतर विकल्प यह है कि किसी भी मौजूदा डुप्लिकेट को साफ किया जाए और फिर इंडेक्स को जोड़ा जाए। अन्यथा आप मौजूदा डेटा को अमान्य करने का जोखिम उठाते हैं (जो उन पंक्तियों को विफल करने के लिए किसी भी अद्यतन का कारण होगा), और आप अभी भी डुप्लिकेट के साथ समाप्त हो सकते हैं यदि आपके पास कोई कोड है जो सत्यापन को रोक देता है। (उदाहरण के लिए, जब एक update_all, या प्रत्यक्ष SQL आवेषण चल रहा है)
Nate
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.