Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>No, it's not OK. Circular references between tables are messy. See this (decade old) article: <a href="http://www.sqlmag.com/article/quering/sql-by-design-the-circular-reference" rel="noreferrer">SQL By Design: The Circular Reference</a></p> <p>Some DBMS can handle these, and with special care, but MySQL will have issues. </p> <hr> <p>The first choice is, as your design, to make one of the two FKs nullable. This allows you to solve the chicken-and-egg problem (which table should I first Insert into?).</p> <p>There is a problem though with your code. It will allow a product to have a default picture where that picture will be referencing another product!</p> <p>To disallow such an error, your FK constraint should be:</p> <pre><code>CONSTRAINT FK_products_1 FOREIGN KEY (id, default_picture_id) REFERENCES products_pictures (product_id, id) ON DELETE RESTRICT --- the SET NULL options would ON UPDATE RESTRICT --- lead to other issues </code></pre> <p>This will require a <code>UNIQUE</code> constraint/index in table <code>products_pictures</code> on <code>(product_id, id)</code> for the above FK to be defined and work properly.</p> <hr> <p>Another approach is to remove the <code>Default_Picture_ID</code> column form the <code>product</code> table and add an <code>IsDefault BIT</code> column in the <code>picture</code> table. The problem with this solution is how to allow only one picture per product to have that bit on and all others to have it off. In SQL-Server (and I think in Postgres) this can be done with a partial index:</p> <pre><code>CREATE UNIQUE INDEX is_DefaultPicture ON products_pictures (Product_ID) WHERE IsDefault = 1 ; </code></pre> <p>But MySQL has no such feature.</p> <hr> <p>A third approach, which allows you to even have both FK columns defined as <code>NOT NULL</code> is to use deferrable constraints. This works in PostgreSQL and I think in Oracle. Check this question and the answer by @Erwin: <a href="https://stackoverflow.com/questions/8394177/complex-foreign-key-constraint-in-sqlalchemy/8395021#8395021">Complex foreign key constraint in SQLAlchemy</a> (the <strong>All key columns NOT NULL</strong> Part).</p> <p>Constraints in MySQL cannot be deferrable.</p> <hr> <p>A fourth approach (which I find cleanest) is to remove the <code>Default_Picture_ID</code> column and add another table. No circular path in the FK constraints and all FK columns will be <code>NOT NULL</code> with this solution:</p> <pre><code>product_default_picture ---------------------- product_id NOT NULL default_picture_id NOT NULL PRIMARY KEY (product_id) FOREIGN KEY (product_id, default_picture_id) REFERENCES products_pictures (product_id, id) </code></pre> <p>This will also require a <code>UNIQUE</code> constraint/index in table <code>products_pictures</code> on <code>(product_id, id)</code> as in solution 1.</p> <hr> <p>To summarize, with MySQL you have two options: </p> <ul> <li><p>option 1 (a nullable FK column) with the correction above to enforce integrity correctly</p></li> <li><p>option 4 (no nullable FK columns)</p></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload