INSERT on update. Compound Key - php

I have a question on This MySQL statement.
I got this from this post
However, I am not sure how to structure the query when I have the table like this.
TableA
--------
id ==> Auto Increment field
question_id
form_id
member_id
event_id
admin_id
desc
is_cand_field
c_field_id
In this, question_id, form_id, memmber_id, event_id, admin_id can be same. desc, is_cand_field, c_field_id can change. When inserting, I want to check if this combination exists. If exists, I want to update the last 3 fields. If not, I want to insert a record.
Is this possible with the above referred query. Its not clear from the page.

Add unique key on combination of these fields:
ALTER TABLE `tablea` ADD UNIQUE INDEX `compound_key` (`question_id`, `form_id`, `member_id`, `event_id`, `admin_id`);
Insert values and add update section:
INSERT INTO tablea (`question_id`, `form_id`, `member_id`, `event_id`, `admin_id`, `desc`, `is_cand_field`, `c_field_id`)
VALUES (1, 2, 3, 4, 5, 1, 0, 1)
ON DUPLICATE KEY UPDATE `desc` = VALUES(`desc`), is_cand_field = VALUES(`is_cand_field`), c_field_id = VALUES(`c_field_id`)

You can add multiple rows in the ON DUPLICATE KEY UPDATE section.
INSERT INTO TableA (form_id, member_id, event_id, admin_id, desc, is_cand_field, c_field_id)
VALUES (2, 3, 4, 5, 'b', 0, 1)
ON DUPLICATE KEY UPDATE desc='a', is_cand_field=1, c_field_id=2

Related

Not able to get distinct and max of the third table join in MySql

Schemas
// First table
CREATE TABLE assignments (
id int,
uid int,
comments varchar(255),
assignmentdate date,
status int
);
INSERT INTO assignments (id, uid, comments, assignmentdate, status)
values (1, 6, 'a', '2019-07-15', 0), (2, 6, 'ab', '2019-07-15', 0),
(3, 6, 'abc', '2019-07-14', 0), (4, 6, 'abc', '2019-07-14', 1)
, (5, 7, 'xyz', '2019-07-14', 1), (6, 7, 'zyx', '2019-07-14', 1);
// Second table
CREATE TABLE users (
id int,
username varchar(255),
status int
);
INSERT INTO users (id, username, status)
values (6, 'user1', 0), (7, 'user2', 0),
(8, 'user3', 1);
// Third table
CREATE TABLE user_images (
id int,
uid int,
imagename varchar(255),
status int
);
INSERT INTO user_images (id, uid, imagename, status)
values (1, 6, 'abc.jpeg', 0), (2, 6, 'def.jpeg', 0), (3, 8, 'ghi.png', 1);
what I'm looking for here is to get
1) distinct and latest row of table assignments which,
2) joins the table users and get a row and then joins,
3) distinct and latest row of table user_images.
So far i have gone through this answer
My trial query:
SELECT
p.*,
u.username,
groupedpi.*
FROM
assignments p
INNER JOIN(
SELECT
comments,
MAX(id) AS latest
FROM
assignments
WHERE
STATUS
= 0
GROUP BY
uid
) AS groupedp
ON
groupedp.latest = p.id
LEFT JOIN users u ON
p.uid = u.id AND u.status = 0
LEFT JOIN(
SELECT
uid,
MAX(id) AS latesti,
imagename
FROM
user_images us
WHERE
STATUS = 0
GROUP BY
uid
order by id desc LIMIT 1
) AS groupedpi
ON
groupedpi.uid = p.uid
Output:
The 3rd result I'm not getting, i.e I'm not getting the distinct and latest record of the third table while joining.
Instead of abc.jpeg, I want to get def.jpeg.
MySQL is tripping you up here, because it automatically adds columns to GROUP BY if they aren't specified, so it's grouping the groupedpi subquery on imagename too - this will lead to duplicated rows. Remove the imagename column from the subquery (and the order by clause is irrelevant too) and have it just output the userid and the max image id
If you want the image name, join the images table in again on images.id = groupedpi.latesti (In the main query not the subquery that is finding the latest image id)
(Note that your screenshot says lastesti 2 but imagename abc- it's not the right pairing. ID 2 is def.jpg. When you want latest Id but also other data from the same row you can't do it in one hit unless you use an analytic (mysql8+) - you have to write a subquery that finds the max id and then join it back to the same table to get the rest of the data off that row)

SQL Statement INSERT, on duplicate columns UPDATE

I have an SQL Table that contains a list of items that users can have linked to their profile. The SQL table looks something like this:
Item_Activity_ID Item_ID User_ID Status Date-Added
1 1 1 1 2015-06-08
2 2 2 1 2015-06-08
3 1 1 0 2015-06-09
The entry shows that someone with the user with id of 1 added item id 1 twice, and the only thing that was changed was the date and status. I want to make it so that when given an INSERT statement such as:
INSERT INTO items (Item_ID, User_ID, Status, Date_Added) VALUES ('$x', '$y', 1, CURDATE()) IF EXISTS SOME Item_ID = $x AND User_ID = $y UPDATE items SET Status = 1, Date_Added = CURDATE() WHERE Item_ID = $x AND User_ID = $y
Item_Activity_ID is an auto_incremented primary key index. How can I accomplish this in one query? Two users can have the same item, but where should never be repeat entries of the same user id and item id.
First, create a unique index for Item_ID, UserID combination,
Then, use the INSERT ... ON DUPLICATE KEY UPDATE statement:
INSERT INTO items (Item_ID, User_ID, Status, Date_Added)
VALUES ('$x', '$y', 1, CURDATE())
ON DUPLICATE KEY UPDATE Status = VALUES(Status), Date_Added = VALUES(Date_Added))
P.S. make sure to sanitize $x and $y to prevent SQL injections!
I would start by adding a unique key index:
ALTER TABLE items
ADD CONSTRAINT uc_UserItem UNIQUE (Item_ID,User_ID);
Then, you can just modify your insert query:
INSERT INTO items (Item_ID, User_ID, Status, Date_Added) VALUES ('$x', '$y', 1, CURDATE()) ON DUPLICATE KEY UPDATE Status=VALUES(1), Date_Added=VALUES(CURDATE());
Try to perform the update first supposing that the user and item already exist. Then check if this update affects any rows (using ##rowcount, in SQL Server).
If not then perform an insert.
Don't forget to put the above two statements in a transaction... ;)
Normal way would be to set a composite constraint at the db level. If you are using mysql and phpmyadmin you do this in the table structure view.
Check both fields (I guess 'user_id' and 'item_id') and click the 'unique' button.
After that is set you can just append
ON DUPLICATE KEY UPDATE status =1, date_added=CURDATE().
It will update the row that violated the constraint you created

PHP, SQL insert value into tables that are linked together?

I have 2 tables,
Table User:
Columns-> id, name, age, position, department, phone
Table Phone:
Columns id, u_id, u_phonetype (foreign key is user.id with on delete cascade and update cascade).
I want to perform this INSERT INTO sql with the u_phonetype from the Phone table:
INSERT INTO `user` (`id`, `name`, `age`, `position`, `department`,
`phone`) values ("'.$name.'", "'.$age.'", "'.$position.'", "'.$department.'", "'.$phone.'") ;
How do I insert into the values of u_phonetype into this SQL? Would I be performing a JOIN?
using php you would just need to use 2 / 3 queries to get this done.
// insert your user
INSERT INTO users (columns) VALUES(vals);
// get the last id
SELECT id FROM users order by id desc limit 1
// this is also work if you just do
SELECT id FROM users where name='name' and age='age' "and whatever values you have";
// then insert into phone with the id retrieved from above
INSERT INTO Phone (columns) VALUES(vals);
3 step process but under the same connection it should be ok
What about
LAST_INSERT_ID();
INSERT INTO table1 (column1,column2) VALUES ('test', 1);
SET #last_id_in_table1 = LAST_INSERT_ID();
INSERT INTO table2 (column3,column4,column5) VALUES (#last_id_in_table1, 2, 3);

copy all rows with matching field value

I would like to copy all mysql rows with a matching field value into a new row and change one field.
So I have a mysql table with the following fields
`lessonplan`, `group`, `category`, `sort_id`, `item`
So I want to copy all rows that have lessonplan=10 and set change the value of lessonplan to 11 for all new rows. Lesson plan is not an auto increment field.
What is best practice for a scenario like this one?
INSERT INTO tableName( lessonplan, `group`, category, sort_id, item )
SELECT 11, `group`, category, sort_id, item
FROM tableName
WHERE lessonplan = 10

Insert into 2 table and set both foreign key auto increment

I have a database with two tables. When a user posts an article, it will be inserted into both tables, (2 queries in one file)
I use post_id as foreign key, both tables post_id auto increment. Will foreign keys be messed up? For example if users A and B query the database at the same time.
Table 1
post_id user...
1 A
2 B
Table 2
post_id content...
1 A
2 B
First off you can't have auto increment on both tables.
Usually, what you do is insert in table 1, get the ID of the just inserted row.
Then you use this ID, to insert in table 2 which references table 1.
See: mysqli::$insert_id at
http://www.php.net/manual/en/mysqli.insert-id.php
Example:
$query = "INSERT INTO table1(user,whatever) VALUES ('A','something')";
$mysqli->query($query);
printf ("New Record has id %d.\n", $mysqli->insert_id);
$query = "INSERT INTO table2(post_id,content) VALUES ($mysqli->insert_id,'This is content')";
$mysqli->query($query);
You could also do this using a stored procedure based on: stackoverflow.com/a/1723325/1688441
DELIMITER //
CREATE PROCEDURE new_post_with_content(
user_id CHAR(5), content_text CHAR(100)
BEGIN
START TRANSACTION;
INSERT INTO table1 (user)
VALUES(user_id);
INSERT INTO table2 (post_id, content)
VALUES(LAST_INSERT_ID(), content_text);
COMMIT;
END//
DELIMITER ;
And you call it like so:
CALL new_engineer_with_task('A','This is the content');
Why not use table1 as user table and second with posts?
users
user_id(autoinc) username
1 A
2 B
3 C
posts
post_id(autoinc) user_id posts_text
1 2 text
2 1 other text

Categories