PRIMARY KEY definition in MySQL CREATE TABLE statement - mysql

What's the difference between this code:
CREATE TABLE samples (
sampleid INT(11) NOT NULL AUTO_INCREMENT,
sampledate DATE NOT NULL,
location VARCHAR(25) NOT NULL,
PRIMARY KEY (sampleid)
)
ENGINE=InnoDB;
and this:
CREATE TABLE samples (
sampleid INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
sampledate DATE NOT NULL,
location VARCHAR(25) NOT NULL,
)
ENGINE=InnoDB;
code?
So a separate PRIMARY KEY statement or as part of a column definition. Same question for UNIQUE INDEX and UNIQUE keyword in column definition.

The second syntax is merely a shortcut allowing you to specify the column and add an index on it in a single clause.
This works out fine in cases where you simply want to create a column and add an index on it.
You'll need to use the first syntax if you want to do something more complicated, such as adding an index based on multiple columns rather than a single column, or if you are adding or changing an index on an existing column; that is, you are not creating the column and the index on it at the same time.

MySQL allows uses the PRIMARY KEY directive to allow you to set the Primary Key dynamically. Supplying PRIMARY KEY as an argument to the constructor can only be called on creating the column. PRIMARY KEY(X), PRIMARY KEY(Y), PRIMARY KEY(Z) allows for changing the primary keys on subsequent queries.

The way I see it is.. The first method is used to create composite keys. While the second method (more readable to me) is primarily used if there is only primary key in the table.
The second method cannot be used if you want to implement composite key

There are many ways to skin a cat and above 2 examples are just 2 of them. They are identical. There's no difference.

They are literally the same. Here is a quick site that shows you the different ways (3) to do it. http://www.java2s.com/Code/SQL/Key/Defineanduseprimarykey.htm

Related

Is it good practice to add primary keys to a tables during the alter statement, or it makes no deference to add them when I cam creating the table

I created/defined an admin table, now I have seen other programmers alter the table and add keys to the tables
CREATE TABLE `admin` (
`admin_id` int(11) NOT NULL AUTO_INCREMENT,
`admin_name` varchar(255) NOT NULL,
`admin_surname` varchar(255) NOT NULL,
`phone` CHAR(10) NOT NULL,
`admin_email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `admin`
ADD PRIMARY KEY (`admin_id`),
ADD UNIQUE KEY `admin_email` (`admin_email`);
If I have already defined the table why should I alter the definition again here?
In InnoDB there exists clustered index always.
When primary key exists in a table then it is used as clustered index.
When no primary key but unique index(es) which's expression does not innclude NULLable columns exists then the most upper unique index from them in the table definition is clustered.
When no such unique index then inner hidden row number is used as an expression for clustered index.
Hence, if you create a table (and some expression is used for clustered index) and then use ALTER TABLE for to add primary key then the table must be rebuilt. It doesn't matter when the table is empty, but when there is data in it the process may be long enough (because COPY method is used).
If you create primary key as a part of CREATE TABLE then this is always fast.
I like to put all the index definitions inside the CREATE TABLE, and put them at the end instead of sitting on the column definitions.
Potential problem 1:
But I notice that some dump utilities like to add the indexes later. This may be a kludge to handle FOREIGN KEY definitions. Those have trouble if the tables are not created in just the right order.
It would seem better to simply ADD FOREIGN KEY... after all the tables are created and indexed.
Potential problem 2:
If you will be inserting a huge number of rows, it is usually more efficient to make the secondary keys after loading the data. This is more efficient than augmenting the indexes as it goes. For small tables (under, say, a million rows), this is not a big deal.
I do not understand why they ADD PRIMARY KEY after loading the data. That requires (as Akina points out) tossing the fabricated PK, sorting the data, and adding the real PK. That seems like extra work, even for a huge table.
If the rows are sorted in PK order, the loading is more efficient. The table is ordered by the PK (for InnoDB); inserting in that order is faster than jumping around. (mysqldump will necessarily provide them in PK order, so it is usually a non-issue.)

external GUID to satisfy unique constraint in mysql

I have a MYSQL 8.x table, each row is unique since the PK is auto incremented. A column transactionID is used to store an external transactionID that needs to be coupled with the row/record.
However a new requirement came and we want to create a new row with the same transactionID. I was thinking to add a new column that holds the GUID of the transaction.
Is this good idea? Is this going to be slow? Are there any second thougths regarding uuid as strings? MySQL 8.0 added UUID_TO_BIN and BIN_TO_UUID function that could store UUID as number.
CREATE TABLE `testme`.`new_table` (
`ID` INT NOT NULL AUTO_INCREMENT,
`transactionID` INT NOT NULL,
`maybe_uuid` VARCHAR(45) NOT NULL,
PRIMARY KEY (`ID`));
ALTER TABLE `testme`.`new_table`
ADD UNIQUE INDEX `index2` (`transactionID` ASC, `maybe_uuid` ASC) VISIBLE;
;
GUIDs are not great for use as a primary key for many reasons that i will not detail here and it would faster to use you auto_increment key that is already in place. But if you also need to store the GUID it is perfectly reasonable to just add another column for that. And you can use the two functions you mentioned.

do we have to explicitly mention the not null constraint for a primary key?

Do we have to explicitly mention that a primary key shouldn't be null, when creating a table? Even if we don't mention the 'not null' constraint for the primary key, SQL wouldn't allow us to insert a NULL value into the primary key field. therefore which of the following is a good practice?
1) create table registration(
id int primary key,
name varchar(10)
)
2) create table registration(
id int primary key not null,
name varchar(10)
)
No you don't.
A PRIMARY KEY is a unique index where all key columns must be defined
as NOT NULL. If they are not explicitly declared as NOT NULL, MySQL
declares them so implicitly (and silently). A table can have only one
PRIMARY KEY. The name of a PRIMARY KEY is always PRIMARY, which thus
cannot be used as the name for any other kind of index.
I'd however consider it good practice to state it explicitly - as that makes things more clear,
and you don't have to look it up this rule every time you're in doubt.
Ask yourself, for the sake of it, why would you not if it makes something, not necessarily less clear without it, but more explicitly clear? Following this, I see no reason to omit it and perfectly valid reasons to emit it in the script.
The best practice is generally the most sensible one.

mysql - referencing one foreign key to multiple possible primary keys

I'd like to set up the following database scenario:
CREATE TABLE IF NOT EXISTS `points` (
`po_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`po_north` INT,
`po_east` INT,
PRIMARY KEY (`po_id`),
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `lines`(
`li_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`li_from` INT NOT NULL,
`li_to` INT NOT NULL,
PRIMARY KEY (`li_id`),
FOREIGN KEY (`li_from`) REFERENCES points(`po_id`),
FOREIGN KEY (`li_to`) REFERENCES points(`po_id`),
) ENGINE=InnoDB;
Now I want to set up a third table, that sores some metadata like who created or altered a point or a line:
CREATE TABLE IF NOT EXISTS `metadata` (
`me_type` ENUM('point','line') NOT NULL,
`me_type_id` INT UNSIGNED NOT NULL,
`me_permissions` VARCHAR(255) NOT NULL,
`me_created_by` INT UNSIGNED NOT NULL,
`me_created_on` DATETIME NOT NULL,
`me_last_modified_by` INT UNSIGNED NOT NULL,
`me_last_modified_by` DATETIME NOT NULL,
) ENGINE=InnoDB;
My first approach was to set an ENUM with two types (points and lines). But the problem is still, that I cannot properly reference a foreign key to one of the tables. Is there any recommended solution for such problem in MySQL?
BTW:
The fields for me_created_by and me_last_modified_by shall reference to a table storing some user data.
Your case appears to be yet another instance of the design pattern known as "generalization specialization" or perhaps "table design for class inheritance".
If you think of points and lines as classes of objects, they are both subclasses of some more general class of objects. I'm not sure what name to give the superclass in this case. Here's one of several previous questions that address the same issue.
Extending classes in the database
Fowler gives an extensive treatment of the subject. Your case has an added wrinkle, because you are dealing with metadata. But that need not alter the design. You need a third table, which I'll call "Items" for lack of a better term. The key, "it_id" would be assigned an auto number, and you would add an item every time you add either a point or a line. The two columns "po_id" and "li_id" would not be assigned an auto number. Instead they would be foreign keys, referencing "it_id" in the Items table.
The references to points or lines in the metadata table would then be references to "items" and you could use that information to find information about points or lines as the case may be.
How helpful this is depends on what you are trying to do with the metadata.
Your tables points and lines should contain a foreign key to metadata – not the other way around. Doing so will save you from defining any more complicated table setups. Using this approach, a single metadata-entry could be re-used several times for many different points or lines. This isn't even MySQL specific but a general, normalized database structure.
you can do this using a trigger, you need to trigger an event that can create reference key for either point or line before you insert a record based on respective tables

Add another primary key to table in mysql

I want to add another primary key to a table in mysql.
I use phpmyadmin to communicate with mysql server.
When I click the primary icon for the desired field it gives me this error:
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
Edited:
here's the query:
ALTER TABLE `files` DROP PRIMARY KEY ,ADD PRIMARY KEY ( `file_type` )
How can I do it?
As the name "primary" key says, there may be only one of that (ref: Highlander).
What you might want to try is a UNIQUE KEY, that acts just like a primary for most purpouses. Auto_increment doesn't seem to fulfill any purpouse if used a second time - what'ts the point of two fields carrying exactly the same information?
I believe in your case, what you need is a composite key. I do not know your table structure, but here is a general example taken from here,
CREATE TABLE track(
album CHAR(10),
disk INTEGER,
posn INTEGER,
song VARCHAR(255),
PRIMARY KEY (album, disk, posn)
)
In this case, there is a combination of 3 columns which avoid the duplicate records as you require. Please let me know if I have any mistakes in understanding your scenario.
The error message says it, I think:
the auto_increment column must be key.
So use this query first:
ALTER TABLE 'files' CHANGE 'id' 'id' INT( 10 ) UNSIGNED NOT NULL;
this will remove the auto_increment.
Also, I recommend the Uniqe key as suggested by other answer. I believe there should always (almost) be an Id column in each table.
We can Give Primary Key only once for a table. You can prefer UNIQUE KEY to prevent duplicate records
ALTER TABLE Persons
ADD UNIQUE (P_Id)
You can mark all the fields you want as primary keys, including the existing one. The system internally will drop the existing one and will set all you marked.