INSERT INTO SELECT with VALUES in one query - php

Bit new to MYSQL and PHP - I have the following code that will create a new record in multiple tables that I have setup however I need to merge the following code together somehow as it creates separate rows instead of one record
$sql .=("INSERT INTO orders (customer_id) SELECT customer_id FROM
customer_details;");
foreach($result as $item){
$mysql_desc = $item['product_description'];
$mysql_mode = $item['delivery_mode'];
$mysql_cost = $item['course_cost'];
$sql .=("INSERT INTO orders(product_description, delivery_mode, course_cost) VALUES('$mysql_desc', '$mysql_mode', '$mysql_cost');");
}
The result I'm getting:

Based on your data I assume that you want to insert the customer id and the values from php into the same record. In this case you need to combine them into the same insert ... select ... statement:
$sql .=("INSERT INTO orders(customer_id, product_description, delivery_mode, course_cost) select customer_id, '$mysql_desc', '$mysql_mode', '$mysql_cost' from customer_details;");
Couple of things to note:
This insert ... select ... statement will insert the same records for all customers in the customer details table. I'm not sure if this is your ultimate goal.
Pls consider the advices made in the comments regarding the old mysql API and the use of prepared statements.

To put this more into what I would expect to happen, something along the lines of - prepare statement, then loop through each item and add in new row...
$insert = $connection->prepare("INSERT INTO orders (customer_id,product_description, delivery_mode, course_cost)
VALUES (?,?,?,?)");
foreach($result as $item){
$customerID = 1; // Have to ensure this is what your after
$mysql_desc = $item['product_description'];
$mysql_mode = $item['delivery_mode'];
$mysql_cost = $item['course_cost'];
$insert->execute([customerID,mysql_desc,mysql_mode,mysql_cost]);
}

Related

Running an insert script from multiple values

I'm trying to run a pretty simple script that does the following: Takes the id of a content module and assigns it to multiple locations
So say I click the link on a content module with ID of 123, I want to assign it to all multiple locations. In SQL I would just say :
INSERT INTO table (cont_id,loc_id)
VALUES (123, select(id from location_table where active = 1))
I'm currently using this:
$pageID = $_GET['pageID'];
$assignPage = "
INSERT INTO locationContent(page_id, display_id)
VALUES ( '$pageID', select(id from locations where active = 1))
ON DUPLICATE KEY UPDATE active = 1
";
$performAssign = $mysqlConn->query($assignPage);
The issue I'm wondering about though, is do I need to put this into a foreach or while loop? If I were to just run as is, I feel like that would only work for one record
You seem to be looking for MySQL INSERT ... SELECT syntax.
From the documentation:
With INSERT ... SELECT, you can quickly insert many rows into a table from the result of a SELECT statement, which can select from one or many tables.
Query:
INSERT INTO locationContent (page_id, display_id)
SELECT ?, id FROM locations WHERE active = 1
ON DUPLICATE KEY UPDATE active = 1
The ? stands for parameter $pageID (you do want to use parameterized queries and prepared statement to protect your code against SQL injection).
You can't mix the INSERT INTO .. VALUES and INSERT INTO ... SELECT syntax, however SELECT constant, var FROM .. is possible like:
$assignPage = $mysqlConn->prepare("
INSERT INTO locationContent(page_id, display_id)
SELECT :page as page_id, id FROM locations WHERE active = 1
ON DUPLICATE KEY UPDATE active = 1
";
$performAssign = $assignPage->execute(array('page' =>$pageID));

Using On Duplicate Key Update with an array

I'm relatively new to MYSQL and am having trouble combining idea I have read about. I have a form generated from a query. I want to be able to insert or update depending on whether there is currently a matching row. I have the following code which works for inserting but I;m struggling with the On DUPLICATE UPDATE part I keep getting a message saying there is an error in my syntax or unexpeted ON depending on how I put the ' .
require_once("connect_db.php");
$row_data = array();
foreach($_POST['attendancerecordid'] as $row=>$attendancerecordid) {
$attendancerecordid=mysqli_real_escape_string($dbc,$attendancerecordid);
$employeeid=mysqli_real_escape_string($dbc,($_POST['employeeid'][$row]));
$linemanagerid=mysqli_real_escape_string($dbc,($_POST['linemanagerid'][$row]));
$abscencecode=mysqli_real_escape_string($dbc,($_POST['abscencecode'][$row]));
$date=mysqli_real_escape_string($dbc,($_POST['date'][$row]));
$row_data[] = "('$attendancerecordid', '$employeeid', '$linemanagerid', '$abscencecode', '$date')";
}
if (!empty($row_data)) {
$sql = 'INSERT INTO attendance (attendancerecord, employeeid, linemanagerid, abscencecode, date) VALUES '.implode(',', $row_data)
ON DUPLICATE KEY UPDATE abscencecode = $row_data[abscencecode];
echo $sql;
$result = mysqli_query ($dbc, $sql) or die(mysqli_error ($dbc));
}
The various echo statements are showing that the correct data is coming through and my select statement was as expected before I added in the ON DUPLICATE statement.
You need to fix the way the sql statement is constructed via string concatenation. When you create an sql statement, echo it and run it in your favourite mysql manager app for testing.
$sql = 'INSERT INTO attendance (attendancerecord, employeeid, linemanagerid, abscencecode, date) VALUES ('.implode(',', $row_data).') ON DUPLICATE KEY UPDATE abscencecode = 1'; //1 is a fixed value yiu choose
UPDATE: Just noticed that your $row_data array does not have named keys, it just contains the entire new rows values as string. Since you do bulk insert (multiple rows inserted in 1 statement), you have to provide a single absencecode in the on duplicate key clause, or you have to execute each row in a separate insert to get the absence code for each row in a loop.

Inserting data into multiple tables not functioning correctly

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

PDO Move row from one database to another

I have 2 seperate databases with the same structure. I want to move a selected set of rows from one table to another. I am using PDO to select all the rows, then in a while loop I am assuming that I can insert each row into the new table then delete it from the old table.
With normal mysql this is quite a simple task, but I want to use namespaces so that I can easily modify the table structure ect. I have the following working but it does not move the entry to the new table:
try {
$sql = "SELECT * FROM `calls` WHERE `calls`.`status`=0 AND `calls`.`stage` < 4 AND `calls`.`answer` < (NOW() - INTERVAL 10 MINUTE)";
$query = $this->staging->query($sql);
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$sql = "INSERT INTO `table` (`field1`,`field2`) VALUES (?,?)";
$query = $this->production->prepare($sql);
$query->execute($array);
}
}
catch(PDOException $e) {
$this->informer("FATAL", "Unable to process broken IVR surveys. Error: ".$e->getMessage());
}
You can do it without a while:
INSERT INTO db1.table (fields) SELECT fields FROM db2.table
Of course both databases must be on the same machine
It likely does not work because you are using the question mark placeholder style in the prepared statement, but are passing a named array to execute.
If you name the parameters instead, it should work:
$sql = "INSERT INTO `table` (`field1`,`field2`) VALUES (:field1, :field2)";
Another approach is using federated tables in MySQL to do what you're trying to do. There are some limitations.... but here are the docs to get you going...
http://dev.mysql.com/doc/refman/5.0/en/federated-use.html http://dev.mysql.com/doc/refman/5.0/en/federated-limitations.html

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?

Categories