EMPTY TABLE Duplicate entry '1' for key 'PRIMARY' - mysql

I have a strange problem with my MariaDB database. I create an empty table with the following code:
drop table if exists Subject;
CREATE TABLE Subject (
id integer primary key auto_increment,
code varchar(100) unique not null,
name text not null
);
Query executed OK, 0 rows affected.
I try to insert some data into the table:
INSERT INTO Subject (id, code, name) VALUES
(0,'KMI/AIdb/PHW/15','Počítačový hardvér'),
(1,'KMI/AIdb/DBA/15','Tvorba databázových aplikácií'),
(2,'KMI/SPRVdb/INF/16','Informatika a základy správy databáz'),
(3,'KMI/AIdb/PR4/15','Programovanie 4 - Objektové programovanie'),
(4,'KMI/AIdb/DBS/15','Databázové informačné systémy');
Error in query (1062): Duplicate entry '1' for key 'PRIMARY'
If I run the same query one more time:
INSERT INTO Subject (id, code, name) VALUES
(0,'KMI/AIdb/PHW/15','Počítačový hardvér'),
(1,'KMI/AIdb/DBA/15','Tvorba databázových aplikácií'),
(2,'KMI/SPRVdb/INF/16','Informatika a základy správy databáz'),
(3,'KMI/AIdb/PR4/15','Programovanie 4 - Objektové programovanie'),
(4,'KMI/AIdb/DBS/15','Databázové informačné systémy');
Query executed OK, 5 rows affected.
I believe it has something to do with the auto_increment, but I have a huge database dump that I would like to insert. Is this a bug, or is this an expected behavior?

AUTO_INCREMENT attribute can be used to generate a unique identity for new rows.
You can also explicitly assign 0 to the column to generate sequence numbers unless the NO_AUTO_VALUE_ON_ZERO SQL mode is enabled.
Read here for more details

The first insert created id=1. This is because "0" (or NULL) is treated specially to mean "give me the next id". Then the second row tried to explicitly insert id=1 and got a "duplicate".
Did your dump include a row with id=0, as you imply in a Comment. That sounds wrong.

Using id autoincrement don't insert id
INSERT INTO Subject (code, name) VALUES
('KMI/AIdb/PHW/15','Počítačový hardvér'),
('KMI/AIdb/DBA/15','Tvorba databázových aplikácií'),
('KMI/SPRVdb/INF/16','Informatika a základy správy databáz'),
('KMI/AIdb/PR4/15','Programovanie 4 - Objektové programovanie'),
('KMI/AIdb/DBS/15','Databázové informačné systémy');
overall don't insert 0 for id

Related

Auto generate Primary Key if not present in MySQL INSERT Query

I created a table in MySql
CREATE TABLE newuser(id VARCHAR(10) PRIMARY KEY,sname VARCHAR(20));
When I INSERT record it works fine
INSERT INTO newuser VALUE('abc123','monika');
But sometimes I don't want to supply id in the INSERT query and sometimes I want to supply. In case I don't supply id MySql automatically generate one.
What can I do to get both below query works?
INSERT INTO newuser VALUE('abc123','monika');
INSERT INTO newuser VALUE('nikita');
'I don't understood ANYTHING' - very new then.
Firstly second insert statement is invalid please review https://dev.mysql.com/doc/refman/8.0/en/insert.html -
'If you do not specify a list of column names for INSERT ... VALUES or INSERT ... SELECT, values for every column in the table must be provided by the VALUES list, SELECT statement, or TABLE statement.'
Secondly uuid is a function in which 'A UUID is designed as a number that is globally unique in space and time.' https://dev.mysql.com/doc/refman/8.0/en/insert.html
You can easily select uuid() to see what it produces.
You will need to increase the id size
If you wish to use it in an insert
insert into users values (uuid(),<sname>);

MySQL replace into behavior with unique constraint

I have a quick question about MySQL behavior.
Imagine a table with 3(relevant) columns:
id (PK + AI),somedate,someuser,etc...
I have put a unique constraint on (date,user). So when I start with a clean test table and run the following query twice:
REPLACE INTO `testtable` (somedate,someuser) VALUES('2017-01-01','admin');
I expected a row with the 'id' column on 1. but instead everytime I run this query the id goes up because of the auto increment and I can't have that happen (this would corrupt my data relations). Why is this? Can I make it so that I can keep the original primary key when a replace into occurs?
Not with the REPLACE. That's like an INSERT preceded by a DELETE. The behavior you observe with REPLACE is the same as the behavior you would see if you executed these two statements:
DELETE FROM `testtable` WHERE somedate = '2017-01-01' and someuser = 'admin';
INSERT INTO `testtable` (somedate,someuser) VALUES ('2017-01-01','admin');
And that means the auto_increment column on the newly inserted row will have a new value.
Perhaps consider using INSERT ... ON DUPLICATE KEY UPDATE.
Reference: https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
(Note that the attempt to insert a row that gets updated will use an auto_increment value.)
To me looks like you actually wanted an UPDATE statement rather like
update `testtable`
set somedate = '2017-01-01',
someuser = 'admin'
where id = <id of the record> ;

INSERT INTO ... SELECT if destination column has a generated column

Have some tables:
CREATE TABLE `asource` (
`id` int(10) unsigned NOT NULL DEFAULT '0'
);
CREATE TABLE `adestination` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`generated` tinyint(1) GENERATED ALWAYS AS (id = 2) STORED NOT NULL
);
I copy a row from asource to adestination:
INSERT INTO adestination
SELECT asource.*
FROM asource;
The above generates an error:
Error Code: 1136. Column count doesn't match value count at row 1
Ok, quite strange to require me to mention generated query. But ok, I add that column to the query:
INSERT INTO adestination
SELECT asource.*, NULL AS `generated`
FROM asource;
This has worked fine in 5.7.10. However, it generates an error in 5.7.11 (due to a fix:
Error Code: 3105. The value specified for generated column 'generated' in table 'adestination' is not allowed.
Ok, next try:
INSERT INTO adestination
SELECT asource.*, 1 AS `generated`
FROM asource;
But still the same error. I have tried 0, TRUE, FALSE but the error persists.
The DEFAULT value which is stated as the only allowed value (specs or docs). However, the following generates a syntax error (DEFAULT is not supported there):
INSERT INTO adestination
SELECT asource.*, DEFAULT AS `generated`
FROM asource;
So, how can I copy a row from one table to another using INSERT INTO ... SELECT if the destination table adds some columns where some of them are GENERATED?
The code calling this query is generic and has no knowledge what columns that particular tables have. It just knows which extra columns the destination table has. The source table is a live table, the destination table is a historical version of the source table. It has few columns extra like user id made the change, what type of the change it is (insert, update, delete) when etc.
Sadly this is just how MySQL works now to "conform to SQL standards".
The only value that the generated column can accept in an update, insert, etc. is DEFAULT, or the other option is to omit the column altogether.
My poor mans work around for these are to just disable the generated column while I'm working with the data (like for importing a dump) and then go back and add the generated column expression afterwards.
You must declare the columns
Insert into adestination (id, generated)
select id, 1
from asource;
It is best practice to list out the columns, and use null as field1 for the auto incremented id field.
INSERT INTO adestination
(id,
field1,
field2)
SELECT
null AS generated,
asource.field1,
asource.field2
FROM asource;

Can't Insert Row into Table (Column Count Mismatch)

I've got a script that's creating a table, and then inserting a row afterwards. Here is my SQL code executing to create the table:
CREATE TABLE polls (
id INT NOT NULL UNIQUE AUTO_INCREMENT,
name VARCHAR(255) NOT NULL UNIQUE,
author VARCHAR(255) NOT NULL,
created DATETIME NOT NULL,
expires DATETIME,
PRIMARY KEY(id)
)
And here is where I add a new row:
INSERT INTO polls
VALUES ('TestPoll'),('Billy Bob'),('2013-05-01 04:17:31'),('2013-05-01 04:17:31')
or
INSERT INTO polls
VALUES ('TestPoll','Billy Bob','2013-05-01 04:17:31','2013-05-01 04:17:31')
(I get the same error regardless)
I always get this error:
<class '_mysql_exceptions.OperationalError'>, OperationalError(1136, "Column count doesn't match value count at row 1"), <traceback object at 0x7f7bed982560>
Your syntax is wrong, try:
INSERT INTO polls
VALUES ('TestPoll','Billy Bob','2013-05-01 04:17:31','2013-05-01 04:17:31')
but if your table structure changes, your code will break, a safer version is:
INSERT INTO polls (name, author, created, expires)
VALUES ('TestPoll','Billy Bob','2013-05-01 04:17:31','2013-05-01 04:17:31')
Your INSERT query is not correctly formatted.
INSERT INTO polls (name, author, created, expires)
VALUES ('TestPoll','Billy Bob','2013-05-01 04:17:31','2013-05-01 04:17:31');
For more information, visit MySQL Reference Manual for the INSERT statement.
EDIT: It's always a good idea to explicitly type each column name, in case the table structure will change in some foreseeable future.
In mysql you have to pass column name in your insert query.After assigning column name your query will look like
INSERT INTO polls (name,author,created,expires) values ('TestPoll','Billy Bob','2013-05-01 04:17:31','2013-05-01 04:17:31');
Hope it helps.

inserting new rows to table without updating old ones

Alright, i have revised the question to also include what i have so far, and what i want to do. So here goes it:
CREATE ORDER (
product_nat_id int(3) NOT NULL,
name VARCHAR(20),
PRIMARY KEY (product_nate_id)
)
INSERT INTO ORDER(product_nat_id, name) VALUES(1, 'Product 1');
INSERT INTO ORDER(product_nat_id, name) VALUES(2, 'Product 2');
INSERT INTO ORDER(product_nat_id, name) VALUES(3, 'Product 3');
CREATE TABLE INT_PRODUCT (
product_id INTEGER NOT NULL AUTO_INCREMENT,
product_nat_id INTEGER NOT NULL,
title TINYTEXT,
dateCreate TIMESTAMP CURRENT_TIMESTAMP,
CONSTRAINT INT_PRODUCT_PK PRIMARY KEY (product_id),
UNIQUE INT_PRODUCT_NK (product_nat_id));
But what i want is, whenever a record arrives with an updated value but duplicate key, i need to insert it (and not updated), but avoid duplicate constraint based on the difference in time inserted. Hope this makes sense now.
I would suggest the following:
Look up the previous record. I assume you should know what that would be
SELECT Count(*) FROM dim WHERE recordId = '$recordid'
If in step 1 the records returned are larger than 0 then invalidate the 'previous' record:
UPDATE dim SET datevalid = '$datevalue' where recordId = '$recordid' and status = 2
Continuing with step 1 where the ecords return in the check are larger than 0 now do the insert:
INSERT INTO dim (recordId,field1,field2,date,status) VALUES (1,'sad','123123','2013-03-26',1)
If step 1 was false then just do the insert:
INSERT INTO dim (recordId,field1,field2,date,status) VALUES (1,'sad','123123','2013-03-26',1)
I would add a status field just as an extra measure when you need to find records and distinguish between valid or invalid then you do not need to filter between dates. You can then use the status field. Also have a unique auto-increment key for every record even though the data might be the same for a set of valid and invalid records. recordId and unique key will not be the same in this case. You assign the recordId and the system will assign the unique key on the table. status = 1 is valid and status = 2 is invalid.
Hope this helps!
sample code of your post like as:
Insert query syntax looks like this:
INSERT INTO table (primarykeycol,col1,col2)
VALUES (1,2,3) ON DUPLICATE KEY UPDATE col1=0, col2=col2+1
If there is already a row with primarykeycol set to 1 this query is equal to:
UPDATE table SET col1=0, col2=col2+1 WHERE primarykeycol = 1
explanation as:
Ordinarily to achieve the same result you would have to issue an
UPDATE query, then check if there were affected rows and if not
issue an INSERT query.
This way, you can do everything in one step – first try insert and
then update if insert fails.
One situation for which this type of syntax is perfect is when you
work with daily counters. For example, you might have a table with
PostID, Date and Count columns.
Each day you’d have to check if you already created an entry for
that day and if so increase the count column – and this can be
easily substituted with one INSERT … ON DUPLICATE KEY UPDATE query.
Unfortunately there are some caveats. One being that when you have
multiple unique indexes it will act as if you had an OR condition in
WHERE clause of UPDATE query.
This means that multiple rows should be update, but INSERT … ON
DUPLICATE KEY UPDATE will update only one row.
MySQL manual: INSERT ON DUPLICATE KEY UPDATE Syntax