Insert on Join Tables Mysql - php

I've seen several questions and answers about this, but none is quite similar to my problem, so now I am asking.
Here is the situation
I have a table called users, roles, and user_role
table: users
fields: user_id, username, password
table: roles
fields: role_id, role_name
table: user_role
fields: user_id, role_id
foreign key of user_role.user_id is user.user_id
foreign key of user_role.role_id is role.role_id
My problem is when I create a user, I also want to set their roles to a default value or a selected value I chose in <select> element.
I tried several things like:
INSERT INTO users as t1 (t1.username, t1.password, t2.role)
JOIN user_role as t2 ON t1.user_id = t2.user_id
VALUES (:username, :password, :role)
Am I doing it super wrong?
EDIT BECAUSE OF AN ANSWER BELOW
I think something is still wrong, it gives me a blank screen
$this->db->beginTransaction();
$string = "INSERT INTO users (username, password)
VALUES (:user,:pass,:first,:middle,:last,:course)";
$sth = $this->db->prepare($string);
$sth->execute(array(
':user'=> $data['user'],
':pass'=> $data['pass']
));
$sth = $this->db->prepare("INSERT INTO user_roles (user_id, role_id)
VALUES (' . $this->db->lastInsertId(user_id) . ', :role)");
$sth->execute(array(
':role' => 3
));
$this->db->commit();

Since it seems like you're using PHP & PDO, this simplified code will take care of your insert:
$pdo->beginTransaction();
$stmt = $conn->prepare('INSERT INTO users (username, password) VALUES (?, ?)');
$stmt->execute(array($username, $password));
$stmt = $conn->prepare('INSERT INTO user_roles (user_id, role_id) VALUES (' . $pdo->lastInsertId() . ', ?)');
$stmt->execute(array($role));
$pdo->commit();
After you insert a user into the users table, the value returned by $pdo->lastInsertId() is the id that was just inserted into the users table.
Read more on lastInsertId().
Encase these two insert statements in a transaction and you're good to go.

Related

Obtain UserID after inserting new record

I am currently working with a form where you are able to create new users. You would specify the username, firstname, etc and a new record would be inserted into the Users table in a database.
Right after the creation of an user more steps follow, but for these having the auto generated UserID in the session would be very useful.
How can I accomplish this? I tried the following:
sqlsrv_query($conn1,"INSERT INTO Users (Username, Firstname, Lastname, JobTitle)
VALUES ('$_POST[Username]', '$_POST[Firstname]', '$_POST[Lastname]', '$_POST[JobTitle]'); SELECT SCOPE_IDENTITY() AS UserID;");
$result = sqlsrv_query($conn1); $next_result = sqlsrv_next_result($result); $row = sqlsrv_fetch_array($result);
$_SESSION['UserID'] = $result;
Use OUTPUT INSERTED in your query.
Change Your Code Like,
$result = sqlsrv_query($conn1,"INSERT INTO Users
(Username, Firstname, Lastname, JobTitle) OUTPUT INSERTED.UserID
VALUES ('$_POST[Username]', '$_POST[Firstname]', '$_POST[Lastname]', '$_POST[JobTitle]');
and you will get last inserted id in $result

SQL INSERT INTO table(a, b , c) VALUES (:a, :b, :c, SELECT ...)

So I'm trying to insert 4 values into a table. I'm getting 3 values from POST and the other one I want to get it from another table. This is how I thought about implementing it but it doesn't seem to be working. Any suggestions?
$query = "INSERT INTO topics (subject, data, uid, role) VALUES (:user, :pass, :uid, SELECT role FROM users WHERE uid=:uid) ";
In SQL, all subqueries need to be surrounded by their own parentheses. So, you can fix your query by using:
INSERT INTO topics (subject, data, uid, role)
VALUES (:user, :pass, :uid, (SELECT role FROM users WHERE uid = :uid));
Personally, I much prefer the INSERT . . . SELECT version of SELECT:
INSERT INTO topics (subject, data, uid, role)
SELECT :user, :pass, :uid, u.role
FROM users u
WHERE uid = :uid;

INSERT into mySQL

So I have 3 tables: donor, blood_type, user_account. I am trying to populate the donor table which contains user_id and blood_id, but there is no join between the blood_group and the user_account table so I tried this, but it didn't work. Can someone please tell what I am doing wrong? I am very new to php and databases.
<?php
if(isset($_POST['submit'])) {
$conn = mysqli_connect("localhost", "root" , "");
if(!$conn) {
die("Cannot connect: ");
}
mysqli_select_db($conn,"blood_bank_project");
$sql = "INSERT INTO user_account(username, password) VALUES ('$_POST[user]', '$_POST[psw]');";
$sql .="INSERT INTO donor(first_name,last_name,email_add,gender, birthday, telephone, city, last_donation,user_id, blood_id)VALUES('$_POST[fname]', '$_POST[lname]', '$_POST[email]', '$_POST[gender]', '$_POST[Birthday]', '$_POST[Telephone]', '$_POST[city]', '$_POST[lastdonation]')";
$sql .="UPDATE donor SET blood_id = (SELECT blood_id from blood_type where blood_group= '$_POST[bloodgroup]');";
$sql .="UPDATE donor SET user_id = (SELECT user_id from user_account where username= '$_POST[user]')";
if(mysqli_multi_query($conn, $sql)){
echo'executed';
}
}
?>
You can use a SELECT clause to produce the values for an INSERT. In this case, you can use that to select the appropriate values from the other tables.
INSERT INTO donor (user_id, blood_id, first_name,last_name,email_add,gender, birthday, telephone, city, last_donation)
SELECT u.user_id, b.blood_id,
'$_POST[fname]', '$_POST[lname]', '$_POST[email]', '$_POST[gender]', '$_POST[Birthday]', '$_POST[Telephone]', '$_POST[city]', '$_POST[lastdonation]'
FROM user_accounts AS u
CROSS JOIN blood_type AS b
WHERE u.username = '$_POST[user]' AND b.blood_group= '$_POST[bloodgroup]'
I also strongly recommend you use prepared queries instead of substituting $_POST variables, as the latter subjects you to SQL-injection. I also recommend against using mysqli_multi_query -- it's rarely needed and only makes checking for success harder. If you insert into user_accounts using a separate query, you can then use mysqli_insert_id($conn) to get the user_id assigned when you inserted into user_accounts, instead of using the above JOIN. You can also use the MySQL built-in function LAST_INSERT_ID() to get it.
$stmt = mysqli_prepare($conn, "INSERT INTO user_account(username, password) VALUES (?, ?);") or die("Can't prepare user_account query: " . mysqli_error($conn));
mysqli_stmt_bind_param($stmt, "ss", $_POST['user'], $_POST['psw']);
mysqli_execute($stmt);
$stmt2 = mysqli_prepare($conn, "
INSERT INTO donor (user_id, blood_id, first_name,last_name,email_add,gender, birthday, telephone, city, last_donation)
SELECT LAST_INSERT_ID(), b.blood_id, ?, ?, ?, ?, ?, ?, ?, ?
FROM blood_type AS b
WHERE b.blood_group= ?") or die ("Can't prepare donor query: " . mysqli_error($conn));
mysqli_stmt_bind_param($stmt2, "sssssssss", $_POST['fname'], $_POST['lname'], $_POST['email'], $_POST['gender'], $_POST['Birthday'], $_POST['Telephone'], $_POST['city'], $_POST['lastdonation'], $_POST['bloodgroup']);
mysqli_execute($stmt2);
theres a few things wrong with that code snippet:
Line 15: You've got a rogue 'w' at the start of the line before your $sql variable
All of your $_POST'ed parameters need to be in the format $_POST['parameter'] (Missing quotes, remember to escape your already quoted ones in places)
The where clause sub-select query in line 14 is selecting from a table that does not exist (blood_type)
I guess what your trying to achieve is a mapping between 'user_account' and 'donor' of which you may be better either storing a foreign key in the user account table of the 'donor_id', or a matrix/mapping table that links the two together.
The matrix/mapping table would hold the primary key date from both user_account and donor to create your matrix.
You can then get to either table information from the other knowing just one side of the information.
I'd also make sure your escaping your inbound variables in your queries to prevent any SQL Injection attacks (see here)

Stop next index from increasing upon integrity violation

I've got the following method in my UserDAO class:
public function insert(Array $params)
{
$sql = 'INSERT INTO users (firstname, lastname, email, password, register_date) ';
$sql .= 'VALUES(:firstname, :lastname, :email, :password, FROM_UNIXTIME(:register_date))';
$sth = $this->pdo->prepare($sql);
$sth->bindValue(':firstname', $params['firstname'], \PDO::PARAM_STR);
$sth->bindValue(':lastname', $params['lastname'], \PDO::PARAM_STR);
$sth->bindValue(':email', $params['email'], \PDO::PARAM_STR);
$sth->bindValue(':password', $params['password'], \PDO::PARAM_STR);
$sth->bindValue(':register_date', $params['registerDate'], \PDO::PARAM_STR);
return $sth->execute();
}
I've got a UNIQUE constraint on my email column, so whenever I'm inserting a new record with a duplicate email, it will throw an exception. That works fine, but I noticed that it still increments the next primary key id number while nothing was inserted, so it actually gets skipped over.
How can I stop it from increasing in a case like that, so that I still get a consecutive increase of the index number? (Like 1, 2, 3, 4 instead of 1, 3, 5, 7, etc).
While it is not really an issue having a non-consecutive id column in a table, if you are concerned about the limit of the ids datatype you have a two realistic options.
Firstly simply SELECT check for the email's existence before the INSERT.
Or use something similar to this:
INSERT INTO users (firstname, lastname, email, password, register_date)
SELECT :firstname, :lastname, :email, :password, FROM_UNIXTIME(:register_date)
FROM dual
WHERE NOT EXISTS (SELECT 1 FROM users WHERE email = :email)
You can use the returned row count to check whether a row has been INSERTed.
Check if you've email in your database before send insert query.
//...
$sth = $this->pdo->prepare("SELECT count(*) FROM users WHERE email = ?");
$sth->execute(array($params['email']));
$rows = $sth->fetch(PDO::FETCH_NUM);
if ($rows[0]) {
return $sth->execute();
}
How to get the number of rows grouped by column?

select and insert mysql

I would like to select one column from other table and insert it into another one.
I have column named image in table2 and want to select that and insert along with the below data to table1. is that possible?
$stmt = $mysqli->prepare("insert into table1 (username, firstname, lastname, image) ")
$stmt->bind_param('sss', $username, $fname, $lname);
$stmt->execute();
Yes, it's possible:
$stmt = $mysqli->prepare("
insert into table1 (username, firstname, lastname, image)
select ?,?,?,image from table2
");
...but I hope table2 has only one row!
You could do a INSERT ... SELECT query - http://dev.mysql.com/doc/refman/5.1/en/insert-select.html
INSERT INTO table1 (username, firstname, lastname, image)
SELECT ?, ?, ?, image FROM table2 t2 WHERE t2.image_id = ?
The first 3 ? are your bound params - $username, $fname, $lname
t2.image_id = ? represents the id/unique field of your desired img.

Categories