SQL for one to one between a single table - mysql

I'd like to know what the best way of reflecting relations between precisely two rows from a single (my)sql table is?
Exemplified, we have:
table Person { id, name }
If I want to reflect that persons can be married monogamously (in liberal countries at least), is it better to use foreign keys within the Person:
table Person { id, name, spouse_id(FK(Person.id)) }
and then create stored procedures to marry and divorce Persons (ensuring mutual registration of the marriage or annulment of it + triggers to handle on_delete events..
or use a mapping table:
table Marriage {
spouse_a(FK(Person.id)),
spouse_b(FK,Person.id) + constraint(NOT IN spouse_a))
}
This way divorces (delete) would simply be delete queries without triggers to cascade, and marriage wouldn't require stored procedure.
The constraint is to prevent polygamy / multi-marriage
I guess the second option is preferred? What is the best way to do this?
I need to be able to update this relation on and off, so it has to be manageable..
EDIT:
Thanks for the replies - in practice the application is physical point-to-point interfaces in networking, where it really is a 1:1 relationship (monogamous marriage), and change in government, trends etc will not change this :)
I'm going to use a separate table with A & B, having A < B checked..

To ensure monogamy, you simply want to ensure that the spouses are unique. So, this almost does what you want:
create table marriage (
spouse_a int not null unique,
spouse_b int not null unique
);
The only problem is that a given spouse can be in either table. One normally handles this with a check constraint:
check (spouse_a < spouse_b)
Voila! Uniqueness for the relationship.
Unfortunately, MySQL does not support check constraints. So you can implement this using a trigger or at the application layer.

Option #1 - Add relationships structurally
You can add one additional table for every conceivable relationship between two people. But then, when someone asks for a new ralationship you forgot to add structurally, you'll need to add a new table.
And then, there will be relationship for three people at a time. And then four. And then, variable size relationships. You name it.
Option #2 - Model relationships as tables
To make it fool proof (well... never possible) you could model the relationships into a new table. This table can have several properties such as size, and also you can model restrictions to it. For example, you can decide to have a single person be the "leader of the cult" if you wish to.
This option requires more effor to design, but will resist much more options, and ideas from your client that you never thought before.

Related

MySQL Database Layout/Modelling/Design Approach / Relationships

Scenario: Multiple Types to a single type; one to many.
So for example:
parent multiple type: students table, suppliers table, customers table, hotels table
child single type: banking details
So a student may have multiple banking details, as can a supplier, etc etc.
Layout Option 1 students table (id) + students_banking_details (student_id) table with the appropriate id relationship, repeat per parent type.
Layout Option 2 students table (+others) + banking_details table. banking_details would have a parent_id column for linking and a parent_type field for determining what the parent is (student / supplier / customers etc).
Layout Option 3 students table (+others) + banking_details table. Then I would create another association table per parent type (eg: students_banking_details) for the linking of student_id and banking_details_id.
Layout Option 4 students table (+others) + banking_details table. banking_details would have a column for each parent type, ie: student_id, supplier_id, customers_id - etc.
Other? Your input...
My thoughts on each of these:
Multiple tables of the same type of information seems wrong. If I want to change what gets stored about banking details, thats also several tables I have to change as opposed to one.
Seems like the most viable option. Apparently this doesnt maintain 'referential integrity' though. I don't know how important that is to me if I'm just going to be cleaning up children programatically when I delete the parents?
Same as (2) except with an extra table per type so my logic tells me this would be slower than (2) with more tables and with the same outcome.
Seems dirty to me with a bunch of null fields in the banking_details table.
Before going any further: if you do decide on a design for storing banking details which lacks referential integrity, please tell me who's going to be running it so I can never, ever do business with them. It's that important. Constraints in your application logic may be followed; things happen, exceptions, interruptions, inconsistencies which are later reflected in data because there aren't meaningful safeguards. Constraints in your schema design must be followed. Much safer, and banking data is something to be as safe as possible with.
You're correct in identifying #1 as suboptimal; an account is an account, no matter who owns it. #2 is out because referential integrity is non-negotiable. #3 is, strictly speaking, the most viable approach, although if you know you're never going to need to worry about expanding the number of entities who might have banking details, you could get away with #4 and a CHECK constraint to ensure that each row only has a value for one of the four foreign keys -- but you're using MySQL, which ignores CHECK constraints, so go with #3.
Index your foreign keys and performance will be fine. Views are nice to avoid boilerplate JOINs if you have a need to do that.

What is the Best Practice for Composite Key with JPA?

I am creating a DB for my project and I am facing a doubt regarding best practice.
My concrete case is:
I have a table that stores the floors of a building called "floor"
I have a second table that stores the buildings called "building"
I have a third table that stores the relationship between them, called building_x_floor
The problem is this 3rd table.
What should I do?
Have only two columns, one holding a FK to the PK of building and another holding an FK to the PK of floor;
Have the two columns above and a third column with a PK and control consistency with trigger, forbidding to insert a replicated touple of (idbuilding, idfloor)?
My first thought was to use the first option, but I googling around and talking I heard that it is not always the best option.
So I am asking for guidance.
I am Using MySQL 5.6.17
You don't need third table. Because there is one-to-many relationship between building and floor.
So one building has many floors and a floor belongs to one building. Don't get things complicated. Even though you need a table with composite keys, you should be careful. You need to override equals and hashCode methods.
I am still not confortable with that approach. I am not saying it is wrong or innapropriate, very far from that. I am trying to understand how the informations would be organized and how performatic it would be.
If I have a 1:* relationship, like a student may be attending to more than one subject along its university course within a semester I would Have the 3rd table with (semester, idstudent, iddiscipline).
If I try to get rid of the join table my relationship would be made with a FK inside student table or inside subject table. And it does not make sense to do that because student table is a table for a set of information related with registering the info of a person while the discipline table holds the data of a discipline, like content, hours...it is more a parametric table.
So I would need a table for the join.

How can I implement a dual relationship (Null, Not Null) in MySQL without creating two classes?

If I have a TABLE that consists of a LIST of attributes of one TYPE and another TABLE that is also composed by the same TYPE of LIST, so how can I implements them into MySQL without having to create two TABLES of the same TYPE?
For example:
Like the EMPLOYEE table, the COMPANY table has a list of ADDRESSES.
And I want to implement without having to make one table ADDRESS for COMPANY and another for EMPLOYEE, as in this case:
To me the solution seems to be a dual relationship where one of the foreign keys must be null while the other may not be, but I don't even know how to do it.
I believe your underlying hyopthesis is flawed: a one-person Company, founded by an Employee, could be registered at the founder's personal adress. Therefore an Employee may have the same address as a Company.
Likewise, two Employees may share the same address (a husband and a wife could be coworkers). Therefore I would define the relationship between adress and each of the other two entities a regular many-to-many, without any further condition.
You might be worried that changing the address of (eg.) a Company would wrongly alter the Employee's address. But instead of updating the Address entity, treat this case as creating a new Address and linking the (eg.) Company to this new Address.
Now, if you really need to implement the constraint, regardless of the (oh so dull ;) reality, I see no other option but implementing a form of inheritance as decribed here.
Notice that:
your initial design actually implements the Single Table Inheritance pattern
your alternative proposal (based on two separate address tables) actually implements the Concrete Table Inheritance pattern1
In your initial design, the constraint can be implemented with a simple CHECK constraint2 on the address table, the condition being company_id IS NULL XOR employee_id IS NULL
1 Migrating to the Class Table Inheritance pattern is "left as an exercise". However this pattern does not help in enforcing this constraint (in fact, this elegant pattern has serious additional limitations with enforcing integrity constraints in general). Nevertheless the constraint could still be enforced with a CHECK constraint.
2 MySQL does not enforce CHECK constraints, but a similar effect can be achieved through the use of triggers.

Guaranteeing a FK relationship through multiple tables

I'm using MySQL / InnoDB, and using foreign keys to preserve relationships across tables. In the following scenaro (depicted below), a 'manager' is associated with a 'recordLabel', and an 'artist' is also associated with a 'recordLabel'. When an 'album' is created, it is associated with an 'artist' and a 'manager', but both the artist and the manager need to be associated with the same recordLabel. How can I guarantee that relationship with the current table setup, or do I need to redesign the tables?
You cannot achieve this result using pure DRI - Declarative Referential Integrity, or the linking of foreign keys to ensure the schema's referential integrity.
There are 2 ways to solve this problem:
Consider the requirement a database problem, and use a trigger on INSERT and UPDATE to validate the requirements, and fail otherwise.
Consider the nested link a business logic requirement, and implement it in your business logic in PHP/C#/whatever.
As a sidenote, I think the structure is rather strange from a practical perspective - as far as I know an Artist is signed to a RecordLabel, and assigned a Manager separately (either from the label or individually, many artists retain their own manager when switching to another label). Linking the Manager also to the Album only makes sense to record historic managers, enabling you to retrieve who was the manager to the artist when the album was released, but that automatically means your requirement is invalid if the artist switches labels and/or manages later on. I think therefore it is wrong from a practical data view to enforce this link.
What you do is add recordLabel id to the albums table. Then you put two, two column indexes on albumns (recordLabel_id, artist_id) and (recordLabel_id, managers_id).
Because the record_id can only have one value in each row of the albumns table you will have insured integrity.

Best way to link a table to 2 different keys?

I'm designing a mySQL DB and I'm having the following issue:
Say I have a wall_posts table. Walls can belong to either an event or a user.
Hence the wall_posts table must references either event_id or user_id (foreign key constraint).
What is the best way to build such a relationship, considering I must always be able to know who the walls belong to ... ?
I've been considering using 2 tables, such as event_wall_posts and user_wall_posts so one got an event_id field and the other a user_id one, but I believe there must be something much better than such a redundant workaround ...
Is there a way to use an intermediate table to link the wall_posts to either an event_id or a user_id ?
Thanks in advance,
Edit : seems there is not a clear design to do this and both approach seem okay, so,
which one will be the fastest if there is a lots of data ?
Is it preferable to have 2 separates table (so queries might be faster, since there will be twice less data in tables ...), or is it still preferable to have a better OO approach with a single wall_posts table referencing a wall table (and then both users and events will have a uniquewall_id`)
Why is it redundant? You won't write code twice to handle them, you will use the same code, just change the name of the table in the SQL.
Another reason to take this approach is that some time in the future you will discover you need new different fields for each entity.
What you're talking about is called an exclusive arc and it's not a good practice. It's hard to enforce referential integrity. You're probably better off using, in an object sense, a common supertype.
That can be modelled in a couple of ways:
A supertype table called, say, wall. Two subtype tables (user_wall and event_wall) that link to a user and event respectively as the owner. The wall_posts table links to the supertype table; or
Putting both entity types into one table and having a type column. That way you're not linking to two separate tables.
Go for the simplest solution: add both an event_id and a user_id column to the wall_posts table. Use constraints to enforce that one of them is null, and the other is not.
Anything more complex smells like overnormalization to me :)
A classical approach to this problem is:
Create a table called wall_container and keep properties common to both users and events in it
Reference both users and events to wall_container
Reference wall_posts to wall_container
However, this is not very efficient and it's not guaranteed that this wall_container doesn't containt records that are not either a user or an event.
SQL is not particularly good in handling multiple inheritance.
Your wall and event has their own unique IDs .. right?? then their is no need for another table . let the wall_post table have a attribute as origin which will direct to the record of whatever the record is event's or users. '
If the wall and event may have same ID then make a table with three attributes origin(primary), ID number and type. There ID number will be what you set, type defining what kind of entity does the ID represent and origin will be a new ID which you will generate maybe adding different prefix. In case of same ID the origin table will help you immensely for other things to other than wall posts.