MySQL naming conventions, should field name include the table name? - php

A friend told me that I should include the table name in the field name of the same table, and I'm wondering why? And should it be like this?
Example:
(Table) Users
(Fields) user_id, username, password, last_login_time
I see that the prefix 'user_' is meaningless since I know it's already for a user. But I'd like to hear from you too.
note: I'm programming in php, mysql.

I agree with you. The only place I am tempted to put the table name or a shortened form of it is on primary and foreign keys or if the "natural" name is a keyword.
Users: id or user_id, username, password, last_login_time
Post: id or post_id, user_id, post_date, content
I generally use 'id' as the primary key field name but in this case I think user_id and post_id are perfectly OK too. Note that the post date was called 'post_date" because 'date' is a keyword.
At least that's my convention. Your mileage may vary.

I see no reason to include the table name, it's superfluous. In the queries you can refer to the fields as <table name>.<field name> anyway (eg. "user.id").

With generic fields like 'id' and 'name', it's good to put the table name in.
The reason is it can be confusing when writing joins across multiple tables.
It's personal preference, really, but that is the reasoning behind it (and I always do it this way).
Whatever method you choose, make sure it is consistent within the project.

Personally I don't add table names for field names in the main table but when using it as a foreign field in another table, I will prefix it with the name of the source table. e.g. The id field on the users table will be called id, but on the comments table it, where comments are linked to the user who posted them, it will be user_id.
This I picked up from CakePHP's naming scheme and I think it's pretty neat.

Prefixing the column name with the table name is a way of guaranteeing unique column names, which makes joining easier.
But it is a tiresome practice, especially if when we have long table names. It's generally easier to just use aliases when appropriate. Besides, it doesn't help when we are self-joining.
As a data modeller I do find it hard to be consistent all the time. With ID columns I theoretically prefer to have just ID but I usually find I have tables with columns called USER_ID, ORDER_ID, etc.
There are scenarios where it can be positively beneficial to use a common column name across multiple tables. For instance, when a logical super-type/sub-type relationship has been rendered as just the child tables it is useful to retain the super-type's column on all the sub-type tables (e.g. ITEM_STATUS) instead of renaming it for each sub-type (ORDER_ITEM_STATUS, INVOICE_ITEM_STATUS, etc). This is particularly true when they are enums with a common set of values.

For example, your database has tables which store information about Sales and Human resource departments, you could name all your tables related to Sales department as shown below:
SL_NewLeads
SL_Territories
SL_TerritoriesManagers
You could name all your tables related to Human resources department as shown below:
HR_Candidates
HR_PremierInstitutes
HR_InterviewSchedules
This kind of naming convention makes sure, all the related tables are grouped together when you list all your tables in alphabetical order. However, if your database deals with only one logical group of tables, you need not use this naming convention.
Note that, sometimes you end up vertically partitioning tables into two or more tables, though these partitions effectively represent the same entity. In this case, append a word that best identifies the partition, to the entity name

Actually, there is a reason for that kind of naming, especially when it comes to fields, you're likely to join on. In MySQL at least, you can use the USING keyword instead of ON, then users u JOIN posts p ON p.user_id = u.id becomes users u JOIN posts p USING(user_id) which is cleaner IMO.
Regarding other types of fields, you may benefit when selecting *, because you wouldn't have to specify the list of the fields you need and stay sure of which field comes from which table. But generally the usage SELECT * is discouraged on performance and mainenance grounds, so I consider prefixing such fields with table name a bad practice, although it may differ from application to application.

Sounds like the conclusion is:
If the field name is unique across tables - prefix with table name. If the field name has the potential to be duplicated in other tables, name it unique.
I found field names such as "img, address, phone, year" since different tables may include different images, addresses, phone numbers, and years.

We should define primary keys with prefix of tablename.
We should use use_id instead if id and post_id instead of just id.
Benefits:-
1) Easily Readable
2) Easily differentiate in join queries. We can minimize the use of alias in query.
user table : user_id(PK)
post table : post_id(PK) user_id(FK) here user table PK and post table FK are same
As per documentation,
3) This way we can get benefit of NATURAL JOIN and JOIN with USING
Natural joins and joins with USING, including outer join variants, are
processed according to the SQL:2003 standard. The goal was to align
the syntax and semantics of MySQL with respect to NATURAL JOIN and
JOIN ... USING according to SQL:2003. However, these changes in join
processing can result in different output columns for some joins.
Also, some queries that appeared to work correctly in older versions
(prior to 5.0.12) must be rewritten to comply with the standard.
These changes have five main aspects:
1) The way that MySQL determines the result columns of NATURAL or USING join operations (and thus the result of the entire FROM clause).
2) Expansion of SELECT * and SELECT tbl_name.* into a list of selected columns.
3) Resolution of column names in NATURAL or USING joins.
4) Transformation of NATURAL or USING joins into JOIN ... ON.
5) Resolution of column names in the ON condition of a JOIN ... ON.
Examples:-
SELECT * FROM user NATURAL LEFT JOIN post;
SELECT * FROM user NATURAL JOIN post;
SELECT * FROM user JOIN post USING (user_id);

Related

Good practice for handling naturally JOINed results across an application

I'm working on an existing application that uses some JOIN statements to create "immutable" objects (i.e. the results are always JOINed to create a processable object - results from only one table will be meaningless).
For example:
SELECT r.*,u.user_username,u.user_pic FROM articles r INNER JOIN users u ON u.user_id=r.article_author WHERE ...
will yield a result of type, let's say, ArticleWithUser that is necessary to display an article with the author details (like a blog post).
Now, I need to make a table featured_items which contains the columnsitem_type (article, file, comment, etc.) and item_id (the article's, file's or comment's id), and query it to get a list of the featured items of some type.
Assuming tables other than articles contain whole objects that do not need JOINing with other tables, I can simply pull them with a dynamicially generated query like
SELECT some_table.* FROM featured_items RIGHT JOIN some_table ON some_table.id = featured_items.item_id WHERE featured_items.type = X
But what if I need to get a featured item from the aforementioned type ArticleWithUser? I cannot use the dynamically generated query because the syntax will not suit two JOINs.
So, my question is: is there a better practice to retrieve results that are always combined together? Maybe do the second JOIN on the application end?
Or do I have to write special code for each of those combined results types?
Thank you!
a view can be thot of as like a table for the faint of heart.
https://dev.mysql.com/doc/refman/5.0/en/create-view.html
views can incorporate joins. and other views. keep in mind that upon creation, they take a snapshot of the columns in existence at that time on underlying tables, so Alter Table stmts adding columns to those tables are not picked up in select *.
An old article which I consider required reading on the subject of MySQL Views:
By Peter Zaitsev
To answer your question as to whether they are widely used, they are a major part of the database developer's toolkit, and in some situations offer significant benefits, which have more to do with indexing than with the nature of views, per se.

select table name to join from SQL query

In current database design, I have a main table called "Leads" and some other tables starting with product_ ( product_life_insurance, product_medical_insurance , ... )
-Leads Table :
--ID
--Product
...
-Product_Life_insurance Table :
--ID
--LeadID
...
a Lead Row :
ID 5
Product: life_insurance
a product_life_insurance Row:
ID 1
LeadId 5
..
Is there anyway to create a query to select table Name from Leads and add "product_" prefix to it and then join it to product table ?
I mean :
SELECT *
FROM `leads` JOIN `product_life_insurance` ON `leads`.`id` = `product_life_insurance`.`leadID`
WHERE `leads`.`id` = '5';
I want to select table name for join from leads table and add "product_" prefix to it and use it in my query.
Thanks :)
You asked:
Is there any way to create a query to select table Name from Leads and
add the "product_" prefix to it and then join it to product table ?
The answer is no. In pure SQL, you can't make variables of table names and then use them in your queries. You can, of course, do this in your host php code. But you'll need to use one query to fetch the table names, and more queries to fetch the results from that table name.
You can also use Dynamic SQL. That's a MySQL feature allowing you to create the text of SQL queries dynamically in the MySQL server, and then run those queries.
It sounds to me like you're trying to store several classes of entities (life insurance, annuities, vehicle insurance, others) having widely differing attributes.
This presents you with some schema-design options.
Should you use different tables (as you are doing), showing the
entity (lead) class (life insurance) in a master table, and joining
the particular table you need?
Should you try to coerce all the attributes into a single entity,
leaving NULL or blank the attributes that are irrelevant for a
particular class of entity?
Should you use a key/value store for your entities, the way
WordPress's wp_postmeta table does?
Option 3 has a disadvantage if you do a lot of searching on attribute values: it requires your attributes to all be stored with the same data type. That data type is probably varchar(n). That means that it's hard to search on ranges of numeric attribute values. For example '10' is BETWEEN '1' AND '9' considered as text, but that's nonsense numerically. You can beat that problem using implicit typecasting, but that defeats the use of an index. That is,
0+meta_value BETWEEN 0 AND 9
forces the comparison to work numerically on the meta_value column. It works, but not fast. That being said, Option 3 is the most flexible by far; you can add new attributes without changing table definitions.
A combination of Option 2 and Option 3, putting the most commonly searched attribute values into your main lead table, will probably yield the most robust solution.
Option 1 -- your present solution -- is a performance nightmare waiting to attack you when you can least afford it: as your application is scaling up.
NOTE: if you are using the MariaDB fork of MySQL your key_value table can contain a persistent, indexed, virtual column. For example,
meta_key VARCHAR(255),
meta_value VARCHAR(255),
meta_value_int BIGINT(20) AS (0+meta_value) PERSISTENT,
meta_value_float FLOAT AS (CAST(meta_value AS DECIMAL(30,10))) PERSISTENT
You can then index those virtual (defined with AS) columns and search them fast. meta_value columns that don't start with numbers will have the value 0 in the virtual columns.

more efficient database structure across multiple tables

I am setting up a MySQL database with multiple tables. Several of the tables will have fields with similar names that aren't necessarily for the same purpose.
For example, there's a users table that will have a name field, a category table with a name field and so on.
I've previously seen this setup up either with or without a preface to the field name, so in the above example using user_name, cat_name etc.
As these are all in separate tables, is there any benefit to structuring the database with or without this preface? I know that when using joins and calling the data through PHP you have to add a SELECT users.name AS username... to keep the fields from overwriting each other when using mysql_fetch_array. But i'm not sure if there's any efficiencies in using one method over the other?
It depends on what your shop does or your preference. There is nothing about a prefix that will make this better. Personally I would just keep it as name since: Users.Name and Orders.Name and Products.Name all contain tuples with different object types.
At the end of the day you want to be consistent. If you prefer a cat_ and a user_ prefix just be consistent with your design and include this prefix for all object types. To me less is more.
It's really just a matter of preference. I personally prefer the approach of using just name.
One thing to watch out for though, if you're doing any SELECT * FROM ... queries (which you shouldn't be; always select fields explicitly), you may end up selecting the wrong data.
One disadvantage is if anyone is stupid enough to use natural joins (you can guess that I find this a poor practice but mysql does allow it so you need to consider if that will happen) you may end up joining on those fields with the same name by accident.

Fetching records from different tables in the database

My application has a facebook-like stream that displays updates of various types. So it will show regular posts (from the "posts" table), and events (from the "events" tables) table and so on.
The problem is I have no idea how to fetch these records from different tables since they have different columns. Shall I query the database multiple times and then organize the data in PHP? if so, how? I'm not sure how I should approach this.
Your help is much appreciated :)
Unless the events and post are related to each other, then you'd probably query them separately, even if they show up on the same page.
You're not going to want to use JOIN just for the sake of it. Only if there is a foreign key relationship. If you don't know what that is, then you don't have one.
If the data tables are related to each other you can generally get the data back in a single query using some combination of JOINs and UNIONs. For a better answer, however, you'll have to post the structure of your data tables and a sample of what (combined) records you need for the website.
If you don't know the columns, you can get the table meta-data and find out what the columns represent and their corresponding data types.
If you know which columns, you can select from the multiple tables or even use nested selects or joins to get the data out.
Ideally you'd simply use a JOIN to obtain data from multiple tables in one query. However, without knowing more about your table schemas it's hard to provide any useful specifics. (It most likely won't be possible unless you've factored this in from the beginning that said.)
As such, you might also want to create a generic "meta" table that provides information for each of the posts/events in a common format, and provides a means to link to the relevant table. (i.e.: It would contain the "parent" type and ID.) You could then use this meta table as the source for the "updates" stream and drill down to the approriate content as required.
Join the tables on user_id i.e.
Select * from posts p
left join status_updates su on p.user_id = su.user_id
limit 25;
or if your tables differ too much then play with a temporary table first
create table tmp_updates
(
select user_id, p.id as update_id, 'post' as update_type, p.text from posts;
);
insert into table tmp_updates
(
select user_id, su.id as update_id, 'status' as update_type, su.text from status_updates;
);
Select * from tmp_updates
where user_id = '...'
limit 25;

What is the best approach to list a user's recent activities in PHP/MySQL?

I want to list the recent activities of a user on my site without doing too many queries. I have a table where I list all the things the user did with the date.
page_id - reference_id - reference_table - created_at - updated_at
The reference_id is the ID I need to search for in the reference_table (example: comments). If I would do a SELECT on my activity table I would then have to query:
SELECT * FROM reference_table where id = reference_id LIMIT 1
An activity can be a comment, a page update or a subscription. Depending which one it is, I need to fetch different data from other tables in my database
For example if it is a comment, I need to fetch the author's name, the comment, if it is a reply I need to fetch the orignal comment username, etc.
I've looked into UNION keyword to union all my tables but I'm getting the error
1222 - The used SELECT statements have a different number of columns
and it seems rather complicated to make it work because the amount of columns has to match and none of my table has the same amount of tables and I'm not to fond of create column for the fun of it.
I've also looked into the CASE statement which also requires the amount of columns to match if I remember correctly (I could be wrong for this one though).
Does anyone has an idea of how I could list the recent activities of a user without doing too many queries?
I am using PHP and MySQL.
You probably want to split out the different activities into different tables. This will give you more flexiblity on how you query the data.
If you choose to use UNION, make sure that the you use the same number of columns in each select query that the UNION is comprised of.
EDIT:
I was down-voted for my response, so perhaps I can give a better explanation.
Split Table into Separate Tables and UNION
I recommended this technique, because it will allow you to be more explicit about the resources for which you are querying. Having a single table for inserting is convenient, but you will always have to do separate queries to join with other tables to get meaningful information. Also, you database schema will be obfuscated by a single column being a foreign key for different tables depending on the data stored in that row.
You could have tables for comment, update and subscription. These would have their own data which could be queried on individually. If, say, you wanted to look at ALL user activity, you could somewhat easily use a UNION as follows:
(SELECT 'comment', title, comment_id AS id, created FROM comment)
UNION
(SELECT 'update', title, update_id as id, created FROM update)
UNION
(SELECT 'subscription', title, subscription_id as id, created
FROM subscription)
ORDER BY created desc
This will provide you with a listing view. You could then link to the details of each type or load it on an ajax call.
You could accomplish this with the method that you are currently using, but this will actually eliminate the need for the 'reference_table' and will accomplish the same thing in a cleaner way (IMO).
The problem is that UNION should be used just to get similar recordsets together. If you try to unify two different queries (for example, with different columns being fetched) it's an error.
If the nature of the queries is different (having different column count, or data types) you'll need to make several different queries and treat them all separately.
Another approach (less elegant, I guess) would be LEFT JOINing your activities table with all the others, so you'll end up with a recordset with a lot of columns, and you'll need to check for each row which columns should be used depending on the activity nature.
Again, I'd rather stick with the first one, since the second procudes a rather sparse recorset.
With UNION you don't have to get all of the columns from each table, just as long as all of the columns have the same datatypes.
So you could do something like this:
SELECT name, comment as description
FROM Comments
UNION
SELECT name, reply as description
FROM Replies
And it wouldn't matter if Comments and Replies have the same number of columns.
This really depends on the amount of traffic on your site. The union approach is a straightforward and possibly the correct one, logically, but you'll suffer on the performance if your site is heavily loaded since the indexing of a UNIONed query is hard.
Joining might be good, but again, in terms of performance and code clarity, it's not the best of ways.
Another totally different approach is to create an 'activities' table, which will be updated with activity (in addition to the real activity, just for this purpose). In old terms of DB correctness, you should avoid this approach since it will create duplicate data on your system, I, however, found it very useful in terms of performance.
[Another side note about the UNION approach if you decide to take it: if you have difference in parameters length, you can SELECT bogus parameters on some of the unions, for example.. (SELECT UserId,UserName FROM users) UNION (SELECT 0,UserName from notes)

Categories