Update MySQL table if non-primary key column is duplicate, insert otherwise? - php

I have a MySQL table with an autoincremented primary key, and a column for a person's name, and some data.
Is there a MySQL query where I can insert a new row if the name of the person is unique, but if it's a duplicate name, then I would update that row?
I.e.
ID, Name, Data
1 , Michael, x
2 , Stephen, y
3 , Christopher, z
If I were to add a "Michael" to the database with "qq" data, I would want the database to look like this:
ID, Name, Data
1 , Michael, qq
2 , Stephen, y
3 , Christopher, z
If I were to add "John" with "zz" data, the database would look like this:
ID, Name, Data
1 , Michael, x
2 , Stephen, y
3 , Christopher, z
4 , John, zz
I know of the command, ON DUPLICATE KEY UPDATE, but I only want to update if the name is the same, not if the primary key is the same.

Create a UNIQUE index on Name. ON DUPLICATE KEY UPDATE will then work correctly.

Create a stored procedure and simply call it in your query code
PROCEDURE:
DROP PROCEDURE IF EXISTS InsUpdTable $$
CREATE PROCEDURE InsUpdTable
(
IN _name VARCHAR(45),
IN _data VARCHAR(45)
)
BEGIN
if exists (select ID from mytable where name = _name)
Then
update mytable set data = _data where name=_name;
else
insert into mytable(name, data) values(_name, _data);
END IF;
END $$
DELIMITER ;
Query:
call InsUpdTable('John','zzz')

Related

Insert data in 3rd table with the values inserted in 2 other table

I have 3 table in postgres database. Created with this code:
CREATE TABLE AUTHOR(
ID SERIAL PRIMARY KEY,
NAME TEXT
);
CREATE TABLE BOOK(
ID SERIAL PRIMARY KEY,
NAME TEXT
);
CREATE TABLE BOOK_AUTHOR(
BOOK_ID INTEGER REFERENCES BOOK(ID),
AUTHOR_ID INTEGER REFERENCES AUTHOR(ID)
);
A book can have multiple author.
I want to insert multiple author in AUTHOR table.
A book in BOOK table.
And pair in BOOK_AUTHOR table.
For example: If BOOK X is written by Mr. A and Mr. B
I want the table content be like this
AUTHOR
ID-NAME
1, Mr. A
2, Mr. B
BOOK
ID-NAME
1, X
BOOK_AUTHOR
BOOK_ID-AUTHOR_ID
1,1
1,2
I am using postgres-php.
I know I can insert data in author table. Insert data in book table. Make query over them to get the ids.
Then insert in book_author table.
But is there any way to insert those data more efficiently?
What is the possible best way?
PostgreSQL has a very handy 'RETURNING' function you can use here like this:
WITH authors AS (
INSERT INTO
author (name)
VALUES
('Mr. A'), ('Mr. B')
RETURNING
id
), books AS (
INSERT INTO
book (name)
VALUES
('X')
RETURNING
id
)
INSERT INTO
book_author
SELECT
b.id
, a.id
FROM
books b
, authors a;
Just make a Cartesian product of the output and use it as input for the third insert.

Update another table when another one is updated

I'm not quite figuring out how to do what I'm after.So what I'm making is an online game.When a user buy's a new car I do an INSERT:
$c->query("INSERT INTO user_cars (carid, userid, acc, speed) VALUES ('$buyid','$id','$acc','$speed')");
Now I have another table that I need to insert info to right after the query above FROM the query above.What I need is the carid .The user can have more than 2 cars.What should I do now?
You have multiple options:
You can build a trigger to insert a new row in table2, when row is inserted in the cars table (Read more here http://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html)
There is this function mysql_insert_id() which returns the last inserted id ( Read more here http://php.net/manual/en/function.mysql-insert-id.php )
If you use PDO , there is a smillar command for it
etc.
This is a basic demonstration of the trigger you would want to create. For illustrative purposes I've also included the ddl and an example insert into your user_cars table to show that another table, which I've called "your_other_table" receives the insert (just the carid value) of an insert going into the user_cars table.
Fiddle:
http://sqlfiddle.com/#!9/f76a7/1/0
(notice how "your_other_tabe" has one row with the carid of the insert into "user_cars", despite having no direct inserts into itself)
delimiter //
create table user_cars
(
carid int,
userid int,
acc int,
speed int,
constraint id_pk primary key (carid, userid)
)//
create table your_other_table
(
carid int
)//
create trigger your_trigger_name before insert on user_cars
for each row begin
insert into your_other_table (carid)
values (new.carid);
end
//
insert into user_cars values
(1, 2, 3, 99)//
delimiter ;
select *
from your_other_table;
Output:
| CARID |
|-------|
| 1 |
This is the only portion of the above sql that creates the trigger:
delimiter //
create trigger your_trigger_name before insert on user_cars
for each row begin
insert into your_other_table (carid)
values (new.carid);
end
//
delimiter ;

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

ON DUPLICATE KEY UPDATE-like behaviour on multiple columns

I have a table like this:
id | userid | commentid | value
-------------------------------
Each user is permitted to vote a comment once. The value can be between -1 and 1. Is there a easy way for a table model to achieve an change of this vote in one single query, without checking EXISTS() first? I already thought about a hash-column like this
MD5(CONCAT(userid, commentid))
but is there any better solution for this?
Just use an unique key on userid + commentid and you can use ON DUPLICATE KEY UPDATE.
INSERT INTO `yourTable` (
`userid`,
`commentid`,
`value`
) VALUES (
x,
y,
z
) ON DUPLICATE KEY UPDATE
`value` = z

SQL Query for fetching the data of users not submitting their time for a particular week?

I have two tables one containing user information and the other having their time entered for the weeks as below!
Table1
------
UserID (PK)
Username
Email
Phone
Table2
------
Timesheetid (PK)
UserID (FK)
Weekenddate(date)
Totaltimeworked
From the above tables I want to retrieving the user ID,username and email from TABLE 1 for the user who have not entered information in the table 2 based on the weekend date(weekend date is selected in the search field and not hardcoded).
Please help me with the SQL query to create this table .
Try this working code on SQL Fiddle. As you haven't posted any data and columns definition I assume weekenddate to be a varchar.
On the condition Weekenddate = 'sunday' OR Weekenddate = 'saturday' substitute the values sunday and saturday by your parameter value. In fact, you will only need to use on of the clauses of the condition as you have only one parameter with the weekend value. Then just wrap the code into an
`INSERT INTO your_new_table (UserID, Username)`
Considering your Totaltimeworked column is up to date:
CREATE TABLE newTable(
UserID int not null,
Weekenddate date not null,
FOREIGN KEY(UserID) REFERENCES Table1(UserID)
ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO newTable (UserID, Weekenddate)
(SELECT (UserID, Weekenddate) FROM Table2 WHERE Totaltimeworked > 0);
Or if you meant just for 1 specific week don't add the Weekenddate to newTable and modify query as
INSERT INTO newTable (UserID)
(SELECT (UserID) FROM Table2 WHERE Totaltimeworked > 0
AND Weekenddate = 'year-month-day');

Categories