Table • Name
recently learned singular is correct
Yes. Plural in the table names are a sure sign of someone who has not read any of the standard materials and has no knowledge of database theory.
Some of the wonderful things about Standards are:
- they are all integrated with each other
- they work together
- they were written by minds greater than ours, so we do not have to
debate them.
The standard table name refers to each row in the table, which is used in the all verbiage, not the total content of the table (we know that the Customer
table contains all the Customers).
Relationship, Verb Phrase
In genuine Relational Databases that have been modelled (as opposed to pre-1970's Record Filing Systems [characterised by Record IDs
which are implemented in an SQL database container for convenience):
- the tables are the Subjects of the database, thus they are nouns, again, singular
- the relationships between the tables are the Actions that take place between the nouns, thus they are verbs (i.e they are not arbitrarily numbered or named)
- that is the Predicate
- all that can be read directly from the data model (refer my examples at the end)
- (the Predicate for an independent table (the top-most parent in an hierarchy) is that it is independent)
- thus the Verb Phrase is carefully chosen, so that it is the most meaningful, and generic terms are avoided (this becomes easier with experience). The Verb Phrase is important during modelling because it assists in resolving the model, ie. clarifying relations, identifying errors, and correcting the table names.
[**Diagram_A**][Diagram_A]
Of course, the relationship is implemented in SQL as a CONSTRAINT FOREIGN KEY
in the child table (more, later). Here is the Verb Phrase (in the model), the Predicate that it represents (to be read from the model), and the FK Constraint Name:
Initiates
Each Customer Initiates 0-to-n SalesOrders
Customer_Initiates_SalesOrder_fk
Table • Language
However, when describing the table, particularly in technical language such as the Predicates, or other documentation, use singular and plurals as they naturally in the English language. Keeping in mind the table is named for the single row (relation) and the language refers to each derived row (derived relation):
Each Customer initiates zero-to-many SalesOrders
not
Customers have zero-to-many SalesOrders
So, if I got a table "user" and then I got products that only the user will have, should the table be named "user-product" or just "product"? This is a one to many relationship.
(That is not a naming-convention question; that is a db design question.) It doesn't matter if user::product
is 1::n. What matters is whether product
is a separate entity and whether it is an Independent Table, ie. it can exist on its own. Therefore product
, not user_product
.
And if product
exists only in the context of an user
, ie. it is a Dependent Table, therefore user_product
.
[**Diagram_B**][Diagram_B]
And further on, if I would have (for some reason) several product descriptions for each product, would it be "user-product-description" or "product-description" or just "description"? Of course with the right foreign keys set.. Naming it only description would be problematic since I could also have user description or account description or whatever.
That's right. Either user_product_description
xor product_description
will be correct, based on the above. It is not to differentiate it from other xxxx_descriptions
, but it is to give the name a sense of where it belongs, the prefix being the parent table.
What about if I want a pure relational table (many to many) with only two columns, what would this look like? "user-stuff" or maybe something like "rel-user-stuff" ? And if the first one, what would distinguish this from, for example "user-product"?
Hopefully all the tables in the relational database are pure relational, normalised tables. There is no need to identify that in the name (otherwise all the tables will be rel_something
).
If it contains only the PKs of the two parents (which resolves the logical n::n relationship that does not exist as an entity at the logical level, into a physical table), that is an Associative Table. Yes, typically the name is a combination of the two parent table names.
Note that is such cases the Verb Phrase applies to, and is read as, from parent to parent, ignoring the child table, because its only purpose in life is to relate the two parents.
[**Diagram_C**][Diagram_C]
If it is not an Associative Table (ie. in addition to the two PKs, it contains data), then name it appropriately, and the Verb Phrases apply to it, not the parent at the end of the relationship.
[**Diagram_D**][Diagram_D]
If you end up with two user_product
tables, then that is a very loud signal that you have not normalised the data. So go back a few steps and do that, and name the tables accurately and consistently. The names will then resolve themselves.
Naming Convention
If there is some sort of naming convention standard out there that you guys recommend, feel free to link.
What you are doing is very important, and it will affect the ease of use and understanding at every level. So it is good to get as much understanding as possible at the outset. The relevance of most of this will not be clear, until you start coding in SQL.
Case is the first item to address. All caps is unacceptable. Mixed case is normal, especially if the tables are directly accessible by the users. Refer my data models. Note that when the seeker is using some kind of NonSQL, that has only lowercase, I give that, in which case I include underscores (as per your examples).
Maintain a data focus, not an application or usage focus. We have had Open Architecture since 1984, and databases are supposed to be independent of the apps that use them.
That way, as they grow, and more than the one app uses them, the naming will remain meaningful, and need no correction. (Databases that are completely embedded in a single app are not databases.) Name the data elements as data, only.
Be very considerate, and name tables and columns very accurately. Do not use UpdatedDate
if it is a DATETIME
datatype, use UpdatedDtm
. Do not use_description
if it contains a dosage.
It is important to be consistent across the database. Do not use NumProduct
in one place to indicate number of Products and ItemNo
or ItemNum
in another place to indicate number of Items. Use NumSomething
for numbers-of, and SomethingNo
or SomethingId
for identifiers, consistently.
Do not prefix the column name with a table name or short code, such as user_first_name
. SQL already provides for the tablename as a qualifier:
table_name.column_name -- notice the dot
Exceptions:
The first exception is for PKs, they need special handling because you code them in joins, all the time, and you want keys to stand out from data columns. Always use user_id
, never id
.
- Note that this is not a table name used as a prefix, but a proper descriptive name for the component of the key:
user_id
is the column that identifies an user, not the id
of the user
table.
- (Except of course in record filing systems, where the files are accessed by surrogates and there are no relational keys, there they are one and the same thing).
- Always use the exact same name for the key column wherever the PK is carried (migrated) as an FK.
- Therefore the
user_product
table will have an user_id
as a component of its PK (user_id, product_no)
.
- the relevance of this will become clear when you start coding. First, with an
id
on many tables, it is easy get mixed up in SQL coding. Second, anyone other that the initial coder has no idea what he was trying to do. Both of which are easy to prevent, if the key columns are treated as above.
The second exception is where there is more than one FK referencing the same parent table table, carried in the child. As per the Relational Model, use Role Names to differentiate the meaning or usage, eg. AssemblyCode
and ComponentCode
for two PartCodes
. And in that case, do not use the undifferentiated PartCode
for one of them. Be precise.
Diagram_E
Prefix
Where you have more than say 100 tables, prefix the table names with a Subject Area:
REF_
for Reference tables
OE_
for the Order Entry cluster, etc.
Only at the physical level, not the logical (it clutters the model).
Suffix
Never use suffixes on tables, and always use suffixes on everything else. That means in the logical, normal use of the database, there are no underscores; but on the administrative side, underscores are used as a separator:
_V
View (with the main TableName
in front, of course)
_fk
Foreign Key (the constraint name, not the column name)
_cac
Cache
_seg
Segment
_tr
Transaction (stored proc or function)
_fn
Function (non-transactional), etc.
The format is the table or FK name, an underscore, and action name, an underscore, and finally the suffix.
This is really important because when the server gives you an error message:
____blah blah blah error on object_name
you know exactly what object was violated, and what it was trying to do:
____blah blah blah error on Customer_Add_tr
Foreign Keys (the constraint, not the column). The best naming for a FK is to use the Verb Phrase (minus the "each" and the cardinality).
Customer_Initiates_SalesOrder_fk
Part_Comprises_Component_fk
Part_IsConsumedIn_Assembly_fk
Use the Parent_Child_fk
sequence, not Child_Parent_fk
is because (a) it shows up in the correct sort order when you are looking for them and (b) we always know the child involved, what we are guessing at is, which parent. The error message is then delightful:
____Foreign key violation on Vendor_Offers_PartVendor_fk
.
That works well for people who model their data, where the Verb Phrases have been identified. For the rest, the record filing systems, etc, use Parent_Child_fk
.
- Indices are special, so they have a naming convention of their very own, made up of, in order, each character position from 1 to 3:
U
Unique, or _
for non-unique
C
Clustered, or _
for non-clustered
_
separator
For the remainder:
- If the key is one column or a very few columns:
____ColumnNames
- If the key is more than a few columns:
____PK
Primary Key (as per model)
____AK[*n*]
Alternate Key (IDEF1X term)
Note that the table name is not required in the index name, because it always shows up as table_name.index_name.
So when Customer.UC_CustomerId
or Product.U__AK
appears in an error message, it tells you something meaningful. When you look at the indices on a table, you can differentiate them easily.
- Find someone qualified and professional and follow them. Look at their designs, and carefully study the naming conventions they use. Ask them specific questions about anything you do not understand. Conversely, run like hell from anyone who demonstrates little regard for naming conventions or standards. Here's a few to get you started:
- They contain real examples of all the above. Ask questions re naming questions in this thread.
- Of course, the models implement several other Standards, beyond naming conventions; you can either ignore those for now, or feel free to ask specific new questions.
- They are several pages each, so you will have to click the links.
- Note that PDF files have full navigation, so click on the blue glass buttons, or the objects where expansion is identified:
- Readers who are unfamiliar with the Relational Modelling Standard may find the IDEF1X Notation helpful.
Order Entry & Inventory with Standard-compliant Addresses
Simple inter-office Bulletin system for PHP/MySQL
Sensor Monitoring with full Temporal capability
Answers to Questions
That cannot be reasonably answered in the comment space.
Larry Lustig:
... even the most trivial example shows ...
If a Customer has zero-to-many Products and a Product has one-to-many Components and a Component has one-to-many Suppliers and a Supplier sells zero-to-many Components and a SalesRep has one-to-many Customers what are the "natural" names the tables holding Customers, Products, Components, and Suppliers?
There are two major problems in your comment:
You declare your example to be "the most trivial", however, it is anything but. With that sort of contradiction, I am uncertain if you are serious, if technically capable.
That "trivial" speculation has several gross Normalisation (DB Design) errors.
Until you correct those, they are unnatural and abnormal, and they do not make any sense. You might as well name them abnormal_1, abnormal_2, etc.
You have "suppliers" who do not supply anything; circular references (illegal, and unnecessary); customers buying products without any commercial instrument (such as Invoice or SalesOrder) as a basis for the purchase (or do customers "own" products?); unresolved many-to-many relationships; etc.
Once that is Normalised, and the required tables are identified, their names will become obvious. Naturally.
In any case, I will try to service your query. Which means I will have to add some sense to it, not knowing what you meant, so please bear with me. The gross errors are too many to list, and given the spare specification, I am not confident I have corrected them all.
I will assume that if the product is made up of components, then the product is an assembly, and the components are used in more than one assembly.
Further, since "Supplier sells zero-to-many Components", that they do not sell products or assemblies, they sell only components.
Speculation vs Normalised Model
In case you are not aware, the difference between square corners (Independent) and round corners (Dependent) is significant, please refer to the IDEF1X Notation link. Likewise the solid lines (Identifying) vs dashed lines (Non-identifying).
... what are the "natural" names the tables holding Customers, Products, Components, and Suppliers?
- Customer
- Product
- Component
(Or, AssemblyComponent, for those who realise that one fact identifies the other)
- Supplier
Now that I have resolved the tables, I don't understand your problem. Perhaps you can post a specific question.
Predicate
VoteCoffee:
How are you handling the scenario Ronnis posted in his example where multiple relationships exist between 2 tables (user_likes_product, user_bought_product)? I may misunderstand, but this seems to result in duplicate table names using the convention you detailed.
Assuming there are no Normalisation errors, User likes Product
is a predicate, not a table. Do not confuse them. Refer to my Answer, where it relates to Subjects, Verbs, and Predicates, and my response to Larry immediately above.
Each table contains a set of Facts (each row is a Fact). Predicates (or propositions), are not Facts, they may or may not be true.
The Relational Model is based on First Order Predicate Calculus (more commonly known as First Order Logic). A Predicate is a single-clause sentence in simple, precise English, that evaluates to true or false.
Further, each table represents, or is the implementation of, many Predicates, not one.
A query is a test of a Predicate (or a number of Predicates, chained together) that results in true (the Fact exists) or false (the Fact does not exist).
Thus tables should be named, as detailed in my Answer (naming conventions), for the row, the Fact, and the Predicates should be documented (by all means, it is part of the database documentation), but as a separate list of Predicates.
This is not a suggestion that they are not important. They are very important, but I won't write that up here.
Quickly, then. Since the Relational Model is founded on FOPC, the entire database can be said to be a set of FOPC declarations, a set of Predicates. But (a) there are many types of Predicates, and (b) a table does not represent one Predicate (it is the physical implementation of many Predicates, and of different types of Predicates).
Therefore naming the table for "the" Predicate that it "represents" is an absurd concept.
The "theoreticians" are aware of only a few Predicates, they do not understand that since the RM was founded on the FOL, the entire database is a set of Predicates, and of different types.
And of course, they choose absurd ones from the few that they do know: EXISTING_PERSON
; PERSON_IS_CALLED
. If it were not so sad, it would be hilarious.
Note also that the Standard or atomic table name (naming the row) works brilliantly for all the verbiage (including all Predicates attached to the table). Conversely, the "table represents predicate" name cannot, which is fine for the "theoreticians", who understand very little about Predicates, but not otherwise.
The Predicates that are relevant to the data model, are expressed in the model, they are of two orders.
- Unary Predicate
The first set is diagrammatic, not text: the notation itself. These include various Existential; Constraint-oriented; and Descriptor (attributes) Predicates.
- Of course, that means only those who can 'read' a Standard data model can read those Predicates. Which is why the "theoreticians", who are severely crippled by their text-only mindset, cannot read data models, why they stick to their pre-1984 text-only mindset.
- Binary Predicate
The second set is those that form relationships between Facts. This is the relation line. The Verb Phrase (detailed above) identifies the Predicate, the proposition, that has been implemented (which can be tested via query). One cannot get more explicit than that.
Therefore, to one who is fluent in Standard data models, all the Predicates that are relevant, are documented in the model. They do not need a separate list of Predicates (but the users, who cannot 'read' everything from the data model, do!).
Here is a Data Model, where I have listed the Predicates. I have chosen that example because it shows the Existential, etc, Predicates, as well as the Relationship ones, the only Predicates not listed are the Descriptors. Here, due to the seeker's learning level, I am treating him as an user.
Therefore the event of more than one child table between two parent tables is not a problem, just name them as the Existential Fact re their content, and normalise the names.
The rules I gave for Verb Phrases for relationship names for Associative Tables come into play here. Here is a Predicate vs Table discussion, covering all points mentioned, in summary.
For a good short description re the proper use of Predicates and how to use them (which is quite a different context to that of responding to comments here), visit this answer, and scroll down to the Predicate section.
Charles Burns:
By sequence, I meant the Oracle-style object purely used to store a number and its next according to some rule (e.g. "add 1"). Since Oracle lacks auto-ID tables, my typical use is to generate unique IDs for table PKs. INSERT INTO foo(id, somedata) VALUES (foo_s.nextval, "data"...)
Ok, that is what we call a Key or NextKey table. Name it as such. If you have SubjectAreas, use COM_NextKey to indicate it is common across the database.
Btw, that is a very poor method of generating keys. Not scalable at all, but then with Oracle's performance, it is probably "just fine". Further, it indicates that your database is full of surrogates, not relational in those areas. Which means extremely poor performance and lack of integrity.