I have an table calles SpecialOffer with productId, shopId, from , until , where the last two ones are datetime's.
I know i can do something like this
CREATE UNIQUE INDEX UniqueIndex2 ON SpecialOffer(codP, codS)
for codP to be uniq in scope of codS, but how can I accomplish this uniqueness only between 'from' and 'until' ?
You need to do this with triggers -- insert and update trigger. These can check for overlaps in the time periods.
In general, in MySQL, most constraints are handled through triggers (except for unique constraints and foreign key constraints).
Related
When doing an INSERT INTO {tableA} SELECT a,b,c FROM {tableB} ON DUPLICATE KEY UPDATE x=y
What is the precedence on how the duplicate keys are evaluated? I assume that MySQL first checks to see if a tuple from tableB exists clashes with a unique/primary key in tableA. If the SELECT doesn't include a primary key, or if no other duplicate key exists, then each subsequent UNIQUE INDEX "group" is evaluated and the same checking is performed. But what happens if your tableB has multiple sets of unique, multi-column indexes? Are they evaluated top-to-bottom, as described by SHOW INDEXES FROM tableB ?
Here's my SHOW INDEXES FROM <table>:
Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation
daily_metrics,0,PRIMARY,1,id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,1,line_item_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,2,creative_id,A
daily_metrics,0,unique_lineItem_creative_y_m_d,3,year,A
daily_metrics,0,unique_lineItem_creative_y_m_d,4,month,A
...
Imagine there are additional sets of unique indexes similar to unique_lineItem_creative_y_m_d
The docs don't seem to illustrate this behavior.
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
I also assume that the first matching unique index is used, if a match exists, without any attempt to match subsequent unique indexes that could match. In other words, the first unique index that matches is used, without regard for trying to find the best possible match across all indexes.
You are correct: as soon as MySQL detects a duplicate in any UNIQUE index, it abandons the INSERT and does the update.
The order in which MySQL evaluates the unique indexes does not change the outcome. There's no such thing as a better match for some unique index over another. Because they're unique indexes, any combination of column values that shows up as a duplicate is enough to completely specify the row to be updated.
MySQL's query planner, hopefully, chooses the index that's least costly to evaluate. But, formally speaking, the index it uses for this purpose is unpredictable. This unpredictability is an attribute of declarative languages like SQL. MySQL can do its work any way that works, and it doesn't have to tell you. It can be hard for programmers to grasp, because we're used to procedural languages.
If any primary or unique keys exist in tableB, that's irrelevant. The only thing that matters for INSERT...ON DUPLICATE KEY UPDATE are the primary or unique keys of the table you're inserting into — tableA in your example.
If the values you insert to tableA are already found in any of tableA's primary or unique keys, that triggers the UPDATE part of the IODKU.
It's about the values being inserted, not the constraints of the source table.
You can also trigger the UPDATE without using any source table -- just by inserting a VALUES() clause with a set of constants.
I have a mysql table with i (primary),s and g columns. I have 2 queries:
INSERT INTO usertable (i, s, g) VALUES('1', '2', '5') ON DUPLICATE KEY SET s=(s*g+'2')/(g+'5'), g=g+'5';
and
SELECT s FROM usertable WHERE i='1' LIMIT 1
Is it possible to have both the queries in 1 query? Basically want to reduce number DB queries.
THanks
You can perform an INSERT ON DUPLICATE KEY UPDATE (IODKU) followed by a select, that is, 2 statements. Or you can wrap them in a stored procedure and make one. Perhaps not the answer you wanted to hear.
As for the IODKU, you naturally need a unique key to facilitate the clash that triggers the UPDATE section. That unique key can be one of the following:
Primary Key (single column or composite)
non-Primary key (single column or composite) with unique keyword
Note that an upsert clash can occur on more than one unique key. All it takes is one of the unique key clashes to trigger the UPDATE section.
A single call can be achieved with one to a stored procedure such as:
call myStoredProcName(param1,param2);
Further manual page references:
INSERT ... ON DUPLICATE KEY UPDATE Syntax
Multiple-Column Indexes a.k.a. Composite Indexes
Working with Stored Procedures and CREATE PROCEDURE and CREATE FUNCTION Syntax
I want to know whether it is possible to avoid duplicate entries or data without any keys or group by statement
Create Unique key constrait.
ALTER TABLE Comment ADD CONSTRAINT uc_Comment UNIQUE (CommentId, Comment)
In above case Comment duplication will not be done as we are creating the unique combination of COmmentId and Comment.
Hope this helps.
More info : http://www.w3schools.com/sql/sql_unique.asp OR
SQL Server 2005 How Create a Unique Constraint?
If you want to suppress duplicates when querying, use SELECT DISTINCT.
If you want to avoid putting duplicates into a table, just don't insert records that are already there. It doesn't matter whether you have a primary/unique key: those will make the database not allow duplicate records, but it's still up to you to avoid trying to insert duplicates (assuming you want your queries to succeed).
You can use SELECT to find whether a record already exists before trying to insert it. Or, if you want to be fancy, you can insert the new records into a temporary table, use DELETE to remove any that are already present in the real table, then use INSERT ... SELECT to copy the remaining records from the temporary table into the real one.
I want to do the following:
INSERT INTO table1 (term1, term2, number) values ('A','B',10);
however if values A and B are already present in table1 regardless of their order, ie. the predicate
(term1='A' && term2='B') OR (`term1='B' && term2='A')
holds true, then I just want to update column number. Is there any way of doing that?
A (perhaps the) clean way to handle this situation is to use INSERT ... ON DUPLICATE KEY UPDATE, read the documentation.
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that
would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL
performs an UPDATE of the old row
The important part is would cause a duplicate value in a UNIQUE index. Therefore you need to create an multicolumn unique index.
Now I'm not sure if you can manage the order that way, therefore I'd create an extra field with the concatenation of the sorted values of your fields, and have that field uniquely indexed.
EDIT: Instead of storing the concatenation your fields, you could also just store the hash and index it.
Thanks #okiharaherbst,
This is what I did: I added new column "uniqueKey" as primary key and insert goes as follows:
INSERT INTO table1(term1,term2,num,uniquekey) VALUES ( "a","b",10,
concat(greatest(term1,term2),least(term1,term2))) on duplicate key update num=10;
I have a table with just one column: userid.
When a user accesses a certain page, his userid is being inserted to the table. Userids are unique, so there shouldn't be two of the same userids in that table.
I'm considering two designs:
Making the column unique and using INSERT commands every time a user accesses that page.
Checking if the user is already recorded in the table by SELECTing from the table, then INSERTing if no record is found.
Which one is faster?
Definitely create a UNIQUE index, or, better, make this column a PRIMARY KEY.
You need an index to make your checks fast anyway.
Why don't make this index UNIQUE so that you have another fallback option (if you for some reason forgot to check with SELECT)?
If your table is InnoDB, it will have a PRIMARY KEY anyway, since all InnoDB tables are index-organized by design.
In case you didn't declare a PRIMARY KEY in your table, InnoDB will create a hidden column to be a primary key, thus making your table twise as large and you will not have an index on your column.
Creating a PRIMARY KEY on your column is a win-win.
You can issue
INSERT
IGNORE
INTO mytable
VALUES (userid)
and check how many records were affected.
If 0, there was a key violation, but no exception.
How about using REPLACE?
If a user already exists it's being replaced, if it doesn't a new row is inserted.
what about doing update, e.g.
UPDATE xxx SET x=x+1 WHERE userid=y
and if that fails (e.g. no matched rows), then do an insert for a new user?
SELECT is faster... but you'd prefer SELECT check not because of this, but to escape from rasing an error..
orrrrrrr
INSERT INTO xxx (`userid`) VALUES (4) ON DUPLICATE KEY UPDATE userid=VALUE(`userid`)
You should make it unique in any cases.
Wether to check first using SELECT, depends on what scenario is most common. If you have new users all the time, and only occationally existing users, it might be overall faster for the system to just insert and catch the exception in the rare occations this happens, but exception is slower than check first and then insert, so if it is a common scenario that it is an existing user, you should allways check first with select.