Inserting data into multiple tables not functioning correctly - php

I have the following two tables
Table player:
player_id (int)(primary)
player_name (varchar)
player_report_count (int)
Table report:
report_id (int)(primary)
player_id
report_description
report_location
Firstly I ask the user for the player_name and insert it into the player database. From here the player is given an id.
Then I tried to grab the value of the players report count and increment the current value by one (which isn't working).
This is followed by grabbing the playerId from the player table and then inserting into the corresponding column from the report table (also does not work).
When I insert some values into the database, the names, description and report are added to the database however the playerID remains at 0 for all entries and the player_report_count remains at a consistent 0.
What is the correct way to make these two features function? And also is there a more efficient way of doing this?
<?php
$records = array();
if(!empty($_POST)){
if(isset($_POST['player_name'],
$_POST['report_description'],
$_POST['report_location'])){
$player_name = trim($_POST['player_name']);
$report_description = trim($_POST['report_description']);
$report_location = trim($_POST['report_location']);
if(!empty($player_name) && !empty($report_description) && !empty($report_location)){
$insertPlayer = $db->prepare("
INSERT INTO player (player_name)
VALUES (?)
");
$insertPlayer->bind_param('s', $player_name);
$reportCount = $db->query("
UPDATE player
SET player_report_count = player_report_count + 1
WHERE
player_name = $player_name
");
$getPlayerId = $db->query("
SELECT player_id
FROM player
WHERE player_name = $player_name
");
$insertReport = $db->prepare("
INSERT INTO report (player_id, report_description, report_location)
VALUES (?, ?, ?)
");
$insertReport->bind_param('iss', $getPlayerId, $report_description, $report_location);
if($insertPlayer->execute()
&& $insertReport->execute()
){
header('Location: insert.php');
die();
}
}
}

Main issue here is you are getting player details before inserting it. $getPlayerId will return empty result always.
Please follow the order as follows.
Insert player details in to player table and get payerid with mysql_insert_id. After binding you need to execute to insert details to the table.
Then bind and execute insert report .
Then update the player table by incrementing report count with playerid which you got in step 1.
Note : use transactions when inserting multiple table. This will help you to rollback if any insert fails.
MySQL Query will return result object. Refer it from here https://stackoverflow.com/a/13791544/3045153
I hope it will help you

If you need to catch the ID of the last insterted player, This is the function you need if you're using PDO or if it's a custom Mysql Class, you need the return value of mysql_insert_id() (or mysqli_insert_id()) and then directly use it in the next INSERT INTO statement

Related

INSERT MULTIPLE ROWS in Gerund Table using Insert Into Select

I used INSERT INTO SELECT to copy values (multiple rows) from one table to another. Now, my problem is how do I insert rows with its corresponding IDs from different tables (since it's normalized) into a gerund table because it only outputs one row in my gerund table. What should I do to insert multiple rows and their corresponding IDs in the gerund table.
My code for the gerund table goes like this.
$insert = "INSERT INTO table1 SELECT * FROM sourcetable"; // where id1 is pk of table1.
$result =mysqli_query($conn,$insert)
$id1=mysqli_insert_id($conn);
Now table 1 has inserted multiple rows same as the other 2 tables.
Assuming id.. are the foreign keys
INSERT INTO gerundtable (pk, id1,id2,id3) VALUES ($id1,$id2,$id3);
My problem is it doesn't yield multiple rows.
According to MySql documentation:
For a multiple-row insert, LAST_INSERT_ID() and mysql_insert_id() actually return the AUTO_INCREMENT key from the first of the inserted rows. This enables multiple-row inserts to be reproduced correctly on other servers in a replication setup.
So, grab the number of records being copied, and the LAST_INSERT_ID() and you should be able to map exact IDs with each copied row.
In the lines of:
$mysqli->query("Insert Into dest_table Select * from source_table");
$n = $mysqli->affected_rows; // number of copied rows
$id1 = $mysqli->insert_id; // new ID of the first copied row
$id2 = $mysqli->insert_id + 1; // new ID of the second copied row
$id3 = $mysqli->insert_id + 2; // new ID of the third copied row
...
$mysqli->query("INSERT INTO gerundtable (pk, id1,id2,id3) VALUES ($id1,$id2,$id3)");
Thank you for trying to understand and also answering my question. I resolved my own code. I used while loop to get the ids of every row and didn't use INSERT INTO SELECT.
Here is the run down. SInce I'm just using my phone bare with my way posting.
$sqlselect = SELECT * FROM table1;
While($row=mysqli_fetch_array(table1){
$insertquery...
$id1=mysqli_insert_id($conn)
$insertgerundtable = INSERT INTO gerundtable VALUES ( $id1, $id2);
}

Selecting a row where date=NOW()?

I am trying to create a table that logs steps depending on date and the user id. But when I run my code, it happens that I get duplicate rows if a user logs their steps several times a day. I can't have a date with a unique key because that would cause all other users unable to log steps if a any other user has logged steps the same day. So my point is that I want to remove the option of having duplicate rows where user id and date is identical. I have two tables
Table a and table b, and I will refer to them as something.a and something.b
I have a problem with returning a valid row when using $entry = "SELECT * FROM table.a WHERE userid.a = '$user_id.b' AND date=NOW()"
I want to use it as a conditional to decide to either UPDATE or INSERT INTO table.a. I have user_id.b from an previous query which works as it is, so I will leave that as it is for now.
Here is how I query the database:
$entry_result = mysqli_query($conn, $entry);
Which is used here:
if (mysqli_num_rows($entry_result) > 0){
$conn->query("UPDATE steplogger SET steps='$steps' WHERE userid='$user_id' AND date=NOW()");
} else {
$conn->query("UPDATE users SET totalsteps = totalsteps + ('$steps') WHERE username = '$user'");
$conn->query("INSERT INTO steplogger (steps, userid, date) VALUES ('$steps', '$user_id', NOW())");
}
Any thoughts on what I am doing wrong?
PS. When I echo $entry_result I get a mysqli object.
As you said :
I want to remove the option of having duplicate rows where user id and date
The best way is to create an UNIQUE index on user_id and date, this way you won't be able to insert two rows with same user_id and date.
With an UNIQUE index, you can use INSERT...ON DUPLICATE KEY UPDATE that will do what you want : you will insert a new row (new user_id + date) and if a row already exists with the same user_id and date, you will update the row.
Here is the documentation : https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
You can try like this
if (mysqli_num_rows($entry_result) > 0){
$conn->query("UPDATE steplogger SET steps='$steps' WHERE userid='$user_id' AND date=".NOW().")";
} else {
$conn->query("UPDATE users SET totalsteps = totalsteps + ('$steps') WHERE username = '$user'");
$conn->query("INSERT INTO steplogger (steps, userid, date) VALUES ('$steps', '$user_id', ".NOW()."))";
}
To get current date in NOW() function, you can use this function.
And also format of the two conditions should be same.

How can I insert data to a table which has a foreign key, from a table which has a primary key auto-increment?

I have 4 mySQL tables with the following entries:
user
-user_id PK,AI
-user_name
-user_mobil
-user_passw
-user_email
bookingdetails
-booking_id PK,AI
-booking_date
-booking_time
-person_number
booking
-booking-_id FK
-restaurant_id CK
-user_id CK
restaurant
-restaurant_id PK
-restaurant_name
-restaurant_address
-restaurant_description
I would like to make a booking, I insert all the bookingdetails data, which gives me a AI booking_id, and after I would like to make my booking table and insert the restaurant_id and the user_id With the same booking_id which was given by the bookingdetails table.
I made the following code for achieve that in php on a localserver:
$booking_date=$_POST["booking_date"];
$booking_time=$_POST["booking_time"];
$number_of_place=$_POST["number_of_place"];
$customer_id=$_POST["customer_id"];
$restaurant_id=$_POST["restaurant_id"];
$res;
$sql_query = "INSERT INTO bookingdetails(booking_date, booking_time, number_of_place) VALUES ('$booking_date','$booking_time', '$number_of_place')";
$sql_query2 = "INSERT INTO `booking`(`booking_id`, `customer_id`, `restaurant_id`) SELECT booking_id, '$customer_id', '$restaurant_id' FROM bookingdetails ORDER BY booking_id DESC LIMIT 1 ;";
if(mysqli_query($con,$sql_query))
{
}
else
{
}
if(mysqli_query($con,$sql_query2))
{
}
else
{
}
?>
Is that a legit solution on a server which joining to an Android app? Is there any case, that i don't get the good id on the second query? What would be a better solution?
Answer given in comment by #Mark Ng
Use last insert id, criteria is that your pk has to be AI.
The mysqli_insert_id() function returns the id (generated with AUTO_INCREMENT) used in the last query.
Source: w3schools.com/php/php_mysql_insert_lastid.asp
To elaborate
you have to execute the query from which you need the last inserted id, then you can access that by using
$last_id = $conn->insert_id;
which in turn you can use for your following query.
Note:
I see you use a query to use the results for your insert query, but your syntax is incorrect (your missing values)

How do I get all the ids of the row created by one multiple row insert statement

I'm new to php. So, please forgive me if this seems like a dumb question.
Say i have a MySQL insert statement insert into table (a,b) values (1,2),(3,4),(5,6). table 'table' has a auto increment field called 'id'.
how can I retrieve all the ids created by the insert statement above?
It will be great if i get an example that uses mysqli.
You can't. I would suggest that you maintain your own ids (using guid or your own auto-increment table) and use it when you insert into the table.
But it's possible to get the auto-increment value for the last inserted using LAST_INSERT_ID():
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
AngeDeLaMort's answer is almost right. Certainly, the most appropriate way to deal with the problem is to insert one row at a time and poll the insert_id or generate the sequence elsewhere (which has additional benefits in terms of scalability).
I'd advise strongly against trying to determine the last insert_id and comparing this the most recent insert_id after the insert - there's just too may ways this will fail.
But...an alternative approach would be:
....
"INSERT INTO destn (id, data, other, trans_ref)
SELECT id, data, other, connection_id() FROM source";
....
"SELECT id FROM destn WHERE trans_ref=connection_id()";
....
"UPDATE destn SET trans_ref=NULL where trans_ref=connection_id()";
The second query will return the ids generated (note that this assumes that you use the same connection for all 3 queries). The third query is necessary because connection ids to go back into the pool when you disconnect (i.e. are reused).
C.
In some cases, if you have another identifier of sort such as a UserID, you could filter your query by UniqueID's greater than or equal to mysql_insert_id(), limit by the number of affected rows and only display those by the user. This would really only work inside of a transaction.
$SQL = "INSERT INTO Table
(UserID, Data)
VALUES
(1,'Foo'),
(1,'Bar'),
(1,'FooBar')";
$Result = mysql_query($SQL);
$LastID = mysql_insert_id();
$RowsAffected = mysql_affected_rows();
$IDSQL = "SELECT RecordID
FROM Table
WHERE UserID = 1
AND RecordID >= '$LastID'
LIMIT '$RowsAffected'";
$IDResult = mysql_query($IDSQL);
as a follow up to AngeDeLaMort:
You could seperate your inserts and do it something like this:
$data = array (
array(1,2),
array(3,4),
array(5,6)
);
$ids = array();
foreach ($data as $item) {
$sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
mysql_query ($sql);
$id[] = mysql_insert_id();
}
Now all your new id's are in the $id array.
Maybe I can do this
$insert = "insert into table (a,b) values (1,2),(3,4),(5,6)";
$mysqli->query($insert);
$rows_to_be_inserted=3;
$inserted_id = $mysqli->insert_id // gives me the id of the first row in my list
$last_row_id = ($inserted_id+$rows_to_be_inserted)-1;
$mysql->query("select * from table where id between $inserted_id and $last_row_id");
what to you guys say?

php/mysql creating duplicate records with multiple tables

I'm building a database for making hotel reservations. One table called "reservations" holds the general details of the reservation, while another called "rooms" holds details about specific rooms (each reservation has many rooms, each room belongs to only one reservation).
I would like to be able to easily generate duplicate reservations records (except for the primary key, of course). My problem is in generating the rooms data as an array which is then inserted into the rooms table while being associated to its reservation.
I've come as far as the following trivial code (stripped down to the bare essentials for discussion purposes).
if (isset($_POST['action']) and $_POST['action'] == 'Duplicate')
{
include $_SERVER['DOCUMENT_ROOT'] . '/includes/connect.inc.php';
$id = mysqli_real_escape_string($link, $_POST['id']);
// retrieve reservation
$sql = "SELECT type_of_reservation FROM reservations WHERE id='$id'";
$result = mysqli_query($link, $sql);
$row = mysqli_fetch_array($result);
$type_of_reservation = $row['type_of_reservation'];
// create new reservation record
$sql = "INSERT INTO reservations SET type_of_reservation ='$type_of_reservation'";
$id = mysqli_insert_id($link);
// retrieve rooms
$sql = "SELECT reservation_id, in_date FROM rooms WHERE reservation_id='$id'";
$result = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($result))
{
$rooms[] = array('reservation_id' => $row['reservation_id'], 'in_date' => $row['in_date']);
}
The big question is, now what? Everything I've tried either generates an error or no new entries, and I can't seem to find any discussion that addresses this specific need. Thanks for your help.
PeterC, there is no code listed that shows you inserting the ROOM record information. In the //retrieve room section of your code, you are pulling the data and putting it into an array. If you really want to create a duplicate records, I would use in insert inside the database, then you don't have to pull the records out just to put them back in.
The bit of code you want will be something like this. It will be in place of the //retrieve rooms code you have listed: (psuedo code) [note: $id represents the newly selected id from your sql insert for the duplicated reservation]
INSERT INTO rooms(res_id, other, data)
SELECT $id, other, data FROM rooms WHERE id = $_POST['id'];
This will allow you to duplicate the room data, adding the new reservation_id right inside the database. No need to pull out the records, create inserts, and then put them back in. You can read more about INSERT INTO ... SELECT statements here: http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-select-into-table.html
// create new reservation record
$sql = "INSERT INTO reservations SET type_of_reservation ='$type_of_reservation'";
//ADD HERE CODE BELOW
$id = mysqli_insert_id($link);
with mysql_insert_id you get the inseted id, but you should insert it into db.. so add
mysqli_query($link, $sql);
before retrieving data
If you simply need to duplicate records, you can do it this way:
INSERT INTO
reservations
(
SELECT
null, # assume first column is auto incrementing primary key, so leave null
`all`,
`other`,
`column`,
`names`
FROM
reservations
WHERE
reservation_id = $oldReservationId # id of reservation to duplicate
)
Then for the rooms use the last inserted id (for instance retrieved with mysql_insert_id), like this:
INSERT INTO
rooms
(
SELECT
null, # assume first column is auto incrementing primary key, so leave null
$newReservationId, # this is the new reservation id
`all`,
`other`,
`column`,
`names`
FROM
rooms
WHERE
reservation_id = $oldReservationId # id of reservation to duplicate
)

Categories