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);
}
Related
Okay so this is my first question and I really have no idea how to ask it so I'm going to try and be as specific as possible. My website is an online game and for user inventories when it inserts a new item into the database
Table name "inventory"
Column names "inv_id", "inv_itemid", "inv_userid", "inv_qty"
and it does not add to the column inv_qty and populate properly instead it creates a new inv_id identifier and row for each item. I was wondering if there was a way for me to create a merge function via php to merge all items with the same inv_itemid and inv_userid while adding to the inv_qty colum and populating the inv_id
In my inventory.php file the inv_id column is used to let the user either equip the item or use it as the main variable.
I have seen this done and have tried many times and I just can't get it to work.
If it were a single key to check then you could have used 'ON DUPLICATE KEY UPDATE' of mysql like the following:
INSERT INTO table(field1, field2, field3, ..)
VALUES (val1, val2, val3, ...)
ON DUPLICATE KEY
UPDATE field3='*'
But in your case there is a combination to consider.
If "inv_id", "inv_itemid", "inv_userid" mathces then UPDATE, otherwise INSERT.
One way to achieve this using only mysql in a single query is to create & use a Stored Procedure.
But using php you can achieve this in 2 query. First query is to determine if the combination exists. Then based on this run the next Insert or Update query.
Please check the following example:
$sql1 = SELECT * FROM inventory WHERE inv_id='$inv_id', inv_itemid='$inv_itemid', inv_userid='$inv_userid'
// Execute $sql1 and get the result.
IF result empty, then INSERT:
$sql2 = INSERT INTO inventory ....
otherwise UPDATE.
$sql2 = UPDATE inventory SET inv_qty=(inv_qty + $update_qty) WHERE inv_id='$inv_id', inv_itemid='$inv_itemid', inv_userid='$inv_userid'
About:
Would there be a way to write a php function at the top of the inventory page for my users to click to merge them
Please check with the following php function.
By calling with param: UserID, it will create a new entry with sum of the inv_qty, for each (inv_itemid + inv_userid) combination and removes the previous duplicate entries of (inv_itemid + inv_userid) leaving the newly enterd: (inv_itemid + inv_userid + (SUM of inv_qty)).
Important, please keep a back up of the DB Table Data before running the function.
Please check the comments in the function and update where necessary based on your system, Like getting the last inserted inv_id.
function merger_fnc($user_id) {
// For Each Combination of: inv_itemid + inv_userid
// This function will Insert a new row in the inventory with the SUM of inv_qty
// And then will remove the previous single rows of: inv_itemid + inv_userid + inv_qty
// First get the distinct Items of the User(by UserID);
$inv_itemids = $db->query("SELECT DISTINCT(inv_itemid) FROM inventory WHERE inv_userid=".$user_id);
// Here $inv_itemids will hold all the distinct ItemIDs for the UserID;
foreach ($inv_itemids as $inv_item) {
// We will Insert A new row which will have the sum of 'inv_qty' for the inv_userid & inv_itemid;
$inv_itemid = $inv_item['inv_itemid'];
// I am not sure what type of result set your $db->query(...) returns. So I assumed it is associative array.
// If the result is an Array of objects, then please use: $inv_itemid = $inv_item->inv_itemid;
$insert_sql = "INSERT INTO inventory (inv_itemid, inv_userid, inv_qty) VALUES ('".$inv_itemid."', '".$user_id."', (SELECT SUM(inv_qty) FROM FROM inventory WHERE inv_userid=".$user_id."))";
$inv_itemids = $db->query($insert_sql);
$inserted_new_inventory_id = $db->insert_id;
// Please check the appropriate method for it in your $db class here.
// In mysqli, it is: mysqli_insert_id($db_conn); In PDO it is: $db_conn->lastInsertId();
// Last we remove the previous data of combination(inv_userid & inv_itemid) but leaving our last inserted row.
$delete_sql = "DELETE FROM inventory WHERE inv_id!='".$inserted_new_inventory_id."' AND inv_userid='".$user_id."' AND inv_itemid='".$inv_itemid."'";
$db->query($delete_sql);
}
}
If getting the last inserted inv_id is troublesome from $db(like inv_id is not defined as key in the table), you can try another approach:
Do another query and save the previous inv_id in an array, before the insertion.
After the insertion of the new entry with sum of qty, run a delete query to delete the previous single qty entries, like the following:
DELETE FROM inventory WHERE inv_id IN (3, 4, 7,...)
Here (3, 4, 7,...) are the previous inv_id for (inv_itemid + inv_userid) combination.
I currently have a script that runs every 5 minutes and selects the data from a table on server 1 and an identical table on server2. This is a workaround for replication, essentially, since we don't have that option currently.
The script is successful but I've realized that it misses records sometimes, for whatever reason. The current script selects all records from the destination table, stores the max primary key, selects all data from the source table and then inserts anything with a greater Primary key into the dest. table.
I'd like to modify the script slightly and instead of using max id, just say "if a row has an primary key that doesn't exist in the destination table, insert that row there."
Again these are cloned tables so the structure is the same and they both use AI Primary Keys.
Here's the current working script:
$latest_result = $conn2->query("SELECT MAX(`SESSIONID`) FROM
`ambition`.`session`");
$latest_row = $latest_result->fetch_row();
$latest_session_id = $latest_row[0];
//Select All rows from the source phone database
$source_data = mysqli_query($conn, "SELECT * FROM
`cdrdb`.`session` WHERE `SESSIONID` > $latest_session_id");
// Loop on the results
while($source = $source_data->fetch_assoc()) {
// Check if row exists in destination phone database
$row_exists = $conn2->query("SELECT SESSIONID FROM
ambition.session WHERE SESSIONID = '".$source['SESSIONID']."' ") or
die(mysqli_error($conn2));
//if query returns false, rows don't exist with that new ID.
if ($row_exists->num_rows == 0){
//Insert new rows into ambition.session
$stmt = $conn2->prepare("INSERT INTO ambition.session (SESSIONID,
SESSIONTYPE,CALLINGPARTYNO,FINALLYCALLEDPARTYNO,
DIALPLANNAME,TERMINATIONREASONCODE //etc. There are a lot of columns so I
ommitted the others
Is there a way I can slightly modify this to just insert what doesn't exist rather than relying on the MAX ID?
Or is there something here that would be a culprit as to why it's missing records?
You could use INSERT INTO SELECT and check if value is already in target:
INSERT INTO trg_table (cols)
SELECT cols
FROM src_table s
WHERE NOT EXISTS (SELECT 1 FROM trg_table t WHERE t.id = s.id);
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
I have a php script that uploads csv files into a mysql database.
The database has several columns. Among these columns is an 'email' field. I wrote some mysql that would remove rows that contained duplicate values in the email column. Below is the mysql:
$sql = "CREATE TABLE new_table as SELECT * FROM auto WHERE 1 GROUP BY email";
mysql_query($sql, $conn);
$query = mysql_query("SELECT COUNT(*) FROM new_table");
list($number) = mysql_fetch_row($query);
$query = mysql_query("SELECT COUNT(*) FROM auto");
list($number2) = mysql_fetch_row($query);
$result = $number2 - $number;
mysql_query("DROP TABLE auto");
mysql_query("RENAME TABLE new_table TO auto");
The code works, it removes duplicate values.
Problem:
It removes rows that contain no values. So it assumes that two or more emails values that are empty are duplicates and removes they're rows.
Question:
How do I tell mysql to ignore empty values.
Thanks for the help.
Edit
The where is my database table. One table.
The when is when I execute the code. I plan on putting in a php file to be executed on demand.
The result I expect is a mysql table without duplicate emails.
Something like this would work for a one-time alteration, by allowing NULL in email, and adding a UNIQUE constraint:
-- set empties to NULL
UPDATE tablename SET email = NULL WHERE LENGTH(email)=0;
-- drop all rows violating the UNIQUE constraint on email:
ALTER IGNORE TABLE tablename ADD UNIQUE (email);
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?