Disclaimer: I have only novice knowledge of and experience with databases.
I'm following a Laravel course on Laracasts, and in the database video, the instructor sets the ID column to a type of SERIAL. This is different to how I've seen this done in all other database tutorials, where they will usually check the A_I (auto-increment) checkbox, and this automatically makes the column primary, and leaves the type to be something like INT.
Hovering over the SERIAL type in PHPMyAdmin tells me that it's an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, but is there ever a particular reason to prefer it over the settings that checking the A_I checkbox sets up? Does either way offer any advantages or disadvantages?
I did find this for PostgreSQL, indicating SERIAL is old and outdated, but I couldn't find an equivalent for MySQL and I'm unsure if the same applies to it.
I'm sure MySQL's SERIAL type was implemented to make it easy for folks who were accustomed to PostgreSQL to have one set of CREATE TABLE statements that would work on both brands of database, and do more or less the same thing.
In an old version of the MySQL manual, it was stated that SERIAL is a compatibility feature (without naming the brand it was intended to be compatible with). The language about compatibility was removed (see https://bugs.mysql.com/bug.php?id=7978).
Now that even PostgreSQL has changed its recommended practice and they use IDENTITY columns instead of SERIAL, the MySQL feature is really unnecessary.
There is no advantage to using SERIAL in MySQL. On the contrary, if you do use it in a CREATE TABLE statement, you will see that the syntax isn't saved. It is just an alias for the BIGINT UNSIGNED AUTO_INCREMENT UNIQUE, as documented.
I find that it's actually wasteful to do this, because I typically declare the auto-increment column as a PRIMARY KEY anyway, and this makes the UNIQUE redundant. So you end up with two unique indexes for no reason.
mysql> create table mytable (id serial primary key);
mysql> show create table mytable\G
*************************** 1. row ***************************
Table: mytable
Create Table: CREATE TABLE `mytable` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`) -- this one is superfluous
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
P.S. This question is almost but not quite a duplicate of What is the difference between SERIAL and AUTO_INCREMENT in mysql
Related
Why does phpMyAdmin give me this warning , and lack of function, when selecting from a table named only in lowercase (and underscores) that does have a (single column) primary key? I checked these elements after seeing this
Specifically my query is
SELECT su.* FROM `r8u2d_comps_testsubitem` su
JOIN `r8u2d_comps_testitem` ti ON ti.id=su.testitemid
JOIN `r8u2d_comps_test` t ON ti.testid=t.id
WHERE t.id=241
ORDER BY ti.ordering
The table aliased as "su" has a column "id" (int(11), autoincrement) and a primary key using only this field. It looks to me like this query avoids all the restrictions listed in this answer, so what's the problem? Is it phpMyAdmin (my hosting company has 4.7.9, but I get the same problem locally with 5.0.4) or MySQL (host has 5.7.29-0ubuntu0.16.04.1 - (Ubuntu), I have 10.4.17-MariaDB - MariaDB Server, not strictly comparable I suppose).
Table structure
`id` INT NOT NULL AUTO_INCREMENT,
`testitemid` INT NOT NULL
`marker` CHAR(20) NULL
`text` TEXT NOT NULL,
`ordering` TINYINT NOT NULL,
PRIMARY KEY (`id`),
KEY `testitemid` (`testitemid`),
KEY `ordering` (`ordering`),
CONSTRAINT `subelementToElement`
FOREIGN KEY (`testitemid`) REFERENCES `#__comps_testitem`(`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION
phpMyAdmin makes an effort to work with a primary/unique key for the purposes of enabling grid editing, but that detection logic doesn't hold up very well when using with multiple JOIN statements. It gets difficult for the phpMyAdmin parser to work backwards through some queries and determine which columns come from which tables and whether there's a primary key that could be used for editing the data. I suppose the warning message could better be written as something like "This table or query does not contain a unique column, or your query is a join that obfuscates the original table structure enough that we don't want to risk damaging your data."
Unfortunately, aside from someone rewriting this part of phpMyAdmin, the best solution I can recommend right now is to find the data you want to modify through your JOIN query then open that individual table and scroll through the Browse view to (or use Search to find) the row you wish to modify from the table directly.
Is there any reason to use id int auto-increment for a primary key while a UNIQUE column (that is not a foreign key or anything) already exists in a table?
I'm reading someone else's thesis about a project that uses freebase data.
Every topic in freebase is uniquely identified by an mid. (example: m.gugkl395).
But instead of using mid as the primary key in the topics table he chose to use an id (int auto-increment). So the topics table looks like this
CREATE TABLE topics (
id INT NOT NULL AUTO-INCREMENT,
mid VARCHAR(254) NOT NULL UNIQUE,
name VARCHAR(254) NOT NULL,
description VARCHAR(2048),
type VARCHAR(254) NOT NULL,
PRIMARY KEY (id)
);
I should mention that there are 3 other tables that use this id as a foreign key and that because it has to do with freebase there will probably be a lot of data in the database. Also in case it matters MySQL version 5.7.15 is being used.
Theoretically,IMHO after 26+ years from dbaseIII+, if you have a Unique key, you can use it, auto increment field just simplify the things if you are not sure about uniqueness.
Practically, Regarding actual programming and performance of the database, you need to add multiple lines of code to create the primary key value and some times require connections to the server to get the last value of the key before the new one, these plus the space used by varchar in the design of the tables may affect the performance of the solution and take more time in programming.
I hope this may help.
The m.gugkl395 is the RDF encoding of MID which looks like /m/gugkl395 in its native form, but the prefix is constant and the gugkl395 is a radix 32(?) encoding of an integer. The most space efficient and performant schema would be to just store that integer.
The MID encoding is described in an earlier answer of mine here: https://stackoverflow.com/a/56012791/167425
I have a server running an old MySQL version (5.5.41) where the following was supported:
create table mytest33
(
topicnum mediumint,
postnum mediumint auto_increment,
primary key (topicnum,postnum)
);
So when I insert values into this table, it would go like this:
Topicnum Postnum
1 1
1 2
2 1
And so forth. So the postnum value would go back to 1, if the topicnum was different.
This is no longer supported - when I try creating the same table in MySQL version 5.6.17 I get an error:
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key.
I'm using the MyISAM engine.
How do I get around this?
According to what i could understand ,here is the command that you need to execute:-
create table mytest33(topicnum mediumint, postnum mediumint auto_increment,index(postnum), primary key (topicnum,postnum));
You can get more information from here:-
Mysql Innodb: Autoincrement non-Primary Key.
Hope it helps.
Have a good day!
The MyISAM Engine has that as a feature, and it is still supported. InnoDB has never had the feature. You switched to InnoDB (which is a good thing), but got bitten by one of the few 'deficiencies'.
The link in the previous answer points out that INDEX(id) lets you have postnum be AUTO_INCREMENT and UNIQUE (unless you explicitly set it). However, it won't start over at 1. That is more complex; see my blog.
So this seems to solve the problem:
create table mytest33(
topicnum mediumint,
postnum mediumint auto_increment,
primary key (topicnum,postnum)
) ENGINE=MyISAM;
Let's say we have a (InnoDB) table associations in a MySQL-Database which has the following structure:
CREATE TABLE `associations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fk_id_1` int(11) NOT NULL,
`fk_id_2` int(11) NOT NULL,
`fk_id_3` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `some_unique_constraint` (`fk_id_1`,`fk_id_2`),
KEY `fk_id_2_INDEX` (`fk_id_2`),
KEY `fk_id_3_INDEX` (`fk_id_3`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin$$
There are jumps in the column id (I know this is an issue of how the autoincremented value is generated while multiple threads try to get one). Since no other table is using the column id as a reference I plan to drop the column id and to create it again, hopefully the counting holes will be gone. I backed up my database and tested that. The result was a little confusing. The order of the rows seemed to have changed. If I am not mistaken the order is first by fk_id_1 then fk_id_2 then fk_id_3.
Is this the natural order in which MySQL sets the table, when assignung an new generated autoincrement key to the rows?
Is there more I should know, that happened during this process?
The reason, why I need to know about this is that I need to make the column id useful for another task I intend to accomplish where gaps are a no go.
There is no natural order to a table in any mainstream RDBS.
Only the outermost ORDER BY in a SELECT statement will guarantee the order of results.
If you want "order":
create a new table
INSERT..SELECT..ORDER BY fk_id_1, fk_id_2, fk_id_3
Drop old table
Rename new table
Or live with gaps... OCD isn't good for developers
Edit:
Question says "no dependency" on this value but turns out there is.
If gaps are not allowed then don't use autonumber and use fk_id_1, fk_id_2, fk_id_3 as your key, with a ROW_NUMBER emulation. Or code your downstream to deal with gaps.
Autonumbers will have gaps: immutable fact of life.
I want to make a table in SqlServer that will add, on insert, a auto incremented primary key. This should be an autoincremented id similar to MySql auto_increment functionality. (Below)
create table foo
(
user_id int not null auto_increment,
name varchar(50)
)
Is there a way of doing this with out creating an insert trigger?
Like this
create table foo
(
user_id int not null identity,
name varchar(50)
)
OP requested an auto incremented primary key. The IDENTITY keyword does not, by itself, make a column be the primary key.
CREATE TABLE user
(
TheKey int IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
)
They have answered your question but I want to add one bit of advice for someone new to using identity columns. There are times when you have to return the value of the identity just inserted so that you can insert into a related table. Many sources will tell you to use ##identity to get this value. Under no circumstances should you ever use ##identity if you want to mantain data integrity. It will give the identity created in a trigger if one of them is added to insert to another table. Since you cannot guarantee the value of ##identity will always be correct, it is best to never use ##identity. Use scope_identity() to get this value instead. I know this is slightly off topic, but it is important to your understanding of how to use identity with SQL Server. And trust me, you did not want to be fixing a problem of the related records having the wrong identity value fed to them. This is something that can quietly go wrong for months before it is dicovered and is almost impossible to fix the data afterward.
As others have mentioned: add the IDENTITY attribute to the column, and make it a primary key.
There are, however, differences between MSSQL's IDENTITY and MySQL's AUTO_INCREMENT:
MySQL requires that a unique
constraint (often in the form of a
primary key) be defined for the
AUTO_INCREMENT column.MSSQL doesn't have such a requirement.
MySQL lets you manually insert values into an AUTO_INCREMENT column.
MSSQL prevents you from manually inserting a value into an IDENTITY
column; if needed, you can override
this by issuing a "SET
IDENTITY_INSERT tablename ON"
command before the insert.
MySQL allows you to update values in an AUTO_INCREMENT column.MSSQL refuses to update values in an
IDENTITY column.
Just set the field as an identity field.
declare the field to be identity
As advised above, use an IDENTITY field.
CREATE TABLE foo
(
user_id int IDENTITY(1,1) NOT NULL,
name varchar(50)
)
As others have said, just set the Identity option.