I have a table called words, and in it I'd like to store key/value pairs of words and their occurrences.
I want to make the count column an auto-incrementing column, since I want to keep adding words (from a C++ application) and have the count increment on its own automatically. However, I figured that the table would be searched a lot, so I made word the primary key. I ran into an error, though, saying I cannot set a non-primary key as an auto-incrementing column.
Is there a way to do this properly such that I can insert into the table and have the database handle incrementing and all that?
Create a table to store the words. The word column is the primary key.
CREATE TABLE `words` (
`word` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`count` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`word`)
);
Then insert your words in the table like this:
INSERT INTO `words`(word) VALUES('car') ON DUPLICATE KEY UPDATE `count`=`count`+1;
INSERT INTO `words`(word) VALUES('plane') ON DUPLICATE KEY UPDATE `count`=`count`+1;
INSERT INTO `words`(word) VALUES('car') ON DUPLICATE KEY UPDATE `count`=`count`+1;
If the word doesn't exist in the table, nb defaults to 1 (this is in the table definition).
If the word already exist in the table, the value of nb for this word is increased by 1.
After the 3 inserts above, the table contains:
word | count
car | 2
plane | 1
You may need to adjust:
- the length of the column word
- the character set and collation
Documentation: INSERT ... ON DUPLICATE KEY UPDATE Syntax
You can keep the auto increment column as the primary key, and add an additional index containing the word column only. if you're searching by word, this index will be used
Related
I have a table in which I took two field one is id that is primary key with Auto Increment attribute (tinyint) and another one is name (varchar(20)).
id tinyint(4) NOT NULL AUTO_INCREMENT, name varchar(20) NOT NULL,
PRIMARY KEY (id)
after that I have insert the values in table from 1 to 127 (max limit of tinyint). Now If I try to insert the record in table it gives error because I have reached at max limit of tinyint. I am fine with it. But If I delete all the records and table is empty then also I can't insert any record. I know I can use truncate here that will reset the primary key. But My question is here that why mysql doesn't insert the any available value(from 1 to 127) for primary key and If I manually insert the value for id from 1 to 127 it works.
insert into `new table` (id,name) values(1,'blahblahblah') Working
insert into `new table` (name) values('blahblahblah') Not working
If I have a application with large database and I come this situation and any record insertion can fail in future then how can I know before occurred this.
Is there any way by which I can insert the record(in empty table by delete all records) without truncating the table.
Sorry for my poor English.
Thanks
Mysql saves your AUTO_INCREMENT counter in its INFORMATION_SCHEMA table.
I don't know which version you're using but you should read the docs about it.
As you can read here, you can set the number you want using
ALTER TABLE tablename AUTO_INCREMENT = 1;
I have a column in my db "id" int(11) NOT NULL AUTO_INCREMENT, and I want multiple rows in this table with the same id value. So when inserting to the table I'd like to tell whether it should increment or the value remains the sasme. Is there any easy way how to do that?
As MySQL documentation on auto_increment says (highlighting is mine):
No value was specified for the AUTO_INCREMENT column, so MySQL
assigned sequence numbers automatically. You can also explicitly
assign 0 to the column to generate sequence numbers, unless the
NO_AUTO_VALUE_ON_ZERO SQL mode is enabled. If the column is declared
NOT NULL, it is also possible to assign NULL to the column to generate
sequence numbers. When you insert any other value into an
AUTO_INCREMENT column, the column is set to that value and the
sequence is reset so that the next automatically generated value
follows sequentially from the largest column value.
This means, if you determine before the insert the current maximum of the auto_increment field and you explicitly insert that value in the insert statement, then you can have duplicate values in the auto_increment field.
There a couple things that you need to pay attention to:
If you can have parallel inserts into the table, then you may have to lock the table for reading, so another process does not insert a new record triggering the increment of the field.
You cannot use primary / unique index constraint on the auto_increment field.
The alternative is to have a separate table just for the auto_increment and do not use auto_increment in the main table. If you need a new id, then just insert a record into the auto_ncrement table a get the incremented id and use that to insert a record into the main table. Otherwise, just fetch the id value from the main table and use it in the insert.
An auto_increment column makes sure that the values in it are unique ! So, you can't do it this way.
I'd suggest a trigger instead , combining the needed logic.
For MyISAM tables, you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
**grep id name**
fish 1 lax
mammal 1 dog
mammal 2 cat
mammal 3 whale
bird 1 penguin
bird 2 ostrich
If the AUTO_INCREMENT column is part of multiple indexes, MySQL generates sequence values using the index that begins with the AUTO_INCREMENT column, if there is one. For example, if the animals table contained indexes PRIMARY KEY (grp, id) and INDEX (id), MySQL would ignore the PRIMARY KEY for generating sequence values. As a result, the table would contain a single sequence, not a sequence per grp value
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
The current column is a VARCHAR(255) NOT NULL, so how do I change it to TEXT NOT NULL?
NOTE: The column intended to be changed its property type is a UNIQUE KEY combination of another column. E.g.
UNIQUE KEY (Name, Description)
The column description is currently in varchar(255). It can't be changed because of this:
ERROR 1170 (42000): BLOB/TEXT column 'description' used in key specification without a key length
I need it to be TEXT, else I need to recreate the whole thing?? I got some tedious and important data already in it. It's going to be troublesome to recreate.
Are you going to use TEXT column as part of UNIQUE KEY?
It's VERY inefficient! Don't do that!
I'm strongly suggest you to:
Add additional column named for example 'description_hash' char(32) not null default ''
Store the hash-value for description field into it. For ex. description_hash=MD5(description)
Change your key to UNIQUE KEY (name, description_hash)
Ofcourse you'll need to keep the description_hash column up-to-date in your code, but as see - in most cases it is require just few code changes.
Or you can use trigger for handling this.
I had exactly the same problem.
I added a new char(32) column (I called it hash and added a unique index on it) and two triggers.
delimiter |
CREATE TRIGGER insert_set_hash
BEFORE INSERT ON my_table_name
FOR EACH ROW BEGIN
SET NEW.hash = MD5(NEW.my_text);
END; |
CREATE TRIGGER update_set_hash
BEFORE UPDATE ON my_table_name
FOR EACH ROW BEGIN
SET NEW.hash = MD5(NEW.my_text);
END; |
delimiter ;
By using the triggers and adding a UNIQUE index on hash you can be sure that the hash values will always be up-to-date and unique.
alter table your_table
modify column your_column text not null;
for unique key
alter table your_table
add unique index your_index_name (your_column(your_length));
your_length = allow up 1000 bytes
The maximum key length is 1000 bytes. This can also be changed by changing the source and recompiling. For the case of a key longer than 250 bytes, a larger key block size than the default of 1024 bytes is used
Both length (description + another column can not longer than 1000),so
alter table your_table
add unique index your_index_name (description(800), another_column(200));
RESOLVED
From the developer: the problem was that a previous version of the code was still writing to the table which used manual ids instead of the auto increment. Note to self: always check for other possible locations where the table is written to.
We are getting duplicate keys in a table. They are not inserted at the same time (6 hours apart).
Table structure:
CREATE TABLE `table_1` (
`sales_id` int(10) unsigned NOT NULL auto_increment,
`sales_revisions_id` int(10) unsigned NOT NULL default '0',
`sales_name` varchar(50) default NULL,
`recycle_id` int(10) unsigned default NULL,
PRIMARY KEY (`sales_id`),
KEY `sales_revisions_id` (`sales_revisions_id`),
KEY `sales_id` (`sales_id`),
KEY `recycle_id` (`recycle_id`)
) ENGINE= MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=26759 ;
The insert:
insert into `table_1` ( `sales_name` ) VALUES ( "Blah Blah" )
We are running MySQL 5.0.20 with PHP5 and using mysql_insert_id() to retrieve the insert id immediately after the insert query.
I have had a few duplicate key error suddenly appear in MySql databases in the past even though the primary key is defined and auto_increment. Each and every time it has been because the table has become corrupted.
If it is corrupt performing a check tables should expose the problem. You can do this by running:
CHECK TABLE tbl_name
If it comes back as corrupt in anyway (Will usually say the size is bigger than it actually should be) then just run the following to repair it:
REPAIR TABLE tbl_name
Does the sales_id field have a primary (or unique) key? If not, then something else is probably making inserts or updates that is re-using existing numbers. And by "something else" I don't just mean code; it could be a human with access to the database doing it accidentally.
As the other said; with your example it's not possible.
It's unrelated to your question, but you don't have to make a separate KEY for the primary key column -- it's just adding an extra not-unique index to the table when you already have the unique (primary) key.
We are getting duplicate keys in a table.
Do you mean you are getting errors as you try to insert, or do you mean you have some values stored in the column more than once?
Auto-increment only kicks in when you omit the column from your INSERT, or try to insert NULL or zero. Otherwise, you can specify a value in an INSERT statement, over-riding the auto-increment mechanism. For example:
INSERT INTO table_1 (sales_id) VALUES (26759);
If the value you specify already exists in the table, you'll get an error.
Please post the results of this query:
SELECT `sales_id`, COUNT(*) AS `num`
FROM `table_1`
GROUP BY `sales_id`
HAVING `num` > 1
ORDER BY `num` DESC
If you have a unique key on other fields, that could be the problem.
If you have reached the highest value for your auto_increment column MySQL will keep trying to re-insert it. For example, if sales_id was a tinyint column, you would get duplicate key errors after you reached id 127.