So I'm new to PHP/PDO and I'm having some problems with passing the fetched variable on to the second statement. I'm also having problems with exceptions i don't know how the right structure for this situation.
try {
$connection->beginTransaction();
$stmt = $connection->prepare("CALL sproc_patient_profile_physical_exam_hdr(?,?,?)");
$stmt->bindValue(1,$casenumber_fetch,PDO::PARAM_INT);
$stmt->bindValue(2,$patientid_val,PDO::PARAM_INT);
$stmt->bindValue(3,$enteredby,PDO::PARAM_STR);
while($row = $stmt->fetch()){
echo $physicalexamid_insert=$row['physicalexamid'];
/* I need to use this data for another try and catch or sql statements for example*/
$count_physical_exam_id = count($physical_exam_id);
for ($x=0; $x < $count_physical_exam_id; $x++) {
if (!(empty($physical_exam_id[$x]))) {
try {
$connection->beginTransaction();
$stmt = $connection->prepare("CALL sproc_patient_profile_physical_exam_dtl(?,?,?,?,?,?,?)");
$stmt->bindValue(1,$casenumber_fetch,PDO::PARAM_INT);
$stmt->bindValue(2,1,PDO::PARAM_INT);
$stmt->bindValue(3,$physical_exam_id[$x],PDO::PARAM_INT);
$stmt->bindValue(4,$physical_exam_desc[$x],PDO::PARAM_STR);
$stmt->bindValue(5,$normal[$x],PDO::PARAM_INT);
$stmt->bindValue(6,$undone[$x],PDO::PARAM_INT);
$stmt->bindValue(7,$specific[$x],PDO::PARAM_INT);
$stmt->execute();
$connection->commit();
} catch(PDOException $ex) {
//$connection->rollBack();
echo $ex->getMessage();
}
}
}
}
$stmt->execute();
$connection->commit();
} catch(PDOException $ex) {
$connection->rollBack();
echo $ex->getMessage();
Can someone help me with this? Thanks.
There's a couple of issues with your code:
You're not executing the first statement before you call fetch on it.
You're over-writing the $stmt variable in your loop.
The opening section of your code should be like this:
$stmt = $connection->prepare("CALL sproc_patient_profile_physical_exam_hdr(?,?,?)");
$stmt->bindValue(1,$casenumber_fetch,PDO::PARAM_INT);
$stmt->bindValue(2,$patientid_val,PDO::PARAM_INT);
$stmt->bindValue(3,$enteredby,PDO::PARAM_STR);
$stmt->execute();
Once you've done that you can loop through with a control statement like you're doing (e.g. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { ... }).
Inside that control structure, instead of using the variable $stmt for a new (second) statement, use something like $stmt2 or $inner_stmt, so that you don't over-write the outer variable.
Related
try {$db=mysqli_connect( etc )
catch {
retry on time out
handle errors
}
try { if (!($errors = $db->prepare("insert into errors (`insert`,`error`) values(?,?);
print "\n*********prepare Error:" . $db->error;
}
}
catch { repeat above}
try {$errors->bind_param("ss",$sqlLoad,$errormsg); }
catch {repeat above)
....
try {$error->execute()} catch {repeat above error handling}
Now repeat all of that 10-40 times for different SQL queries on different fields.
That is a lot of duplicated code. Make my code hard to read, and if someone wants to add more sql queries they are forced to reduplicate large blocks of code.
I was thinking something like this but ran into a stumbling block with bind.
$sql[0]=array("name","select ? from <tablename>","s");
$sql[1]=array("name","select ?,? from <tablename>","ss");
$sql[2]=array("name","select ?,?,? from <tablename>","sss");
$sql[3]=array("name","select ?,?,?,? from <tablename>","ssss");
for(i=0;i<=3,i++){
try (
$preQuery[$sql[i][0]=$db->prepare($sql[i][1]);}
catch {}
try {$preQuery[$sql[i][0]]->bind_param($sql[i][2],????);} //Here is the trouble how do I define unique variables
catch { }
}
Here is some real code
It is a work in progress
foreach ($fieldspath as $field)
{
$filepath=$_SERVER[$field];
$result=$queryfile->execute();
$getres = $queryfile->get_result();
$numRows = -1;
$numRows = $getres->num_rows;
if ($numRows <>0)
{
$qryField = $getres->fetch_assoc();
$_SERVER[$field]=$qryField["id"];
$fileCount=$qryField["count"];
$fileRating=$qryField["rating"];
mysqli_query($db, "update Files set count=count+1 where `id` ='" . $qryField["id"] . "';");
continue;
}
else
{
$output = $insertFile->execute();
$result = $queryip->execute();
$getres = $queryip->get_result();
$qryField = $getres->fetch_assoc();
$_SERVER[$field]=$qryField["id"];
}
}
Notice: How I can re-execute a query just by:
$result=$queryfile->execute();
The query doesn't have to be re-stated, nor do the parameters. Everything is automatic. The actual queries are all listed at the top of the program, and I never have to see them, or restate them ever again. Also I don't need to cram my parameters into array before I can use them.
<?php
$pipeName = '/var/run/mysql/mysql.sock';
$username = 'user';
$password = 'password';
$db = new PDO('mysql:unix_socket='.$pipeName.";dbname=dbase", $username, $password);
$sql["errors"]="insert into errors (`insert`,`error`) values(:insert,:error);";
$sql["events"]="insert into event (`message`) values(?);";
$sql["queryip"]="select id,count,rating FROM ip where address=? limit 1;";
$sql["queryUsrAgent"]="select id,count,rating FROM http_user_agent where agent=? limit 1;";
$sql["insUsrAgent"]="insert into http_user_agent (`agent`) values (?);";
$sql["insertIP"]="insert into ip (`address`) values (?);";
$sql["insertReqURI"]="insert into request (`REQUEST_URI`) values (?);";
$sql["queryReqURI"]="select * FROM request where REQUEST_URI=? LIMIT 1;";
$sql["queryfile"]="select id,count,rating FROM Files where path=? limit 1;";
$sql["insertFile"]="insert into Files (`path`) values (?);";
$sql["cntIp"]="update ip set count=count+1 where `address` = :ip";
$sql["cntFiles"]="update Files set count=count+1 where `id` = :id;";
$sql["cntAgent"]="update http_user_agent set count=count+1 where `agent` = :agent;";
$sql["reqRequest"]="select * FROM request where REQUEST_URI= :requesturi LIMIT 1;";
$sql["cntRequest"]="update request set count=count+1 where `REQUEST_URI` = :requesturi;";
$ready=doPrepare($db,$sql);
$ready["errors"]->execute(array("insert"=>"stuff","error" =>"stuff"));
pdoRun($ready,"errors",array("iniisert"=>"iiiii","error" =>"yyyyyggg"));
function doPrepare($db, $enmass) {
foreach ($enmass as $key => $sql) {
try {
$stmt[$key] = $db->prepare($sql);
} catch (PDOException $e) {
print "\nStuff";
trigger_error($e);
return false;
}
}
return $stmt;
}
function pdoRun($ready,$query,$vals) {
try {
$ready[$query]->execute($vals);
} catch (PDOException $e) {
print "\nExecution fail";
}
}
// $stmt->execute(array_values($column_values));
?>
Making prepared queries like you are doing doesn't work like you seem to think it does. The parameter placeholders can only substitute for literal values. You can't use them for column names or table names or anything else.
You also can't prepare a query like "select ? from" because it names no table. It's not a syntactically complete query.
The better practice is to code a "helper function" that does the prepare and execute for you. You can reduce repetitive code that way.
By the way, I find PDO is much easier than Mysqli when coding a helper function like this, because you don't have to use the bind_param() with variable arguments. In PDO, you just pass an array of arguments to execute().
function doInsert($db, $sql, $params) {
try {
$stmt = $db->prepare($sql);
$stmt->execute($params);
} catch (PDOException $e) {
trigger_error($e);
return false;
}
return true;
}
Now call it this way:
$sql = "insert into errors (`insert`, `error`) values(?, ?)";
$success = doInsert($db, $sql, [$sqlLoad, $errormsg]);
You might even like the function to format your INSERT statement for you:
function doInsert($db, $table, $column_values) {
$placeholders = array_fill(1, count($column_values), '?');
$columns = implode(',', array_keys($column_values));
$sql = "INSERT INTO `$table` ($columns) VALUES ($placeholders)";
try {
$stmt = $db->prepare($sql);
$stmt->execute(array_values($column_values));
} catch (PDOException $e) {
trigger_error($e);
return false;
}
return true;
}
Then call it like this:
$success = doInsert($db, "errors", ["insert"=>$sqlLoad, "error"=>$errormsg]);
You'll have to do something to apply back-ticks to the column names too.
Here is my script:
$id = $_GET['id'];
$value = $_GET['val'];
// database connection here
try{
$db_conn->beginTransaction(); // this
$stm1 = $db_conn->prepare("UPDATE table1 SET col = "updated" WHERE id = ?");
$stm1->execute(array($value));
$done = $stm->rowCount();
if ($done){
try {
$stm2 = $db_conn->prepare("INSERT into table2 (col) VALUES (?)");
$stm2->execute(array($id));
} catch(PDOException $e){
if ((int) $e->getCode() === 23000) { // row is duplicate
$stm3 = $db_conn->prepare("DELETE FROM table2 WHERE col = ?");
$stm3->execute(array($id));
}
}
} else {
$error = true;
}
$db_conn->commit(); // this
}
catch(PDOException $e){
$db_conn->rollBack();
}
First of all, I have to say, my script works. I mean the result or it is as expected in tests. Just one thing scares me. I read the documention and seen this sentence:
Won't work and is dangerous since you could close your transaction too early with the nested commit().
I'm not sure what's the meaning of sentence above, just I understand maybe I shouldn't use nested try - catch between beginTransaction() and commit(). Well I got it right? doing that is dangerous?
Exceptions have no direct relation to transactions. You can add as many catch blocks in your code as you need.
So your code is all right, given you already set PDO error reporting to Exceptions.
I'd like to execute some queries that doesn't return result set, and then execute a real query, and fetch its result.
Here is an exemple that doesn't work :
<?php
try {
$db = new PDO('dblib:host=myhost;dbname=master','user','password');
$query = "declare #entier int = 1;";
$db->exec($query);
$query = "select #entier;";
$stmt = $db->query($query);
$rows = $stmt->fetchAll();
print_r($rows);
}
catch (PDOException $e) {
print ($e->getMessage());
}
catch (Exception $e) {
print ($e->getMessage());
}
?>
This code neither doesn't work :
try {
$db = new PDO('dblib:host=myhost;dbname=master','user','password');
$query = "declare #entier int = 1; select #entier;";
$stmt = $db->query($query);
$rows = $stmt->fetchAll();
print_r($rows);
}
catch (PDOException $e) {
print ($e->getMessage());
}
catch (Exception $e) {
print ($e->getMessage());
}
?>
But this code works :
<?php
try {
$db = new PDO('dblib:host=myhost;dbname=master','user','password');
$query = "select 1;";
$stmt = $db->query($query);
$rows = $stmt->fetchAll();
print_r($rows);
}
catch (PDOException $e) {
print ($e->getMessage());
}
catch (Exception $e) {
print ($e->getMessage());
}
?>
Thanks for your help
I know this is old, but for other people finding this from Google: you need to use PDOStatement::nextRowset to iterate over the result sets from your multiple queries.
However, it seems there are memory issues when using nextRowset with dblib in some versions (it tried to allocate 94Tb in my case...), so I ended up re-engineering to avoid multiple SQL queries altogether (instead duplicating the value of the DECLARE where it was being used).
PDO::query docs (http://php.net/manual/it/pdo.query.php) say
PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.
This could mean that you can execute with query() both queries with and without result
Can't seam to find the answer to this.
I have a mysqli loop statement. And in that loop I want to run another query. I cant write these two sql together. Is that possible?
I thought since I use stmt and set that to prepare statement. So i add another variable stmt2. Running them seperate works, but run it like I wrote it gives me "mysqli Fatal error: Call to a member function bind_param() on a non-object"
Pseudocode :
loop_sql_Statement {
loop_another_sql_statement(variable_from_firsT_select) {
echo "$first_statement_variables $second_statemenet_variables";
}
}
$sql = "select dyr_id, dyr_navn, type_navn, dyr_rase_id, dyr_fodt_aar, dyr_kommentar, dyr_opprettet, dyr_endret
from dyr_opphald, dyr, dyr_typer
where dyropphald_dyr_id = dyr_id
and dyr_type_id = type_id
and dyropphald_opphald_id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i",
$p_opphald_id);
$stmt->execute();
$stmt->bind_result($dyr_id, $dyr_navn, $type_navn, $dyr_rase_id, $dyr_fodt_aar, $dyr_kommentar, $dyr_opprettet, $dyr_endret);
echo "<table>";
while($stmt->fetch()) {
echo "<tr><td>$dyr_navn</td><td>$type_navn</td><td>$dyr_rase_id</td><td>$dyr_fodt_aar</td><td>";
$sql2 = "select ekstra_ledetekst, ekstradyr_ekstra_verdi from dyr_ekstrainfo, ekstrainfo where ekstradyr_ekstra_id = ekstra_id and ekstradyr_dyr_id = ?";
try {
$stmt2 = $mysqli->prepare($sql2);
$stmt2->bind_param("i",
$dyr_id);
$stmt2->execute();
$stmt2->bind_result($ekstra_ledetekst, $ekstra_ledetekst);
echo "<td>";
while($stmt2->fetch()) {
echo "$ekstra_ledetekst => $ekstra_ledetekst<br>";
}
}catch (Exception $e) {}
echo "</td></tr>";
}
echo "</table>";
The answer:
Silly me, I didnt know I had to have two mysqli connection. So the solution was to declare another mysqli connection.
$mysqli = new mysqli($start, $name, $pwd, $selected_db);
$mysqli2 = new mysqli($start, $name, $pwd, $selected_db);
You should be able to do that, although you make have to start a second connection.
I'm using PDO to grab records from a mysql table. The data will be encoded with json_encode() and printed through the Slim framework for the API:
$app->get('/get/profile/:id_user', function ($id_user) use ($app) {
$sql = 'SELECT * FROM user WHERE id_user = :id_user';
try {
$stmt = cnn()->prepare($sql);
$stmt->bindParam(':id_user', $id_user, PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_ASSOC); // THIS!!!
if($stmt->rowCount()) {
$app->etag(md5(serialize($data)));
echo json_encode($data,JSON_PRETTY_PRINT);
} else {
$app->notfound();
}
} catch(PDOException $e) {
echo $e->getMessage();
}
});
Should I use
$data = $stmt->fetch(PDO::FETCH_ASSOC);
or
$data = $stmt->fetchObject();
? Any direct benefits on fetching the data as an object? I've read some examples but they never explain why. The only usage for the resulting data will be to print it in JSON format. Thanks!
It doesn't matter. Though I'd cut an object out with Occam's razor.
Also your code is slightly wrong and redundant. Here is a proper version
$sql = 'SELECT * FROM user WHERE id_user = :id_user';
$stmt = cnn()->prepare($sql);
$stmt->bindParam(':id_user', $id_user, PDO::PARAM_INT);
$stmt->execute();
if ($data = $stmt->fetch()) {
$app->etag(md5(serialize($data)));
echo json_encode($data,JSON_PRETTY_PRINT);
} else {
$app->notfound();
}
there is no point in setting fetch mode for the every query when you can set it globally.
numrows() call is also useless.
and of course catching an exception is redundant, insecure and unreliable.