Undesired data insertion to database - php

An employee can claim the amount of money spent on official duty from the employer.
I am working on a website in which after a staff filled in the official duty activity (details), staff is then shown a dynamic form in which they can add/remove transport/meal/hotel claim, depending on how long (days) it takes to complete the duty. Here is the design I came up with.
Here is the output . TransportID 8 & 9 should be in the same row as activityID 11. Is there a way to insert > 1 primary keys into a field?
foreach ( $_POST["dates"] as $index=>$date ) {
$origin = $_POST["origins"][$index];
$destination = $_POST["destinations"][$index];
$cost = $_POST["costs"][$index];
//Insert into transport table
$sql_transport1 = sprintf("INSERT INTO tbl_transport (Date, Origin, Destination, Cost) VALUES ('%s','%s','%s','%s')",
mysql_real_escape_string($date),
mysql_real_escape_string($origin),
mysql_real_escape_string($destination),
mysql_real_escape_string($cost));
$result_transport1 = $db->query($sql_transport1);
$inserted_transport_id1 = $db->last_insert_id();
//Insert into transport_mainclaim table
$sql_transport_mainclaim1 = sprintf("INSERT INTO tbl_transport_mainclaim (claimID, transportID) VALUES ('%s','%s')",
mysql_real_escape_string($inserted_mainclaim_id1),
mysql_real_escape_string($inserted_transport_id1));
$result_transport_mainclaim1 = $db->query($sql_transport_mainclaim1);
$all_transport_id = implode(",",$inserted_transport_id1);
//Insert into mainclaim table
$sql_mainclaim = sprintf("INSERT INTO tbl_mainclaim (activityID, transportID, IC) VALUES ('%s','%s','%s')",
mysql_real_escape_string($inserted_activity_id),
mysql_real_escape_string($all_transport_id),
mysql_real_escape_string($_SESSION['IC']));
$result_mainclaim = $db->query($sql_mainclaim);
$inserted_mainclaim_id = $db->last_insert_id();
}
I have tried using $all_transport_ID = implode(",",$inserted_transport_id1);to separate IDs with comma but failed to do so.
Is the database structure wrongly designed? Please guide me as I want to get this right.

Sorry I couldn't comment on your post because of reputation but I think you gave the wrong link. Your code is operating on table tbl_transport whereas the link you gave shows table named tbl_mainclaim.
Regardless of that,you are trying to insert two integer values 8 and 9 in the column of integer type on the same row as activity id with int value 11. How are you planning to store that?
UPDATE: I think the way which you are implementing this code is wrong. If i am correct your variable $inserted_transport_id is an array whereas in this line you are treating it as a variable. $inserted_transport_id1 = $db->last_insert_id();
As you are using implode which combines array into a string , here you are treating it as an array.
$all_transport_id = implode(",",$inserted_transport_id1);
So I am not sure what you are trying to implement. Its not clear what you are trying to do with that foreach loop for whole SQL.
And if your application permits, you can remove tbl_transport_mainclaim,tbl_meal_mainclaim,tbl_hotel_mainclaim and directly assign foreign key of the tables tbl_transport,tbl_hotel,tbl_meal which references to the respective columns on the tbl_mainclaim.
I might be able to help you with your further explaination about what you are trying to implement in this page.

Don't escape $all_transport_id; do escape (or verify that they are numeric) the values in $inserted_transport_id1.
In the future, do this to help with debugging:
echo $sql_mainclaim;

Related

Update laravel SQL table with Numeric value out of range:

I have an app that is receiving sensor data. As an illustration let's say the expected range is between 0.01 and 10. In this case in the migration I may have something like:
$table->float('example',5, 2)
This way I am able to handle an order of magnitude outside the expected range. However it is possible for the sensor to glitch and send values of say 10 000. As the sensor is sending an array of values it is likely that not all the data is incorrect so it is preferred to still write the data to the DB. For the initial insert I am using the code below which is working as expected:
DB::table($tableName)->insertOrIgnore($insert_array);
However, in some circumstances the sensor can resend the data in which case the record needs to be updated. It's possible that the value(s) that are out of range can remain in the array, in which case the update statement below will throw an out of range error:
DB::table($tableName)->where('$some_id','=', $another_id)->update($insert_array);
I have not been able to find an something akin to an "updateorignore" functionality. What is the best way to handle updating this record? Note I cannot simply put it in a try catch since this table will be a parent table to some children and ignoring it will result in some orphaned entries.
Do you have some unique points of data to tie the records together, such as a timestamp or an id from the origin of the data? If so, you can use updateOrInsert
DB::table($tableName)
->updateOrInsert(
['remote_id' => $insert_array['remote_id'],
[
'example_field_1' => $insert_array['example_field_1'],
'example_field_2' => $insert_array['example_field_2'],
]
);
This is discussed at:
https://laravel.com/docs/master/queries#updates
Thanks to James Clark Developer to help me get to the solution. Below is some sample code to resolve the problem:
$values = array();
//set up values for binding to prevent SQL injection
foreach ($insert_array as $item) {
$values[] = '?';
}
//array values need to be in a "flat array"
$flat_values = implode(", ", $values);
//add in separators ` to column names
$columns = implode("`, `",array_keys($insert_array));
//write sql statement
$sql = "INSERT IGNORE INTO `example_table` (`$columns`) VALUES
($flat_values) ON DUPLICATE KEY UPDATE id = '$id'";
DB::insert($sql, array_values($insert_array));
}

Transform MySQL table and rows

I have one problem here, and I don't even have clue what to Google and how to solve this.
I am making PHP application to export and import data from one MySQL table into another. And I have problem with these tables.
In source table it looks like this:
And my destination table has ID, and pr0, pr1, pr2 as rows. So it looks like this:
Now the problem is the following: If I just copy ( insert every value of 1st table as new row in second) It will have like 20.000 rows, instead of 1000 for example.
Even if I copy every record as new row in second database, is there any way I can fuse rows ? Basically I need to check if value exists in last row with that ID_, if it exist in that row and column (pr2 for example) then insert new row with it, but if last row with same ID_ does not have value in pr2 column, just update that row with value in pr2 column.
I need idea how to do it in PHP or MySQL.
So you got a few Problems:
1) copy the table from SQL to PHP, pay attention to memory usage, run your script with the PHP command Memory_usage(). it will show you that importing SQL Data can be expensive. Look this up. another thing is that PHP DOESNT realese memory on setting new values to array. it will be usefull later on.
2)i didnt understand if the values are unique at the source or should be unique at the destination table.. So i will assume that all the source need to be on the destination as is.
I will also assume that pr = pr0 and quant=pr1.
3) you have missmatch names.. that can also be an issue. would take care of that..also.
4) will use My_sql, as the SQL connector..and $db is connected..
SCRIPT:
<?PHP
$select_sql = "SELECT * FROM Table_source";
$data_source = array();
while($array_data= mysql_fetch_array($select_sql)) {
$data_source[] = $array_data;
$insert_data=array();
}
$bulk =2000;
foreach($data_source as $data){
if(isset($start_query) == false)
{
$start_query = 'REPLACE INTO DEST_TABLE ('ID_','pr0','pr1','pr2')';
}
$insert_data[]=implode(',',$data).',0)';// will set 0 to the
if(count($insert_data) >=$bulk){
$values = implode('),(',$insert_data);
$values = substr(1,2,$values);
$values = ' VALUES '.$values;
$insert_query = $start_query.' '.$values;
$mysqli->query($insert_query);
$insert_data = array();
} //CHECK THE SYNTAX IM NOT SURE OF ALL OF IT MOSTLY THE SQL PART>> SEE THAT THE QUERY IS OK
}
if(count($insert_data) >=$bulk) // IF THERE ARE ANY EXTRA PIECES..
{
$values = implode('),(',$insert_data);
$values = substr(1,2,$values);
$values = ' VALUES '.$values;
$insert_query = $start_query.' '.$values;
$mysqli->query($insert_query);
$insert_data = null;
}
?>
ITs off the top off my head but check this idea and tell me if this work, the bugs night be in small things i forgot with the QUERY structure, print this and PASTE to PHPmyADMIN or you DB query and see its all good, but this concept will sqve a lot of problems..

text input (seperated by comma) mysql input as array

I have a form where I am trying to implement a tag system.
It is just an:
<input type="text"/>
with values separated by commas.
e.g. "John,Mary,Ben,Steven,George"
(The list can be as long as the user wants it to be.)
I want to take that list and insert it into my database as an array (where users can add more tags later if they want). I suppose it doesn't have to be an array, that is just what seems will work best.
So, my question is how to take that list, turn it into an array, echo the array (values separated by commas), add more values later, and make the array searchable for other users. I know this question seems elementary, but no matter how much reading I do, I just can't seem to wrap my brain around how it all works. Once I think I have it figured out, something goes wrong. A simple example would be really appreciated. Thanks!
Here's what I got so far:
$DBCONNECT
$artisttags = $info['artisttags'];
$full_name = $info['full_name'];
$tel = $info['tel'];
$mainint = $info['maininst'];
if(isset($_POST['submit'])) {
$tags = $_POST['tags'];
if($artisttags == NULL) {
$artisttagsarray = array($full_name, $tel, $maininst);
array_push($artisttagsarray,$tags);
mysql_query("UPDATE users SET artisttags='$artisttagsarray' WHERE id='$id'");
print_r($artisttagsarray); //to see if I did it right
die();
} else {
array_push($artisttags,$tags);
mysql_query("UPDATE users SET artisttags='$artisttags' WHERE id='$id'");
echo $tags;
echo " <br/>";
echo $artisttags;
die();
}
}
Create a new table, let's call it "tags":
tags
- userid
- artisttag
Each user may have multiple rows in this table (with one different tag on each row). When querying you use a JOIN operation to combine the two tables. For example:
SELECT username, artisttag
FROM users, tags
WHERE users.userid = tags.userid
AND users.userid = 4711
This will give you all information about the user with id 4711.
Relational database systems are built for this type of work so it will not waste space and performance. In fact, this is the optimal way of doing it if you want to be able to search the tags.

Large MySQL query and insert

hey everyone im new here as well as to php only been at it for about 2 months kinda learning as i go. what i need to get done right now is to take data from about 16 different tables in a data base and duplicate the tables. the table are for applicants and either have an application id in common or a family id in commmon the id's are just genereated hashes. what im doing right now is individually wquerying every table and then doing an insert using the data and just changing the application id and or family id. some tables are pretty big and im trying to figuere out an easier faster way to do this heres an example piece iv writen for one of my tables.
<?
//get family info based on application id
$queryC="SELECT Fam_Type, Fam_Title, Fam_SSNI20, Fam_SSNI20_Select, Fam_Name_First, Fam_Name_Middle, Fam_Name_Last, Fam_Name_Suffix, Fam_Gender, Fam_DOB, Fam_Disabled, Fam_Addy1, Fam_Addy2, Fam_City, Fam_State_Prov, Fam_Zip, Fam_Country, Fam_Home_Phone, Fam_Work_Phone, Fam_Work_Phone_Ext, Fam_Cell_Phone, Fam_Occupation, Fam_Employer, Fam_Primary_Res, Fam_Custody, Fam_Guard_Excuse, Fam_ChiDep_Ans, Fam_ReaVeh_Ans, InstructDone, SetDone, AppDone, HouDone, DepDone, AssDone, ReaDone, IncDone, ExpDone, QueDone, ApplicationDone, StatusDone, Fam_Init, Fam_Start_Date, Fam_End_Date, Fam_Agree, username, password, email, Fam_Letter, Exp_Educational, Fam_Tax, Scan_FileNames, Scan_Descriptions, Fam_Complete, referral, Fam_Holds, appealed, Appeal_Letter, Appeal_Viewed, taxDocuments
FROM familY
WHERE familyID='$famid' AND applicationID='$appid'";
$resultC = mysql_db_query($aidDB, $queryC, $connection); echo $queryC;
while($rC=mysql_fetch_array($resultC)){
$Fam_Type="$rC['0']";
$Fam_Title="$rC['1']";
$Fam_SSNI20="$rC['2']";
$Fam_SSNI20_Select="$rC['3']";
$Fam_Name_First="$rC['4']";
$Fam_Name_Middle="$rC['5']";
$Fam_Name_Last="$rC['6']";
$Fam_Name_Suffix ="$rC['7']";
$Fam_Gender="$rC['8']";
$Fam_DOB="$rC['9']";
$Fam_Disabled="$rC['10']";
$Fam_Addy1 ="$rC['11']";
$Fam_Addy2 ="$rC['12']";
$Fam_City="$rC['13']";
$Fam_State_Prov="$rC['14']";
$Fam_Zip="$rC['15']";
$Fam_Country="$rC['16']";
$Fam_Home_Phone ="$rC['17']";
$Fam_Work_Phone ="$rC['18']";
$Fam_Work_Phone_Ext="$rC['19']";
$Fam_Cell_Phone ="$rC['20']";
$Fam_Occupation ="$rC['21']";
$Fam_Employer="$rC['22']";
$Fam_Primary_Res ="$rC['23']";
$Fam_Custody="$rC['24']";
$Fam_Guard_Excuse ="$rC['25']";
$Fam_ChiDep_Ans ="$rC['26']";
$Fam_ReaVeh_Ans="$rC['27']";
$InstructDone ="$rC['28']";
$SetDone ="$rC['29']";
$AppDone ="$rC['30']";
$HouDone ="$rC['31']";
$DepDone ="$rC['32']";
$AssDone="$rC['33']";
$ReaDone ="$rC['34']";
$IncDone ="$rC['35']";
$ExpDone ="$rC['36']";
$QueDone="$rC['37']";
$ApplicationDone ="$rC['38']";
$StatusDone ="$rC['39']";
$Fam_Init="$rC['40']";
$Fam_Start_Date ="$rC['41']";
$Fam_End_Date ="$rC['42']";
$Fam_Agree ="$rC['43']";
$username ="$rC['44']";
$password ="$rC['45']";
$email ="$rC['46']";
$Fam_Letter="$rC['47']";
$Exp_Educational ="$rC['48']";
$Fam_Tax ="$rC['49']";
$Scan_FileNames="$rC['50']";
$Scan_Descriptions ="$rC['51']";
$Fam_Complete ="$rC['52']";
$referral="$rC[''53]";
$Fam_Holds="$rC['54']";
$appealed="$rC['55']";
$Appeal_Letter="$rC['56']";
$Appeal_Viewed="$rC['57']";
$taxDocuments="$rC['58']";
//insert into family with new applicationid
$queryC2="INSERT INTO family (familyID, applicationID, Fam_Type, Fam_Title, Fam_SSNI20, Fam_SSNI20_Select, Fam_Name_First, Fam_Name_Middle, Fam_Name_Last, Fam_Name_Suffix, Fam_Gender, Fam_DOB, Fam_Disabled, Fam_Addy1, Fam_Addy2, Fam_City, Fam_State_Prov, Fam_Zip, Fam_Country, Fam_Home_Phone, Fam_Work_Phone, Fam_Work_Phone_Ext, Fam_Cell_Phone, Fam_Occupation, Fam_Employer, Fam_Primary_Res, Fam_Custody, Fam_Guard_Excuse, Fam_ChiDep_Ans, Fam_ReaVeh_Ans, InstructDone, SetDone, AppDone, HouDone, DepDone, AssDone, ReaDone, IncDone, ExpDone, QueDone, ApplicationDone, StatusDone, Fam_Init, Fam_Start_Date, Fam_End_Date, Fam_Agree, username, password, email, Fam_Letter, Exp_Educational, Fam_Tax, Scan_FileNames, Scan_Descriptions, Fam_Complete, referral, Fam_Holds, appealed, Appeal_Letter, Appeal_Viewed, taxDocuments )
VALUES
(
'$newfam1id,'
'$newappid,'
'$Fam_Type,'
'$Fam_Title,'
'$Fam_SSNI20,'
'$Fam_SSNI20_Select,'
'$Fam_Name_First,'
'$Fam_Name_Middle, '
'$Fam_Name_Last,'
'$Fam_Name_Suffix,'
'$Fam_Gender,'
'$Fam_DOB,'
'$Fam_Disabled,'
'$am_Addy1,'
'$Fam_Addy2,'
'$Fam_City,'
'$Fam_State_Prov,'
'$Fam_Zip,'
'$Fam_Country,'
'$Fam_Home_Phone,'
'$Fam_Work_Phone, '
'$Fam_Work_Phone_Ext,'
'$Fam_Cell_Phone,'
'$Fam_Occupation,'
'$Fam_Employer,'
'$Primary_Res,'
'$Fam_Custody,'
'$Fam_Guard_Excuse,'
'$Fam_ChiDep_Ans,'
'$Fam_ReaVeh_Ans,'
'$InstructDone,'
'$SetDone,'
'$AppDone,'
'$HouDone,'
'$DepDone,'
'$AssDone,'
'$ReaDone,'
'$IncDone,'
'$ExpDone,'
'$QueDone,'
'$ApplicationDone,'
'$StatusDone,'
'$Fam_Init,'
'$Fam_Start_Date,'
'$Fam_End_Date,'
'$Fam_Agree,'
'$username,'
'$password,'
'$email,'
'$Fam_Letter,'
'$Exp_Educational,'
'$Fam_Tax,'
'$Scan_FileNames,'
'$Scan_Descriptions,'
'$Fam_Complete,'
'$referral,'
'$Fam_Holds,'
'$appealed,'
'$Appeal_Letter,'
'$Appeal_Viewed,'
'$taxDocuments'
)"; echo $queryC2;
}
?>
you do not need to loop all the rows.
use this:
Insert into new_table select * from old_table where {your criteria here}
mysql has INSERT into table (fields,list) SELECT fields,list FROM another_table syntax
You can reduce the amount of PHP code on the SELECT side of things by using mysql_fetch_assoc() instead of array, especially since you're then just reassigning the returned array chunks to individual variables:
$query = "SELECT Fam_Type, Fam_Title, Fam_SSNI20, Fam_SSNI20_Select etc... etc...";
$resultC = mysql_db_query($aidDB, $queryC, $connection); echo $queryC;
while($rC = mysql_fetch_assoc($resultC)) {
...
}
At this point you end up with associated array which you can get at the individual values as:
echo "Fam_Type is " . $rc['Fam_Type'];
echo "Fam_Title is " . $rc['Fam_Title'];
which saves you that long huge blob of variable assignments. Of course, if any of the fields in your query would map internally to the same name (say, you're doing a join and are retrieving two different 'id' fields from two different tables), then you'd need to alias them to different names so they come out distinctly in the array, but that's a simple mod to the query:
SELECT table1.id AS table1_id, table2.id AS table2_id ...
which would leave to:
$result['table1_id'] = ...
As a side node, you should always check to see if the query succeeded. You blindly assume it worked and try to retrieve data. But if the query fails, the mysql functions return FALSE, which would not be a valid result statement and break your fetch attempt. At bare minimum, add some basic error checking
$resultC = mysql_db_query(...) or die("MySQL error: " . mysql_error());
which will spit out the error message and explain why the query failed, instead of then failing with "... is not a valid statement handle" later on. As well, mysql_db_query() is deprecated as of PHP 5.3, and will vanish in some future PHP version. May want to switch to the regular mysql_query() instead.
you can simply do:
INSERT INTO family ( appliction_id, all_the_other_fields )
SELECT 'your_new_app_id', all_the_other_fields
FROM familY
WHERE familyID='$famid' AND applicationID='$appid'
let's hope your $famid and $appid variables are escaped, shall we?

Need help INSERT record(s) MySQL DB

I have an online form which collects member(s) information and stores it into a very long MySQL database. We allow up to 16 members to enroll at a single time and originally structured the DB to allow such.
For example:
If 1 Member enrolls, his personal information (first name, last name, address, phone, email) are stored on a single row.
If 15 Members enroll (all at once), their personal information are stored in the same single row.
The row has information housing columns for all 'possible' inputs. I am trying to consolidate this code and having every nth member that enrolls put onto a new record within the database.
I have seen sugestions before for inserting multiple records as such:
INSERT INTO tablename VALUES
(('$f1name', '$f1address', '$f1phone'), ('$f2name', '$f2address', '$f2phone')...
The issue with this is two fold:
I do not know how many records are
being enrolled from person to person
so the only way to make the
statement above is to use a loop
The information collected from the
forms is NOT a single array so I
can't loop through one array and
have it parse out. My information is
collected as individual input fields
like such: Member1FirstName,
Member1LastName, Member1Phone,
Member2Firstname, Member2LastName,
Member2Phone... and so on
Is it possible to store information in separate rows WITHOUT using a loop (and therefore having to go back and completely restructure my form field names and such (which can't happen due to the way the validation rules are built.)
If you form's structured so that all the fields are numbered properly, so that a "firstname #1" is matched up with all the other "#1" numbered fields, then a loop is the simplest solution.
start_transaction();
$errors = false;
for ($i = 1; $i <= 16; $i++) {
if (... all $i fields are properly filled in ...) {
$field = $_POST["field$i"];
$otherfield = $_POST["otherfield$i"];
etc...
... insert into database ...
} else {
... handle error condition here
$errors = true;
}
}
if (!$errors) {
commit_transaction();
} else {
rollback();
}
If they're numbered randomly, so that firstname1 is matched with lastname42 and address3.1415927, then you'd have to build a lookup table to map all the random namings together, and loop over that
followup per comment:
well, if you absolutely insist on maintaining this database structure, where each row contains 16 sets of repeated firstname/lastname/etc.. records, then you'd do something like this:
$first = true;
for ($i = 1; $i <= 16; $i++) {
if (fields at position $i are valid) {
$firstname = mysql_escape_real_string($_POST["F{$i}name"]);
$lastname = mysql_real_escape_string($_POST["F{$i}lastname"]);
if ($first) {
$dbh->query("INSERT INTO table (f{$i}name, f{$i}lastname) VALUES ($firstname, $lastname);"
$recordID = $dbh->query("SELECT last_insert_id();");
$first = false;
} else {
$dbh->query("UPDATE table SET f{$i}name=$firstname, f{$i}lastname=$lastname WHERE idfield=$recordID");
}
}
}
It's ugly, but basically:
loop through the form field sets until you find a valid set (all required fields filled in, valid data entered, etc..
Insert that data set into the database to create the new record
retrieve ID of that new record
continue looping over the rest of the fields
for every subsequent set of valid records, do an update of the previously created record and add in the new fieldset data.
Though, honestly, unless you've got some highly offbeat design need to maintain a single table with 16 sets of repeated columns, you'd be better off normalizing a bit, and maintain two seperate tables. A parent "enrollment" table, and a child "members" table. That way you can create the parent enrollment table, then just insert new children as you encounter them in the form.
update #2:
well, a simplified form of a normalized layout would be:
signups (id, name, etc...)
signup_members (id, signup_id, firstname, lastname)
and you'd pull the full signup record set with the following query:
SELECT signups.id, signups.name, signup_members.id, firstname, lastname
FROM signups
LEFT JOIN signup_members ON signups.id = signup_members.signup_id
ORDER BY ...
That would give you a series of rows, one for each 'member' signup. To build the CSV, a simple loop with some state checking to see if you've reached a new signup yet:
$oldid = null;
$csv = ... put column headers here if you want ...
while ($signup = $result->fetchrow()) {
if ($signup['signups.id'] != $oldid) {
// current signup doesn't match previous seen id, so got a new signup record
$csv .= "\n"; // start new line in CSV
$csv .= ... add first few columns to new csv row ...
$oldid = $signup['signups.id']; // store new record id
} else {
$csv .= ... add extra member columns to current csv row ...
}
}
What you're trying to do could be simpler, but to solve the problem, you can join the user information into one variable, separated by a char of your choice and send it to Mysql DB...
$user1 = $f1name . ';' . $f1address . ';' . $f1phone;
$user2 = $f2name . ';' . $f2address . ';' . $f2phone;
$user3 = $f3name . ';' . $f3address . ';' . $f3phone;
INSERT INTO table-name VALUES('$user1','$user2','$user3')
To extract, just "explode" the value by the ";".
If you use the same order for all users data, and if you send a verification string in case one user leaves a field blank, works just fine :)
humm... this work's just fine if the user isn't allowed to use ";" as "personal data" :)
Hope it helps U!
I think you might want to look at "variable variables":
http://php.net/manual/en/language.variables.variable.php
Then you could conceivably loop through from 1 to 15, without having to rename your form fields.

Categories