Let's say I have a two tables - book and author. A book can have many authors and an author can have many books, which means they are in a many to many relationship and I'll need a third table to implement that.
I really want to avoid this, as I am a beginner and this makes the queries more complicated for me.
So my question is : what would be the best way to implement this type of relationship excluding many-to-many?
I was thinking just to put a foreign key in each table so I have an authoridFK in my books table and bookIdFK in my authors table. But I am not sure what will type of a relationship would that be, will it me correct and how it will look on an ERD?
Can someone clarify these to me?
The 'best', and most standard way is to use a third table to maintain the relationship.
As for query complexity, you can either look into using JOIN in your queries or getting an ORM which handles these type of relationships for you.
An example join query for the given context which will return a list of all authors and all books they have contributed to would look like this:
select a.AuthorName, b.BookName
from author a
join AuthorBookMapping m on m.AuthorID = a.AuthorID
join Book b on m.BookID = b.BookID
The intermediate table is the only correct way to build your relation.
This logic does not complicate the structure, but on the opposite, it allows to comply with good practices:
each data item must be located in a unique place in the database
each record (object) must have a unique primary key.
This way you can both link authors to their books, possibly assign several authors to the same book, and of course several books to the same author.
Advanced CRUD systems also allow you to display the author(s) in the book list and edit these relationships.
Here's a tutorial about relationships in a MySQL database
It explains the main things about direct / indirect relationships, and identifying / non-identifying relationships
I have more experience with SQL databases than I do with Symfony and am hoping someone can clarify the association mappings on how Doctrine connects the database to Symfony.
Taking a one-to-many mapping between Category and Product as an example:
I have very little need to record productIDs as a long string in each category record and I assume that having it is an unnecessary overhead. If I really needed to get a list of all products in a category record in the future though then I assume I could just manually query it still?
By extension, to get the above, I would need a unidirectional many-to-one association. If this is the case though, then would I still (and how would I?) be able to control such things as on delete cascade if required?
I think you are not totally understanding how this works in Doctrine. I hope this helps:
If you do a one-to-many between your Category and Product (one category has many products) with doctrine then it means that all you need is a category_id column in your product table (product is in this case the owning side of the relationship). You can make the relationship bi-directional without any consequences for the category table. Doctrine will allow you to get the products for a category easily by doing:
$category->getProducts();
In the background a query will be performed where all products with matching category_id column are resolved from your database and added to the products collection in the Category entity.
Check the example in the docs. It is exactly like yours, but then a one-to-many between product and features.
To prevent all products from loading when querying your category you can mark the inverse side as fetch="EXTRA_LAZY".
If you still have questions after this, just leave a comment.
Update:
So to make it very clear: doctrine does not add a column inside the category table. In your case the products property only exist in the object model not in the database model.
I need some advice on modeling an ecommerce domain.
The client sells two products:
Custom art work, the design specified by the customer.
Prints of art with a message on the back specified by the customer.
Here is my cut down database model so far.
Products:
Id
Description
Price
Orderlines:
Id
OrderId
ProductId
Attributes:
Id
Name
OrderAttributes:
AttributeId
OrderlineId
Value
The products table will have the 2 products from above.
The order line links the selected product to an order.
The attributes holds the custom field names for each product.
For example the custom artwork product would have the attribute design.
The order attributes links the ordered product to it's customs attributes and has the value.
For example custom artwork product, with an attribute of design, with a value of paint a house.
I would also like to map this database model to code as well using nhibernate.
Is there a better way of modeling this data?
A couple of suggestions:
The Orderlines table should contain the price (and possibly the description) of the product so that item prices can change without affecting existing orders. Similarly, the Orders table (not shown) should contain customer information (e.g. shipping address) that may change. The data that makes up an order can't change and the easiest approach is to flatten and denormalize it.
The OrderAttributes structure is called an entity-attribute-value model and it has many drawbacks. In general I recommend avoiding it and adding the needed columns to the Orderlines table. If needed, your application can subclass Product and OrderLine so that a CustomArtWorkProduct creates a CustomArtWorkOrderLine when it's added to an order.
In an object-oriented program relations are expressed as associations.
That is:
If Product has Orders then Product must have a collection of Orders.
If an Order is for a Product, the Order must have a property Product.
and so on.
In object-oriented programming you don't associate by an identifier: you don't need this because this is a different world ruled by hierarchical data.
Honestly, if you follow what I said before, NHibernate will be a very powerful tool as it'll be able of loading objects and properties without your intervention.
Think about "getting all orders of some product": you're not going to intentionally execute an SQL Join but you're going to access to the Orders property of Product and NHibernate will translate this access to the database world.
This is the point of using an OR/M. It's not just "I map tables as is". It's about joining two very different worlds: the object-oriented hierarchical world with relational data with no pain.
Check this very old (2004!) CodeProject article and how it creates the Northwind SQL Server database-based model:
http://www.codeproject.com/Articles/8773/NHibernate-in-real-world-applications
Don't pay attention to how maps the model to the database but to the model design.
Check this article, it's more modern than the other one:
http://litemedia.info/introduction-to-nhibernate
I am learning about databases and SQL for the first time. In the text I'm reading (Oracle 11g: SQL by Joan Casteel), it says that "many-to-many relationships can't exist in a relational database." I understand that we are to avoid them, and I understand how to create a bridging entity to eliminate them, but I am trying to fully understand the statement "can't exist."
Is it actually physically impossible to have a many-to-many relationship represented?
Or is it just very inefficient since it leads to a lot of data duplication?
It seems to me to be the latter case, and the bridging entity minimizes the duplicated data. But maybe I'm missing something? I haven't found a concrete reason (or better yet an example) that explains why to avoid the many-to-many relationship, either in the text or anywhere else I've searched. I've been searching all day and only finding the same information repeated: "don't do it, and use a bridging entity instead." But I like to ask why. :-)
Thanks!
Think about a simple relationship like the one between Authors and Books. An author can write many books. A book could have many authors. Now, without a bridge table to resolve the many-to-many relationship, what would the alternative be? You'd have to add multiple Author_ID columns to the Books table, one for each author. But how many do you add? 2? 3? 10? However many you choose, you'll probably end up with a lot of sparse rows where many of the Author_ID values are NULL and there's a good chance that you'll run across a case where you need "just one more." So then you're either constantly modifying the schema to try to accommodate or you're imposing some artificial restriction ("no book can have more than 3 authors") to force things to fit.
A true many-to-many relationship involving two tables is impossible to create in a relational database. I believe that is what they refer to when they say that it can't exist. In order to implement a many to many you need an intermediary table with basically 3 fields, an ID, an id attached to the first table and an id atached to the second table.
The reason for not wanting many-to-many relationships, is like you said they are incredibly inefficient and managing all the records tied to each side of the relationship can be tough, for instance if you delete a record on one side what happens to the records in the relational table and the table on the other side? Cascading deletes is a slippery slope, at least in my opinion.
Normally (pun intended) you would use a link table to establish many-to-many
Like described by Joe Stefanelli, let's say you had Authors and Books
SELECT * from Author
SELECT * from Books
you would create a JOIN table called AuthorBooks
Then,
SELECT *
FROM Author a
JOIN AuthorBooks ab
on a.AuthorId = ab.AuthorId
JOIN Books b
on ab.BookId = b.BookId
hope that helps.
it says that "many-to-many relationships can't exist in a relational database."
I suspect the author is just being controversial. Technically, in the SQL language, there is no means to explicitly declare a M-M relationship. It is an emergent result of declaring multiple 1-M relations to the table. However, it is a common approach to achieve the result of a M-M relationship and it is absolutely used frequently in databases designed on relational database management systems.
I haven't found a concrete reason (or better yet an example) that explains why to avoid the many-to-many relationship,
They should be used where they are appropriate to be used would be a more accurate way of saying this. There are times, such as the books and authors example given by Joe Stafanelli, where any other solution would be inefficient and introduce other data integrity problems. However, M-M relationships are more complicated to use. They add more work on the part of the GUI designer. Thus, they should only be used where it makes sense to use them. If you are highly confident that one entity should never be associated with more than one of some other entity, then by all means restrict it to a 1-M. For example, if you were tracking the status of a shipment, each shipment can have only a single status at any given time. It would over complicate the design and not make logical sense to allow a shipment to have multiple statuses.
Of course they can (and do) exist. That sounds to me like a soapbox statement. They are required for a great many business applications.
Done properly, they are not inefficient and do not have duplicate data either.
Take a look at FaceBook. How many many-to-many relationships exist between friends and friends of friends? That is a well-defined business need.
The statement that "many-to-many relationships can't exist in a relational database." is patently false.
Many-to-many relationships are in fact very useful, and also common. For example, consider a contact management system which allows you to put people in groups. One person can be in many groups, and each group can have many members.
Representation of these relations requires an extra table--perhaps that's what your book is really saying? In the example I just gave, you'd have a Person table (id, name, address etc) and a Group table (id, group name, etc). Neither contains information about who's in which group; to do that you have a third table (call it PersonGroup) in which each record contains a Person ID and a Group ID--that record represents the relation between the person and the group.
Need to find the members of a group? Your query might look like this (for the group with ID=1):
SELECT Person.firstName, Person.lastName
FROM Person JOIN PersonGroup JOIN Group
ON (PersonGroup.GroupID = 1 AND PersonGroup.PersonID = Person.ID);
It is correct. The Many to Many relationship is broken down into several One to Many relationships. So essentially, NO many to many relationship exists!
Well, of course M-M relationship does exist in relational databases and they also have capability of handling at some level through bridging tables, however as the degree of M-M relationship increases it also increases complexity which results in slow R-W cycles and latency.
It is recommended to avoid such complex M-M relationships in a Relational Database. Graph Databases are the best alternative and good at handling Many to Many relationship between objects and that's why social networking sites uses Graph databases for handling M-M relationship between User and Friends, Users and Events etc.
Let's invent a fictional relationship (many to many relationship) between books and sales table. Suppose you are buying books and for each book you buy needs to generate an invoice number for that book. Suppose also that the invoice number for a book can represent multiple sales to the same customer (not in reality but let's assume). We have a many to many relationship between books and sales entities.
Now if that's the case, how can we get information about only 1 book given that we have purchased 3 books since all books would in theory have the same invoice number? That introduces the main problem of using a many to many relationship I guess. Now if we add a bridging entity between Books and sales such that each book sold have only 1 invoice number, no matter how many books are purchases we can still correctly identify each books.
In a many-to-many relationship there is obvious redundancy as well as insert, update and delete anomaly which should be eliminated by converting it to 2 one-to-many relationship via a bridge table.
M:N relationships should not exist in database design. They are extremely inefficient and do not make for functional databases. Two tables (entities) with a many-to-many relationship (aircraft, airport; teacher, student) cannot both be children of each other, there would be no where to put foreign keys without an intersecting table. aircraft-> flight <- airport; teacher <- class -> student.
An intersection table provides a place for an entity that is dependent on two other tables, for example, a grade needs both a class and a student, a flight needs both an aircraft and an airport. Many-to-many relationships conceal data. Intersection tables reveal this data and create one-to-many relationships that can be more easily understood and worked with. So, the question arises, what table should the flight be in--aircraft or airport. Neither, they should be foreign keys in the intersection table, Flight.
I am creating an online blog website and for each blog post, I'd like to have the user be able to create/edit/delete their own category so that they may categorize their post.
What is generally considered a good database design for user generated categories?
This is my proposed table design. (Is there a name for this type of db?)
USER_TABLE
user_id (pk), user_name
CATEGORY_TABLE
category_id (pk), category_name
USER_CATEGORIES
user_id (fk), category_id (fk)
Thanks for helping out. I'm confident there's a post somewhere regarding this but I was unable to find it. If this is a dupe please let me know and I will remove this question.
This is a many to many relationship. This would allow each user to potentially have many different categories and each category to potentially have many different users. This seems like a useful model for what you are trying to do.
I think your schema looks good. You are keeping the category labels in one table to avoid duplication and then just assigning their IDs to the users.
If what you are trying to do is to have "private" categories for each user then this is fine.
If on the other hand categories are supposed to be public (sth like tags on stackoverflow) then you may consider another option - not storing user<->category relationship, instead add field use_counter to category table and use triggers to increment it when category is being used(blog entry is categorized) or decrement when it's "freed" (blog entry is deleted/ its category is removed). When the use_counter reaches 0 - remove the category.