Related
This question already has answers here:
Check if MySQL table exists without using "select from" syntax?
(19 answers)
Closed 5 years ago.
if($count <= 0 ) // IF TABLE DOES NOT EXIST -> CREATE AND INSERT DATA
{
$CREATE_TABLE= "CREATE TABLE $TABLE_NAME LIKE student; INSERT $TABLE_NAME SELECT * FROM student;";
$created = $connect->exec($CREATE_TABLE);
if($created!=FALSE)
{
$SQL = "INSERT INTO $TABLE_NAME (name, roll_number, father_name, dob, gender, address, email, phone, department, program, semester, section) VALUES(:name, :roll_number, :father_name, :dob, :gender, :address, :email, :phone, :department, :program, :semester, :section)";
$pdo_statement = $connect->prepare($SQL);
$pdo_statement->bindparam(':name', $name);
$pdo_statement->bindparam(':roll_number', $roll_number);
$pdo_statement->bindparam(':father_name', $father_name);
$pdo_statement->bindparam(':dob', $dob);
$pdo_statement->bindparam(':gender', $gender);
$pdo_statement->bindparam(':address', $address);
$pdo_statement->bindparam(':email', $email);
$pdo_statement->bindparam(':phone', $phone);
$pdo_statement->bindparam(':department', $department);
$pdo_statement->bindparam(':program', $program);
$pdo_statement->bindparam(':semester', $semester);
$pdo_statement->bindparam(':section', $section);
$result = $pdo_statement->execute();
}
}
else if($count > 0) // IF TABLE EXIST -> INSERT DATA
{
$SQL = "INSERT INTO $TABLE_NAME (name, roll_number, father_name, dob, gender, address, email, phone, department, program, semester, section) VALUES (:name, :roll_number, :father_name, :dob, :gender, :address, :email, :phone, :department, :program, :semester, :section)";
$pdo_statement = $connect->prepare($SQL);
$pdo_statement->bindparam(':name', $name);
$pdo_statement->bindparam(':roll_number', $roll_number);
$pdo_statement->bindparam(':father_name', $father_name);
$pdo_statement->bindparam(':dob', $dob);
$pdo_statement->bindparam(':gender', $gender);
$pdo_statement->bindparam(':address', $address);
$pdo_statement->bindparam(':email', $email);
$pdo_statement->bindparam(':phone', $phone);
$pdo_statement->bindparam(':department', $department);
$pdo_statement->bindparam(':program', $program);
$pdo_statement->bindparam(':semester', $semester);
$pdo_statement->bindparam(':section', $section);
$result = $pdo_statement->execute();
} // ELSE IF ENDS
So i understand you will create the table, if it does not exist and insert data. So call first
$pdo->query("CREATE TABLE $TABLE IF NOT EXISTS;");
It will do nothing, when table exists.
And then insert your data.
$pdo->query("INSERT INTO $TABLE ... ");
No 'if then else' in PHP!
function tableExists($pdo, $table) {
// Try a select statement against the table
// Run it in try/catch in case PDO is in ERRMODE_EXCEPTION.
try {
$result = $pdo->query("SELECT 1 FROM $table LIMIT 1");
} catch (Exception $e) {
// We got an exception == table not found
return FALSE;
}
// Result is either boolean FALSE (no table found) or PDOStatement Object (table found)
return $result !== FALSE;
}
To give you some background, the flow is: Connect to a 3rd party API, pull data stored as json, convert to php and use the data in the below code.
I found this work originally but unable to figure out how to modify it to my needs. Perhaps one of you could understand it better?
I am doing 3 things here. First checking the ID of a house + last_update stamp to determine which houses need to be updated in my database. If they exist but details have changed, drop the current data and store it in a variable ready to be inserted. If the data does not exist, insert it.
Something to note: The script takes so long to execute that I have to set set_time_limit(0); which I realise is bad practise but I needed to force the script to complete.
I have cut my code down quite a lot given that I had over 40 different manually entered prepared statements for either:
Updating records
Deleting records
Inserting records
I have identified the expected outputs using screenshots so please ignore any open braces at this point as the main issue is refining the code to a more dynamic approach and making it quicker of course.
<?php
$update = '';
$add = '';
if (!empty($houses)) {
foreach($houses as $travel_Prop) {
$Prop = $travel_Prop['data'][0]; // Need to check this!
if ($Prop['id'] > '0') { // Ignore empty arrays
$sql= "SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id";
$stmt = $extDb->prepare("$sql");
$stmt->bindParam(':travel_prop_id', $Prop['id'], PDO::PARAM_INT);
$stmt->execute();
$Result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($Result)) {
$travel_last_update = $Prop['last_update'];
$local_last_update = $Result[0]['last_update'];
if ($travel_last_update > $local_last_update) {
$update[] = $Prop;
echo 'Property ID: ' .$Prop['id'] .' Property modified: Updating Records.<br>';
} else {
echo 'Property ID: ' .$Prop['id'] .' Property details: Up to Date.<br>';
}
} else {
$add[] = $Prop;
echo 'Property ID: ' .$Prop['id'] .' Property Created: Adding to Records.';
}
}
}
NOTE: Code will carry on after screenshot output
# UPDATE
if (!empty($update)) {
//print_r($update);
foreach ($update as $PropUpdate) {
// Get all_prop_id
$sql= "SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id";
$stmt = $extDb->prepare("$sql");
$stmt->bindParam(':travel_prop_id', $PropUpdate['id'], PDO::PARAM_INT);
$stmt->execute();
//$Result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$obj = $stmt->fetchObject();
//echo $obj->filmName;
$all_prop_id = $obj->all_prop_id;
echo $all_prop_id;
// Update master db table a_property
$sql = "UPDATE travel_a_property SET last_update = :last_update
HERE all_prop_id = :all_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':last_update', $PropUpdate['last_update'], PDO::PARAM_STR);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->execute();
echo '<br>Prop Updated - all_prop_id : ' .$all_prop_id .'<br>';
# DELETe & INSERT
$sql = "DELETE FROM ot_b_address WHERE glob_prop_id = :glob_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':glob_prop_id', $glob_prop_id, PDO::PARAM_INT);
$stmt->execute();
$sql = "INSERT INTO ot_b_address(glob_prop_id, address1, address2, city, state, zip_code,
country, latitude, longitude) VALUES ( :glob_prop_id, :address1, :address2, :city, :state,
:zip_code, :country, :latitude, :longitude)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':glob_prop_id', $glob_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':address1', $PropUpdate['address']['address1'], PDO::PARAM_STR);
$stmt->bindParam(':address2', $PropUpdate['address']['address2'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropUpdate['address']['city'], PDO::PARAM_STR);
$stmt->bindParam(':state', $PropUpdate['address']['state'], PDO::PARAM_STR);
$stmt->bindParam(':zip_code', $PropUpdate['address']['zip_code'], PDO::PARAM_STR);
$stmt->bindParam(':country', $PropUpdate['address']['country'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropUpdate['address']['city'], PDO::PARAM_STR);
// use PARAM_STR although a number
$stmt->bindParam(':latitude', $PropUpdate['address']['latitude'], PDO::PARAM_STR);
$stmt->bindParam(':longitude', $PropUpdate['address']['longitude'], PDO::PARAM_STR);
$stmt->execute();
echo 'Address Updated <br>';
$sql = "DELETE FROM travel_d_urls WHERE all_prop_id = :all_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->execute();
if (!empty($PropUpdate['urls'])) {
foreach($PropUpdate['urls'] as $row => $Url) {
$sql = "INSERT INTO travel_d_urls(all_prop_id, type, url)
VALUES ( :all_prop_id, :type, :url)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':type', $Url['type'], PDO::PARAM_STR);
$stmt->bindParam(':url', $Url['url'], PDO::PARAM_STR);
$stmt->execute();
echo 'URL '.$row .' Updated <br>';
}
}
}
} else {
echo 'no rates to Update <br>';
}
The output is pretty much just the same thing (whatever is being updated)
URL ADDED
URL ADDED
etc
The following code is the last if statement which tells the script to add the remaining properties if they do not exist.
} // end foreach $update
# INSERT ONLY
if (!empty($add)) {
foreach ($add as $PropAdd) {
$sql = "INSERT INTO travel_a_property(travel_prop_id, last_update)
VALUES ( :travel_prop_id, :last_update)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':travel_prop_id', $PropAdd['id'], PDO::PARAM_INT);
$stmt->bindParam(':last_update', $PropAdd['last_update'], PDO::PARAM_STR);
$stmt->execute();
$all_prop_id = $extDb->lastInsertId(); // Use this ID in all the following record inserts
echo '<br>Prop Added - all_prop_id : ' .$all_prop_id .'<br>';
##########################
$sql = "INSERT INTO travel_b_address(all_prop_id, address1, address2, city, state, zip_code, country,
latitude, longitude) VALUES ( :all_prop_id, :address1, :address2, :city, :state, :zip_code, :country,
:latitude, :longitude)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':address1', $PropAdd['address']['address1'], PDO::PARAM_STR);
$stmt->bindParam(':address2', $PropAdd['address']['address2'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropAdd['address']['city'], PDO::PARAM_STR);
$stmt->bindParam(':state', $PropAdd['address']['state'], PDO::PARAM_STR);
$stmt->bindParam(':zip_code', $PropAdd['address']['zip_code'], PDO::PARAM_STR);
$stmt->bindParam(':country', $PropAdd['address']['country'], PDO::PARAM_STR);
// use PARAM_STR although a number
$stmt->bindParam(':latitude', $PropAdd['address']['latitude'], PDO::PARAM_STR);
$stmt->bindParam(':longitude', $PropAdd['address']['longitude'], PDO::PARAM_STR);
$stmt->execute();
echo 'Address Added <br>';
} // end foreach
} // end !empty
$extDb = null;
}
?>
So to reiterate, the question here is not to identify what is wrong with my code as other than the speed, it is actually working fine. I would like to know if someone could identify the best way to make this dynamic to avoid having to tediously write the code 40 + times?
If anything is unclear, please let me know.
Cheers,
bench.
You are creating the prepared statements inside the foreach loop. Try to create the prepared statement outside of it. The idea of a prepared statement is that you prepare the statement once and execute it multiple times with different parameter values. This way the database only have to compile and optimize the SQL query once, which is more efficient than doing it foreach iteration.
if (!empty($houses)) {
$stmt = $extDb->prepare("SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id");
//$stmt2 = ...
foreach ($houses as $travel_Prop) {
$prop = $travel_Prop['data'][0]; // Need to check this!
if ($prop['id'] > '0') { // Ignore empty arrays
if ($stmt->execute(array(':travel_prop_id' => $prop['id']))) {
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Do something with $result
}
}
//$stmt2->execute(...);
}
}
I have tried lots of ways to get the last inserted ID with the code below (snipplet from larger class) and now I have given up.
Does anyone know howto get PDO lastInsertId to work?
Thanks in advance.
$sql = "INSERT INTO auth (surname, forename, email, mobile, mobilepin, actlink, regdate) VALUES (:surname, :forename, :email, :mobile, :mobpin, :actlink, NOW())";
$stmt = $this->dbh->prepare($sql);
if(!$stmt) {
return "st";
}
$stmt->bindParam(':surname', $this->surname);
$stmt->bindParam(':forename', $this->forename);
$stmt->bindParam(':email', $this->email);
$stmt->bindParam(':mobile', $this->mobile);
$stmt->bindParam(':mobpin', $this->mobilePin);
$stmt->bindParam(':actlink', $this->actlink);
$result = $stmt->execute();
//return var_dump($result);
$arr = array();
$arr = $stmt->errorInfo();
$_SESSION['record'] = 'OK' . $dbh->lastInsertId();
$arr .= $_SESSION['record'];
return $arr;
In your code snippet, I saw some minor inconsistencies that may have an effect on the problem. For an example, in the code to prepare your SQL statement you use,
$stmt = $this->dbh->prepare($sql);
Notice the $this keyword. Then to retrieve the ID, you call,
$dbh->lastInsertId();
Have you tried using,
$this->dbh->lastInsertId();
i am getting this error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO student_details (student_id, first_name, last_name, dob, address_lin' at line 2
for this code: any idea?
//create variables from each value that was submitted from the form */
$student_info_id = $_POST['student_info_id'];
$class_id = $_POST['class_id'];
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$dob = $_POST['dob'];
$address_line_1 = $_POST['address_line_1'];
$address_line_2 = $_POST['address_line_2'];
$town = $_POST['town'];
$county = $_POST['county'];
$postcode = $_POST['postcode'];
$gender = $_POST['gender'];
$ethnicity = $_POST['ethnicity'];
try {
$conn = new PDO("mysql:host=$host; dbname=$dbname", $user, $password);
$conn->exec("SET CHARACTER SET utf8"); // Sets encoding UTF-8
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "
INSERT INTO student_info (student_info_id, class_id) VALUES (:student_info_id, :class_id)
INSERT INTO student_details (student_id, first_name, last_name, dob, address_line_1, address_line_2, town, county, postcode, gender, ethnicity, student_info_id)
VALUES (:student_id, :first_name, :last_name, :dob, :address_line_1, :address_line_2, :town, :county, :postcode, :gender, :ethnicity, :student_info_id)
";
$statement = $conn->prepare($sql);
$statement->bindValue(":student_info_id", $student_info_id);
$statement->bindValue(":class_id", $class_id);
$statement->bindValue(":student_id", $student_id);
$statement->bindValue(":first_name", $first_name);
$statement->bindValue(":last_name", $last_name);
$statement->bindValue(":dob", $dob);
$statement->bindValue(":address_line_1", $address_line_2);
$statement->bindValue(":address_line_2", $address_line_1);
$statement->bindValue(":town", $town);
$statement->bindValue(":county", $county);
$statement->bindValue(":postcode", $postcode);
$statement->bindValue(":gender", $gender);
$statement->bindValue(":ethnicity", $ethnicity);
$statement->bindValue(":student_info_id", $student_info_id);
$count = $statement->execute();
$conn = null; // Disconnect
}
catch(PDOException $e) {
echo $e->getMessage();
}
I'm not sure if PDO support multiple statements, but if so, the error is that you did not terminate the first statement,
INSERT INTO student_info (student_info_id, class_id)
VALUES (:student_info_id, :class_id);
^ add this one
You'll have to finish the first INSERT with a ; Like this:
INSERT INTO student_info (
student_info_id,
class_id
) VALUES (
:student_info_id,
:class_id
); <-- a semicolon is the default statement separator, use it
....
Note that, although it is possible to run multiple queries at once, I would not advice you to do it. If you would run each query one by one you would have a better control over errors.
You can't run multiple queries in one call.
Run them separately, one by one.
i have a pdo block for inserting values into my table as follows
try{
$user = 'root';
$pass = null;
$pdo = new PDO('mysql:host=localhost; dbname=divebay', $user, $pass);
$name = $_POST['name'];
$desc = $_POST['description'];
$cond = $_POST['condGroup'];
$sprice = $_POST['sprice'];
$iprice = $_POST['iprice'];
$incprice = $_POST['incprice'];
$duration = $_POST['duration'];
$img = $_POST['img'];
$owner = $_SESSION['username'];
$valid = "set";
$stmt2 = $pdo->prepare("SELECT * FROM auction WHERE ID = :id");
$stmt2->bindParam(":id", $random, PDO::PARAM_INT);
while(isset($valid)){
$random = rand(100000,999999);
$stmt2->execute();
if(!$stmt2->fetch(PDO::FETCH_ASSOC)){
unset($valid);
}
}
$timestamp = time() + ($duration * 24 * 60 * 60);
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description");
$stmt->bindParam(':id', $random, PDO::PARAM_INT);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':owner', $owner, PDO::PARAM_STR);
$stmt->bindParam(':holder', $owner, PDO::PARAM_STR);
$stmt->bindParam(':iprice', $iprice, PDO::PARAM_STR);
$stmt->bindParam(':sprice', $sprice, PDO::PARAM_STR);
$stmt->bindParam(':incprice', $incprice, PDO::PARAM_STR);
$stmt->bindParam(':etime', $timestamp, PDO::PARAM_INT);
$stmt->bindParam(':img', $img, PDO::PARAM_STR);
$stmt->bindParam(':condition', $condition, PDO::PARAM_STR);
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
if($stmt->execute()){
$worked ="yes";
}
}catch(PDOException $e){
echo $e->getMessage();
}
i cant tell why this statement wont execute, the $worked variable has not been set when it is the script is run. all database column names and datatypes have been checked correct as they are. ive never had a problem with a statement not executing until now. whats wrong? how do i go about debugging this?
If you setup the database connection with error mode exception PDO will throw an exception if something is wrong with your statement. I also see that you are using the MySQL driver for PDO. If you do this you should always disable emulated prepared statements. So I would write you connection as following (note that I have also set the encoding):
$pdo = new PDO('mysql:host=localhost; dbname=divebay;charset=utf8', $user, $pass);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Also see this post for more information about this.
Once you have done this you will see that your statement is wrong. You have one missing ) at the end of the statement:
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description)");
^
Modify this line:
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description");
To
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description)");
The difference is the ) at the end.
And tell me if it works now.