Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>... Part II</strong></p> <h2>V1.3 and Response</h2> <p>Holy Toledo ! You are cooking with gas, young fella. All the issues are either minor, or relate to the new step you are learning.</p> <p><strong>Identifiers vs Id columns</strong></p> <p>I am not going to give you a full rundown here, as I have posted at least 20 times about how <code>Id</code> columns cripple a database an d rob it of Relational Power. I will deal with the issue in the context of this question only.</p> <ul> <li><p>Here is <a href="https://stackoverflow.com/q/4334173/484814"><strong>▶an example◀</strong></a>, check the question in detail <em>first</em>. Note that Mark is quite capable, but completely stuck. <em>Then</em> read my answer, <em>then</em> look at the Data Model. (Please do that now, it provides context)</p></li> <li><p>The idea is <em>either</em> model the data, as data, which we are doing, and you will end up with a database, <em>xor</em> stick <code>Id</code> columns on everything that moves, which obstructs the modelling exercise and Normalisation, and you will end up with a bunch of spreadsheets "linked" to each other with massive duplication and no performance.</p></li> <li><p>Therefore, remove all columns of the form <code>[Table]Id</code> from all tables (leave the Migrated Keys alone, they are correct), <em>except</em> the Following tables (these are the <strong>major</strong> Identifiers, reflected throughout the database. Note how ERwin will correct all child, grandchild, etc. tables:<br> <code>Party</code><br> <code>Address</code><br> <code>Item</code> </p></li> </ul> <p><strong>Relational/IDEF1X Identifiers</strong></p> <p>You are learning about Identifiers. These are the Natural Keys. Either Keys that the user uses, or Keys that have been Migrated from a parent to a child as Foreign Keys. These are therefore not only identifying the Relation but also <strong>Identifying</strong> the child. Your last name tells me not just about you, but also about your father, and also that you are your father's son. Want to make that unique ? No problem, just add a first name.</p> <p>You have been reading my answers, looking at my Data Models, and then <strong>adding</strong> Identifiers to your model. It is **much* easier than that. ERwin (since it implements IDEF1X) does that for you.</p> <ul> <li><p>Take Party, Band and Person. The Identifier for Party is <code>PartyId</code><br> <em>(ok, that is a Surrogate Key, not a Natural key; but the Natural Key <code>Lastname, FirstName,BirthDate</code>, etc. is very long, if we use that as the Primary Key, it would be Migrated to the children, grandchildren, great-grandchildren, which is not desirable, so we <strong>add</strong> a short Surrogate Key, and make that the Primary Key)</em></p></li> <li><p>When you create the subtypes in ERwin, and indicate the Relation, it will automatically place <code>PartyId</code> in Band and Person, as the PK; it will mark it as "(FK)". (Note: I use bold font to denote (FK) in my models.)</p></li> <li><p>That's it, you are done. Party::Band is 1:0-1, Band Primary Key is <code>PartyId</code>. Because it is a Subtype, ERwin will ensure the Relation is <strong>Identifying</strong>, and therefore the parent PK ends up in the child PK, and the Dependent child has round corners.</p> <ul> <li>If subtypes were <em>not</em> involved, it would be the same, except the Relation may not be 1::0-1, it may be 1::1-n. In which case, you need to add another element to make it unique, such as f<code>FirstName</code>, or <code>SequenceNo</code> </li> <li>And you have to indicate to ERwin that you want an <strong>Identifying</strong> Relation. (If you don't then it is a plain FK, and the columns will be below the line; the table will be Independent,; the corners square).</li> <li>And if at some point you decide to use those FK columns to form the PK, you simply click on the <strong>Relation</strong> and change it from Non-identifying to Identifying; the columns will be moved above the line; the corners will be round. </li> </ul></li> </ul> <p><strong>Role</strong></p> <ul> <li><p>Now for the next step. We know that Band::Party is 1::1; that Band is a child of Party; that <code>Band.PartyId</code> is the perfect PK (no <code>Id</code> column is required). Same for Person. But they are silly names, or put another way, Band is actually a different Role to Person, and they are both a Party. So we want to identify the Role clearly.</p> <ul> <li><p>In Band, we would like to call <code>PartyId</code>, <code>BandId</code>, to reflect its Role. Edit the <strong>Relation</strong>, between the subtype symbol and the child, not the table. In the dialogue, fill in the RoleName as <code>BandId</code>. That's it. You are done. </p></li> <li><p>Thus the following change from ... to:<code><pre> FloorItem.ItemId FloorItemId BandItem.ItemId BandItemId</code></pre> Consequently ... <code><pre> Other.BandItemId OtherId Album.BandItemId AlbumId Song.BandItemId SongId Performance.BandItemId PerformanceId</code></pre></p></li> </ul></li> <li><p>Removing all the <code>[Table]Id</code> columns will leave the following tables without a PK. For now, add a <code>Name</code> column as the PK. You can tell me later what the user would like for a natural key, an Identifier for these tables: Event<br> Genre </p></li> <li><p>PartyAddress is an example (ie. modelled correctly) of what all I have discussed above. It had no <code>PartyAddressId</code>. <code>PartyId</code> and <code>AddressId</code> together form the PK. Both Relations are Identifying.</p></li> </ul> <p><strong>Identifying vs Non-identifying Relations</strong></p> <p><em>In reading a lot on the subject there seems to be a lot of disagreement and indecisiveness on the subject</em></p> <ul> <li><p>Yes. Unfortunately, anyone with a keyboard and a modem can "publish" these days. People post opinions as facts; they post nonsense about subjects they are clueless about. This confuses people who are trying to learn.</p></li> <li><p>It is science, not magic or a black art, not opinion.</p></li> <li><p>When learning, read only definitions, and listen only to people who clearly transfer the science (not to anyone who is confused or treats the science like it is an art or that it is subject to opinion). We are learning facts, laws of physics, not opinions about the laws; the laws work the same for everyone, across the planet. You can't learn from someone who thinks a fact is an opinion.</p></li> <li><p>Let's take it from the top:</p> <ol> <li><p>The Relation is the defining criteria (renders the child Independent/Dependent), not the other way round.</p></li> <li><p>A <strong>Relation</strong> is always an FK in the child, of the parent PK.</p></li> <li><p>In an <strong>Identifying</strong> Relation, that FK is the PK (or the first part of the PK, where the PK is a composite key). And the child is a <strong>Dependent</strong> table.</p></li> <li><p>In a <strong>Non-Identifying</strong> Relation that FK is a non-PK column, and the child is <strong>Independent</strong> (it may be forced into Dependence by some other Relation).</p></li> <li><p>All Subtypes have Identifying Relations from the Supertype. Otherwise they would not be Subtypes, they would be Independent of the Supertype.</p></li> <li><p>All 1:0-1 Relations are Identifying.</p></li> </ol></li> </ul> <p><em>so I did what I thought represented the right things in my model.</em></p> <ul> <li>Which may be why you ended up adding <code>[Table]Id</code> keys.</li> </ul> <p><em>When to force (identifying) and when to be free (non-identifying)?</em></p> <ul> <li><p>Never force anything re modelling (Database and Function), especially re data. It is the uncontrollable that we want to administer, manage, mould, control, etc. But to do that effectively, we have to understand it first. We cannot understand anything when we force it. Forcing it deprives it from exposing itself, and deprives us from noticing the subtleties and flavours (because we "know" it). Let it be free, but constrained, like a horse in a paddock, not a prisoner in a stable.</p> <p>That is why the act of sticking <code>Id</code> columns on every spreadsheet prevents understanding of the data, and therefore any modelling of it.</p></li> <li><p>As per above, it is the Relation that is Identifying or not; not whether the Entity is Independent or not, that is a consequence. </p></li> </ul> <p>Do it Relational/IDEF1X/ERwin style:</p> <ol> <li><p>You want an Entity, draw an Entity. Name it. Unless it is the first entity on the canvas, <strong>do not add keys</strong>. </p></li> <li><p>Now consider its Relations. How do the Entities you have already modelled relate to this new Entity ? Draw that Relation (Relations are drawn Parent-to-child).</p></li> <li><p>Of course, it defaults to Identifying, because most Relations in a (wait for it) <strong>Relational</strong> Database are Identifying. The parent PK is placed in the child PK.</p></li> <li><p>If you think, <em>no, no, I want this to be Independent</em>, then you better have a good reason. The key question here is, does this entity exist completely on its own, does it exist outside the context of other Independent entities ? AFAIC, there are five in your model:<br> Address<br> Party<br> Item<br> Event<br> Genre </p> <p>Every other entity exists only within the context of one of these Independent Entities. Thus you drew Identifying Relations, and thus they are all Dependent.</p> <ul> <li><p>Recall, we had Item as Independent earlier; then we had a new form of Item; which made the old Item, BandItem; which made BandItem Dependent on the new Item.</p></li> <li><p>We had a great Identifier in <code>ItemId</code>, which was carried not only in the (then) Item cluster but throughout, in OrderItem, Review, etc.</p></li> <li><p>We changed the context of Item (created a higher order Item), and due to the Identifying Relations, <em>that</em> was then Migrated throughout, and the new BandItem was Migrated in its context.</p></li> <li><p>The new <code>ItemId</code> continues to be a great Identifier. <code>BandItemId</code> is exactly <code>ItemId</code>, but plays a particular Role, it is a subset/subtype of <code>ItemId</code>. </p></li> </ul></li> <li><p>So if it is a true Independent entity, go ahead and give it a new PK. </p> <ul> <li><p>But at this stage, not an <code>Id</code> column, something meaningful that identifies the entity. <code>Event.Name</code>, <code>Customer.Code</code>. No human being identifies a Customer as number 123456, no, they think of "IBM", "3M", etc. Later on, as the model progresses, we will make sure we have really good Keys; right now with the new Entity, we care that it has an Identifier. </p></li> <li><p>Exception. For Address, Party, Item, you knew at V1.0 you were going to have millions, thousands, thousands of them; that these were major Identifiers that would be MIgrated throughout the database; that the true PK was very long; and that you needed a short Surrogate Key as the PK; so you set that up from the outset, and you got no argument from me. </p> <ul> <li><p>If you are ready for Domains, then INT, INTor SMALLINT, SMALLINT.</p></li> <li><p>Otherwise <code>Name</code>, CHAR(30). </p></li> </ul></li> </ul></li> <li><p>The next step is to finish the PK on the new entity. If the cardinality from the parent is 1::n, it already has the PK of the Parent, just add an element to make the PK unique. Let's look at Order. It already has <code>PartId</code>, so <code>OrderNo</code> can be within <code>PartyId</code>. Just change the order of the PK columns to <code>(1) PartyId, (2) OrderNo</code>.</p></li> <li><p>The only time we do a little bit of forcing, is when the number of columns forming the PK becomes too many, or the total width of the PK becomes too wide, to Migrate as an FK into the children. Then, and only then, we create an additional Surrogate Key of the form <code>[Table]Id</code> (they are <strong>always</strong> additional, we can't lose the real PK or the uniqueness, because it supports other requirements).</p> <ul> <li><p>AFAIC, that magic number is seven (magic no for a many things, actually; even this item appears as number seven), and that maximum width is 30 bytes. That was done from the outset with Address (already highly optimised), Party (otherwise 64 bytes), Item (over 30 bytes).</p></li> <li><p>If we are going to break the intrinsic Relational power, we need the pain of carrying that Relational power itself to be really bad, and for no other reason. Not even approaching that in your model.</p></li> </ul></li> </ol> <p><strong>Review Cluster</strong></p> <p>You've done a very good job, so consider this as the next progression. Basically you have two options, and of course we are comparing/relating this to the Item cluster.</p> <ol> <li><p>Going with the Review cluster as is. We need a SongReview and an AlbumReview. And get rid of ItemReview (that encapsulates all Items, which means we are doubling up). I thought we were excluding Reviews for non-Band Items.</p></li> <li><p>Allow the non-BandReview to be about any BandItem, eg. change the ItemReview FK from Item to BandItem. That encapsulates all BandItems in ItemReview. Get rid of PerformanceReview.</p> <ul> <li>Sure, you may not want BandItem.Other to be reviewed; that can be constrained by other means. But if you want to be strict, then you need (1).</li> </ul></li> </ol> <p><strong>Colour</strong></p> <p>It is great that you have adopted my colour scheme. </p> <ul> <li><p>The meaning, the visual relevance, does not show up in a tiny model (most of my models on SO); it only shows up on larger models such as yours.</p></li> <li><p>Because you have done such a great job with V1.3, the teacher has an <a href="http://www.softwaregems.com.au/Documents/Student%20Resolutions/swisscheese%20Band%20ERD%20V1_3.pdf" rel="nofollow noreferrer"><strong>▶apple for you◀</strong></a>. Actually, the <a href="http://www.softwaregems.com.au/Documents/Documentary%20Examples/IDEF1X%20Notation.pdf" rel="nofollow noreferrer"><strong>▶IDEF1X Notation◀</strong></a> document is worth reading again, it is very condensed, and I am told that people get more value out of it when they read it <em>after</em> modelling something. What I need to know is, whether the Natural Hierarchy and the Colour do anything for you. </p></li> <li><p>That's just finishing off the Entity level Logical.</p></li> </ul> <p>You can continue with the Logical, Key level (the only Attributes are FKs, and we know what they are). But feel free to start identifying Attributes (in which case, show the Attribute Level).</p> <p><strong>Optional Column</strong></p> <p>U.1) An Optional Parent has crept back into the model. <code>PartyAddress is shipped for Order</code> is not Nullable. </p> <ul> <li><p>If you intended to model that the shipping address is optional, then you need an OrderShipAddress Entity, which is a child of Order, and the cardinality is 1::0-1. </p> <ul> <li>Nulls (optional columns) are like a cancer collecting all over the body, Nullable FKs (optional parent) are cancer of the throat in an orphan before the age of five.<br> . </li> </ul></li> <li>That's the basic method to handle any optional column, not limited to one that is an FK (optional parent) such as here.</li> </ul> <p><strong>Minor</strong></p> <p>M.11) These were correct in V1.2<br> Review::Comment is 1::0-1<br> BandMember:: Comment is 1:0-n </p> <p>M.12) Event::Person is n::n (and the columns will not show at the logical level)</p> <h2>V1.4 and Response</h2> <p>Very good progress. Are you happy with the Identifiers, the Keys ?</p> <p>U.8) (If you do this first, the remainder will follow easily.) ERwin Limitation. Congratulations, you have produced a model that has reached the limitations of ERwin's capability in Logical modelling. To be clear, this is not really a limit, in that it gets resolved in the Physical Model, and of course it is not a limitation in IDEF1X or Relational Databases. But right now, at the Logical, it interferes with your learning and progress.</p> <ul> <li><p>In BandItem we want the PK to be (BandItemId, BandId). But ERwin won't allow it because it says <em>a Subtype PK must be the Supertype PK and nothing but</em>. Actually, as long as the Supertype PK is the leading Identifier, another Identifying Relation is acceptable. To work around this: </p> <ul> <li>drop the subtype symbol </li> <li>create two Identifying Relations Item::FloorItem and Item::BandItem </li> </ul></li> <li><p>The Relations that we had to make Non-identifying can now be Identifying.</p></li> <li><p>ERwin will now resolve the Migrated PKs as FKs, without duplication. </p></li> <li><p>Yes, chuck the Roles back in.</p></li> </ul> <p>U.9) Now I understand what you are trying to do with the Review cluster, so first, let me say that you have modelled it correctly, all the way down to Rating. </p> <ul> <li>But there is a basic problem at Review itself. With a PK of ReviewerId, one Reviewer will only be allowed one review. Of course, you want one Review per Reviewer per Band/BandItem, but that is hidden further down in the subtype. Basically the use of Supertype-Subtype here is too restrictive. Good to understand, in that early stage, but now we need to move beyond it. <ul> <li>Instead of the Review cluster, create two Review tables, a BandReview and ItemReview. </li> <li>The Relations will be Person::BandReview and Band::BandReview, and Person::ItemReview and BandItem::ItemReview </li> <li>Then each of them will have children %Rating, %Comment, %CommentRating. </li> </ul></li> </ul> <p>M.13) Order::OrderShipAddress is 1::0-1, correct. PartyAddress::Order is 1::0-n, correct Therefore the Shipping Address should be PartyAddress::OrderShipAddress 1::0-n</p> <p>M.14) Payment currently allows only one payment per Order, which may be what you require, but the relation is 1::1-n. If you need more, then add a SequenceNo to the PK.</p> <p>M.15) Genre is fine. But SubGenre needs something in the PK to allow more than one Genre. I would now change Genre.Name to Genre.Genre, and add SubGenre to the SubGenre PK. - that will fix Event.GenreId as well.</p> <p>M.16) Venue needs a Name for a PK for now. If you are ready for better keys, then ShortName, and Name moves down as an attribute.</p> <p>Q.4) Confirming. Since we have an Identifying Relation in Order, and the PK (PartyId, OrderNo) therefore OrderNo is a sequential number within PartyId, correct ?</p> <p><strong><em>Go for V1.5</em></strong>. Include some Attributes. The best way to identify them is to either start a Function Model (and now work the Data Model side-by-side with it) or at least work through all the functions for all the screens.</p> <p>Cheers</p>
    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. This table or related slice is empty.
    1. 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