Define a unique primary key based on 2 columns

后端 未结 7 584
长情又很酷
长情又很酷 2021-01-31 02:52

I would like to define a unique key for records based on 2 columns : \'id\' and \'language\'

to let the user submits the following strings : id=1 language=en value=bl

相关标签:
7条回答
  • 2021-01-31 03:15

    In Rails 5 you can do the following:

    create_table :words, primary_key: %i[id language_id] do |t|
      t.integer :id
      t.integer :language_id
      t.string :value
      t.timestamps
    end
    

    It is also NOT necessary to set the primary_key attribute on the Word model.

    0 讨论(0)
  • 2021-01-31 03:18

    add_index :words, ["id", "language_id"], :unique => true

    It should work. Maybe you have already some non-unique data in your db and index can't be created? But (as @Doon noticed it will be redundant since id is always unique). So you need create primary key on two columns.

    To define 2 column primary key in rails use:

    create_table :words, {:id => false} do |t|
      t.integer :id
      t.integer :language_id
      t.string :value
      t.timestamps
    end
    execute "ALTER TABLE words ADD PRIMARY KEY (id,language_id);"
    

    And set primary_key in your model with this gem: http://rubygems.org/gems/composite_primary_keys:

    class Word < ActiveRecord::Base
        self.primary_keys = :id,:language_id
    end
    
    0 讨论(0)
  • 2021-01-31 03:26

    Just like @rogal111 said, but if a primary key already exists then you'll want to do this

    ALTER TABLE sections DROP PRIMARY KEY, ADD PRIMARY KEY(id, workspace_id, section_key);
    
    0 讨论(0)
  • 2021-01-31 03:30

    As I said in my comments you will be fighting rails if you try this, and it isn't really supported out of the box. you can look at http://compositekeys.rubyforge.org which offers a way to do composite primary keys in rails. I haven't used it, as I haven't had a need yet (normally when I have something that is composite key like it is just a join table with no primary key and a unique index on the joined pair (HABTM).

    0 讨论(0)
  • 2021-01-31 03:35

    I faced a similar problem when migrating a site to Rails. I had a table which stores text data for each language my site is available in so I had something like this:

    CREATE TABLE Project_Lang(
        project_id INT NOT NULL,
        language_id INT NOT NULL,
        title VARCHAR(80),
        description TEXT,
    
        PRIMARY KEY pk_Project_Lang(project_id, language_id),
    
        FOREIGN KEY fk_Project_Lang_Project(project_id)
            REFERENCES Project(project_id)
            ON DELETE RESTRICT ON UPDATE CASCADE,
    
        FOREIGN KEY fk_Project_Lang_Language(language_id)
            REFERENCES Language(language_id)
            ON DELETE RESTRICT ON UPDATE CASCADE
    )ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_spanish_ci;
    

    But since Rails doesn't handle composite primary keys out of the box I was forced to change the structure of the table so it had it's own primary key:

    CREATE TABLE Project_Lang(
        project_lang_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
        project_id INT NOT NULL,
        language_id INT NOT NULL,
        title VARCHAR(80),
        description TEXT,
    
        UNIQUE INDEX(project_id, language_id),
    
        FOREIGN KEY fk_Project_Lang_Project(project_id)
            REFERENCES Project(project_id)
            ON DELETE RESTRICT ON UPDATE CASCADE,
    
        FOREIGN KEY fk_Project_Lang_Language(language_id)
            REFERENCES Language(language_id)
            ON DELETE RESTRICT ON UPDATE CASCADE
    )ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 DEFAULT COLLATE = utf8_spanish_ci;
    

    I also created a unique index for the columns that previously made the composite primary key so that no duplicate record is inserted. Then in my Rails model I could simply:

    self.primary_key = "project_lang_id"
    

    And that did the trick. Is not what I wanted but is better than fighting the framework.

    0 讨论(0)
  • 2021-01-31 03:38

    Model

    class User < ActiveRecord::Base
      has_secure_password
      self.primary_keys = :name
    end
    

    Migration

    class CreateUsers < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.string :name, null: false
          t.string :emailid
          t.string :password_digest
          t.integer :locked, :default => 0
          t.text :secretquestion
          t.string :answer
    
          t.timestamps null: false
        end
        add_index :users, :name, :unique => true
      end
    end
    

    You will get this table

    image

    0 讨论(0)
提交回复
热议问题