This isn't an (exact) duplicate of this questions so I'Ve started a new one.
I have this table (ID is primary and auto increment)
ID | mykey | myfoo | mybar
============================
1 | 1.1 | abc | 123
2 | 1.1.1 | def | 456
3 | 1.2 | abc | 789
4 | 1.1 | ghi | 999
I would like to UPDATE row 1 with mybar = "333" only if mykey = '1.1' AND myfoo = 'abc'
If either mykey != '1.1' OR myfoo != 'abc' I would like to INSERT an new row.
Is this possible with one statement?
A unique index in MySQL does not have to be on a single column. You can add a UNIQUE index on multiple columns simply by specifying more columns in your ALTER TABLE..ADD UNIQUE statement:
ALTER TABLE myTable ADD UNIQUE (
mykey,
myfoo
);
Now you can use a regular INSERT INTO...ON DUPLICATE KEY statement.
SQLFiddle DEMO (note that the multiple repeated values are not added - all others are)
Note:
If either is NULL, it will not be counted as unique. mykey being 'bar' and myfoo being NULL could be added to infinity even though they have the "same" values (NULL isn't really a value).
Related
I'm trying to achieve something in MySQL that I have not heard is possible before (maybe it is, researching didn't help me much).
What I'm trying to do is enforce uniqueness in MySQL across two columns. What I mean by this is not setting UNIQUE(column1,column2) but the following two conditions:
If a value exists in column1, it cannot be repeated in column1 (same as setting UNIQUE(column1)).
If a value exists in either column, it cannot exist in the other column.
Hence, for the data set {column1,column2}, if {1,2}, {3,4}, {5,6} are data already present, then neither of the two columns can have any of the above data items for new data,i.e. new data item {x,y} where x=NOT{column1} AND y=NOT{column2} AND x!=y
Is this possible? Please help me out here. Thank you.
This might be an overkill, but you can store column1 and column2 in a separate table.
Let's say your table is
create table items (
id int primary key,
column1 int,
column2 int
);
with data:
id | column1 | column2
---|---------|--------
1 | 1 | 2
1 | 3 | 4
1 | 5 | 6
You can change your schema to
create table items (
id int primary key
);
create table item_columns (
item_id int,
position int,
val int,
primary key (item_id, position),
unique key (val),
foreign key (item_id) references items(id)
);
with data:
item_id | position | val
--------|----------|----
1 | 1 | 1
1 | 2 | 2
2 | 1 | 3
2 | 2 | 4
3 | 1 | 5
3 | 2 | 6
You can simulate the old schema with
select i.id, c1.val as column1, c2.val as column2
from items i
left join item_columns c1
on c1.item_id = i.id
and c1.position = 1
left join item_columns c2
on c2.item_id = i.id
and c2.position = 2
You can use it in a view if you like.
Demo: http://rextester.com/PPBT42478
To guaranty the integrity for the position column, you can make it a foreign key to a positions table, which will only contain the values 1 and 2. You could also use ENUM('1', '2'), but ENUM always allow an empty string as a value.
I have a table with key/value columns. I need to update a key/value pair based on another value's condition.
Table:
--------------------------
| id | key | value |
--------------------------
| 1 | country | canada |
| 2 | privacy | default |
--------------------------
In this case I need to change value to canada where key = privacy only IF country = canada.
I've tried something like this:
UPDATE settings
SET value =
CASE
WHEN key = 'country' AND value = 'canada' THEN 'canada'
ELSE value
END
WHERE key = 'privacy'
but it results in an error on the CASE condition. I think I might need to do some sort of sub-query?
Your statement won't work as you can't have a record with both a key of 'privacy' and 'country'. You need to perform a SELECT on the table itself to check if 'country' is set to 'canada'. Something like the following may work.
UPDATE settings
SET value = 'canada'
WHERE key = 'privacy'
AND EXISTS(SELECT * FROM (SELECT * FROM settings WHERE key = 'country' AND value = 'canada') AS temp_settings);
Because I am using a data structure beyond my control, there is a table in my DB which will potentially have millions of Foreign-key => (key => value) pairs. Now, I know that one of the keys will be a certain value (in this case the key is related_content). Is it possible for MySQL to optimize the query so that it does not have to search the entire table for results?
Example table (called meta):
fk | key | value
====================================
1 | 'related_content' | '[2,3,4]'
1 | 'condiment' | 'mayo'
1 | 'condiment' | 'bananas'
29 | 'condiment' | 'ketchup'
29 | 'related_content' | '[1,7,9]'
95 | 'condiment' | 'mustard'
95 | 'related_content' | '[5,6,8]'
Example query:
SELECT value FROM meta WHERE fk = 29 AND key = 'related_content';
What I would like to do is:
ALTER TABLE `meta` ADD INDEX `meta_related` ON (`key`) WHERE `key` = 'related_content';
(Before anyone asks, the key column already has an index on it)
Add a 'composite' index
INDEX(fk, key)
what if you will add the key_index (int11) column that will represent the string in a key column like : related_content =1, condiment=2 and you will add index on key_index column, the index on int will be faster than on string, at the end you will select using two indexed integer field. It's gonna be fast
I have tgot the following table structure
mysql> desc test
-> ;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(19) | NO | PRI | | |
| name | varchar(19) | YES | | NULL | |
| age | varchar(19) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.05 sec)
Initialy i have done an insert as shown
insert into test (id, name, age) values("1", "A", 19);
my requirement is that , i need to extract the age of id "1" and add some integer to the existing age
I have seen this below example , can tis be useful in my case ??
insert into test (id, name, age) values("1", "A", 30) on duplicate key update age=values(age)
I am using JAVA , i have symbols of 300 , for which i need to update contonouslly
Is it possible to do a select and update the existing column with new value in the same query ??
For example
how can i get the existing age 19 and add it with 30 in the same query for the id 1 ??
(This question has already been answered by Marc B in the comments section.)
Yes, the statement OP has posted will work just fine, because there is a primary key constraint on the id column, and INSERT ... ON DUPLICATE KEY will cause an UPDATE of the existing row.
To "add" the value being inserted to the value that already exists in the column, we'd assign an expression that does that operation to the column:
e.g.
insert into test (id, name, age) values("1", "A", 30)
on duplicate key update age = age + values(age)
^^^^^
Note that the only change required in OP statement is the reference to the existing column value and an addition operation.
N.B. If either the existing value in the column, or the new value being supplied in the INSERT statement is NULL, the result of the expression will be NULL. A different expression would be needed if this is undesired behavior.
This should work:
UPDATE test SET age=age+1 WHERE id=1;
I've got the flowing tables in mysql db for a shopping bag:
BAGS
-----
| bagID | date_added |
| primary Key | |
------------------------------
| 1 | 2012-01-04 |
BAGS_CONTENT
-----
| ID | productID | qyt |
| foreign key->bagID | | |
-----------------------------------------
| 1 | 103 | 4 |
// $sql Could contain this:
$sql = "(1,103,5),
(1,101,3)";
INSERT INTO BAGS_CONTENT
( ID, product_id, qty)
VALUES
".$sql."
I like the BAGS_CONTENT to update an existing record (if exists ID and product_id) and add a new row if not exists (the ID and product_id).
I've tried using REPLACE INTO and ON DUPLICATE KEY UPDATE but I can't get it to work.
May be its has something to do with the keys?
How should you query the db in a situation like this?
ON DUPLICATE KEY UPDATE triggers the UPDATE statement when the unique value is already existing in the table. Make sure that you've set the right fields to be unique. I think you have to put an UNIQUE on ID and productID (both in one combined unique):
ALTER TABLE BAGS_CONTENT ADD UNIQUE (ID, product_id)
Your query should look like this:
INSERT INTO BAGS_CONTENT (ID, product_id, qty) ".$sql." ON DUPLICATE KEY UPDATE qty = VALUES(qty);
Here's more information about 'on duplicate key':
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
To use ON DUPLICATE KEY UPDATE you first need to create a unique key on BAGS_CONTENT(ID,productID)
Then use
INSERT INTO BAGS_CONTENT (ID,productID,qyt) VALUES(1,101,3) ON DUPLICATE KEY UPDATE qyt=VALUES(qyt);
You need to create a key error in order to trigger the special behavior of REPLACE. To get the proposed behavior add an index:
mysql> create table bag_content (id INT,productID INT,qty SMALLINT);
mysql> create unique index baggy on bag_content (id,productID);
mysql> replace bag_content values(1,111,5);
mysql> replace bag_content values(1,112,5);
mysql> replace bag_content values(1,111,500);
mysql> select * from bag_content;
+------+-----------+------+
| id | productID | qty |
+------+-----------+------+
| 1 | 111 | 500 |
| 1 | 112 | 5 |
+------+-----------+------+
Also watch out: you're using SQL supported in mysql only. The pejorative is 'their sql'... because of all the innovations of mysql that don't go through a standards process. The replace functionality is great, but it will increase the barrier to moving your code to other databases.