I have this code to insert a new row into MySQL DB using PDO:
$query = INSERT INTO asset_positions (pos_asset_id, pos_latitude, pos_longitude, pos_timestamp) VALUES (:pos_asset_id, :pos_latitude, :pos_longitude, :pos_timestamp)
$statement = $pdo->prepare($query);
$array = [':pos_asset_id' => 1, ':pos_latitude' => -8.5, ':pos_longitude' => 125.5, ':pos_timestamp' => 1398160487];
$statement->execute($array);
echo $pdo->lastInsertId();
The query runs without any error shown. The newly inserted row ID is echoed. However, when i look in the DB, it only insert the latitude, longitude and timestamp. The pos_asset_id field in the newly inserted row is empty.
Could somebody point out where is the problem? There is no error message displayed. I've been trying to solve this for hours without avail.
Ps. This is my first time using PDO, so please bear with me. Thanks.
EDIT
Solved! I didn't notice that there's a FK relation between asset_positions.pos_asset_id and asset.asset_id. Once i remove this relationship constrains, the INSERT works properly now, the pos_asset_id value is inserted to the record.
Anyway, thanks all! :)
try running with error catching, it will give you better understanding of what is happening.
try {
$stmt->execute();
} catch (PDOException $p) {
echo $p->getMessage();
} catch (Exception $e) {
echo $e->getMessage();
}
But your common sense and user3540050 are right... it's a column related issue probably
Related
Its very strange. I do a SQL query which works totally fine when he found entries that match. But I tested it with no database entries to show the user "NOTHING TO SHOW" but then it gives me back the complete user row which is in another table and I don't can figure out why this is happening.
my connection
try
{ $db = new PDO("mysql:host={$_MYSQL['host']};
dbname={$_MYSQL['database']}", $_MYSQL['user'], $_MYSQL['pass'], [ PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_PERSISTENT => true ]);
}
catch (PDOException $e) { exit($e->getMessage());
}
my code
$sql = $db->query("SELECT id, oname, datum, prov FROM completed_tasks WHERE user_id =" .$db->quote($user['id']));
if ($sql->rowCount() != 0) {
$row = $sql->fetchAll();
}
When in completed_task are entries with the user_id it works like expected. When there is nothing to match in table completed_tasks it gives me the complete user row from a totally different table users. So how can this happen?
Code you provided seems to be correct.
It might be, that $row variable is also used somewhere else in your code - maybe before of after snippet you provided. And since this particular query has no rows in the result, content of $row remains the same - so it might contain result from the previous query. It might also be, that it will be overwritten later on.
Here is the database and PHP information:
Database vendor and version : 10.2.32-MariaDB
PHP Version : PHP 7.3
I am running into an issue when trying to retrieve the last inserted id to use in another insert statement using PHP PDO and MariaDB...
Sorry for the vague pseudo-code below but trying to mask proprietary data:
try {
include_once $pdo connection stuff here;
$pdo->beginTransaction();
$sql = 'AN INSERT STATEMENT HERE';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':some_value', $some_value);
$stmt->bindValue(':another_one', $another_one);
$stmt->bindValue(':additional_value', $additional_value);
$stmt->execute();
// have tried to call $pdo->commit(): here to no avail.
//should get the last inserted id here on the AUTO_INCREMENT column in the target table from above prepared statement
// the AI column is not included in the insert statement above nor any value specified in the VALUES clause so should
// set to the next available value (and does so according to peeking at row over in phpMyAdmin).
$last_insert_id = $pdo->lastInsertId();
// don't really want to commit the above insert here just yet in case something goes wrong below and can rollback
// a file could be uploaded but it's not mandatory
if (!empty($_FILES['some_file'])) { // file has been attached.
// some file operations here
// some file operations here
// some file operations here
// some file operations here
$extensions = array("extension I am expecting");
if (in_array($file_ext, $extensions) === false) {
//Uh-oh not the correct extension so rolling back
$pdo->rollback();
die('message here...');
} else {
// file type is ok so proceeding
// if the file already exists, get rid of it so we don't have 2 copies on the server
if (file_exists($file_dir.$file_name)) {
unlink($file_dir.$file_name);
}
// storing the attached file in designated directory
move_uploaded_file($file_tmp, $file_dir.$file_name);
// going to parse the file...
$xml = simplexml_load_file('xml file to parse');
// have tried to call $pdo->commit(): here to no avail.
foreach ($xml->children() as $row) {
foreach ($row as $obj) {
if (some checking things with the obj here yada yada yada) {
$insert_sql = "INSERT INTO another table(columns.....) //there is no AUTO_INCREMENT column attribute on any column in this table just FYI
VALUES(column values...)";
$stmt = $pdo->prepare($insert_sql);
// want the AI value here from the very first insert above but it's always zero (0)
$stmt->bindValue(':last_insert_id', intval($last_insert_id), PDO::PARAM_INT);
$stmt->bindValue(':some_column', strval($some_column));
$stmt->bindValue(':another_one', strval($another_one));
$stmt->execute();
}
}
}
// all is good so committing the first insert
$pdo->commit();
}
} else {
// the file was not uploaded and it is not mandatory so committing the first insert here and the second insert never happens
$pdo->commit();
}
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollback();
}
throw $e;
echo 'An error occurred.';
echo 'Database Error '. $e->getMessage(). ' in '. $e->getFile().
': '. $e->getLine();
}
}
My goal is that the first insert always gets inserted (should nothing fail in it). The second insert is optional depending if a file is attached.
If the file is attached and all the file operations are good, then I'll insert some values in another table and use the auto_increment value from the first insert in this second table ( the idea is as a foreign key).
But for whatever reason, the value inserted is always zero (0).
When the code executes successfully both table inserts complete (granted a file is present and the second insert even fires)...
The row in the first table is created and 1 or more rows in the second insert's table are created but they have a value of 0 in the designated column, where I would expect them to contain the AI value from the first insert...
I've tried to call $pdo->commit() in several other places that "make sense" to me thinking that the first insert must be committed for an AI value to even exist on that table but no luck with any of them...
I even tried this I saw in another Stackoverflow post as a test to make sure PDO isn't doing anything wonky, but PDO is fine...
$conn = new PDO(connection info here);
$conn->exec('CREATE TABLE testIncrement ' .
'(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50))');
$sth = $conn->prepare('INSERT INTO testIncrement (name) VALUES (:name)');
$sth->execute([':name' => 'foo']);
var_dump($conn->lastInsertId());
And the above does return: string(1) "1"
So I think PDO is ok (granted the above was not wrapped in a transaction and I haven't tried that yet)
Hope I have provided enough clear details...
Does anyone know why I am getting 0 and not the last insert id?
Any help is greatly appreciated and thank you!
You need to check the result of $stmt->execute. Read the docs on PDOStatement::execute and you'll see that it returns a boolean value:
Returns TRUE on success or FALSE on failure.
Then read the docs on PDOStatement::errorInfo. Check this if execute returns FALSE.
$stmt->execute();
echo "\nPDOStatement::errorInfo():\n";
$arr = $stmt->errorInfo();
print_r($arr);
EDIT: it's not generally a good idea to output errors to the screen, I did so in this case for convenience. A better approach would be to write a log file:
$arr = $stmt->errorInfo();
file_put_contents("/path/to/file.log", print_r($arr, TRUE));
I wonder whether it matters where to start the transaction.
Example 1:
$transaction = Yii::app()->db->beginTransaction();
try
{
$savedSuccessfully = $object->save();
$transaction->commit();
}
catch (Exception $ex)
{
$transaction->rollBack();
$result = $e->getMessage();
}
Example 2:
$transaction = Yii::app()->db->beginTransaction();
try
{
$object = $model()::model()->findByPk(1); //!!!!!!! - line
// what makes the difference
$savedSuccessfully = $object->save();
$transaction->commit();
}
catch (Exception $ex)
{
$transaction->rollBack();
$result = $e->getMessage();
}
Should transaction be started before selecting data from db or or just before updating/inserting data? Will yii take care of it instead of me?
Thanks
Example 2 would be the solution of choice.
By retrieving the model within the transaction, you make sure that it is consistent throughout your changes.
If you retrieve the model, like in example 1, outside the transaction, other threads/users could change the corresponding database entry before you commit your changes. So you could end up with potentially inconsistent data.
Actually 2nd one is correct , if you are saving data which is more critical like banking transaction or payment system then example 2 is very correct way. for example , you are doing some code like this.
insert into table 1
select from table 1
insert into table 2
update table 2
select from table 1.
so if you start transaction from first , it will rollback all query if any query fails which will be more efficient. for example in online payment system.
I´m very new to PDO. I just wonder what´s the best way to get the result when the data insert to the database comletely. I´m looking around in googl. seems like it´s flexible. That makes me wonder what is correct and what is incorrrect way.
Let see example:
$sql = $conn->prepare("INSERT INTO tb_user(user_name, user_email) VALUES(:user_name,:user_email);
$sql->execute(array(':user_name'=>$user_name, ':user_email'=>$user_email));
$affected_rows = $sql->rowCount();
From this script I want to get result if the data is finish to be insert in database.
If it done-->I will echo it like "complete" and send it back to ajax or etc...
I have tried :
if($affected_rows){
echo"YEZZ!! complete";
}
And
$all = $slq->fetchAll();
if(count($all)) {
echo"YEZZ!! complete";
}
And
if ($sql->execute){
echo"YEZZ!! complete";
//this one i know it will double insert data to database because I called it twice//
But I still want to know when can I use this method
And maybe more ways out there which make me crazy and want to know what is the best way to get result if the thing is done:
AFter insert, after delete, after update these 3 statements is the most important to know each.
Any suggestions could be wonderful !
}
}
you could do:
$id = $conn->lastInsertId('IDCOLUMN');
and then execute a query and search for the id
$stmt = $conn->prepare("SELECT * FROM tb_user WHERE IDCOLUMN = :id");
$stmt->execute(array("id", $id);
if($stmt->rowCount() > 0) {
$result = $stmt->fetch(PDO::FETCH_ASSOC);
}
the result variable will contain your last inserted record
Yes, your approach with rowCount() is a right one. Stick with it.
I am trying to implement an action that can get me the last inserted id before I insert a record.
The action is basically supposed to get the last inserted id, then i add 1 to it then the value will be used in the current data been inserted.
This how far I have gotten and the error am getting
//the action to get the last inserted id
public function getLastID(){
$lastcourseid = $this->tableGateway->select(function (Select $select){
$select->columns(array('id'));
$select->order('id ASC')->limit(1);
});
var_dump($lastcourseid);
return $lastcourseid;
}
I call the function here before saving
if($id == 0){
$data['course_code'] = $this->getLastID();
$this->tableGateway->insert($data);
}else{
if($this->getAlbum($id)){
$this->tableGateway->update($data, array('id' => $id));
}else{
throw new \Exception("Form id does not exist");//an error is thrown in case the id is not found
}
}
This is the error am getting
Catchable fatal error: Object of class Zend\Db\ResultSet\ResultSet
could not be converted to string
I do not know where am going wrong.
Any help will be appreciated. Thanks
There is no such thing like "last id before insert".
And you don't need it.
First insert a record and then get your id. This is how it works.
You do not mention the underlying database (postgressql, mysql, etc.). I am more familiar with MySQL. The Perl and php AIP's have "last row id" functions. For example, php has "mysqli_insert_id()". This assumes that your rowID is an AUTO_INCREMENT column. Other DBs may have different requirements.