I am inserting search terms into a database, and when I run it to test, I was seeing duplicates inserted into the database. I was able to solve that, but, now I am inserting, and it no longer inserts as a duplicate, but I am trying to get the on duplicate to work - and the on duplicate updates the popularity by 2 each time? what do I have wrong here?
$entryDate = date("c");
$insertsearchquery="insert into article_searches (termSafe,entryDate) values (\"$termSafe\",\"$entryDate\") on duplicate key update popularity=popularity+1";
mysql_query($insertsearchquery);
I have a UNIQUE key set for both termSafe and entryDate.
TABLE `article_searches` (
`id` bigint(20) NOT NULL AUTO INCREMENT ,
`termSafe` varchar(150) ,
`entryDate` varchar(255),
`popularity` tinyint(6) UNSIGNED NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `termSafe` USING BTREE (`termSafe`),
UNIQUE INDEX `entryDate` USING BTREE (`entryDate`)
)
Although I just deleted the entryDate unique Index.
I'm guessing that this is because you have a UNIQUE (termSafe) and UNIQUE (entryDate), perhaps you just want a UNIQUE (termSafe,entryDate).
Bear in mind mysql_* functions are deprecated.. you should use PDO or mysqli_* instead.
Try dropping the two unique indexes and create only one:
create unique index idx_article_searches_termSafe_EntryDate on article_searches(termSafe, EntryDate);
When using on duplciate key update, the behavior can be ill-defined when more than one unique constraint violation is detected. I think it is doing the update twice, once for each constraint.
Here is the warning in the documentation:
In general, you should try to avoid using an ON DUPLICATE KEY UPDATE
clause on tables with multiple unique indexes.
Related
I am trying to drop the existing primary keys and add two new primary primary keys in an existing database table using the following query:
ALTER TABLE `match_team_recruit` DROP PRIMARY KEY,
ADD PRIMARY KEY (`ind_stnum`, `team_send`);
However, I get the following error when running the query.
#1062 - Duplicate entry '183-0' for key 'PRIMARY'
Please see attached Image below:
Can anyone advise how I can solve this?
A primary key in MySQL has to follow these three rules.
A primary key must contain unique values. If the primary key consists of multiple columns, the combination of values in these columns must be unique.
A primary key column cannot contain NULL values. It means that you have to declare the primary key column with the NOT NULL attribute. If you don’t, MySQL will force the primary key column as NOT NULL implicitly.
A table has only one primary key.
Courtesy: Introduction to MySQL primary key
To fix your problem you should just add one Primary Key to your table. The Primary Key is used to distinguish Row's, therefor you can't have multiple Primary Key's in one table!
how to limit the number of entry in inserting data in mysql database using php to 1
Any suggestions? Thanks .
You probably can't get it right in PHP since the trip back and forth to the database leaves room for another part of your application to create an entry. Normally we achieve this sort of thing by putting a unique index on the table that prevents duplication of data. For example:
CREATE TABLE alf_mimetype
(
id BIGINT NOT NULL AUTO_INCREMENT,
version BIGINT NOT NULL,
mimetype_str VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
UNIQUE (mimetype_str)
) ENGINE=InnoDB;
If you attempt to insert a row with duplicate mimetype_str, the database will generate an exception. Catch it in your application and you'll know that your single entry for that particular row is already there.
You can create UNIQUE keys on multiple columns as well. Your primary key also represents a unique constraint and can consist of multiple columns.
I have an InnoDB MySQL database with a table that needs to be able to connect to one of 26 other tables via a foreign key. Each record will only connect to one of these 26 at a time. The table will probably consist of no more than 10,000 records. Is there an alternative way to do this?
-- -----------------------------------------------------
-- Table `db_mydb`.`tb_job`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `db_mydb`.`tb_job` (
`job_id` INT(11) NOT NULL AUTO_INCREMENT ,
// Removed 26 other fields that the table requires
`job_foreignkey_a_id` INT(11) NULL DEFAULT NULL ,
`job_foreignkey_b_id` INT(11) NULL DEFAULT NULL ,
`job_foreignkey_c_id` INT(11) NULL DEFAULT NULL ,
// Removed the other 23 foreign keys fields that are the same
PRIMARY KEY (`job_id`) ,
CONSTRAINT `fka_tb_job_tb`
FOREIGN KEY (`job_foreignkey_a_id` )
REFERENCES `db_mydb`.`tb_foreignkey_a` (`foreignkey_a_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fkb_tb_job_tb`
FOREIGN KEY (`job_foreignkey_b_id` )
REFERENCES `db_mydb`.`tb_foreignkey_b` (`foreignkey_b_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fkc_tb_job_tb`
FOREIGN KEY (`job_foreignkey_c_id` )
REFERENCES `db_mydb`.`tb_foreignkey_c` (`foreignkey_c_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
// Removed the other 23 foreign keys constraints that are the same
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE INDEX `fka_tb_job_tb` ON `db_mydb`.`tb_job` (`job_foreignkey_a_id` ASC) ;
CREATE INDEX `fkb_tb_job_tb` ON `db_mydb`.`tb_job` (`job_foreignkey_b_id` ASC) ;
CREATE INDEX `fkc_tb_job_tb` ON `db_mydb`.`tb_job` (`job_foreignkey_c_id` ASC) ;
// Removed the other 23 foreign keys indexes that are the same
This is the problem of generic foreign keys, which MySQL and friends tend not to support. There are two ways you can do this.
The first, as you have done, is nullable foreign keys, one for every type.
The other, as in Django's Content Types, is to have a join table, each row having a row id and a field that specifies the table to look up on. Your code then has to formulate the SQL query depending on the contents of the field. It works well, but has limitations:
The downside of the first one is bloat, but it brings you the upsides of normal FKs, i.e. referential integrity and SQL joins etc, both of which are very valuable. You can't get those with the second method.
Depends if you want to maintain foreign key constraint, you can have one table that references one of the tables by a key or table type. Problem is you will loose the foreign key constraint. Of course, if you can create a function based constraint, then it can work for you. Or you can enforce the relationship using a trigger. Function based constraints are not available in mysql.
Yes, you can do that. These two StackOverflow answers illustrate the underlying principles in a slightly different context.
Same data from different entities in Database - Best Practice - Phone numbers example
Different user types / objects own content in same table - how?
Using MySQL, you'll need to replace critical CHECK() constraints with foreign key references. This doesn't work in the most general case for MySQL, but it does work in this particular application.
If this isn't enough information to get you going, leave me a comment, and I'll try to expand this answer a little more.
Ok, so i'm a newbie here at SQL..
I'm settings up my tables, and i'm getting confused on indexes, keys, foreign keys..
I have a users table, and a projects table.
I want to use the users (id) to attach a project to a user.
This is what I have so far:
DROP TABLE IF EXISTS projects;
CREATE TABLE projects (
id int(8) unsigned NOT NULL,
user_id int(8),
name varchar(120) NOT NULL,
description varchar(300),
created_at date,
updated_at date,
PRIMARY KEY (id),
KEY users_id (user_id)
) ENGINE=InnoDB;
ALTER TABLE projects (
ADD CONSTRAINT user_projects,
FOREIGN KEY (user_id) REFERENCES users(id),
ON DELETE CASCADE
)
So what I'm getting lost on is what is the differences between a key, an index, a constraint and a foreign key?
I've been looking online and can't find a newbie explanation for it.
PS. I'm using phpactiverecord and have the relationships set up in the models
user-> has_many('projects');
projects -> belongs_to('user');
Not sure if that has anything to do with it, but thought i'd throw it in there..
Thanks.
EDIT:
I thought it could possible be something to do with Navicat, so I went into WampServer -> phpMyAdmin and ran this...
DROP TABLE IF EXISTS projects;
CREATE TABLE projects (
id int(8) unsigned NOT NULL,
user_id int(8) NOT NULL,
name varchar(120) NOT NULL,
description varchar(300),
created_at date,
updated_at date,
PRIMARY KEY (id),
KEY users_id (user_id),
FOREIGN KEY (user_id) REFERENCES users(id)
) ENGINE=InnoDB;
Still nothing... :(
Expanding on Shamil's answers:
INDEX is similar to the index at the back of a book. It provides a simplified look-up for the data in that column so that searches on it are faster. Fun details: MyISAM uses a hashtable to store indexes, which keys the data, but is still linearly proportional in depth to the table size. InnoDB uses a B-tree structure for its indexes. A B-tree is similar to a nested set - it breaks down the data into logical child groups, meaning search depth is significantly smaller. As such, lookups by ranges are faster in a InnoDB, whereas lookups of a single key are faster in MyISAM (try to remember the Big O of hashtables and binary trees).
UNIQUE INDEX is an index in which each row in the database must have a unique value for that column or group of columns. This is useful for preventing duplication, e.g. for an email column in a users table where you want only one account per email address. Important note that in MySQL, an INSERT... ON DUPLICATE KEY UPDATE statement will execute the update if it finds a duplicate unique index match, even if it's not your primary key. This is a pitfall to be aware of when using INSERT... UPDATE statements on tables with uniques. You may wind up unintentionally overwriting records! Another note about Uniques in MySQL - per the ANSI-92 standard, NULL values are not to be considered unique, which means you can have multiple NULL values in a nullable unique-indexed column. Although it's a standard, some other RDBMSes differ on implementation of this.
PRIMARY KEY is a UNIQUE INDEX that is the identifier for any given row in the table. As such, it must not be null, and is saved as a clustered index. Clustered means that the data is written to your filesystem in ascending order on the PK. This makes searches on primary key significantly faster than any other index type (as in MySQL, only the PK may be your clustered index). Note that clustering also causes concerns with INSERT statements if your data is not AUTO_INCREMENTed, as MySQL will have to shift data around on the filesystem if you insert a new row with a PK with a lower ordinal value. This could hamper your DB performance. So unless you're certain you know what you're doing, always use an auto-incremented value for your PK in MySQL.
FOREIGN KEY is a reference to a column in another table. It enforces Referential Integrity, which means that you cannot create an entry in a column which has a foreign key to another table if the entered value does not exist in the referenced table. In MySQL, a FOREIGN KEY does not improve search performance. It also requires that both tables in the key definition use the InnoDB engine, and have the same data type, character set, and collation.
KEY is just another word for INDEX.
A UNIQUE index means that all values within that index must be unique, and not the same as ant other within that index. An example would be an Id column in a table.
A PRIMARY KEY is a unique index where all key columns must be defined as NOT NULL, i.e, all values in the index must be set. Ideally, each table should have (and can have) one primary key only.
A FOREIGN KEY is a referential constraint between two tables. This column/index must have the same type and length as the referred column within the referred table. An example of a FOREIGN KEY is a userId, between a user-login table and a users table. Note that it usually points to a PRIMARY KEY in the referred table.
http://dev.mysql.com/doc/refman/5.1/en/create-table.html
I keep finding myself writing queries to avoid inserting when there are duplicates - things like
select * from foobar where bar=barbar and foo=foofoo
and then checking in PHP with mysql_num_rows() to see if the number of results is > 0 to determine whether to go forward with my insert.
EDIT: for instance, let's say a user wants to send an invitation to another user. I want to make sure that in my invitations table, I don't add another entry with the same pair invited_id AND game_id. so this requires some sort of check.
this feels inefficient (and slightly dirty). is there a better way?
What about unique index?
A UNIQUE index creates a constraint such that all values in the index must be distinct. An error occurs if you try to add a new row with a key value that matches an existing row. For all engines, a UNIQUE index permits multiple NULL values for columns that can contain NULL.
http://dev.mysql.com/doc/refman/5.1/en/create-table.html
EDIT:
A column list of the form (col1,col2,...) creates a multiple-column index. Index values are formed by concatenating the values of the given columns.
http://dev.mysql.com/doc/refman/5.0/en/create-index.html
In this case, create a unique index on (bar, foo), so that the insert fails on duplicated value. You just need to handle the exception in php. This way, the code is cleaner and faster.
Just use a UNIQUE key on the columns and the INSERT IGNORE statement to insert new rows (duplicate rows are IGNORED).
Beware that the UNIQUE key may not exceed a 1000 bytes, meaning that the potential number of bytes contained in the fields foo and bar together may not exceed a 1000 bytes. If this creates a problem, just MD5 the CONCATENATED values into its own column at insert time, like (in PHP) md5($foo.$bar), and set the unique key to that column.
CREATE TABLE `test_unique` (
`id` int(10) unsigned NOT NULL auto_increment,
`foo` varchar(45) default NULL,
`bar` varchar(45) default NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `Unique` (`foo`,`bar`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT IGNORE INTO `test_unique` VALUES
(1, 'foo1', 'bar1'),
(2, 'foo2', 'bar2');
INSERT IGNORE INTO `test_unique` VALUES
(2, 'foo2', 'bar2');