열 조합에 고유 제한 조건을 추가하기위한 마이그레이션


140

필요한 것은 열 조합에 고유 제약 조건을 적용하는 마이그레이션입니다. A에 대한 즉 people테이블의 조합 first_name, last_Name그리고 Dob고유해야합니다.

답변:


244

add_index :people, [:firstname, :lastname, :dob], :unique => true


12
제약 조건이 아닌 고유 색인을 추가하고 있다고 생각합니다 . 아니면 인덱스가 제약 조건을 추가합니까?
폴 캔 트렐

17
아니, 다 괜찮아 내 잘못이야! 고유 제한 조건은 고유 색인과 함께 제공됩니다.
폴 캔 트렐

7
@ paul-cantrell에 동의합니다 : 인덱스가 아닌 제약 조건 만 추가 할 수있는 방법이 없습니다 (db 스토리지에 영향을 미침)
Augustin Riedinger

17
모델 수준 유효성 검사의 문제는 크기가 조정되지 않는다는 것입니다. 두 대의 서버가 동시에 동일한 데이터를 실행할 수 있습니다 (예 : api heavy 앱을 두 번 탭하는 것). 현재 DB에 두 개의 동일한 레코드가 있고 모델의 유효성이 검사되었습니다.
baash05

6
나는 모두가 좋아 .. 그냥 확인합니다
baash05

25

howmanyofme.com에 따르면 미국에만 "John Smith라는 46,427 명의 사람들이있다"고합니다. 약 127 년입니다. 이것은 인간의 평균 수명보다 훨씬 길기 때문에 이것은 DOB 충돌이 수학적으로 확실하다는 것을 의미합니다.

내가 말하고 싶은 것은 고유 필드의 특정 조합이 미래에 극단적 인 사용자 / 고객 불만을 야기 할 수 있다는 것입니다.

적절한 경우 국가 식별 번호와 같이 실제로 고유 한 것을 고려하십시오.

(나는이 파티에 매우 늦었다는 것을 알고 있지만 앞으로 독자에게 도움이 될 수 있습니다.)


3
흠 ... 당신은 확실히 맞습니다. 그러나 아마도 이것은 이안이 질문을 명확하게하기 위해하고 싶었던 일의 예일뿐입니다.
eritiro

1
아마도. 대답은 이안을위한 것이 아닙니다. 또는 실제로 랑갈로.
페이더 어둡게

Ian이나 rangalo뿐만 아니라 모든 foo-s를위한 것입니다.
ARK

21

인덱스없이 제약 조건을 추가 할 수 있습니다. 사용중인 데이터베이스에 따라 다릅니다. 다음은 Postgres의 샘플 마이그레이션 코드입니다. (tracking_number, carrier)제약 조건에 사용하려는 열 목록입니다.

class AddUniqeConstraintToShipments < ActiveRecord::Migration
  def up
    execute <<-SQL
      alter table shipments
        add constraint shipment_tracking_number unique (tracking_number, carrier);
    SQL
  end

  def down
    execute <<-SQL
      alter table shipments
        drop constraint if exists shipment_tracking_number;
    SQL
  end
end

추가 할 수있는 다른 구속 조건이 있습니다. 문서를 읽으십시오


12
PostgreSQL 9.4 용 문서 : 고유 제약 조건을 추가하면 제약 조건에 사용 된 열 또는 열 그룹에 고유 한 btree 인덱스가 자동으로 생성됩니다. 부분 인덱스를 작성하여 일부 행에 대한 고유성 제한 조건을 적용 할 수 있습니다. 따라서 IMHO는 결과가 기본적으로 add_index메소드 를 사용하는 것과 동일 할 때 원시 SQL로 드롭 할 필요가 없습니다 . ;)
Rafał Cieślak

8
실제로 한 가지 이유가 있습니다. 구현 세부 사항이며 docs에 의해 권장되지 않습니다 . 또한 제한 조건이 pg_constraint테이블에 추가되지 않으므로 이름으로 제한 조건을 참조 할 수 없습니다 .
kaikuchn

8

안녕 당신은 예를 들어 열에 마이그레이션에서 고유 색인을 추가 할 수 있습니다

add_index(:accounts, [:branch_id, :party_id], :unique => true)

또는 각 열마다 별도의 고유 색인


죄송합니다. 먼저 편집하고 기존 마이그레이션이 작동하지 않는 것을 시도한 다음 새 마이그레이션을 추가하여 작동했습니다. 감사합니다.
rangalo

4

사용자와 게시물 간 조인 테이블의 일반적인 예에서 :

create_table :users
create_table :posts

create_table :ownerships do |t|
  t.belongs_to :user, foreign_key: true, null: false
  t.belongs_to :post, foreign_key: true, null: false
end

add_index :ownerships, [:user_id, :post_id], unique: true

두 개의 유사한 레코드를 만들려고하면 데이터베이스 오류가 발생합니다 (필자의 경우 Postgres).

ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_ownerships_on_user_id_and_post_id"
DETAIL:  Key (user_id, post_id)=(1, 1) already exists.
: INSERT INTO "ownerships" ("user_id", "post_id") VALUES ($1, $2) RETURNING "id"

예를 들면 :

Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)

완전히 실행 가능한 예 : https://gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced

db/schema.rb생성 : https://gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a


4

완전성을 위해 혼동을 피하기 위해 여기에 동일한 작업을 수행하는 3 가지 방법
이 있습니다. Rails 5.2+의 열 조합에 명명 된 고유 제한 조건 추가

광고주에 속하는 Locations 테이블이 있고 reference_code 열이 있고 광고 주당 하나의 참조 코드 만 원한다고 가정 해 봅시다. 따라서 열 조합에 고유 제한 조건을 추가하고 이름을 지정하려고합니다.

하다:

rails g migration AddUniquenessConstraintToLocations

그리고 마이그레이션을 다음과 같은 라이너로 만드십시오.

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
  def change
    add_index :locations, [:reference_code, :advertiser_id], unique: true, name: 'uniq_reference_code_per_advertiser'
  end
end

또는이 블록 버전.

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
  def change
    change_table :locations do |t|
     t.index ['reference_code', 'advertiser_id'], name: 'uniq_reference_code_per_advertiser', unique: true
    end
  end
end

또는이 원시 SQL 버전

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
  def change
      execute <<-SQL
          ALTER TABLE locations
            ADD CONSTRAINT uniq_reference_code_per_advertiser UNIQUE (reference_code, advertiser_id);
        SQL
  end
end

이 중 하나라도 같은 결과를 낼 것입니다. schema.rb

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.