Solved

Optional Foreign Keys in MySQL?

Posted on 2014-04-03
4
428 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

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Foreword This is an old article.  Instead of using the MySQL extension that was used in the original code examples, please choose one of the currently supported database extensions instead.  More information is available here: MySQLi / PDO (http://…
Does the idea of dealing with bits scare or confuse you? Does it seem like a waste of time in an age where we all have terabytes of storage? If so, you're missing out on one of the core tools in every professional programmer's toolbox. Learn how to …
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

743 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now