I am obviously missing something. I am using this sequence to prepare a statement and execute it.
$result = pg_prepare($link,"getacctname",'SELECT accounts.acctname FROM accounts WHERE accounts.acctname = $1') or die(pg_last_error());
$result = pg_execute($link,"getacctname",array($this->valuetofind)) or die(pg_last_error());
I always get the error "prepared statement already exists". I have read the other posts and even tried adding before the prepare and same result.
pg_query($link, "DEALLOCATE getacctname");
I even tried changing the name of the query and rebooting my machine to make sure there was nothing stuck that I was not seeing. same result.
Using pg_query($link, "DEALLOCATE ALL"); before the prepare fixed the problem.
However the troubling issue is that the only place prepare statement was used for that name query name was at that location. After turning off my machine and coming back to puzzle I tried the process that ran the code and it said that the statement already existed even though that was the first time the code was run.
Related
After a lot of searching the web, the times I see this error, it looks really scenario specific. So far, I haven't found one that matched my scenario. I think my issue is coming from a prepared statement with spatial data type params.
The way I'm executing my code is:
$sql = $conn->prepare("INSERT INTO states(`name`, `poly`) VALUES(':name',GeomFromText('GEOMETRYCOLLECTION(:coords)'));");
$res = $sql->execute(['name'=>$name, 'coords'=>$coords]);
if($res){
echo "... Successfully Inserted<br><br>";
}
else{
echo "... Failed<br><br>";
print_r($sql->errorInfo());
echo "<br><br>";
}
The above is failing. The connection to the database has been tested. Since these are rather large geometry sets, instead of pasting my code, I'll show how I verified my SQL:
Dumping a raw SQL file and copy/pasting the SQL into a phpMyAdmin window, everything inserted just fine.
$sqlStr = "INSERT INTO states(`name`, `poly`) VALUES('$name',GeomFromText('GEOMETRYCOLLECTION($coords)'));";
$check = file_put_contents('./states/'.$name.'2.sql', $sqlStr);
So it's because of this, that I believe my sql is correct, but it my problem is likely due to the prepare/execute portion somehow. I'm not sure if spatial data types can't be assigned like this?
Edit
I also want to note that I am on PHP version 5.5.9 and I've executed queries in the original method, with the params in the execute just fine.
There's no way the code at the end could be working. Parameters in the query must not be put inside quotes.
Since GEOMETRYCOLLECTION(:coords) has to be in a string, you need to use CONCAT() to create this string.
$sql = $conn->prepare("
INSERT INTO states(`name`, `poly`)
VALUES(:name,GeomFromText(CONCAT('GEOMETRYCOLLECTION(', :coords, ')')));");
So, I'm working with PHP and prepared statements sent to a MySQL database. I've ran into a problem that I can't quite debug. Here is my code:
// Check if the input username is in the database
$stmtQuery = "SELECT * FROM updatedplayers WHERE Player=?;";
$preparedStmt = $dbc->prepare($stmtQuery);
$preparedStmt->bind_param("s", $setUsername);
$preparedStmt->execute();
$preparedStmt->bind_result($resultUUID, $resultUsername);
$preparedStmt->fetch();
// If it's not, kill the page.
if ($resultUUID == null) {
incorrect();
}
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
The fist prepared statement works fine, it's at the line $preparedStmt->bind_param("s", $resultUUID);. There are also a couple other prepared statements before these, so I know I'm doing this correctly, but I'm not too sure about the last statement.
The code just seems to stop running after echo 'flag2 ';, which I put there to find the specific line. I don't get any error messages, it just doesn't print out flag3.
I've tried replacing $resultUUID with a static string, yet I get the same outcome. Also, I know my SQL statement is correctly formatted, I've tested within the console manually.
That's pretty much it, I'd love to hear some criticism, as I am new to PHP. Also, is there any way to get a better idea about the errors I get, instead of trying to pinpoint the error myself? Thanks!
So, adding ini_set('display_error', 1);, suggested by #user2182349, gave me a little more insight, I got "Fatal error: Call to a member function bind_param() on boolean".
After some research, I tried adding mysqli_report(MYSQLI_REPORT_ALL);, which ended up throwing "No index used in query/prepared statement".
I did some research on that to realize that it wasn't a problem, just MySQLI reporting unnecessary errors (which is what I asked it to do lol). In order to get a better, more insightful stack trace, I used mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);.
This threw "Commands out of sync; you can't run this command now". Again, more research taught me to use $preparedStmt->store_result();, in order to allow for another prepared statement to run.
Big thanks to all y'alls' help, hope this can help someone too.
You should be able to use a single select statement similar to this:
SELECT u.UUID, u.Username, l.Password, l.Salt
FROM updatedplayers AS u
JOIN logins AS l ON (u.UUID = l.UUID)
WHERE u.Player = ?
Check the case of the field names to be sure they match the database.
At the top of the file, add ini_set('display_errors',1);. If you have any PHP errors, they will be displayed. Also check the return values from the database calls and use the error display functions.
I think you need to close the prepared statement before you use the variable for another query:
$preparedStmt->close();
Or use another variable name like $preparedStmt2 for the second query.
I would suggest you should start using PDO... I have issues encountered with mysqli prepared statement years ago. Since then, PDO gives me no headaches when it comes to multiple queries at a time.
You should try PDO.. :-) it's more efficient.
http://php.net/manual/en/intro.pdo.php
http://php.net/manual/en/class.pdostatement.php
Or you can do the following "if you want alternative solution"..
//Close connection
$preparedStmt->close();
//AND OPEN YOUR CONNECTION AGAIN TO PREPARE NEW QUERIES..
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
the issue
So I bumped into something curious this morning when I was updating my database. I executed a collation change in my database, changing it from latin1 to uft8. However, my queries failed suddenly on my table. After some debugging, (rebuilding the table even with its original setup, but to no such avail) and receiving 500 internal errors, i realized it had to do with the prepared statement, so i tore it out, and replaced it with a regular mysqli_query, and it surprisingly worked. So now I am wondering, was my prepared statement wrong the whole time, or did it fail because of a change in the database.
the setup
This is the current table set up. I changed it back to latin (and its innoDB) yet it didnt gave me the results back i wanted when i changed everything back to the original settings (which is how it is now)
the code
the original code was this and it worked fine until the change
require_once '../db/dbControl.php';
$id = mysqli_real_escape_string($con,$_GET["id"]);
$sql = "SELECT *
FROM project
WHERE project.ProjectId = ? ";
$stmt1 = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt1,'i',$id);
mysqli_stmt_execute($stmt1);
mysqli_stmt_bind_result($stmt1,$ProjectId,$ProjectTitel,$ProjectOmschrijving, $ProjectOmschrijving,$ProjectDatum,$ProjectClient,$ProjectUrl);
while (mysqli_stmt_fetch($stmt1)){
the code itself of the page
}
So right now I am just using a regular mysqli_query in order to make it work
require_once '../db/dbControl.php';
id = mysqli_real_escape_string($con,$_GET["id"]);
$sql = "SELECT *
FROM project
WHERE project.ProjectId = '". $id ."'";
$result = mysqli_query($con,$sql);
while($rows=mysqli_fetch_array($result)){
$ProjectId = $rows['ProjectId'];
$ProjectTitel = $rows['ProjectTitel'];
$ProjectExpertise = $rows['ProjectExpertise'];
$ProjectOmschrijving = $rows['ProjectOmschrijving'];
$ProjectDatum = $rows['ProjectDatum'];
$ProjectClient = $rows['ProjectClient'];
$ProjectUrl = $rows['ProjectUrl'];
the code itself of the page
}
I am a little bit confused (maybe i overlooked something here because to focussed on a little bit of code) but it only happens on the project table. I checked it against code that involves readouts, and they work all fine with prepped statements.
Hope anyone can spot what I couldn't
I wont be able to tell you what happened but here are two thought's.
The prepared statement execution consists of two stages: prepare and
execute. At the prepare stage a statement template is sent to the
database server. The server performs a syntax check and initializes
server internal resources for later use.
A prepared statement can be executed repeatedly. Upon every execution
the current value of the bound variable is evaluated and sent to the
server. The statement is not parsed again. The statement template is
not transferred to the server again.
Maybe this is what happened, it could be that the prepared statements never reseted after you changed to utf8.
Every prepared statement occupies server resources. Statements should be closed explicitly immediately after use. If not done explicitly, the statement will be closed when the statement handle is freed by PHP.
Using a prepared statement is not always the most efficient way of
executing a statement. A prepared statement executed only once causes
more client-server round-trips than a non-prepared statement. This is
why the SELECT is not run as a prepared statement above.
Maybe the server memory (is/was) full?
Tekst from:
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
I'm trying to loop data from a api and then post these values to a MySQL db.
something like this:
$values = json_decode(file_get_contents("my-json-file"));
$SQL = new mysqli(SQL_HOST, SQL_USER, SQL_PASS, DB_NAME);
$SQL->autocommit(FALSE);
foreach($values As $item)
{
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
$SQL->query($query);
if(!$SQL->commit())
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
$SQL->close();
Since the loop is too fast, the SQL can't catch up. (Yea!)
I would then need something like this:
foreach($values As $item)
{
/**** STOP/PAUSE LOOP ****/
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";");
$SQL->query($query);
if($SQL->commit())
{
/**** START THE LOOP AGAIN ****/
}
else
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
Or how should I do this the right way?
EDIT: It inserts random posts every time.
EDIT 2: This is just example code. It does escape and all that, and yes the semi colon is wrong here but since so many commented on it i will not change it. This was not the problem in the real case.
I tried to run it on another server and there it worked. The problem was fixed by restarting MAMP.
Firstly, your idea that the loop runs too fast for MySQL to keep up is completely totally wrong. The $SQL->query() call will wait for the MySQL to return a response before proceeding, so the loop won't run any faster than MySQL is responding.
Now onto the actual problem.... your query:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
There's a semi-colon in there at the end, after value2 which is invalid. I guess you intended to type a quote mark there? The semi-colon will be causing all your queries to fail and throw errors.
This may be the cause of your problem but you haven't got any error checking in there, so you won't know. Add some error checking to your code after calling the query; even if the query is right, it's still possible to get errors, and your code should check for them. See the examples on this manual page: http://www.php.net/manual/en/mysqli-stmt.error.php
Finally, since you're using the mysqli API, it's worth mentioning that your code would be a lot better and probably more secure if you used prepared statements. See the examples in PHP manual here: http://www.php.net/manual/en/mysqli-stmt.bind-param.php
[EDIT]
Another possible reason your query is failing is that you're not escaping the input values. If any of the input values contains a quote character (or any other character that is illegal in SQL) then the query will fail. In addition, this problem makes your code vulnerable to a SQL injection hacking attack.
You need to escape your input using $SQL->real_escape_string() OR by changing your query to use prepared statements (as recommended above).
Your query is inside the loop, which means that the loop will wait until your query finished executing before it continue, php code is processed in order...
Has #phpalix said, PHP goes in order, and waits for the previous action to finish.
I think you SQL is wrong. Try replacing your INSERT with this:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2."');";
And don't forget to run at least mysql_real_escape_string for each variable, for security measures.
As many of the answers and comments say, it does not continue until the SQL is done. The problem was in my local apache/mysql server. It was fixed by restarting it. Yes, stupid post.
Given the following code:
// Connect to MySQL up here
$example_query = $database->prepare('SELECT * FROM table2');
if ($example_query === false) die('prepare failed');
$query = $database->prepare('SELECT * FROM table1');
$query->execute();
while ($results = $query->fetch())
{
$example_query = $database->prepare('SELECT * FROM table2');
if ($example_query === false) die('prepare failed'); //it will die here
}
I obviously attempt to prepare statements to SELET everything from table2 twice. The second one (the one in the WHILE loop) always fails and causes an error.
This is only on my production server, developing locally I have no issues so it must be some kind of setting somewhere.
My immediate thought is that MySQL has some kind of max_connections setting that is set to 1 and a connection is kept open until the WHILE loop is completed so when I try to prepare a new query it says "nope too many connected already" and shits out.
Any ideas?
EDIT: Yes I know there's no need to do it twice, in my actual code it only gets prepared in the WHILE loop, but like I said that fails on my production server so after some testing I discovered that a simple SELECT * query fails in the WHILE loop but not out of it. The example code I gave is obviously very watered down to just illustrate the issue.
Problem was that I couldn't do something while an unbuffered query was running (which it was in the WHILE loop)
Solution was to add the following line to ensure buffered queries were being used:
$database->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,true);
There shouldn't be a need to prepare $example_query more than once. Simply execute the query inside your loop.
EDIT: If you must prepare a new query in each loop iteration, an explicit $example_query->closeCursor() at the end of the loop should free any resources associated with the statement object.