Solved

Optional Foreign Keys in MySQL?

Posted on 2014-04-03
4
433 Views
Last Modified: 2014-04-03
In the table below, I need to be able to create an opportunity with just opportuntys_name at first because we may not yet know how we are quoting it to or even what they want. We  just know they want something.


CREATE TABLE IF NOT EXISTS `mcdb2`.`opportunitys` (
  `opportunitys_id` INT NOT NULL AUTO_INCREMENT,
  `opportunitys_ts_created` INT NULL,
  `opportunitys_name` VARCHAR(45) NULL,
  `opportunitys_amount` DOUBLE NULL,
  `opportunitys_quoted_by` INT(11) NOT NULL,
  `opportunitys_quoted_by_company` INT(11) NOT NULL,
  `opportunitys_ts_received` INT NULL,
  `opportunitys_ts_due_by` INT NULL,
  `opportunitys_ts_next_followup` INT NULL,
  `opportunitys_supplier` INT NOT NULL,
  `opportunitys_stage` INT NOT NULL,
  `opportunitys_quoted_to` INT(11) NOT NULL,
  `opportunitys_quoted_to_company` INT(11) NOT NULL,
  `opportunitys_company` INT(11) NOT NULL,
  PRIMARY KEY (`opportunitys_id`, `opportunitys_quoted_by`, `opportunitys_quoted_by_company`, `opportunitys_supplier`, `opportunitys_stage`, `opportunitys_quoted_to`, `opportunitys_quoted_to_company`, `opportunitys_company`),
  INDEX `fk_opportunitys_contacts1_idx` (`opportunitys_quoted_by` ASC, `opportunitys_quoted_by_company` ASC),
  INDEX `fk_opportunitys_suppliers1_idx` (`opportunitys_supplier` ASC),
  INDEX `fk_opportunitys_stages1_idx` (`opportunitys_stage` ASC),
  INDEX `fk_opportunitys_contacts2_idx` (`opportunitys_quoted_to` ASC, `opportunitys_quoted_to_company` ASC),
  INDEX `fk_opportunitys_companys1_idx` (`opportunitys_company` ASC),
  CONSTRAINT `fk_opportunitys_contacts1`
    FOREIGN KEY (`opportunitys_quoted_by` , `opportunitys_quoted_by_company`)
    REFERENCES `mcdb2`.`contacts` (`contacts_id` , `contacts_company`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_opportunitys_suppliers1`
    FOREIGN KEY (`opportunitys_supplier`)
    REFERENCES `mcdb2`.`suppliers` (`suppliers_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_opportunitys_stages1`
    FOREIGN KEY (`opportunitys_stage`)
    REFERENCES `mcdb2`.`stages` (`stages_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_opportunitys_contacts2`
    FOREIGN KEY (`opportunitys_quoted_to` , `opportunitys_quoted_to_company`)
    REFERENCES `mcdb2`.`contacts` (`contacts_id` , `contacts_company`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_opportunitys_companys1`
    FOREIGN KEY (`opportunitys_company`)
    REFERENCES `mcdb2`.`companys` (`companys_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

Open in new window


Right now, when I try to create the record, I am getting this error:
This opportunity could not be created. You have a database error: (1452) Cannot add or update a child row: a foreign key constraint fails (`mcdb2`.`opportunitys`, CONSTRAINT `fk_opportunitys_contacts1` FOREIGN KEY (`opportunitys_quoted_by`, `opportunitys_quoted_by_company`) REFERENCES `contacts` (`contacts_id`, `contacts_company`)

Open in new window


How do I re-arrange this table definition so that I still keep the foreign key reference, but it doesn't reject an insertion when those references are blank (to be entered at a later time)?
0
Comment
Question by:DrDamnit
  • 2
  • 2
4 Comments
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 39974604
you could create a "dummy" record in the referenced tables, which could be used for all of these "prospect" records.
I usually use the PK value of 0, for example, for such a dummy record, and use a default value of 0 in the FK fields.
0
 
LVL 32

Accepted Solution

by:
DrDamnit earned 0 total points
ID: 39974615
I think I figured it out, is the correct answer:

"For columns that reference foreign keys, use a non-idenitifying relationship, and then allow that column to be null with ON DELETE CASCADE"

The ON DELETE CASCADE is optional, but would maintain data integrity.

Is this right? It appears to be working...
0
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 39974630
yes, that also works. but there are quite some people that have some arguments about avoiding the "NULL" value, especially as the indexing impacts on using NULL values (and later searching for those NULL values) is normally not optimal.
0
 
LVL 32

Author Closing Comment

by:DrDamnit
ID: 39974639
This actually works out better. The dummy company and the dummy contact are ID: 1, which is actually better to test for when looking to see what's been done with the record.
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of articles have been written on splitting mysqldump and grabbing the required tables. A long while back, when Shlomi (http://code.openark.org/blog/mysql/on-restoring-a-single-table-from-mysqldump) had suggested a “sed” way, I actually shell …
Load balancing is the method of dividing the total amount of work performed by one computer between two or more computers. Its aim is to get more work done in the same amount of time, ensuring that all the users get served faster.
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question