Im getting to grips with the basics of PDO.
However Im trying to get the id of the inserted row, Im using:
$query = $system->db->prepare("INSERT INTO {$this->_table} (name,description) VALUES (:name,:description)");
$query->execute(array('name'=>$name,'description'=>$description));
The tutorials I have come across are regarding transactions, however I am not using transactions!
You're probably looking for lastInsertId. "Returns the ID of the last inserted row or sequence value".
$insertedId = $system->db->lastInsertId() ;
Pay attention when using transactions.
If you call lastInsertedId after you call commit, lastInsertedId will return 0 instead of the id.
Call lastInsertedId right after execute, but before commit.
$this->db->beginTransaction();
$this->stmt->execute();
$id = $this->db->lastInsertId();
$this->db->commit();
Related
In my test-surroundings there is a database containing some Person Information (Name, E-Mail, Adress etc.). These Informations can be inserted by anyone into the database via a form. In the background they are inserted with a parameterized INSERT into the database after submission.
What I now would like to do is to detect if some person tries to insert the same values into the database again, and if he does, not inserting the new values and instead showing an error message. (So every person name in the database is unique, there are no multiple rows linked to one name).
I had a numerous number of ideas on how to accomplish this. My first one was to use a query like REPLACE or INSERT IGNORE, but this method would not give me feedback so I can display the error message.
My second attempt was to first do a SELECT-query, checking if the row already exists, and if num_rows is greater than 0, exit with the error message (and else do the INSERT-part). For this to work I will have to use parameterized queries for the SELECT too, as I´m putting some user input into it. Figuring that parameterized queries need special functions for everything you could normally do with way less lines of code, I researched in the internet on how to get num_rows from my $statement parameterized-statement-object. This is what I had in the end:
$connection = new mysqli('x', 'x', 'x', 'x');
if (mysqli_connect_error()) {
die("Connect Error");
}
$connection->set_charset("UTF-8");
$statement = $connection->stmt_init();
$statement = $connection->prepare('SELECT Name FROM test WHERE Name LIKE ?');
flags = "s";
$statement->bind_param($flags, $_POST["person_name"]);
$statement->execute();
$statement->store_result();
$result = $statement->get_result(); //Produces error
if ($result->num_rows >= 1) {
$output = "Your already registered";
} else {
$output = "Registering you...";
}
exit($output);
After all, I can´t get why mysqli still won´t give me num_rows from my statement. Any help is appreciated, thanks in advance!
Oh, and if you guys could explain to me what I have to do to get affected_rows,that would be awesome!
EDIT: I know I could to this by using unique constraints. I also found out that I can find out if INSERT IGNORE skipped the INSERT or not. But that won´t answer my complete question: Why does the SELECT num_rows alternative not work?
ANOTHER EDIT: I changed the code snippet to what I now have. Although my mysql(i)-version seems to be 5.6.33 (I echo´d it via $connection->server_info) get_result() produces the following error message:
Fatal error: Call to undefined method mysqli_stmt::get_result() in X on line X (line of get_result)
The behaviour of mysqli_num_rows() depends on whether buffered or unbuffered result sets are being used. For unbuffered result sets, mysqli_num_rows() will not return the correct number of rows until all the rows in the result have been retrieved. Note that if the number of rows is greater than PHP_INT_MAX, the number will be returned as a string.
Also make sure that you declare ->store_result() first. Moreover the function doesn't work with LIMIT used jointly with SQL_CALC_FOUND_ROWS. If you want to obtain the total rows found you must do it manually.
EDIT:
If nothing from the suggestions does not work for you, then I would propose to rewrite your SQL query:
SELECT `Name`, (SELECT COUNT(*) FROM `Persons`) AS `num_rows` FROM `Persons` WHERE `Name` LIKE ?
This query will return the total number from your Persons table, as well as Name, if exist.
i want to get the id of last inserted row and i m using mysql_insert_id() function. but giving issue
here is my code :
if($i == 0)
{
$query = "update events set e_did ='".$multi_event."' where eid = '".$display_id."'";
mysqli_query($con,$query);
file_put_contents('log.txt', mysql_insert_id(), FILE_APPEND);
}
else
{
$query = "INSERT INTO events (start_date, end_date, text, rec_type, event_pid, event_length, e_did) VALUES ('".$row['start_date']."','".$row['end_date']."','".$row['text']."','".$row['rec_type']."','".$row['event_pid']."','".$row['event_length']."','".$multi_event."')";
mysqli_query($con,$query);
file_put_contents('log.txt', 'A'.mysql_insert_id().'A', FILE_APPEND);
}
now both time i m getting same id. what is the issue. is i m doing wrong something somewhere ?
If you use the mysqli functions, you must use mysqli_insert_id. You can't mix ext/mysql and ext/mysqli.
Also, UPDATE does not generate a new auto-increment id. You should call mysqli_insert_id() after INSERT, but not UPDATE.
mysqli_insert_id() only returns an id for INSERT queries. An update query will NOT return an id, because by definition you must already have a row in the database for it be getting updated.
With UPDATE, you are editing records, not adding ones. So no new IDs are generated. You can only use mysql_insert_id on INSERT.
Note: mysql_* functions are deprecated and won't be supported in future versions. You should be using either mysqli_* or PDO.
i have a question...
Im using pdo and beginTransaction() but i dont understand some things.
My SQL table have 3 columns : id(autoincrement), username(unique), and password
And in my code i have this:
$pdo->beginTransaction();
$prepared = $pdo->prepare("INSERT INTO (username,password) VALUES(?,?)");
$prepared->$pdo->bindParam(1,"stefan");
$prepared->bindParam(2,"111111");
$prepared->execute();
$count= $prepared->rowCount();
if($count === FALSE):
$pdo->rollback();
var_dump($prepared->errorInfo());
else:
$pdo->commit();
echo "row count: {$count}";
endif;
When i execute this code, all works fine, generates id=1, username="stefan" and password="111111".
Now, I am generating an error on purpose to test rollback() function. I tried to insert same data 4 times in a row and i got unique error in $prepared->errorInfo().Works fine too.
The problem is, when im insert a new record after those 4 errors (for example, username="luv", password="222222") this new record has been inserted, but with ID=6 and not ID=2.
That is ok? rollback() should not leave the autoincrement at the last value that was correct?
I miss something?
Thanks for help.
auto inc values get "burned" when you do rollbacks. this is normal and expected.
reference this stackoverflow entry
I have the following SQL that works directly in MySQL
INSERT INTO `my_tabel` (`data`) VALUES ("my_value");
SELECT * from `my_tabel` ORDER BY `id` DESC LIMIT 1
It inserts a row, and then gets the new row so that I can return the new ID to use later.
When I try to run the SQL in codeIgniter I get an error message stating that I have an error in my SQL
$m = new my_model();
$sql = 'INSERT INTO `my_tabel` (`data`) VALUES ("'.$my_value.'"); SELECT * from `my_tabel` ORDER BY `id` DESC LIMIT 1';
$m->query($sql);
Running a single SQL statement works fine in codeIgniter, but not when I add the second SELECT... statement.
Any ideas (or alternative solutions)?
Thanks
This is not a limitation of CI but that of the database client libraries.
only a single query can be executed at a time.
Why not run two $m->query() statements? That way you can check the success of each individually from CI.
In most SQL interfaces, having multiple statements in a query is problematic because of the different types of result from each. Even when calling a stored procedure, it is necessary to carefully craft the stored procedure not to return extraneous results, though even that can usually be handled with a special, relaxed api which allows multiple results.
insert_id() is your friend!
$this->db->insert_id()
From here http://codeigniter.com/user_guide/database/helpers.html
So something like:
$insert_data = array(
'data' => $my_value
);
$this->db->insert('my_table', $insert_data);
$last_id = $this->db->insert_id();
Instead of running 2 queries, to get the id created after the insert query use:
$this->db->insert_id();
As noted in the other answers, use $this->db->insert_id() is better because there is a chance that another user inserts a row between your two queries. Since PHP can only execute one query at a time, this can become a race condition.
Thanks for everyone's help. The solution that worked for me was
$m = my_model();
$m->data = $value;
$m->save();
echo $m->id;
http://www.codeigniter.com/userguide2/database/active_record.html#caching
You can use Caching to control multiple queries without conflicts.
Hi guys I was hoping from some help here, please.
I have a INSERT query to a table, after this is done I am calling:
mysql_insert_id();
In order to send the last ID inserted into the table to the next page like this:
$insertGoTo = "confirm_booking.php?booking_ID=" .$_POST['booking_ID']. "";
Unfortunately it does not work, all I get is a zero.
The table I am inserting into has an auto increment number and values are inserted into it.
I have also tried SELECT MAX(id) FROM mytable. This dosn't work neither.
I know that this problem has been talked about already. I read all posts but nothing came useful.
Many thanks Francesco
You have to use the value returned by MySql_Insert_Id () when you generate your link:
// your query
$newId = MySql_Insert_Id ();
$insertGoTo = "confirm_booking.php?booking_ID=" . $newId;
It is possible that your table does not have any AUTO_INCREMENT field!
It could also happen because you have two or more mysql connections at the same time.
In this case you should use a link identifier.
$link = mysql_connect( ... );
mysql_select_db('mydb', $link);
mysql_query('INSERT mytable SET abc="123"', $link);
$inserted_id = mysql_insert_id($link);
Some key points from the PHP Manual:
The ID generated for an AUTO_INCREMENT
column by the previous query on
success, 0 if the previous query does
not generate an AUTO_INCREMENT value,
or FALSE if no MySQL connection was
established.
If not having an AUTO_INCREMENT field is not your problem, you might want to try storing the result of the mysql_query call and using that as an argument to the id function
$result = mysql_query("...");
$id = mysql_insert_id($result);
Had an issue using a query like this:
INSERT INTO members (username,password,email) VALUES (...)
reason being that the id (which is my primary key and Auto Increment field) is not part of the query.
Changing it to:
INSERT INTO members (id,username,password,email) VALUES ('',...)
using a an empty value '' will have MySQL use the Auto Increment value but also allow you to use it in your query so you can return the insert id
mysql_insert_id may return 0 or false if your insert fails right?
So if you have trouble with mysql_insert_id not retunring what you expect confirm that you don't have a unique constraint or some other problem with your sql that would cause the insert to fail. Using max is a terrible idea if you consider this.
Make sure to put mysql_insert_id()after the
mysql_query($sql, $con); //Execute the query
Above query responsible for execute your Insert INTO ... command.
After you can get the last ID inserted
I have also suffer from this problem. Finally I found that the problem occur in my connection to the database. You can use this following connection code to connect the database then you can easily use mysqli_insert_id().
$db_connect = mysqli_connect("localhost", "root", "", "social");
Then you can use mysqli_insert_id() as
$id = mysqli_insert_id($db_conx);
I hope this will help you. I you have any problem then leave your comment.
The mysqli_insert_id function has been deprecated. This may be your problem.
Instead, try $mysqli->insert_id. See the documentation for more info.