select from view -> update OR insert into table - mysql

I want to select data from a mysql-view which collects and joins data from "federated"-tables.
This data should be inserted into a table which looks very similar to the view.
an example would be:
table where data needs to be inserted or updated:
insertTable
+----+-----------+------+-------------+
| id | foreignId | data | foreignData |
+----+-----------+------+-------------+
| 1 | a | 111 | aaa |
| 2 | b | 222 | bbb |
+----+-----------+------+-------------+
the view where the data comes from:
dataView
+-----------+-------------+
| foreignId | foreignData |
+-----------+-------------+
| a | AAA |
| b | BBB |
| c | CCC |
+-----------+-------------+
insertTable
+----+-----------+------+-------------+
| id | foreignId | data | foreignData |
+----+-----------+------+-------------+
| 1 | a | 111 | AAA |
| 2 | b | 222 | BBB |
| 3 | b | | CCC |
+----+-----------+------+-------------+
and at this point i think i need a stored procedure which does following written in pseudo code
$result = SELECT * FROM dataView;
foreach $result as $row {
if(SELECT COUNT(*) FROM inserTable WHERE foreignId=$row[foreignId]>0)
UPDATE insertView SET foreignData = $row[foreignData] WHERE foreignId=$row[foreignId];
else
INSERT INTO insertView (id, foreignId, foreignData) VALUES (null,$row[foreignId],$row[foreignData];
}

You can use REPLACE query.
REPLACE INTO insertView (id, foreignId, foreignData) VALUES (null,$row[foreignId],$row[foreignData];
From mysql documentation
REPLACE works exactly like INSERT, except that if an old row in the
table has the same value as a new row for a PRIMARY KEY or a UNIQUE
index, the old row is deleted before the new row is inserted. See
Section 13.2.5, “INSERT Syntax”.
PRIMARY KEY or a UNIQUE index not specified it will insert a new row.
So no need to SELECT checking.

The magic which is ideal for this problem was ON DUPLICATE KEY UPDATE
In my example the solution would look like this:
INSERT INTO insertTable
(
`foreignId`,
`foreignData`
)
SELECT
`dataView`.`foreignId`,
`dataView`.`foreignData`
FROM
`dataView`
ON DUPLICATE KEY UPDATE
`foreignId` = `dataView`.`foreignId`,
`foreignData` = `dataView`.`foreignData`;

Related

How do I add multiple values to a column in SQL which already has other rows filled

I'm trying to update this table (name: sports_club):
+----+-----------+----------------+
| id | name | sport_interest |
+----+-----------+----------------+
| 7 | Winston | NULL |
| 8 | Winnefer | NULL |
| 9 | Winsteen | NULL |
| 10 | Wincifer | NULL |
| 11 | Winster | NULL |
| 12 | Winstonia | NULL |
| 13 | Wilson | NULL |
| 14 | Winnerva | NULL |
| 15 | WinDiesel | NULL |
+----+-----------+----------------+
I'm trying to add values to just the sport_interest column of the existing records, I tried to do that by using:
insert into sport_interest values ('cricket'), ('football'), etc.
But it did not work as it was trying to add it to new records which I don't want to do.
I'm using MySQL
You can do the updates manually like:
update sport_interest set sport_interest = 'cricket' where id=7;
update sport_interest set sport_interest = 'football' where id=8;
And so on...
But, if you have the id of the values that you need to update it is much easier.
You can create another table like:
create table sport_interest_bak (
id int ,
sport_interest varchar(50));
You can use LOAD DATA to insert the data on the new table and then update using inner join, it is simpler and much faster.
update sport_interest s
inner join sport_interest_bak sb on s.id=sb.id
set s.sport_interest=sb.sport_interest;
I suggest reading https://www.mysqltutorial.org/mysql-basics/ or https://www.techonthenet.com/mysql/index.php this are much better than W3Schools
Use the 'Update' command for existing entries.
"UPDATE table SET sport_interest = 'football'" should work.
Use WHERE clause if you did not want all cells to update. ex.
UPDATE table SET sport_interest = 'football' WHERE name = 'Winston'

how to convert table columns into a table in mysql?

I know it's a bad title, but I don't know how to describe my question in a line.
I want to store following information in my database.
+----+----------+-----------+-----------+
| id | name | cluster_1 | cluster_2 |
+----+----------+-----------+-----------+
| 1 | content_1| true| false |
| 2 | content_2| false| true |
| 3 | content_3| true| true |
+----+----------+-----------+-----------+
cluster_1=true means that the content exists on the cluster_1.
As some clusters may added or deleted, I want to store my cluster information in a new table "clusters", and indicate the relation between contents and clusters with a "content_cluster" table.
table contents
+----+----------+
| id | name |
+----+----------+
| 1 | content_1|
| 2 | content_2|
| 3 | content_3|
+----+----------+
table clusters
+----+----------+
| id | name |
+----+----------+
| 1 | cluster_1|
| 2 | cluster_2|
+----+----------+
table content_cluster
+----------+----------+
|content_id|cluster_id|
+----------+----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
+----------+----------+
But, writing in this way, I don't know how to get a content which is on cluster_1 but isn't on cluster_2, or vice versa. I have to do this query frequently. So what is the efficient way to do this?
how to get a content which is on cluster_1 but isn't on cluster_2
in general
SELECT contents.name
FROM contents
JOIN content_cluster ON contents.id = content_cluster.content_id
LEFT JOIN clusters ON clusters.id = content_cluster.cluster_id
GROUP BY contents.name
HAVING SUM(clusters.name = 'cluster_1') -- not zero, may add ">0"
AND !SUM(clusters.name = 'cluster_2') -- zero, may replace NOT ("!") with "=0"
The following should work:
-- For cluster 1
INSERT INTO new_table (content_id, cluster_id)
SELECT old_table.content_id, 1
FROM old_table
WHERE old_table.cluster_1 = TRUE;
-- For cluster 2
INSERT INTO new_table (content_id, cluster_id)
SELECT old_table.content_id, 2
FROM old_table
WHERE old_table.cluster_2 = TRUE;

How to insert data for one column for all the rows in single query in Mysql?

+----+------------+------------+------------+----------+
| id | phone_no | join_date | city | blood_gp |
+----+------------+------------+------------+----------+
| 1 | 80077672xx | 1997-07-19 | Delhi | NULL |
| 2 | 80077642xx | 1998-07-19 | New Delhi | NULL |
| 3 | 80477642xx | 1999-07-19 | Mumbai | NULL |
| 4 | 80077654xx | 1997-05-31 | Kolkata | NULL |
+----+------------+------------+------------+----------+
I want to enter all the blood groups at once . Is there a way to do so ?
you can use single query with select and update
UPDATE table1 , (SELECT * FROM table2 where 1) src
SET table1.blood_gp = src.filed2 where 1 ;
if you want to insert multiple row data using single query then use this code
INSERT INTO yourtable (x,y,z) VALUES (a1,a2,a3), (b1,b2,b3);
or if you want to update one column value all filed then use this code
update yourtable set blood_gp = 'yourvalue' where 1;
if any problem then inform me
Just make an update query without where clause.
update table set blood_gp = 'value'
That's generalize query.

how to update table using trigger

i am new to this and want some help.i have table with name "abc" with following entries
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 101 | john | abc |
| 102 | Miller | cbz |
+------+--------+------+
and another table "xyz"
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 102 | Miller | cbz |
+------+--------+------+
i applied trigger on table "abc" which will update the table "xyz" with recently inserted values and will delete all previous entries...
for example, when i fire insert query on "abc" table i get ,"abc" as follow
insert into abc Values(103,'Joseph','xyz');
i get output for table "abc" as,
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 101 | john | abc |
| 102 | Miller | cbz |
| 103 | Joseph | xyz |
+------+--------+------+
and table "xyz" as,
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 103 | Joseph | xyz |
+------+--------+------+
now my question is how to acheive this using only one table(i dont want to use two table as this is not my requirement).
like following ..
insert into xyz values(104,'Ridhit','pqr');
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 104 | Ridhit | pqr |
+------+--------+------+
Please help.Trigger i used is
DELIMITER !!
create trigger OnlyOne BEFORE INSERT on abc
for each row
BEGIN
DECLARE a1 INT;
Select count(1) INTO a1 from xyz;
IF a1>0 THEN
delete from xyz limit 1;
insert into xyz(Id,Name,City) values (new.Id,new.Name,new.City);
ELSE
insert into xyz(Id,Name,City) values (new.Id,new.Name,new.City);
END IF;
END;
!!
DELIMITER ;
Do this on application level, but you better make sure you use transactions. You probably don't want to have an empty table, when the operation crashes in the middle.
You may also consider to have following approach.
Instead of deleting/updating whenever an insert occurs, add a column like created with default value of current timestamp to your table so that it looks something like this:
CREATE TABLE abc(
id int auto_increment primary key,
name varchar(50),
city varchar(50),
created timestamp default current_timestamp
);
To get the latest entry you just do
SELECT * FROM abc ORDER BY created DESC LIMIT 1;
Or you put this in a view
CREATE VIEW just_latest_entry_from_abc AS
SELECT * FROM abc ORDER BY created DESC LIMIT 1;
Then you just do
SELECT * FROM just_latest_entry_from_abc;
When table size matters, create a cronjob or a scheduled event to delete older entries on a regular basis.

mySQL cross table field linking

Basically I have two tables A and B. These are linked by unique ID's where the entries in B point to one entry in A. The entries in A and B also have a 'status' field denoting if the entry is active or not...
My questions is therefore; is it possible to link the status field of the entries in B and have them update, every time the 'status' field in A (pointed to by the unique ID) is updated? I could do this fairly easy with an SQL command however I'm wondering if there is a more automatic solution. Example:
table A
|------ID------|----status----|
| 1 | on |
| 2 | on |
|---------------|----------------|
table B
|-----eID------|------ID------|----status----|
| 1 | 1 | on |
| 2 | 1 | on |
| 3 | 2 | on |
|---------------|---------------|----------------|
I then run:
UPDATE `A` SET `status` = 'off' WHERE `ID` = 1;
And the result would be:
table A
|------ID------|----status----|
| 1 | off |
| 2 | on |
|---------------|---------------|
table B
|-----eID------|------ID------|----status----|
| 1 | 1 | off |
| 2 | 1 | off |
| 3 | 2 | on |
|---------------|---------------|----------------|
Is that possible?
Many Regards,
Andreas
i hope this trigger code can help u.
CREATE TRIGGER `abc` AFTER UPDATE ON `tablea` FOR EACH ROW BEGIN UPDATE tableb SET STATUS = new.status WHERE id = new.id;
END