I had some Prepared Statements working in PHP using mysqli. The requirements changed and now I'm supposed to move them to the DB, as Stored Procedures. This worked fine for most of the PSs, except for a couple that read the insertId for some further processing.
Ex:
$idAsdf = $stmtAsdf->insert_id;
where the PS performs an INSERT operation.
I've tried using an OUT parameter on the procedure which works fine on PHPMyAdmin, but can't connect it with the PHP server code outside the DB. I haven't found any example of this combination of elements being done. How can I get this insertId using both SPs and PSs?
Thanks
For PDO Prepared Statement you can use PDO::lastInsertId -http://php.net/manual/en/pdo.lastinsertid.php
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $dbh->prepare("INSERT INTO test (name, email) VALUES(?,?)");
try {
$dbh->beginTransaction();
$tmt->execute( array('user', 'user#example.com'));
print $dbh->lastInsertId();
$dbh->commit();
} catch(PDOExecption $e) {
$dbh->rollback();
print "Error!: " . $e->getMessage() . "</br>";
}
} catch( PDOExecption $e ) {
print "Error!: " . $e->getMessage() . "</br>";
}
?>
Just remember when using transaction return lastInsertId or store lastInsertId before commit.
For Stored Procedure - use LAST_INSERT_ID();
BEGIN
INSERT INTO test (name, email) VALUES ('value1', 'value2');
SET out_param = LAST_INSERT_ID();
END
EDIT 1 :
If you using MySQLi - then use mysqli_insert_id - http://php.net/manual/en/mysqli.insert-id.php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$stmt = mysqli->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john#example.com";
$stmt->execute();
printf ("New Record has id %d.\n", $stmt->insert_id);
/* close connection */
$mysqli->close();
If facing problem with out_param, use select to return last insert id as result.
BEGIN
DECLARE last_id INT DEFAULT 0;
INSERT INTO test (name, email) VALUES ('value1', 'value2');
SET last_id = LAST_INSERT_ID();
SELECT last_id;
END
EDIT 2 :
If you are facing problem in retrieving Stored Procedure result set use following code -
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
printf("%s\n", $row[0]);
}
$result->free();
}
/* print divider */
if ($mysqli->more_results()) {
printf("-----------------\n");
}
} while ($mysqli->next_result());
}
To access the out param use follwing code -
// execute the stored Procedure
// #uid - IN param, #userCount - OUT param
$result = $connect->query('call IsUserPresent(#uid, #userCount)');
// getting the value of the OUT parameter
$r = $connect->query('SELECT #userCount as userCount');
$row = $r->fetch_assoc();
$toRet = ($row['userCount'] != 0);
insert_id is a property of mysqli class, while you are trying to get it from a statement object.
inside SP you can set like this outParam = LAST_INSERT_ID();
LAST_INSERT_ID() returns the most recently generated ID is maintained in the server on a per-connection basis.
Related
I am using mysqli_multi_query to insert user's information and a default null profile photo, there are two tables for that, "esc_usuarios" for the personal data and "esc_usuarios_fotos" for the photos.
What do I want is, after inserting the personal data, insert this null image in the "esc_usuarios_fotos" table binding "img_usu_codigo" with this inserted person, the person's id is being auto incremented in the column "usu_codigo" from the table "esc_usuarios".
The query:
<?php
$inserir_usuario = "INSERT INTO `esc_usuarios`
(
usu_nome,
usu_senha,
usu_sobrenome,
usu_cpf,
usu_rg,
usu_nasc,
usu_endereco,
usu_numero,
usu_bairro,
usu_cep,
usu_cidade,
usu_uf,
usu_tel,
usu_cel,
usu_genero,
usu_email,
usu_indicador_codigo,
usu_datacadastro
) VALUES (
'$nome',
'".md5('$password')."',
'$sobrenome',
'$cpf',
'$rg',
'$nascimento',
'$endereco',
'$numero',
'$bairro',
'$cep',
'$cidade',
'$uf',
'$tel',
'$cel',
'$genero',
'$email',
'" . $_SESSION['codigo'] . "',
'$trn_date'
);
INSERT INTO esc_usuarios_fotos(img_local,img_usu_codigo) VALUES ('null', //i want to insert here the inserted person's id "usu_codigo" of the first insert statement)";
$re = mysqli_multi_query($conexao, $inserir_usuario);
Tackling a few issues here. You really should be using parameterized inserts for security reasons. Split out your inserts and then use insert_id to grab the newly created ID from your person insert. Wrap everything in a transaction as others in the comments pointed out - this will ensure you get everything or nothing.
And lastly, use mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); to turn MySQL errors into PHP exceptions. You can then wrap everything in a try/catch block. Good luck!
Pseduo code:
// Turn MySQL errors into PHP exceptions.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// Open connection
$connection = new mysqli(...);
// check connection
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
// Start transaction here
...
/***********************************/
/********** PERSON INSERT **********/
/***********************************/
if ($stmt = $connection->prepare("INSERT INTO `esc_usuarios` ... (?, ?, ...)")) {
/* bind parameters for markers */
$stmt->bind_param("s", $...);
...
/* execute first query */
$stmt->execute();
/* This is the newly created ID */
$id = $connection->insert_id
/***********************************/
/********** PHOTOS INSERT **********/
/***********************************/
if ($stmt = $connection->prepare("INSERT INTO `esc_usuarios_fotos` ... (?, ?)")) {
/* Use that newly created ID here along with other params for your query */
$stmt->bind_param("s", $id);
/* execute query */
$stmt->execute();
}
}
// Commit transaction here
...
}
catch ( Exception $e ) {
// Rollback transaction if the exception is DB related
...
}
I have tried to insert two insert intos through a transaction statement but it did not work. The console is giving me database errors. I have checked the documentation http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers and it is obvious I am missing something.
The goal is simply insert into two different tables different information. I tried the following:
// create record
function create(){
try {
$stmt->beginTransaction();
$query = "INSERT INTO " . $this->table_name . "
SET user_id = ?, ";
// prepare query statement
$stmt = $this->conn->prepare($query);
// bind values to be inserted
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
$query2 = "INSERT INTO legalcases_report
SET user_id = ?, ";
// prepare query statement 2
$stmt = $this->conn->prepare($query2);
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
$stmt->commit();
return true;
} catch (Exception) {
$stmt->rollBack();
return false;
}
}
There are lots of problems in this code, I hope I can catch them all
// create record
function create(){
try {
// transaction work on a connection and not a statement
//$stmt->beginTransaction();
$this->conn->beginTransaction();
// Incorrect syntax for an INSERT command
// Error - Trailing comma in sytax
$query = "INSERT INTO " . $this->table_name . "
SET user_id = ?, ";
// prepare query statement
$stmt = $this->conn->prepare($query);
// bind values to be inserted
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
// Incorrect syntax for an INSERT command
// Error - Trailing comma in sytax
$query2 = "INSERT INTO legalcases_report
SET user_id = ?, ";
// prepare query statement 2
$stmt = $this->conn->prepare($query2);
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
// commit also works on a connection object
//$stmt->commit();
$this->conn->commit();
return true;
// PDO generates a PDOException so you should really catch that,
// it will fallback to the parent Exception object, BUT
// there may be times when you want to catch them seperately
// from the same try block, so use the correct one or both
} catch (PDOException $pex) {
$this->con->rollback();
$pex->getMessage();
exit; // because you have a serious problem
// or throw your own exception to the calling code
throw new Exception('Create user failed ' . $pex->getMessage());
}
}
Incorrect syntax for an INSERT command
The PHP PDO manual
I guess you should use PDO object, not PDOStatement:
try {
$this->conn->beginTransaction();
...
$this->conn->commit();
I am very new to MySQl and I'm trying to check if an inputed email matches with any from my table. If it matches, I need to put the email and the other columns of the same row in another table.
What I get now is a blank row added to table2.
<?php
include "config.php";
$email = $_POST['email'];
$match = mysqli_query("SELECT email FROM table1 WHERE email = $email");
if($conn->query($match)){
//here i have to find the name, school, and grad_year that matches
// with the email from table 1 which is in the same row. I tried a couple of
//things but it didn't work. So i don't know what to put in there.
$insert = "INSERT INTO table2 VALUES(name,'$email',school,grad year )";
$conn->query($insert);
}
?>
Any help would be much appreciated!
Don't ever use the mysql* functions. They are deprecated and insecure. Use mysqli* or PDO instead. See below for sample code (I have NOT run it and there may be errors - the idea is to get you on the right road...)
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$email = $_POST['email'];
/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT * FROM table1 WHERE email=?")) {
/* bind parameters for markers */
$stmt->bind_param("s", $email);
/* execute query */
$stmt->execute();
/* bind result variables */
# NOTE: You may prefer $stmt->get_results() and $result->fetch_assoc()
# to this $stmt->bind_result() and $stmt->fetch().
$stmt->bind_result($name, $junk, $school, $grad_year);
/* fetch value */
if ($stmt->fetch()) {
$stmt2 = $mysqli->prepare("INSERT INTO table2 VALUES (?,?,?,?)");
$stmt2->bind_param("ssss", $name, $email, $school, $grad_year);
$stmt2->execute();
$stmt2->close();
}
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
?>
Or, if you don't care to know details along the way, this is a lot faster and simpler:
// yada,yada - get a conx
$email = $_POST['email'];
/* create a prepared statement */
if ($stmt = $mysqli->prepare("INSERT INTO table2 SELECT * FROM table1 WHERE email=?")) {
/* bind parameters for markers */
$stmt->bind_param("s", $email);
/* execute query */
$stmt->execute();
/* the total number of affected rows can be determined by using the mysqli_stmt_affected_rows() function */
}
(SOURCE: Example copied from http://php.net/manual/en/mysqli.prepare.php and modified)
It does not print the result. Dont know why. Everything is neatly commented
I get no error displays, no syntax blasphemes, it just does not print any result. However, I do know that the values are passed by the form to this processing php page, so the error is not in there. In the DB I have encrypted all fields except 'company'- Thus, I want to see if this will work by trying to fetch the results back.
// 1. Creating a new server connection
$db = new mysqli('localhost', 'root', '', 'developers');
if ($db->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
// 2, Creating statement object
$stmt = $db->stmt_init();
// 3, Creating a prepared statement
if($stmt->prepare("SELECT company FROM accesoweb WHERE username = AES_DECRYPT(?, 'salt')")) {
//4. Binding the variable to replace the ?
$stmt->bind_param('s', $username);
printf("Error: %d.\n", $stmt->errno);
// 5. Executing query
$stmt->execute();
// 6. Binding the result columns to variables
$stmt->bind_result($company);
// 7. Fetching the result of the query
while($stmt->fetch()) {
echo $company;
}
// 8. Closing the statement object
$stmt->close();
// 9. Closing the connection
$mysqli->close();
}
The inserting code that I just included in the MySQL was:
INSERT INTO accesoweb (company, username,email,password)
VALUES
('hola',
AES_ENCRYPT('maria','salt'),
AES_ENCRYPT('sumail','salt'),
AES_ENCRYPT('password',' salt')
);
So, that row above(actually, the "company" is what I am trying to recover through the PHP code
SELECT company FROM accesoweb WHERE username = AES_DECRYPT(?, 'salt')
Should be
SELECT company FROM accesoweb WHERE username = AES_ENCRYPT(?, 'salt')
OR
SELECT company FROM accesoweb WHERE AES_DECRYPT(username, 'salt') = ?
$query = "INSERT INTO users (name, password) VALUES ('$myusername', '$mypassword')";
if (!($result = $mysqli->query($query)))
die("WHAT???? " . $mysqli->error . " EEEEEFFFFFFF.");
$count = $result->num_rows;
while ($row = $result->fetch_array()) {
if ($row[name] == $myusername) {
$mysqli->query("DELETE FROM users WHERE name='$myusername' AND password='$mypassword'");
$count = 5;
}
}
When I run this, it gives me an error:
Fatal error: Call to a member function fetch_array() on a non-object in /home/appstore/public_html/phpstoof/signedup.php on line 26
Where line 26 is where the while statement starts (while(x)). $mysqli ALREADY an instance of mysqli(). I don't see the how this is an error if the same code works on another file.
An INSERT statement has nothing to fetch.
As #mellamokb says, INSERT has nothing to fetch. Also you have used a mix of MySQL and MySQLi.
With MySQLi, the code should be like:
$mysqli = new mysqli($db_host, $db_username, $db_password, $db_database);
$str_sql = 'INSERT INTO users (name, password) VALUES (?, ?)';
// Create a prepared statement
$stmt = $mysqli->prepare($str_sql);
// Bind parameters for markers; same order and same count in prepared statement
$stmt->bind_param('ss', $myusername, $mypassword);
// Execute query
$stmt->execute();
// *************************************************************************
// If you're using a SELECT statement, each output field must be bound to
// a variable in the same order as in SELECT
// Bind result variables
$stmt->bind_result($_var1, $_var2, $_var3, ...);
// Fetch results and generate output as an associative array
while ($stmt->fetch())
{
// Handle $_var1, $_var2, $_var3, ...
}
// *************************************************************************
// Free stored result memory
$stmt->free_result();
// Close statement
$stmt->close();
// Close connection
$mysqli->close();