Nested stmt mysqli PHP - php

I'm trying to create a third table taking two indexes from two different tables for creating a correlation between them using following code:
$query1 = "select iduniverse from universe";
$query2 = "select idfiles from files";
$query3 = "select iduniFiles from uniFiles where filesId = ? and universeId = ?";
$query4 = "insert into uniFiles (filesId, universeId) values (?,?)";
if($stmt1 = $conn->prepare($query1)){
if($stmt2 = $conn->prepare($query2)){
if($stmt3 = $conn->prepare($query3)){
if($stmt4 = $conn->prepare($query4)){
$stmt1->execute();
$stmt1->bind_result($iduniverse);
while($stmt1->fetch()){
$stmt2->execute();
$stmt2->bind_result($idfiles);
while($stmt2->fetch()){
$stmt3->bind_param("ii", $idfiles, $iduniverse);
$stmt3->execute();
$stmt3->store_result();
if($stmt3->num_rows == 0){
$stmt4->bind_param("ii", $idfiles, $iduniverse);
$stmt4->execute();
}
}
}
}
$stmt4->free_result();
}
$stmt3->free_result();
}
$stmt2->free_result();
}
$stmt1->free_result();
But if I put an echo "here\n" after second while loop:
while($stmt2->fetch()){
echo "here\n";
...
When I launch my code I don't see anything on screen output and also table uniFiles remains empty.
I have already checked query via SQL Browser and works without any issue. So I don't understand where is the mistake.
What is wrong in my script?

You can create a join table using INSERT INTO INTO SELECT ...
insert into uniFiles (filesId, universeId)
select iu.iduniverse, if.idfiles
from universe iu
join files if on if.idfiles = iu.idfiles
If there could be duplicates, then combine with INSERT IGNORE
insert ignore into uniFiles (filesId, universeId)
select iu.iduniverse, if.idfiles
from universe iu
join files if on if.idfiles = iu.idfiles

A mysqli connection can only hold a single active prepared statement at a time.
Therefore, you can't have nested prepared statements active on the same connection. You'll have to have a separate connection for each level of the nesting if you need to keep them all active (at least for each one you don't want squashed by the next level's query.

Related

Insert data into database if value doesn't exists in specific column

I've tried to follow several answers on this question but can't seem to get it to work for my specific problem.
I want to insert data but only if the flight_number doesn't exists already. How can I do that?
$sql = mysqli_query($con,
"INSERT INTO space (`flight_number`, `mission_name`, `core_serial`, `payload_id`)
VALUES ('".$flight_number."', '".$mission_name."', '".$core_serial."', '".$payload_id."')"
);
Rob since you saying flight_number is a unique then you can use INSERT IGNORE
<?php
$sql = "INSERT IGNORE INTO space (`flight_number`, `mission_name`, `core_serial`, `payload_id`) VALUES (?,?,?,?)";
$stmt = $con->prepare($sql);
$stmt->bind_param('isss',$flight_number,$mission_name,$core_serial,$payload_id);
if($stmt->execute()){
echo 'data inserted';
// INSERT YOUR DATA
}else{
echo $con->error;
}
?>
OR you could select any row from your database that equal to the provided flight number then if u getting results don't insert.
$sql = "SELECT mission_name WHERE flight_number = ? ";
$stmt = $con->prepare($sql);
$stmt->bind_param('i',$flight_number);
if(mysqli_num_rows($stmt) === 0){
// INSERT YOUR DATA
}
A unique index on flight number should do the trick.
CREATE UNIQUE INDEX flight_number_index
ON space (flight_number);
If you want to replace the existing row with the new one use the following:
$sql = mysqli_query($con,
"REPLACE INTO space (`flight_number`, `mission_name`, `core_serial`, `payload_id`)
VALUES ('".$flight_number."', '".$mission_name."', '".$core_serial."', '".$payload_id."')"
);
Make note that I just copied your code and changed INSERT to REPLACE to make it easy to understand. PLEASE PLEASE PLEASE do not use this code in production because it is vulnerable to injection.
If you don't want to replace the existing row, run an insert and check for errors. If there is an error related to the index, the row already exists.
Disclaimer: I haven't tested any of this code, so there may be typos.

How to keep temporary mysqli table available in php during statement execution?

I am busy trying to execute a set of statements that involve the use of a temporary table.
My goal is to create the temporary table, insert values to it and then do a like comparison of the temporary tables contents to another table.
These statements are working perfectly in phpmyadmin when executed from RAW SQL, but I'm assuming that the table is not available when I try to insert the data.
Below is the code for my php function + mysqli execution:
function SearchArticles($Tags){
global $DBConn, $StatusCode;
$count = 0;
$tagCount = count($Tags);
$selectText = "";
$result_array = array();
$article_array = array();
foreach($Tags as $tag){
if($count == 0){
$selectText .= "('%".$tag."%')";
}else {
$selectText .= ", ('%".$tag."%')";
}
$count++;
}
$query = "CREATE TEMPORARY TABLE tags (tag VARCHAR(20));";
$stmt = $DBConn->prepare($query);
if($stmt->execute()){
$query2 = "INSERT INTO tags VALUES ?;";
$stmt = $DBConn->prepare($query2);
$stmt->bind_param("s", $selectText);
if($stmt->execute()){
$query3 = "SELECT DISTINCT art.ArticleID FROM article as art JOIN tags as t ON (art.Tags LIKE t.tag);";
$stmt = $DBConn->prepare($query3);
if($stmt->execute()){
$stmt->store_result();
$stmt->bind_result($ArticleID);
if($stmt->num_rows() > 0){
while($stmt->fetch()){
array_push($article_array, array("ArticleID"=>$ArticelID));
}
array_push($result_array, array("Response"=>$article_array));
}else{
array_push($result_array, array("Response"=>$StatusCode->Empty));
}
}else{
array_push($result_array, array("Response"=>$StatusCode->SQLError));
}
}else{
array_push($result_array, array("Response"=>$StatusCode->SQLError));
}
}else{
array_push($result_array, array("Response"=>$StatusCode->SQLError));
}
$stmt->close();
return json_encode($result_array);
}
The first statement executes perfectly, however the second statement gives me the error of:
PHP Fatal error: Call to a member function bind_param() on a non-object
If this is an error to do with the Temp table not existing, how do i preserve this table long enough to run the rest of the statements?
I have tried to use:
$stmt = $DBConn->multi_query(query);
with all the queries in one, but i need to insert data to one query and get data from the SELECT query.
Any help will be appreciated, thank you!
You have a simple syntax error use the brackets around the parameters like this
INSERT INTO tags VALUES (?)
This is not an issue with the temporary table. It should remain throughout the same connection (unless it resets with timeout, not sure about this part).
The error is that $stmt is a non-object. This means that your query was invalid (syntax error), so mysqli refused to create an instance of mysqli_stmt and returned a boolean instead.
Use var_dump($DBConn->error) to see if there are any errors.
Edit: I just noticed that your query $query2 is INSERT INTO tags VALUES ? (the ; is redundant anyway). If this becomes a string "text", this would become INSERT INTO tags VALUES "text". This is a SQL syntax error. You should wrap the ? with (), so it becomes INSERT INTO tags VALUES (?).
In conclusion, change this line:
$query2 = "INSERT INTO tags VALUES ?;";
to:
$query2 = "INSERT INTO tags VALUES (?);";
also note that you don't need the ; to terminate SQL statements passed into mysqli::prepare.

How to use one stmt query inside another

i have to get data from one table from my database, BUT after getting the data, i have to access another table to get more data using the id found in the first query.
Here is my code:
$query = "SELECT id,name,datetime FROM table1 WHERE id=?";
if($stmt=mysqli_prepare($mysqli,$query)){
mysqli_stmt_bind_param($stmt,"i",$_SESSION['id']);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt,$id,$name,$datetime);
while(mysqli_stmt_fetch($stmt)){
$query2 = "SELECT id FROM table2 WHERE id=?";
if($stmt2=mysqli_prepare($mysqli,$query2)){
mysqli_stmt_bind_param($stmt2,"s",$id2);
mysqli_stmt_execute($stmt2);
mysqli_stmt_store_result($stmt2);
$num = mysqli_stmt_num_rows($stmt2);
}
The code does not work, i know i can't do that. I'm new with mysqli, in MySQL it works, but in MySQLi don't.

Multiple prepared statements (SELECT)

I'm trying to change my SQL queries with prepared statements.
The idea: I'm getting multiple records out of the database with a while loop and then some additional data from the database in the loop.
This is my old SQL code (simplified):
$qry = "SELECT postId,title,userid from post WHERE id='$id'";
$rst01 = mysqli_query($mysqli, $qry01);
// loop trough mutiple results/records
while (list($postId,$title,$userid) = mysqli_fetch_array($rst01)) {
// second query to select additional data
$query05 = "SELECT name FROM users WHERE id='$userid";
$result05 = mysqli_query($mysqli, $query05);
$row05 = mysqli_fetch_array($result05);
$name = $row05[name ];
echo "Name: ".$name;
// do more stuff
// end of while loop
}
Now I want to rewrite this with prepared statements.
My question: is it possible to run a prepared statement in the fetch of another prepared statement ? I still need the name like in the old SQL code I do for the $name.
This is what've written so far.
$stmt0 = $mysqli->stmt_init();
$stmt0->prepare("SELECT postId,title,userid from post WHERE id=?");
$stmt0->bind_param('i', $id);
$stmt0->execute();
$stmt0->bind_result($postId,$title,$userid);
// prepare second statement
$stmt1 = $mysqli->stmt_init();
$stmt1->prepare("SELECT name FROM users WHERE id= ?");
while($stmt0->fetch()) {
$stmt1->bind_param('i', $userid);
$stmt1->execute();
$res1 = $stmt1->get_result();
$row1 = $res1->fetch_assoc();
echo "Name: ".$row1['name'] ;
}
It returns an error for the second statement in the loop:
Warning: mysqli_stmt::bind_param(): invalid object or resource mysqli_stmt in ...
If I use the old method for the loop and just the prepared statement to fetch the $name it works.
You can actually do this with a single JOINed query:
SELECT p.postId, p.title, p.userid, u.name AS username
FROM post p
JOIN users u ON u.id = p.userid
WHERE p.id = ?
In general, if you are running a query in a loop, there is probably a better way of doing it.

mySQLi Prepared Statement Select with Escape Characters

I am trying to select from a mySQL table using prepared statements. The select critera is user form input, so I am binding this variable and using prepared statements. Below is the code:
$sql_query = "SELECT first_name_id from first_names WHERE first_name = ?";
$stmt = $_SESSION['mysqli']->prepare($sql_query);
$stmt->bind_param('s', $_SESSION['first_name']);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows == '1') {
$stmt->bind_result($_SESSION['first_name_id']);
$stmt->fetch();
} else {
$stmt->close();
$sql_query = "INSERT INTO first_names (first_name) VALUES (?)";
$stmt = $_SESSION['mysqli']->prepare($sql_query);
$stmt->bind_param('s', $_SESSION['first_name']);
$stmt->execute();
$_SESSION['first_name_id'] = $_SESSION['mysqli']->insert_id;
}
$stmt->close();
Obviously my code is just determining whether or not the first_name already exists in the first_names table. If it does, it returns the corresponding ID (first_name_id). Otherwise, the code inserts the new first_name into the first_names table and gets the insert_id.
The problem is when a user enters a name with an escape character ('Henry's). Not really likely with first names but certainly employers. When this occurs, the code does not execute (no select or insert activity in the log files). So it seems like mySQL is ignoring the code due to an escape character in the variable.
How can I fix this issue? Is my code above efficient and correct for the task?
Issue #2. The code then continues with another insert or update, as shown in the code below:
if (empty($_SESSION['personal_id'])) {
$sql_query = "INSERT INTO personal_info (first_name_id, start_timestamp) VALUES (?, NOW())";
} else {
$sql_query = "UPDATE personal_info SET first_name_id = ? WHERE personal_info = '$_SESSION[personal_id]'";
}
$stmt = $_SESSION['mysqli']->prepare($sql_query);
$stmt->bind_param('i', $_SESSION['first_name_id']);
$stmt->execute();
if (empty($_SESSION['personal_id'])) {
$_SESSION['personal_id'] = $_SESSION['mysqli']->insert_id;
}
$stmt->close();
The issue with the code above is that I cannot get it to work at all. I am not sure if there is some conflict with the first part of the script, but I have tried everything to get it to work. There are no PHP errors and there are no inserts or updates showing in the mySQL log files from this code. It appears that the bind_param line in the code may be where the script is dying...
Any help would be very much appreciated.
you should validate/escape user input before sending it to the db.
checkout this mysql-real-escape-string()

Categories