I am learning about SQL and using Mysql to work out the queries. On topic of Primary Key, I read that
Whichever column is declared as Primary Key, it can not be null.
So, I made a simple employee table with fields id and name with PRIMARY KEY as id;
And put in the following queries,
INSERT INTO employee (id, name) VALUES (1, 'John');
INSERT INTO employee (id, name) VALUES (2, 'Frank');
Now to test the primary key column not being Null property I put in the following query.
INSERT INTO employee(name) VALUES('Joe');
Turns out no error was shown and the query ran successfully
Upon selecting the records from the whole table I see
id |name
0 | Joe
1 | John
2 | Frank
I was expecting to see error something like
Column 'id' cannot be NULL
but as you can see, Primary Key for Joe was automatically set to 0.
I try inserting again it with not giving id
Now I get the message,
Duplicate entry for '0' for key 'PRIMARY'
So what happened here? And Doesn't Primary key begins from 1?
MySQL (before 5.7) uses an implicit default value of 0 for your primary key, see the documentation:
If the column cannot take NULL as the value, MySQL defines the column with no explicit DEFAULT clause. Exception: If the column is defined as part of a PRIMARY KEY but not explicitly as NOT NULL, MySQL creates it as a NOT NULL column (because PRIMARY KEY columns must be NOT NULL). Before MySQL 5.7.3, the column is also assigned a DEFAULT clause using the implicit default value. To prevent this, include an explicit NOT NULL in the definition of any PRIMARY KEY column.
If you insert null into such a column, the implicit value is taken, unless you set strict mode:
For data entry into a NOT NULL column that has no explicit DEFAULT clause [...]
If strict SQL mode is enabled, an error occurs for transactional tables and the statement is rolled back. For nontransactional tables, an error occurs, but if this happens for the second or subsequent row of a multiple-row statement, the preceding rows will have been inserted.
If strict mode is not enabled, MySQL sets the column to the implicit default value for the column data type.
The implicit default value for numeric types is 0. So every time you use null (or not use the column at all), MySQL uses 0. This works the first time, but not the second time.
You've set the AUTO_INCREMENT attribute on the id field. That's a nice little feature that ensures the value is always unique so you don't have to worry about it being null, and worry about stuff that matters. But if you try this, errors will surely be thrown at you;
INSERT INTO `employee` (`id`, `name`) VALUES (null, `Joe`);
EDIT Ah, I didn't really see the error you posted. What happened here; you did actually not set the AUTO_INCREMENT attribute (although you should have ;)). Now, the id field is an integer field. If you do not give any value, mysql tries to save your ass by giving it the most probable value, or most close to no value at all, which is 0. The first time all is well, the second time it sees the value is already present, and it fails.
Related
In my database, all Primary Keys are surogate. There are some Unique keys, but not always, so the most safe way to access specific row is Primary Key. Many of them use AUTO_INCREMENT. Do I have to lock access to database when inserting into two related table? For example.
create table foo
(
foo_id numeric not null auto_increment,
sth varchar,
PRIMARY KEY(foo_id)
)
create table bar
(
bar_id numeric not null auto_increment,
foo_id numeric not null,
PRIMARY KEY(bar_id),
FOREIGN KEY (foo_id) REFERENCES foo(foo_id)
)
First I insert sth to foo, and then I need foo_id value to insert related stuff into bar. This value I can get from INFORMATION_SCHEMA.TABLES. But what if somebody will add new row into foo before I get the auto_increment value? If all these steps are in stored procedure is there implicitly started transactions which locks all needed resources for one procedure call? Or maybe I have to use explicitly START TRANSACTION. What if I dont use procedure - just sequence of inserts and selects?
Instead of looking in INFORMATION_SCHEMA.TABLE, I would suggest that you use LAST_INSERT_ID.
From the MySQL documentation: The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client.
This imply that an insert done at the same time on a different connection will not change the value that is returned on your current connection.
Run queries in that sequence:
INSERT INTO foo (sth) VALUES ('TEST');
Than:
INSERT INTO bar (foo_id) VALUES (SELECT LAST_INSERT_ID());
I tried to add primary key in a table and set it as a column that has default value and is not null and is not unique.MySQL accepted that column as Primary Key...I want to know that this is wrong as if a user enters 2 records having default values he will not be able to do so..Is this a problem where SQL should have checked column as non default values or this is a designer end problem that default columns should not be made Primary Key...?
I'm not fully understanding the problem. You have declared a column to be a primary key that has these characteristics:
NOT NULL
Default value
A primary key imposes these characteristics:
NOT NULL
Unique
These characteristics are not mutually incompatible. The only issue is that the default value can only be assigned once in the column. The second time you try to insert a row with the default value, you will get a violation of the uniqueness constraint.
In other words, MySQL (and I think other databases as well) allow you declare this even if it doesn't seem like a good idea.
Null:
every column that is flagged wiht NULL is just specified that this column may contain a NULL value. The column can still have another default value.
Primary key:
A PK is always treated unique and you cannot have two identical values on a row
There can only be one PK per table, its the main index which is very fast when querying the table on its primary column.
A PK is always a single column and cannot be spread over multiple columns as every other index (unique or usual index) can do.
A PK column cannot accept NULL values
Sample:
ID (INT, PK) | Name (varchar)
1 | Foo ->Valid
2 | Bar ->Valid
2 | FooBar ->Invalid (Duplicate Primary key value ID)
Conclusion: Yes MySQL should and will throw an error at second attempt to put a default value because its simply treated UNIQUE and a given default value is const. The MySQL server will attempt to insert the default value when you dont specify any value for this column in your insert statement.
Pretty much means: A PrimaryKey column with a default value makes no sense, except you use an auto-increment which is a pseudo "default value" which is different each time you try to insert something.
I hope this answers your questions
This simple script:
create table test (a integer not null, b integer, c integer not null);
create unique index test1 on test (a, b, c);
insert into test values(1, null, 1);
insert into test values(1, null, 1);
select * from test;
runs successfully with MySQL and fails with ORA-0001 "unique constraint violated" with Oracle.
I am unsure what the standard says about unique index on multiple null columns but MySQL should probably behave similarly as Oracle.
See also http://lists.mysql.com/mysql/183630
Alexandre.
MySQL, by design, allows multiple NULL values in a column which has a UNIQUE index on it.
The BDB storage engine on MySQL was an exception, and it did not allow multiple NULL values in a coulmn, having UNIQUE index on it.
On the other hand, Oracle behaved differently with regards to NULL values. When you create a UNIQUE index on a single column in Oracle, it will allow you to have multiple NULL values, since NULL basically means an Unknown value, so two NULL values can't be compared to one another. More than that, NULL values are not stored in Index in case of Oracle. What this means is, when you create a UNIQUE index on multiple columns in Oracle, where two columns are NOT NULL and one column is NULLABLE, it will not allow you insert two records with same values, even though one column contains NULL.
Consider this:
CREATE TABLE test (a NUMBER NOT NULL,
b NUMBER,
c NUMBER NOT NULL
);
INSERT INTO test VALUES (1, NULL, 1);
1 rows inserted.
INSERT INTO test VALUES (1, NULL, 1);
SQL Error: ORA-00001: unique constraint (RQ4151.UQ_TEST) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
This happens, since Oracle is not storing NULL values in the index, and so tries to compare the NOT NULL column values for uniqueness in the index, which fails, causing the error to be flagged.
I've just checked and it's allowed to create a table with a column that is NULL by default, although it's a UNIQUE KEY at the same time:
CREATE TABLE IF NOT EXISTS `u789` (
`column1` varchar(10) DEFAULT NULL,
UNIQUE KEY (column1)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
As I understand, it looks odd and has not much sense. I expected the second insert of
INSERT INTO u789 VALUE (NULL);
will fail.
But, it inserts first, second, third NULL value without any problems. Who can explain me why it iserts second and third columns if NULL is already in the table?
This is a theoretical question (as I understand nobody uses DEFAULT NULL + UNIQUE KEY for the same column in most situations), but I want to understand why it doesn't throw an error once one NULL is already in the column. Am I doing something wrong with declaring a unique column?
Thank you.
According to the SQL 92 specification (and how you read it) unique constraints are meant to denote candidate keys and therefore should not allow duplicate values nor NULL values. DB2 implements their unique constraints in this manner. More than a few database vendors (including MySQL) read the specification as ignoring NULL values much like the Group By clause ignores NULL values and thus they implement unique constraints such that it only applies to non-NULL values. Still others, treat the NULL as its own special value and only allow one entry which is NULL. Microsoft SQL Server implements unique constraints this way. The only aspect that is consistent amongst all vendors with respect to unique constraints is that non-NULL values must be unique.
Because NULL is not equal to NULL. Even though some RDMS, SQLServer for instance, treat 2 NULLs as equal when it comes to unique constraints.
I have an email column that I want to be unique. But I also want it to accept null values. Can my database have 2 null emails that way?
Yes, MySQL allows multiple NULLs in a column with a unique constraint.
CREATE TABLE table1 (x INT NULL UNIQUE);
INSERT table1 VALUES (1);
INSERT table1 VALUES (1); -- Duplicate entry '1' for key 'x'
INSERT table1 VALUES (NULL);
INSERT table1 VALUES (NULL);
SELECT * FROM table1;
Result:
x
NULL
NULL
1
This is not true for all databases. SQL Server 2005 and older, for example, only allows a single NULL value in a column that has a unique constraint.
From the docs:
"a UNIQUE index permits multiple NULL
values for columns that can contain
NULL"
This applies to all engines but BDB.
I am unsure if the author originally was just asking whether or not this allows duplicate values or if there was an implied question here asking, "How to allow duplicate NULL values while using UNIQUE?" Or "How to only allow one UNIQUE NULL value?"
The question has already been answered, yes you can have duplicate NULL values while using the UNIQUE index.
Since I stumbled upon this answer while searching for "how to allow one UNIQUE NULL value." For anyone else who may stumble upon this question while doing the same, the rest of my answer is for you...
In MySQL you cannot have one UNIQUE NULL value, however you can have one UNIQUE empty value by inserting with the value of an empty string.
Warning: Numeric and types other than string may default to 0 or another default value.
A simple answer would be : No, it doesn't
Explanation : According to the definition of unique constraints (SQL-92)
A unique constraint is satisfied if and only if no two rows in a table have the same non-null values in the unique columns
This statement can have two interpretations as :
No two rows can have same values i.e. NULL and NULL is not allowed
No two non-null rows can have values i.e NULL and NULL is fine, but StackOverflow and StackOverflow is not allowed
Since MySQL follows second interpretation, multiple NULL values are allowed in UNIQUE constraint column. Second, if you would try to understand the concept of NULL in SQL, you will find that two NULL values can't be compared at all since NULL in SQL refers to unavailable or unassigned value (you can't compare nothing with nothing). Now, if you are not allowing multiple NULL values in UNIQUE constraint column, you are contracting the meaning of NULL in SQL. I would summarise my answer by saying :
MySQL supports UNIQUE constraint but not on the cost of ignoring NULL
values
Avoid nullable unique constraints. You can always put the column in a new table, make it non-null and unique and then populate that table only when you have a value for it. This ensures that any key dependency on the column can be correctly enforced and avoids any problems that could be caused by nulls.