How to create an primary key in phpmyadmin? - mysql

I have two tables, the first one is called BOOKSNAME and the second is called AUTHORNAME.
I have made the ID column for the BOOKSNAME table as the primary key (BIGINT auto increment) then my AUTHORNAME table has NAME and ADDRESS as it's columns but I have no ID/Primary key on this.
I want to make a relation between them by primary key, if anyone has an example of how this is achieved, could they share it?

What you need to do is add a new column to your AUTHORNAME table called AuthorID or something similar, you can select 'Primary' on a drop down list under the INDEX when adding a new column to your table, and you also want to tick the A_I box (auto increment).
If you are unsure how to add a new column, follow these steps:
Firstly go to your phpmyadmin, and select the table in which you need to add this new column/ primary key to, and select the structure tab.
Here you will see the current column headings that your table already has, so from here you want to look towards the bottom of that list of columns where it will display options on how to add a new column to your table.
Ideally, you want to add the ID at the beginning of the table, as it will make it look far more structured and easier to read.
From here you want to enter the name of the column, in your case AuthorID, the type will be an INT, and you will want to make your index as PRIMARY, then lastly you will need to tick the A_I / Auto increment box (This may appear differently depending on what version of phpmyadmin you are running).
If you then want to make relations between the two tables, you can use something called JOINS, if you do a simple Google search, you can find many guides on how these are carried out.

Also add integer primary key to the author table, next you can have author_id field to another table, which is same datatype as authors table primary key, and store author id to that field.
Also if you use Innodb engine you can add foreign key constraint, it is very useful, for more see documentation: http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

Related

Modify database table best practices

As my title states, I'm curious about the best practices for modifying an existing table in a (mysql) database. In my scenario, I have a table that is already full of data and has a column named product_id that is currently the primary key for the table. I'm working on a feature where I'm finding product_id doesn't necessarily need to be unique or the primary key, since I want to allow multiple records for the same product. Database design isn't a strength of mine yet, but in my head I feel like what I would want to do is run the command DROP PRIMARY KEY for the product_id column, then add a column called id and making this the new primary key. Then I would need to update the id column for each record with a unique id for it to be a valid primary key. As far as database design is concerned, is this the best practice for doing this or is it better to create a new table with the updated structure and copying the current records into the new table?
EDIT:
More about the feature I'm working on. The products are books and I'm trying to allow multiple sections of these books to be previewed. In order to do this, I'm storing page ranges that can be previewed. Right now, only one page range is allowed, which is why the product id doesn't need to be unique anymore.
A primary key is ALWAYS unique.
Why do you don't want it to be unique? It sounds like you are exposing the key outside the database, that the PK is visible somehow and some user(s) think it should behave differently. If this is the case then this is a really bad practice.
This is the typical case of the notorious "natural keys". They are a disaster waiting to happen; I don't like big time bombs. I've been strongly opposed to them for some time now. It's good they teach them in schools so you know what not to use in the real world.
Now for the solution. If product_id is exposed, then it shouldn't be the PK at all. Solution?
Create a new column (id maybe?) that is internal, that is unique, and not exposed to the user, while keeping product_id. This new column could have the exact same value as product_id at first.
Change all FK references from other tables to the new id column.
Then, remove the PK constraint from product_id and do whatever you want to do with it.
Add the PK contraint to the new id column.

Is it possible to have a foreign key that is NOT NULL pointing to no row in MySQL database?

I have a table storing comments on a service, the table looks like something like this:
Comment table
---------------------------
comment_id (auto-increment integer, primary key)
comment (string)
email (string)
Now, a member system is added to the system, a table storing the member information that looks something like this:
Member table
---------------------
member_id (auto-increment integer, primary key)
.... some other member info .....
email (string, unique)
A member can leave multiple comment, while one comment can only be left by one member, or it can be left by a non-member (i.e. email not exist in member table). I know I can handle it by opening a new table (member_comment_pair), but I am curious if there is a way I can set up a foreign key on email in comment table, such that it allows email that may not be able to find a match in member table?
NOTE: I am using MySQL, but in case it is not possible in MySQL but allowed in other type of DB system, I would also like to know.
No self respecting database system will allow such a thing, since it defeats the entire purpose of having foreign keys.
You see, a foreign key is the database way to ensure relational integrity.
A short explanation would be that data in the referencing column can't exists if it doesn't exists in the referenced column.
Once you allow a loop hole like you are describing you might as well throw the foreign key out the window.
I've seem some strange things that MySql allows (Like it's strange group by behavior) but if it will allow a broken foreign key to exists it should not be called a relational database.
Having said that, You can choose one of at least 3 possible solutions:
Create a dummy record in the Member table that "orphan" records in the Comment table would be linked to it.
Allow null values in the Comment table's email column.
Remove the foreign key completely.
I would choose (and have done before when needed) solution number one. Create a record in the Member table (have it's display name as "guest" or whatever) and link all the orphan comments to it.

Finding the right primary key

I have decided to set combination of three values as a primary key(composite key) for my database table.Most of the times the first two columns will be unique.But in a few cases they are both same at which time the third columns value will be always unique for that row.The problem is that the third column is a description which is any string that the user can enter.I know it is not recommended to have a user given string as a primary key.But is it okay to have it as a part of the composite key.I really see no other option.
If at all possible, you should add a surrogate primary key, meaning a key that is unique and has no business meaning whatsoever.
Composite primary keys very often turn out to be less 'stable' than anticipated - but if you MUST use one, using one or more component columns over which the user has little or no control (like created_timestamp) would be preferable.
Add a separate column called id and make it auto increment and use this column as a primary key.
Hope this will solve your problem.
Cheers.

Does MySQL require a primary key for a many-to-many link table?

Note to Mod: I read through about a dozen posts that seemed to pertain to this issue, but none of them answered my question. Please do not flag this post for deletion; this is not a duplicate question.
I am building a database for a web-gallery that will contain many-to-many relationships. For example, tags and images. Obviously, to accomplish this a third, link, table will be created. I can see a use for having a primary key column in the tags table and the images table, but I can't imagine a use for it in the links table. It would just take up server space. So, I'm thinking of just not having a primary key column in the links table. Does MySQL allow this? Or, would there be any compelling reason to have a primary key in the links table? Thanks.
Link Table:
+--------------+---------+-----------+
| primary key? | tag ids | image ids |
+--------------+---------+-----------+
Clarification
Will not having a primary key in a table break the database?
There is no requirement that you have a primary key.
However, there is also no requirement that a primary key be only one field. In this case you might declare your primary key to be (tag_id, image_id).
You've got a question in reply to another post that gives me the idea that maybe you're thinking you should concatenate the two fields to make the primary key. Don't. Define the key as
alter table link add primary key (tag_id, image_id);
Do NOT say
alter table link add primary key (tag_id + image_id);
(I think "+" is the concatenation operator in MySQL. It's been a while. The SQL standard is "&" but MySQL uses that for something else.)
There's a big difference between the two, namely, in the first case, 25,34 and 253,4 are two different values, while in the second case they both get turned into 2534.
Will you always go from tag to image, or will you also want to go from image to tag? If you need to go in both directions, then you should create two indexes, or a primary key and an index, with the fields in both directions. Like:
create index link_tag_image on link(tag_id, image_id);
create index link_image_tag on link(image_id, tag_id);
If you make only the first (for example), then consider this query:
select tag.name
from image
join link on image.image_id=link.imagae_id
join tag on tag.tag_id=link.tag_id
where image.foo='bar'
This seems plausbile enough: find all the tags that match images that meet a certain condition. But without the second index, this query could take a very long time, because the db will have to read the entire link table sequentially to find all the records with a given image_id.
There is no need for primary key in the link table. Although a compound key is a good idea. Uniqueness can be achieved by using UNIQUE ( tag_ids, image_ids)
Yes, your primary key should be a compound/composite key of tag_id and image_id, i.e. PRIMARY KEY (tag_id, image_id). There's no need for an extra autoincrement column in this case.
When working with MySQL Workbench it's highly advisable because without a primary key it won't allow any access to your tables other than read only, which is a pain when trying to test your database. Although it does seem wasteful to have a PK that is never going to be referenced in a relationship.

Deal with table that's composite primary key I wanted to include a nullable column

Assume a table that may look like this:
userId INT (foreign key to a users table)
profileId INT (foreign key to a profiles table)
value INT
Say that in this table preferences for users are saved. The preference should be loaded according to the current user and the profile that the current user has selected. That means that the combination of userId and profileId is unique and can be used as a composite primary key.
But then I want to add the ability to also save a default value that should be used if no value for a specific profileId is save in the database. My first idea would be to set the profileId column to nullable and say that the row that has null as profileId contains the default value. But then I can't use a composite primary key that involves this table, because nullable columns can't be part of a primary key.
So what's the "best" way to work around this? Just drop the primary key completely and go without primary key? Generate an identity column as primary key that I never need? Create a dummy profile to link to in the profile table? Create a separate table for default values (which is the only option that guarantees that no userId has multiple default values??)?
Update: I thought about Dmitry's answer but after all it has the drawback that I can't even create a unique constraint on the two columns userId and profileId (MySQL will allow duplicate values if profileId is null and DB2 will refuse to even create a unique constraint on a nullable column). So with Dmitry's solution I will have to live without this consistency check of the DB. Is that acceptable? Or is that not acceptable (after all consistency checks are a major feature of relational DBs). What is your reasoning?
Create ID autoincrement field for your primary key.
AND
Create unique index for (userId, profileId) pair. If necessary create dummy profile instead of null.
Dmitry's answer is a good one, but since your case involves what is essentially an intersection table, there is another good way to solve this. For your situation I also like the idea of creating a default user profile that you can use in your code to establish default settings. This is good because it keeps your data model clean without introducing extra candidate keys. You would need to be clear in this dummy/default profile that this is what it is. You can give it a clear name like "Default User" and make sure that nobody but the administrator has access to the user credentials.
One other advantage of this solution is that you can sign on as the default user and use your system's GUI to modify the defaults rather than having to fiddle with the data through DB access tools. Depending on the policies in your shop, direct access to the data tables by programmers may be hard or impossible. Using the tested/approved GUIs for modifying defaults removes a lot of red tape and prevents some kinds of accidental damage to the data.
Bottom Line: Primary keys are important. In a transactional system every table should have a at least one unique index one of which should be the primary key. You can always enforce this by adding a surrogate (auto increment) key to every table. Even if you do, you still generally want a natural unique index whenever possible. This is how you will generally find what you're looking for in a table.
Creating a Default User entry in your user table isn't a cheat or a hack, it's using your table structure the way it's meant to be used and it allows you to put a usable unique contraint on the combination of user ID and profile ID, regardless of whether you invent an additional, arbitrary unique constraint with a surrogate key.
This is the normal behaviour of UNIQUE constrain on a NULL column. It allows one row of data with NULL values. However, that is not the behaviour we want for this column. We want the column to accept unique values and also accept multiple NULL values.
This can be achieved using a computed column and adding a contraint to the computed column instead default null value.
Refer below article will help you more in this matter:
UNIQUE Column with multiple NULL values
I always always always use a primary auto_increment key on a table, even if its redundant; it just gives me a fantastically simple way to identify a record I want to access later or refer to elsewhere. I know it doesn't directly answer your question, but it does make the primary key situation simpler.
create table UserProfile ( int UserProfileID auto_increment primary key etc.,
UserID int not null, ProfileID int );
Then create a secondary index UserProfileIDX(UserID, ProfileID) that's unique, but not the primary key.