Update many-to-many relation table without violating primay contraint - mysql

Considering two tables with a many-to-many relation :
Company Speciality
--------- ---------
id id
--------- ---------
1 21
2 22
3 23
4
CompanySpeciality
--------------------------
company_id | speciality_id
--------------------------
1 | 21
1 | 22
4 | 21
4 | 23
I want to delete company 4, and associate its specialities to the company 1.
If I use a simple UPDATE statement on CompanySpeciality to set "company_id = 1 WHERE company_id=4", I'm facing the primary contraint violation because the pair 1|21 already exists.
Is the a way to update the relation table with a single query ? This query should only affect rows that will not be duplicated.
The result would be :
CompanySpeciality
--------------------------
company_id | speciality_id
--------------------------
1 | 21
1 | 22
1 | 23

something to the effect of:
UPDATE CompanySpecialty
SET company_id=1
WHERE company_id=4
AND NOT EXISTS (SELECT * FROM CompanySpecialty cs WHERE cs.company_id=1 AND cs.specialty_id=CompanySpecialty.specialty_id);
should work for you. (i haven't tested the exact syntax, but using a NOT EXISTS clause should help you eliminate the problem of violating primary key restraints).
you will then have to remove the extra records left in the table for company 4 in a separate query:
DELETE FROM CompanySpecialty
WHERE company_id=4;

You don't want to UPDATE, you want to INSERT and ignore dupes:
INSERT IGNORE INTO CompanySpeciality (company_id, speciality_id)
SELECT 1, speciality_id
FROM CompanySpeciality
WHERE company_id=4

you won't be able to both update and delete records in a single query. You can use transactions:
mysql: select, insert, delete and update in one query

Related

Inserting a foreign key, on missing key, update

I have two tables:
tbl1:
============================
ID | TOKEN(indexed)
============================
1 | 2176
2 | 2872
3 | 2881
4 | 1182
tbl2:
=======================
ID | TOKEN_REF
=======================
1 | 2
2 | 3
3 | 1
4 | 1
in each iteration the server would receive a 'token', and would update tbl1 if no token exists, in this example token "5241" would require an insert into tbl1.
I need to update tbl2 where tbl2.ID is AUTO_INCREMENTed whenever a token is received (existing or not).
If the token is a new one, first update tbl1, and only then update tbl2 with the id of the new token.
I was thinking on the INSERT ON EXIST UPDATE, but I don't know how to combine it into a single command.
To summarize:
I need to INSERT ON EXIST UPDATE tbl1 in each iteration and INSERT the resulting ID into tbl2 in a single command. is that possible?
ideas?
I have prepared an SQLFiddle of as per Ondřej's suggestion, which may be found here.
In the schema I have proposed the following After Insert trigger:
CREATE TRIGGER tbl1_ai AFTER INSERT ON tbl1
FOR EACH ROW
INSERT INTO tbl2(TOKEN_REF)
VALUES(new.ID);

Mysql select query different tables comparison

first of all sorry if this question is very bad , but I 'm really confused and google doesn't help :(
I have a table named "project" which has the following columns:
Name | Description | Max Grade |
1 | blabla | 2 |
I have another table named "uploaded_projects" which has the following columng:
Pname | Team Code | Grade | Max Grade |
1 | 234 | 2 | (that's what i want) |
I added a foreign key constrait with the following code.
ALTER TABLE uploaded_projects
ADD CONSTRAINT 'fk_u_p' FOREIGN KEY 'fk_u_p'(Pname)
REFERENCES 'project'(Name)
Now I want to fill the second table's column " Max Grade" with the values of 1st table's "max grade" column , which are conected through columns "Name"(1st tabled primary key) and "Pname" ( 2nd table column). How can I do that?
Thank you in advance
You can try update statement
UPDATE uploaded_projects, project
SET uploaded_projects.max_grade= project.max_grade
WHERE project.`name`= uploaded_projects.pname
or use join
UPDATE uploaded_projects AS t1
INNER JOIN project AS t2 ON t1.pname= t2.`name`
SET t1.max_grade = t2.max_grade
Update upload_projects
Inner join project on (upload_projects.pName = project.Name )
set upload_projects.MaxGrade = project.MaxGrade

Merge 2 databases into another one without duplicate records

I have a question I want to merge 2 databases into another one but the problem is there are duplicate rows. So how can I merge the 2 databases into another one without duplicate records? I hope someone can help me.
Database 1
Name | Number | Code
Demo | 0293 | 827
Test | 0482 | 923
Database 2
Name | Number | Code
Lol | 0223 | 182
Stack| 1923 | 829
Demo | 0293 | 827
Thanks
This should really be done with a unique key and ON DUPLICATE KEY. If not willing to do that, the following would also work:
Assuming the tables are identical and that you only want to exclude a row when ALL columns are the same as a row in the target table.
INSERT into Table1
SELECT * from Table2
WHERE concat(Name,'|',Number,'|',Code) not in (
SELECT concat(Name,'|',Number,'|',Code)
FROM Table1
)
Select A.*,B.* from TABLE1 AS A,TABLE2 AS B where A.code=B.code GROUP BY A.code;
I think you are talking about TABLE not DATABASE. Use GROUP BY clause or find DISTINCT value with the query. And you have not specified any primary key..so read mysql tutorial first..

Mysql (php) update or replace shopping bag content in one query, with multiple values

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.

Reorder rows in a MySQL table

I have a table:
+--------+-------------------+-----------+
| ID | Name | Order |
+--------+-------------------+-----------+
| 1 | John | 1 |
| 2 | Mike | 3 |
| 3 | Daniel | 4 |
| 4 | Lisa | 2 |
| 5 | Joe | 5 |
+--------+-------------------+-----------+
The order can be changed by admin hence the order column. On the admin side I have a form with a select box Insert After: to entries to the database. What query should I use to order+1 after the inserted column.
I want to do this in a such way that keeps server load to a minimum because this table has 1200 rows at present. Is this the correct way to save an order of the table or is there a better way?
Any help appreciated
EDIT:
Here's what I want to do, thanks to itsmatt:
want to reorder row number 1 to be after row 1100, you plan to leave 2-1100 the same and then modify 1 to be 1101 and increment 1101-1200
You need to do this in two steps:
UPDATE MyTable
SET `Order` = `Order` + 1
WHERE `Order` > (SELECT `Order`
FROM MyTable
WHERE ID = <insert-after-id>);
...which will shift the order number of every row further down the list than the person you're inserting after.
Then:
INSERT INTO MyTable (Name, `Order`)
VALUES (Name, (SELECT `Order` + 1 FROM MyTable WHERE ID = <insert-after-id>));
To insert the new row (assuming ID is auto increment), with an order number of one more than the person you're inserting after.
Just add the new row in any normal way and let a later SELECT use ORDER BY to sort. 1200 rows is infinitesimally small by MySQL standards. You really don't have to (and don't want to) keep the physical table sorted. Instead, use keys and indexes to access the table in a way that will give you what you want.
you can
insert into tablename (name, `order`)
values( 'name', select `order`+1 from tablename where name='name')
you can also you id=id_val in your inner select.
Hopefully this is what you're after, the question isn't altogether clear.