MYSQL UPDATE on KEY - duplicates [duplicate] - php

This problem seems easy at first sight, but I simply have not found a solution that is reasonable time wise.
Consider a table with the following characteristics:
ID INTEGER PRIMARY KEY AUTOINCREMENT
name INTEGER
values1 INTEGER
values2 INTEGER
dates DATE
Every day, N amount of new rows are generated, for dates into the future, and with the 'name' coming from a finite list. I would like to insert a new row when there is new data, but if there is already a row with 'name' and 'dates', simply update it.
Please note that a current proposed solution of an SPROC that checks the conditional is not feasible, as this is data being pushed from another language.

that is what insert on duplicate key update is for.
The Manual page for it is here.
The trick is that the table needs to have a unique key (can be a composite) so that the clash of doing an insert can be detected. As such, the update to occur on that row, otherwise an insert. It can be a primary key, of course.
In your case, you could have a composite key such as
unique key(theName,theDate)
If the row is already there, the clash is detected, and the update happens.
Here is a complete example
create table myThing
( id int auto_increment primary key,
name int not null,
values1 int not null,
values2 int not null,
dates date not null,
unique key(name,dates) -- <---- this line here is darn important
);
insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1;
insert myThing(name,values1,values2,dates) values (778,1,1,'2015-07-11') on duplicate key update values2=values2+1;
-- do the 1st one a few more times:
insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1;
insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1;
insert myThing(name,values1,values2,dates) values (777,1,1,'2015-07-11') on duplicate key update values2=values2+1;
show results
select * from myThing;
+----+------+---------+---------+------------+
| id | name | values1 | values2 | dates |
+----+------+---------+---------+------------+
| 1 | 777 | 1 | 4 | 2015-07-11 |
| 2 | 778 | 1 | 1 | 2015-07-11 |
+----+------+---------+---------+------------+
As expected, insert on duplicate key update works, just 2 rows.

This is easy:
Create a unique key on the columns to check
Use the INSERT .. ON DUPLICATE KEY UPDATE construct

Related

Auto Increment From A Six Seven Number

I know this may seem like a similar question out there, but it really is not. I am trying to create a seven digit ID number that is saved in my mySQL database.
I'm using this sprintf("%07d", $idNumber);
This works, and creates a seven digit id number. However, I want to insert this into my database. The problem is I don't know how to increment this ID number then insert it into the database.
Any ideas?
Thanks!
You can define a column with the ZEROFILL option, and then insert unformatted integers.
mysql> create table foo (id int(7) zerofill auto_increment primary key);
mysql> insert into foo values (123);
mysql> insert into foo () values ();
mysql> select * from foo;
+---------+
| id |
+---------+
| 0000123 |
| 0000124 |
+---------+
This is the only time the numeric argument to the INT type has any practical use. I wish they had made the argument on the ZEROFILL keyword instead of the INT keyword. It would have avoided a lot of confusion.

Prevent inserting matching rows in MySql

I have a table in MySql Database. I would like to prevent inserting matching rows in MySql. Like I have 4 columns in a table. I would not like to insert any row which has matching values of these 4 columns. I am trying to show that below
My table
----------
product_name| product_sku |product_quantity| product_price
----------
Computer | comp_007 | 5 | 500
I would like to prevent to insert same row again. How can I do that using MySql Query ??
UPDATE
I would not like to insert again
Computer | comp_007 | 5 | 500
But I would like to insert below rows
mouse | comp_007 | 5 | 500
Computer | comp_008 | 5 | 500
Computer | comp_007 | 50 | 500
Computer | comp_007 | 5 | 100
mouse | mou_007 | 5 | 500
Create a combined unique key / composite key on the columns in question:
ALTER TABLE `table` ADD UNIQUE (
`product_name` ,
`product_sku` ,
`product_quantity`,
`product_price`
);
Any attempts to insert duplicate rows will result in a MySQL error.
If possible you should add a Unique Key to your columns:
ALTER TABLE `table_name`
ADD UNIQUE INDEX `ix_name` (`product_name`, `product_sku`, `product_quantity`, `product_price`);
and then use INSERT IGNORE:
INSERT IGNORE INTO table_name (product_name, product_sku, product_quantity, product_price) VALUES (value1, value2, value3, value4);
If the record is unique MYSQL inserts it as usual, if the record is a duplicate then the IGNORE keyword discards the insert without generating an error.
SQLfiddle
The simplest way would be to make your columns unique. On undesired inserts, your MySQL driver should throw an exception then, which you can handle.
From a domain logic point of view, this is a bad practice, since exceptions should never handle expected behaviour. By the way, your DB table could use a primary key.
So, to have a better solution, your approach could be:
- Define a unique field (the SKU seems suitable); think about using this as the primary key as well
- With MySQL, use a REPLACE statement:
REPLACE INTO your_tablename
SET product_name='the name'
-- and so on for other columns
WHERE product_sku = 'whatever_sku';
REPLACE does the Job of trying to INSERT, and doing an UPDATE instead if the PK exists.

Sql insert ignore does not work because of timestamp now()

I am trying to prevent duplicate entries like this
INSERT IGNORE INTO myTable( `val_1`, `val_2`, `val_3`, `date` )
VALUES ( '$var_1', '$var_2', '$var_3', now() )
The values i would like to check are the 3 val_x but because now() will be a unique value, insert ignore does not work.
How can i not check that last variable as unique?
note: this is kind of like a cart, so i cannot make the first 3 values unique. There is a session variable that allows each user to see a a unique collection.
From this diagram, the first 2 rows are duplicate since they belong to the same user session. The 3rd row is not a duplicate becase it belongs to a different user session
+---------+-------+--------+
| session | var 1 | var 2 |
+---------+-------+--------+
| abc1234 | aaaaa | bbbbb |
+---------+-------+--------+
| abc1234 | aaaaa | bbbbb |
+---------+-------+--------+
| 5678def | aaaaa | bbbbb |
+---------+-------+--------+
| 5678def | aaaaa | ccccc |
+---------+-------+--------+
as paqogomez suggested i removed now() from the query and altered the table but it looks like i need a primary key for insert ignore to work, but for my scenario i cant make these 3 columns unique
ERROR 1062: Duplicate entry 'aaaaa' for key 'var 1'
I would suggest moving the date into the default value of the column.
ALTER TABLE mytable CHANGE `date` `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
This way, you can still deal with the duplicates in the data in PHP. The alternative, as others have suggested would result in a database foreign key error if you attempted to insert a duplicate.
Then this sql would work and give the same result:
INSERT IGNORE INTO myTable( `val_1`, `val_2`, `val_3` )
VALUES ( '$var_1', '$var_2', '$var_3' )
EDIT:
You still need a unique index to make it work. See #Gordon's answer
Create a unique index on the first three columns:
create unique index myTable_session_val2_val3 on myTable(session, val_1, val_2);
This will guarantee that combinations of these three are unique, without taking into account any other columns.
You should probably define the UNIQUE keys for the combination of columns you don't want to be duplicated. So, don't specify column date as UNIQUE. Did you verify that? Define rest of three values as unique columns. It will probably work.

MySQL Export Import with ID auto_increment for Foreign Key

Consider i have 2 database that have same field.
first database is for export data,
second database act as copy have database
Database 1 will export database in file format csv that output from PHP Script.
Database 2 will import database from php script.
There is two table is in each database that relations with foreign key.
table_transaction
create table `table_transaction` (
`id` int auto_increment primary key
`date` DATE default now()
) engine = innoDB;
sample data
id | date
1 | 2012-12-31
2 | 2012-12-30
3 | 2012-12-29
table_transaction_product
create table `table_transaction_product` (
`id` int auto_increment primary key
`product` string NOT NULL default '' /* Product Name */
`fk_transaction` int auto_increment NOT NULL
foreign key (`fk_transaction`)
references table_transaction(`id`)
on update cascade
on delete cascade
) engine = innoDB;
sample data
id | product | fk_transaction
1 | shampoo | 1
2 | soap | 1
3 | conditioner | 1
And this is sample exported CSV from database 1 and will be imported to table 2, that exporting transaction id 1.
insert into table_transaction (id, date) values (1, '2012-12-31');
insert into table_transaction_product (id, product, fk_transaction)
values
(1, 'shampoo', 1),
(2, 'soap', 1),
(3, 'conditioner', 1)
Question
Since the ID both table is auto_increment. Isn't there will be any problem that i insert manually the table.id and crash the auto_increment mysql system? But if didn't input the ID and let's mysql decide it, then the foreign key will be not match. What should i do?
Thank you.
It shouldn't cause a problem, but I would recommend changing the table definitions on the second database to remove the auto_increment flag.

Can't insert new row into postgres database table?

I have an issue, I'm trying to insert a new row into a postgres database table and get the following error
ERROR: duplicate key violates unique constraint "n_clients_pkey"
Here my query
insert into n_clients(client_name) values( 'value');
I'm using postgres 8.1.11
PostgreSQL 8.1.11 on x86_64-redhat-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Here's the structure for my table
Table "public.n_clients"
Column | Type | Modifiers
-------------+--------------------------+-----------------------------------------------------------------------
id | integer | not null default nextval(('public.n_clients_id_seq'::text)::regclass)
client_name | character varying(200) | not null
moddate | timestamp with time zone | default now()
createdate | timestamp with time zone | default now()
Indexes:
"n_clients_pkey" PRIMARY KEY, btree (id)
and the sequence
Sequence "public.n_clients_id_seq"
Column | Type
---------------+---------
sequence_name | name
last_value | bigint
increment_by | bigint
max_value | bigint
min_value | bigint
cache_value | bigint
log_cnt | bigint
is_cycled | boolean
is_called | boolean
This row exists already, therefore you cannot insert it. What is the primary key of your relation? Is it a sequence? If so, maybe it got stuck (maybe you imported data). You should reset it manually to the next free ID available (e.g., if the maximum ID is 41, you should do: SELECT setval('your_seq', 42);) then try again.
You must have a UNIQUE constraint on your table, that your insert is violating -- ie, considering the name of your table and index, you are probably trying to insert a client that already exists in your table.
Typically one gets into this situation by manually adding a record with an id field that matches the current value for the sequence. It's easy to introduce this by some common dump/reload operations for example. I wrote an article about correcting for this sort of error across the entire database at Fixing Sequences.
The PostGresSQL should have a primary key while creating a DB , so you are not able to add anything include then only you can add data manually
8.1 version is dated.
8.4 displays a much better error message :
ERROR: duplicate key value violates unique constraint "master_pkey"
DETAIL: Key (id)=(1) already exists.

Categories