I have a table:
CREATE TABLE passenger_details
(
bank_card INT(20) NOT NULL AUTO_INCREMENT,
email VARCHAR(20),
mobile INT(15) NOT NULL,
p_id INT NOT NULL,
PRIMARY KEY (bank_card),
FOREIGN KEY (p_id) REFERENCES passenger(p_id)
);
INSERT INTO passenger_details
VALUES (0123012301230123,'blah_#hotmail.com',0872863492,1234);
select*from passenger_details;
+------------+--------------------+-----------+------+
| bank_card | email | mobile | p_id |
+------------+--------------------+-----------+------+
| 2147483647 | blah_#hotmail.com | 872863492 | 1234 |
+------------+--------------------+-----------+------+
1 row in set (0.00 sec)
As we can see, the previous value, just went wrong into table. Should be 16 numbers and not only 10, actually different numbers.
When i try to insert a new value:
INSERT INTO passenger_details
VALUES (1234258431681842,'blah#icloud.com',0895764829,123548);
I get this error:
ERROR 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY'
If bank_card is AUTO_INCREMENT why there is error? Should I change the PK to another place?
INT has a maximum signed value of 2147483647. Any number greater than that will be truncated to that value. What you need to do is change that column to be a varchar(20) which will hold strings of up to 20 characters since bank card numbers are strings and not actually numbers (you don't do math with the). You also should remove AUTO_INCREMENT as that is not a value you will be incrementing.
Something to ask yourself. How did the number get that big? I did not insert 2 billion rows!
Well, possibly you 'burned' that many AUTO_INCREMENT ids. This can happen in man ways:
INSERT IGNORE ... -- when the insert is ignored (because it the row already exists)
REPLACE
IODKU
and probably others.
With MySQL phpmyadmin panel , this is how I got rid from this issue
>Go to your Table's structure from phpmyadmin panel
>> select that PRIMARY column , click on change
>>> Change Column type to "BIGINT" and Attributes to "unsigned"
with other SQLs > change column attributes to "BIGINT unsigned"
that worked for me
Related
I have a table with a Binary PK:
CREATE TABLE `codes` (
`Code` binary(45) NOT NULL,
PRIMARY KEY (`Code`),
UNIQUE KEY `Code_UNIQUE` (`Code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
When I insert I use BINARY('value').
I attempted to retrieve a row by Code using the following:
SELECT * from codes WHERE `Code` = BINARY('value')
This doesn't work because the length of the Code field is 45, so MySql pads the data with empty bytes.
This can be visualised running the following:
SELECT HEX(Code), HEX(BINARY('value')) FROM codes
I can get it to work with this (ugly) query:
SELECT * FROM codes WHERE TRIM('0' from HEX(Code)) = HEX(BINARY('value'))
So I was just wondering if anyone can provide a nice and performant way to achieve this. This is straightforward if you know the size of your data, but the Code field can be any length.
Instead of Binary datatype, you should use Varbinary. This will not pad the data with trailing 0s, in case the length of data is smaller than the maximum size defined.
When BINARY values are stored, they are right-padded with the pad
value to the specified length. The pad value is 0x00 (the zero byte).
Values are right-padded with 0x00 on insert, and no trailing bytes are
removed on select.
For VARBINARY, there is no padding on insert and no bytes are stripped
on select.
Also, you do not need to define Unique constraint on an already defined Primary Key. Primary Key basically satisfied the Unique constraint, with additional condition of NOT NULL values. So, defining Unique constraint further does not add anything upon it.
This is how the CREATE TABLE statement can be:
CREATE TABLE `codes` (
`Code` Varbinary(45) NOT NULL, -- Changed to Varbinary
PRIMARY KEY (`Code`) -- Removed Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into codes (Code) VALUES (BINARY('value'));
Query #1
SELECT HEX(Code), HEX(BINARY('value')) FROM codes ;
| HEX(Code) | HEX(BINARY('value')) |
| ---------- | -------------------- |
| 76616C7565 | 76616C7565 |
Query #2
SELECT * from codes WHERE `Code` = BINARY('value');
| Code |
| --------------- |
| [object Object] |
View on DB Fiddle
I have the below table columns in MySQL.
id
user_primary_email
user_secondary_email
I want to make the combination of columns user_primary_email and user_secondary_email unique which I can achieve by using UNIQUE KEY unique_key_name (user_primary_email, user_secondary_email)
The above addition of unique key constraint will help me achieve the below scenario or rather just by adding a unique key to the individual column itself.
user_primary_email = 'xyz#gmail.com' AND user_secondary_email = 'pqr#gmail.com'
user_primary_email = 'xyz#gmail.com' AND user_secondary_email = 'pqr#gmail.com' //This will not be allowed to enter due to unique key constraint
Now the problem which I am facing is the same combination should not be allowed to add in a reverse way as mentioned below.
user_primary_email = 'pqr#gmail.com' AND user_secondary_email = 'xyz#gmail.com' //This should not be allowed to add since already same email id combination added once
id | user_primary_email | user_secondary_email
-------------------------------------------------------
1 | xyz#gmail.com | pqr#gmail.com
-------------------------------------------------------
2 | pqr#gmail.com | xyz#gmail.com
-------------------------------------------------------
In the above case during insert of row id 2 it should throw error as both the email id combination is already used in row id 1.
Any help would be great.
In any MariaDB:
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`user_primary_email` varchar(64) DEFAULT NULL,
`user_secondary_email` varchar(64) DEFAULT NULL,
`mycheck` varchar(128) AS (IF(user_primary_email<user_secondary_email,CONCAT(user_primary_email,user_secondary_email),CONCAT(user_secondary_email,user_primary_email))) PERSISTENT,
PRIMARY KEY (`id`),
UNIQUE KEY `mycheck` (`mycheck`)
);
MariaDB [test]> insert into t values (1,'a','b',null);
Query OK, 1 row affected (0.03 sec)
MariaDB [test]> insert into t values (2,'b','a',null);
ERROR 1062 (23000): Duplicate entry 'ab' for key 'mycheck'
There is no direct support for that, but you can use a workaround to create your bidirectional key: You need a unique key on an ordered version of your two columns.
Fortunately, you can very easily do that. MySQL 5.7.6+ supports generated columns and unique indexes for them, which you can use to order your two values and to enforce uniqueness.
create table testBiDirKey (
a varchar(100),
b varchar(100),
a_ordered varchar(100) as (least(a, b)) STORED,
b_ordered varchar(100) as (greatest(a, b)) STORED,
unique key unqBi_test_ab (a_ordered, b_ordered)
);
insert into testBiDirKey(a,b) values('a', 'b');
insert into testBiDirKey(a,b) values('b', 'a');
Error Code: 1062. Duplicate entry 'a-b' for key 'unqBi_test_ab'
This will treat null exactly as your current normal unique key, so
insert into testBiDirKey(a,b) values('a', null);
insert into testBiDirKey(a,b) values('a', null);
insert into testBiDirKey(a,b) values(null, 'a');
are all allowed. You can add coalesce(x,'') to only allow one empty value (either null OR '') if you want. If you verify your values before you add them (e.g. if they don't contain a ,), you can combine the two columns to just one, concatenated with an , - although with little benefit apart from just having 1 additional column.
For 5.7.8+, you don't need the STORED keyword anymore to be able to use these columns in an index. That keyword effects if the values are stored (using disk space) or calculated when required (default).
Before MySQL 5.7.6, you can use a trigger (on update and insert) to update the two columns with the these values, the same logic applies, it's just a little more code.
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
I've got a script running this update:
UPDATE `Cq_Item`
SET `rfq_item_id` = '9',
`value` = 'No Bid',
`datetime_created` = '2012-10-23T20:54:42+00:00',
`id` = '101'
WHERE `id` = '101'
Against this table:
CREATE TABLE IF NOT EXISTS `cq_item` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`rfq_item_id` mediumint(8) unsigned NOT NULL,
`product_id_quoted` mediumint(8) unsigned DEFAULT NULL,
`quantity` mediumint(6) unsigned DEFAULT '0',
`value` float(10,4) NOT NULL,
`datetime_created` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rfq_item_id` (`rfq_item_id`,`product_id_quoted`,`quantity`,`value`),
KEY `product_id` (`product_id_quoted`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=102 ;
and it's throwing this error:
1062 - Duplicate entry '9-321742-1-0.0000' for key 'rfq_item_id'
Granted, i'm no SQL guru, but throwing a dupe error on an update seems a little less than intuitive to me.
I understand why such an error would get thrown on an INSERT, but I can use some help figuring out what i'm doing wrong to get that on this UPDATE :)
An update actually performs two separate operations (when conditions are met of course), a DELETE and then an INSERT. You probably need to make sure that your UPDATE is not causing the row with id = 101 to violate your unique key that is already in place for another row.
So say you had two rows like this before attempting the update
id | rfq_item_id | product_id_quoted | quantity | value | datetime_creates
100 | 9 | 9 | 1 | 0.0000 | <some datetime>
101 | 10 | 9 | 1 | 0.0000 | <some datetime>
Your UPDATE would throw the exact error you are seeing upon execution, because the rfq_item_id/product_id_quoted/quantity/value unique key would be the same.
I would guess your problem is related to trying to set a string value of "No Bid" on the field value which is defined as a float. You thus will get a 0.0000 value in the update.
Also as mentioned in comment to original question, it is generally considered to be bad SQL practice to try to "set" the value of the primary key that you are using in the WHERE clause of an UPDATE statement. That is unless to really have a reason to change the primary key as part of the update.
your table structure says that rfq_item_id is unique key. and the value you are trying too set in update query is already in the table. So, it is not allowing you to update query with rfq_item_id = '9'.
Based on your table description, you have a unique key:
UNIQUE KEY `rfq_item_id` (`rfq_item_id`,`product_id_quoted`,`quantity`,`value`)
You are attempting to perform an UPDATE with values that already meet the criteria of your UNIQUE KEY.
You already have a record with rfq_item_id = '9' and value = 'No Bid', the values for the other two columns in the unique key also already match the values in id = '101'
I need to remove duplicate records (just to keep one copy) from a MySQL table in MyISAM format. I have read many questions in Stackoverflow about similar issues but always the people use an ID field as unique id or similar and I haven't this field because my "Key" could be duplicated. I want to remove rows with the 'Fecha' and 'Equip' duplicated.
CREATE TABLE `pfc` (
`Fecha` datetime NOT NULL,
`Equip` int(10) unsigned NOT NULL,
`Value` double NOT NULL,
KEY `Fecha` (`Fecha`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AVG_ROW_LENGTH=21 ROW_FORMAT=FIXED;
An example table data:
Fecha | Equip | Value
06/02/2011 0:00:11 | 22 | 29.0
06/02/2011 0:22:11 | 22 | 45.3
06/02/2011 0:00:11 | 22 | 29.0
The result should be:
Fecha | Equip | Value
06/02/2011 0:00:11 | 22 | 29.0
06/02/2011 0:22:11 | 22 | 45.3
This structure is not possible to change. I cannot use PRIMARY KEY or UNIQUE INDEX solutions. To create a temporal table without duplicates and then rename would be a poor solutions also, because the KEY and another parameters will be lost.
Thanks
ALTER IGNORE TABLE `pfc` ADD UNIQUE(`Fetcha`, `Equip`);
That will keep the first record it finds and remove duplicates from your table.
From MySQL manual:
IGNORE is a MySQL extension to standard SQL. It controls how ALTER
TABLE works if there are duplicates on unique keys in the new table or
if warnings occur when strict mode is enabled. If IGNORE is not
specified, the copy is aborted and rolled back if duplicate-key errors
occur. If IGNORE is specified, only the first row is used of rows with
duplicates on a unique key. The other conflicting rows are deleted.
Incorrect values are truncated to the closest matching acceptable
value.
Edit:
To create an exact copy of your table, use the following:
CREATE TABLE table_copy SELECT * FROM pfc;
That will copy the table structure and the data. After that, run the ALTER command to add the UNIQUE constraint and filter out the records that are duplicated.
Just as a test, try this to see if it is what you want
CREATE TABLE new_pfc AS
SELECT * FROM pfc GROUP BY fecha, equip
DELETE n1 FROM pfc n1, pfc n2 WHERE n1.Fecha = n2.Fecha AND n1.Equip=n2.Equip AND n1.Value=n2.Value