简体   繁体   中英

How to add two foreign keys and add values in child table with reference of parent table

I have 3 tables in my database USERS, QUESTION, and ANSWER. I want QUESTION table to interact with USERS and ANSWER table and ANSWER table to USER and QUESTION table. So far I have related QUESTION table with USERS table using foreign key and ANSWER table with QUESTION table. When I am trying to add second foreign key in ANSWER table in mysql I am getting an error a) Duplicate foreign key constraint name 'userid' Even if I am trying to add using query it still giving me an error.

Can I add values in QUESTION table in reference with USERS table with help of foreign key? for eg i have user in USERS table with userid 1 i want to add values in QUESTION table where quesid will be 1 and also userid also be 1. Till now I have tried this query

INSERT INTO users_ques 
    SELECT "What is JAVA","Please Share the details" FROM users WHERE quesid = 1;

Below are my tables and their script

USERS TABLE

CREATE TABLE `users` (
  `userid` int NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  `firstname` varchar(45) NOT NULL,
  `lastname` varchar(45) DEFAULT NULL,
  `email` varchar(45) DEFAULT NULL,
  `address` varchar(45) DEFAULT NULL,
  `phone` int DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

QUESTION TABLE

CREATE TABLE `users_ques` (
  `quesid` int NOT NULL AUTO_INCREMENT,
  `ques` varchar(50) NOT NULL,
  `ques_desc` varchar(150) NOT NULL,
  PRIMARY KEY (`quesid`),
  CONSTRAINT `userid` FOREIGN KEY (`quesid`) REFERENCES `users` (`userid`)
 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

ANSWER TABLE

CREATE TABLE `users_ans` (
  `ansid` int NOT NULL AUTO_INCREMENT,
  `ans` varchar(200) NOT NULL,
  PRIMARY KEY (`ansid`),
  CONSTRAINT `quesid` FOREIGN KEY (`ansid`) REFERENCES `users_ques` (`quesid`)
 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

Recommended structure (use as a base, adjust to real data):

CREATE TABLE user (
  user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -- unique index
  username VARCHAR(255) NOT NULL, 
  password VARBINARY(255) NOT NULL,                -- password hash, binary
  firstname VARCHAR(255) NOT NULL,
  lastname VARCHAR(255) DEFAULT NULL,
  email VARCHAR(255) DEFAULT NULL,
  address VARCHAR(255) DEFAULT NULL,
  phone BIGINT DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE question (
  question_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  -- unique index
  question_text TEXT NOT NULL,        
  user_id INT NOT NULL,                                 -- id of the user who have asked
  CONSTRAINT user_to_question FOREIGN KEY (user_id) REFERENCES user (user_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE answer (
  answer_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  -- unique index
  answer_text TEXT NOT NULL,
  question_id INT NOT NULL,                           -- what question it answers on
  user_id INT NOT NULL,                               -- id of the user who have answered
  CONSTRAINT user_to_answer FOREIGN KEY (user_id) REFERENCES user (user_id),
  CONSTRAINT question_to_answer FOREIGN KEY (question_id) REFERENCES question (question_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

In this scheme I do not show the restriction that the user cannot answer his own question. I consider such a restriction to be meaningless. But if you need in it nevertheless then you may add it by creating 2 triggers (BEFORE INSERT and BEFORE UPDATE) on answer table.

The error you are getting is exactly as it says, you are trying to add another constraint with the symbol userid but you already have one with that name on the users_ques table.

As per 13.1.20.5 FOREIGN KEY Constraints

The CONSTRAINT symbol value, if defined, must be unique in the database. A duplicate symbol results in an error similar to: ERROR 1005 (HY000): Can't create table 'test.fk1' (errno: 121).

So, you either need to assign a database unique name to your constraint or allow the server to assign one for you. If you want to explicitly name them use expressive names that are unlikely to collide. Something like FK_<table_name>_<column_name> .

Also, probably a copy and paste error, but your users_ans looks completely wrong. ansid appears to be typical surrogate key but is then used as the foreign key to users_ques . quesid in your constraint. It looks like you are missing userid and quesid . There's a similar issue with your constraint and columns on users_ques

/* Allowing the server to create the indices and auto-name the constraints */
CREATE TABLE `users_ans` (
    `ansid` int UNSIGNED NOT NULL AUTO_INCREMENT,
    `quesid` int UNSIGNED NOT NULL,
    `userid` int UNSIGNED NOT NULL,
    `ans` varchar(200) NOT NULL,

    PRIMARY KEY (`ansid`),

    FOREIGN KEY (`quesid`)
      REFERENCES `users_ques` (`quesid`),
    FOREIGN KEY (`userid`)
      REFERENCES `users` (`userid`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/* Explicitly naming indices and constraints */
CREATE TABLE `users_ans` (
    `ansid` int UNSIGNED NOT NULL AUTO_INCREMENT,
    `quesid` int UNSIGNED NOT NULL,
    `userid` int UNSIGNED NOT NULL,
    `ans` varchar(200) NOT NULL,

    PRIMARY KEY (`ansid`),
    INDEX `idx_users_ans_quesid` (quesid),
    INDEX `idx_users_ans_userid` (userid),

    CONSTRAINT `FK_users_ans_quesid`
      FOREIGN KEY `idx_users_ans_quesid` (`quesid`)
      REFERENCES `users_ques` (`quesid`),
    CONSTRAINT `FK_users_ans_userid`
      FOREIGN KEY `idx_users_ans_userid` (`userid`)
      REFERENCES `users` (`userid`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

If users can only have one answer per question then you can drop the current surrogate key in favour of the natural key on (quesid, userid) -

/* This option only applies if a user can only answer a question once */
CREATE TABLE `users_ans` (
    `quesid` int UNSIGNED NOT NULL,
    `userid` int UNSIGNED NOT NULL,
    `ans` varchar(200) NOT NULL,

    PRIMARY KEY (`quesid`, `userid`),
    INDEX `idx_inv_primary` (`userid`, `quesid`), -- probably needed for joins in both directions and will be used by `FK_users_ans_userid`

    CONSTRAINT `FK_users_ans_quesid`
      FOREIGN KEY (`quesid`)
      REFERENCES `users_ques` (`quesid`)
      ON DELETE RESTRICT
      ON UPDATE RESTRICT,
    CONSTRAINT `FK_users_ans_userid`
      FOREIGN KEY (`userid`)
      REFERENCES `users` (`userid`)
      ON DELETE RESTRICT
      ON UPDATE RESTRICT
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

As show in this last example, I prefer to include the referential actions, even when using the default, as it makes the intent clear.

Here's a little db<>fiddle

Your QUESTION table seems to be inappropriately named. As per your title above the create table statement, questions would appear to be the obvious name for the table.

I do not understand your second question, nor why you would want to add the userid to the "QUESTION TABLE". If you would like more help please add more detail to your question to clarify the issues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM