Always create unique keys whenever possible? - mysql

Should you always create unique keys whenever possible?
For example let's say I have a table with three fields, student ID, first name, last name and the student ID is the primary key.
If no two students have the first & last name, should I create a unique key for those two fields?

Yes, you should use unique indexes even when you already have a primary key when the column or combination of columns are unique. It's good to have constraints in your database to prevent bad data. However, this is not what you have in your case. Even if you currently have no students with duplicate names that can easily happen in the future. Names are not unique in the world.
U.S. Social Security numbers are almost always unique (they can be reused after a number of years, but it's unlikely to ever happen in your case), so they might make for a good candidate for a unique index. If you have non-U.S. students though then you would need to make the column nullable.

Yes, usually having unique IDs (surrogate keys) is best. In this case, last name and first name are not enough for a primary key. Even if you no duplicate names now, you can't be sure you won't have two John Smith's in the future.

Don't make the assumption that no two students will have the same name.
When the underlying model suggests it, it is a good idea to create unique keys. Constraints like these will ensure cohesive data and prevent errors. But in your case the underlying model does not suggest this to be the case.

Unique keys should follow business definitions; if the studentID is a "semi-natural" key (it has unique meaning that exists beyond your specific database), then that should suffice as your unique key.
If the studentID is simply an identity value that is assigned by the database as a row-number, then you probably need some other unique key to avoid entering the same student twice.

Primitive primary key with no relation to data domain is one of widely accepted best practices
( just imagine - one of your students decides to marry )
Another good practice (though from NoSql) world is to use GUID - this way keys are unique, and different datasets can be mixed in same table without collisions.
PS: you could save some storage space, but today it is cheap and there is no need to sacrifice good practices for it

Yes!
If you ever need to update or delete rows from the table, it is very advantageous to have something to uniquely identify each row in the table.
With your example, I don't think it's possible to guarantee no two students will share the same name. Even adding a date of birth still can't guarantee they'll always be unique. I'd recommend adding an auto incrementing INT or BIGINT as the primary key.
You can always add the Unique constraint as well and remove it if it becomes an issue.

A simple way to do it is use an auto-generated Guid (Globally Unique Identifier) to identify a student. It is "guarenteed" to be unique every time it is generated. Names can change (like when somebody gets married), but some auto generated value has no meaning so should never need to be changed.
http://en.wikipedia.org/wiki/Globally_unique_identifier

Your database constraints should be DBMS understood business rules. Is there a business rule that states that no two students may have the same first and last name combination? I presume not, therefore do not create a unique key for those two fields. Perhaps best not to presume, though, and ask a business domain expert e.g. the enrolment officer.
Note that a row in this table is a proposition I.e. that there exists a student enrolled with first name 'x' and last name 'y' and student ID 'z'. Clearly the DBMS has not concept of whether this proposition is true in the real world. What normally happens is that there will be a trusted source to verify data. The enterprise will authorize an officer (director etc) in this role. Let's say it is the enrolment officer who is responsible for verifying that 'x y' is a real person, that they are eligible to be enrolled, and the person is who they say they are. Typically, they will require sight of documents (certificates, passport, etc), take up references, interview the person, check public records, etc. Of course, the enrolment officer may delegate their responsibility to other members of staff or engage an agent.
At some point they will be satisfied and for convenience will issue they own identifier, the student ID. Mistakes do happen and it may turn out that this value is not unique, in which case it would be the enrolment officer's responsibility to resolve the problem and issue a new student to. Perhaps they will use software to generate the value to mitigate against such problems. The student ID will be issued to the student and will be used within the enterprise to identify the person for the convenience of all concerned. They may even be issued with a document (e.g. photo ID card) to assist in identification, based on the level of trust in a given context (e.g. may need to produce photo ID to sit an exam). If the student forgets their ID, loses their issued documents, etc then the enrolment office will be able to retrieve it from records e.g. with reference to copy documents taken during the verification process; they are unlikely to use first name and last name alone.
The point is, the trusted source for the identifier is the enrolment officer on behalf of the enterprise, rather than the database, the DBMS or any other kind of software involved in the process. Therefore, it probably is acceptable to make student ID the sole identifier for stents within the database. Consider, however, that an auto-increment column generated on one hardware build of a single DBMS within the enterprise is probably not suitable for the allocation of such significant identifier values.

Related

Does MySQL database require a unique identifier?

I'm really new to databases in general but could use some advice. I have a database that has about 6000 records (and growing but not crazy amounts). I'd like to build an API so that I can retrieve a property's price history, but have been advised I need a unique ID but I'm not so sure. Can anyone advise?
DB looks like this:
address
price
date_created
status
Address one, main street
£150,000
13/10/2022
new data
Address one, main street
£140,000
16/10/2022
update data
Address two, side road
£350,000
13/10/2022
new data
Maybe you will need to add/edit your data using a CRUD, maybe reference other tables, make foreign keys, etc. I recommend that you add a primary key. I've never worked on tables without a primary key.
I can hear my database teacher in 2001: you should always have a primary key and another unique key apart from the primary one (compound or on a single column) if you don't want your table to be just another excel sheet. And I remember that it was a mathematical demonstration of this rule with injective functions.
Of course, you can ignore these rules, but they are best practice advice for your future self :)
You might find an integer primary key useful, but it's not mandatory.
If the address is sufficient to be the unique column by which you can reference any row, then that's fine. It's called a "natural key." In practice, most of us have experienced that any column you think should be unique ends up not being 100% unique eventually. So a lot of developers recommend adding a "pseudokey" which has no reason not to be unique.
I wrote a chapter called "ID Required" describing the pros and cons of pseudokeys and natural keys in my book SQL Antipatterns, Volume 1: Avoiding the Pitfalls of Database Programming.

Normalize two tables with same primary key to 3NF

I have two tables currently with the same primary key, can I have these two tables with the same primary key?
Also are all the tables in 3rd normal form
Ticket:
-------------------
Ticket_id* PK
Flight_name* FK
Names*
Price
Tax
Number_bags
Travel class:
-------------------
Ticket id * PK
Customer_5star
Customer_normal
Customer_2star
Airmiles
Lounge_discount
ticket_economy
ticket_business
ticket_first
food allowance
drink allowance
the rest of the tables in the database are below
Passengers:
Names* PK
Credit_card_number
Credit_card_issue
Ticket_id *
Address
Flight:
Flight_name* PK
Flight_date
Source_airport_id* FK
Dest_airport_id* FK
Source
Destination
Plane_id*
Airport:
Source_airport_id* PK
Dest_airport_id* PK
Source_airport_country
Dest_airport_country
Pilot:
Pilot_name* PK
Plane id* FK
Pilot_grade
Month
Hours flown
Rate
Plane:
Plane_id* PK
Pilot_name* FK
This is not meant as an answer but it became too long for a comment...
Not to sound harsh, but your model has some serious flaws and you should probably take it back to the drawing board.
Consider what would happen if a Passenger buys a second Ticket for instance. The Passenger table should not hold any reference to tickets. Maybe a passenger can have more than one credit card though? Shouldn't Credit Cards be in their own table? The same applies to Addresses.
Why does the Airport table hold information that really is about destinations (or paths/trips)? You already record trip information in the Flights table. It seems to me that the Airport table should hold information pertaining to a particular airport (like name, location?, IATA code et cetera).
Can a Pilot just be associated with one single Plane? Doesn't sound very likely. The pilot table should not hold information about planes.
And the Planes table should not hold information on pilots as a plane surely can be connected to more than one pilot.
And so on... there are most likely other issues too, but these pointers should give you something to think about.
The only tables that sort of looks ok to me are Ticket and Flight.
Re same primary key:
Yes there can be multiple tables with the same primary key. Both in principle and in good practice. We declare a primary or other unique column set to say that those columns (and supersets of them) are unique in a table. When that is the case, declare such column sets. This happens all the time.
Eg: A typical reasonable case is "subtyping"/"subtables", where entities of a kind identified by a candidate key of one table are always or sometimes also of the kind identifed by the same values in another table. (If always then the one table's candidate key values are also in the other table's. And so we would declare a foreign key from the one to the other. We would say the one table's kind of entity is a subtype of the other's.) On the other hand sometimes one table is used with attributes of both kinds and attributes inapplicable to one kind are not used. (Ie via NULL or a tag indicating kind.)
Whether you should have cases of the same primary key depends on other criteria for good design as applied to your particular situation. You need to learn design including normalization.
Eg: All keys simple and 3NF implies 5NF, so if your two tables have the same set of values as only & simple primary key in every state and they are both in 3NF then their join contains exactly the same information as they do separately. Still, maybe you would keep them separate for clarity of design, for likelihood of change or for performance based on usage. You didn't give that information.
Re normal forms:
Normal forms apply to tables. The highest normal form of a table is a property independent of any other table. (Athough you might choose that form based on what forms & tables are alternatives.)
In order to normalize or determine a table's highest normal form one needs to know (in general) all the functional dependencies in it. (For normal forms above BCNF, also join dependencies.) You didn't give them. They are determined by what the meaning of the table is (ie how to determine what rows go in it in any given situation) and the possible situtations that can arise. You didn't give them. Your expectation that we could tell you about the normal forms your tables are in without giving such information suggests that you do not understand normalization and need to educate yourself about it.
Proper design also needs this information and in general all valid states that can arise from situations that arise. Ie constraints among given tables. You didn't give them.
Having two tables with the same key goes against the idea of removing redundancy in normalization.
Excluding that, are these tables in 1NF and 2NF?
Judging by the Names field, I'd suggest that table1 is not. If multiple names can belong to one ticket, then you need a new table, most likely with a composite key of ticket_id,name.

Proper database model for a user feedback system (an interesting case)

I am developing an application using PHP and Yii Framework. I've been thinking about the most suitable database structure for the given functionality and here's what I've come up with. Yet I'm not 100% positive that's how it should be done so I've decided to ask the community.
App Description:
Registered users may participate in an event. Every event can have an
unlimited number of users, called "participants of the event").
Once the event is over, every participant can leave a feedback about every other participant of the same event.
Database structure:
Since every event can have an unlimited number of users and users can participate in an unlimited number of events, I've created a table "Participant", which resolves the many-to-many relation.
Other tables are self-explanatory.
And here's the most important thing:
Every participant of an event can have the maximum number of feedbacks which equals the number of participants of the same event excluding the given participant (Example, if there are 5 participants of the event, the given participant can receive 4 feedbacks from participants of the same event).
Let me emphasize, only participants of the same event can leave a feedback (and only one) about the given participant.
Below are the steps I took to ensure the integrity of the database:
I've created the "id" column in the "Participant" table to give a unique ID to every user who participates in a certain event. This ID is composite (user_id and practice_id concatenated together). So, the participant id of the user 23 who participated in event 14 would be 14-23.
You may ask why I decided to create a separate column with this ID instead of simply defining the primary key like this:
PRIMARY KEY (user_id, event_id)
Read on.
When the event is over, every participant can leave a feedback about the others. Now, this participant ID can be references by the foreign keys "sender_id" and "recipient_id" in the feedback table.
Further on, the primary key of the feedback table will also be formed by combining "the sender_id" and the "recipient_id", so if the user 23 wants to leave a feedback about the user 45 (both participated in the event 71), the primary key for the feedback would be: 71-45-71-23.
This approach allows us to make sure on the database level that no participant leaves a feedback about the same participant twice and that a user can't participate in the same event twice.
Questions:
Does this approach has the right to exist?
What are the pros and
other, better way to approach this functionality?
Can I generate the primary keys based on the values of the other columns
automatically on record insertion?
This is a bad design. Just make a 2-column primary key, and 2-column foreign keys to it. This is a fundamental anti-pattern called "encoding information in keys" which (thereby) are called "smart", "intelligent" or "concatenated" keys. A good key is a "dumb" key.
Eg::
Despite it now being easy to implement a Smart Key, it is hard to
recommend that you create one of your own that isn't a natural key,
because they tend to eventually run into trouble, whatever their
advantages, because it makes the databases harder to refactor, imposes
an order which is
difficult to change and may not be optimal for your queries, requires
a string comparison if the Smart Key includes non-numeric characters,
and is less effective than a composite key in helping range-based
aggregations. It also violates the basic relational guideline that
every column should store atomic values
Smart Keys also tend to outgrow their original coding constraints
Besides, there is no need to do this.
Many DBMSes allow "computed columns" whose values are automatically calculated from other columns. To make one a primary key or foreign key you would usually need it "persisted", ie have take up memory like a normal column vs just being calculated when needed like a view. MySQL does not have these, but 5.7.5 has some functionality where they are called "generated columns", which can be "stored". But don't do this for PKs or FKs!
The actual design issue is handling database/SQL subtypes/hierarchies/inheritance/polymorphism.

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.

Determing correct key values for multiple MySQL tables

I am trying to determine how the tables need to be linked in which ways.
The employees tables is directly linked to a number of tables which provide more information. A few of those tables have even more details.
Employees have a unique employeeid but I understand best practice is to still have a id?
Customers have a unique customerid
Employees have a manager
Managers are employees
Customers have a manager associated with them. manager associated with them
Employees may have a academic, certification and/or professional information.
With all of this said what would be the best recommendation for creating primary and foreign keys? Is there a better way to handle the design?
EDIT
Updated diagram to reflect feedback thus far. See comments to understand changes taking place.
Though your question is sensible, before you go any further in design, I would suggest for you to spend some time understanding relationships, foreign keys and how they propagate through relationships.
The diagram is utterly wrong. It will help it you start naming primary keys with full name, TableNameID, like EmployeeID; then it will become obvious how keys propagate through relationships. If you had full names you would have noticed that all your arrows are pointing in the wrong direction; parent and child are reversed. Anyway, takes some practice. So I would suggest that you rework the diagram and post the new version, so that we can comment on that one. It should start looking something like this (just a small segment)
EDIT
This is supposed to point you to towards the next step. See if you can read description (specification) and follow the diagram at the same time.
Each employee has one manager, a manager manages many employees.
A manager is an employee.
Each customer is managed by an employee who acts as an account manager for that customer.
Account manages for a customer may change over time.
Each employee is a member of one team, each team has many employees.
Employee performance for each employee is tracked over time.
Employee may have many credentials, each credential belongs to one employee only.
Credential is academic or professional.
Employees have unique employeeID but I understand best practice is to
still have a id?
No. (But keep reading.) You need an id number in two cases: 1) when you don't have any other way to identify an entity, and 2) when you're trying to improve join performance. And that doesn't always work. ID numbers always require more joins, but when the critical information is carried in human-readable codes or in natural keys, you don't need a join to get to it. Also, routine use of ID numbers often introduces data integrity problems, because unique constraints on natural keys are often omitted. For example, USPS postal codes for state names are unique, but tables that use ID numbers instead of USPS postal codes often omit the unique constraint on that two-character column. In your case, you need a unique constraint on employee number regardless. (But keep reading.)
Employees have a manager.
Does the table "team" implement this requirement? If the "manager" table identifies managers, then your other manager columns should reference "manager". (In this diagram, that's customers, team, and customer_orders.)
Managers are employees.
And that information is stored in the table "manager"?
Customers have a manager associated with them.
And so does each order. Did you mean to do that?
Employees may have a academic, certification and/or professional
information.
But apparently you can't record any of that information unless you store a skill first. That doesn't sound like a good approach. Give it some more thought.
Whenever you design tables with overlapping predicates (overlapping meanings), you need to stop and sit on your hands for a few minutes. In this case, the predicates of the tables "employees" and "customers" overlap.
If employees can be customers, which is the case for almost every business, then you have set the stage for update anomalies. An employee's last name changes. Clearly, you must update "employees". But do you have to update "customers" too? How do you know? You can't really tell, because those two tables have independent id numbers.
An informal rule of thumb: if any real-world entity has more than one primary key identifying it in your database, you have a problem. In this case, an employee who is also a customer would have two independent primary keys identifying that person--an employee id and a customer id.
Consider adding a table of persons, some of whom will be employees, and some of whom will be customers. If your database is well-designed and useful, I'll bet that later some of the persons will be prospects, some will be job applicants, and so on. You will need an id number for persons, because in the most general case all you can count on knowing is their name.
At some point, you'll have to take your database design knowledge to the next level. For an early start, read this article on people's names.