Mysqli prepare giving error, even though SQL statement is valid? - php

I'm having some trouble with a SQL transaction using PHP and mySQL. Here is my statement:
START TRANSACTION;
INSERT INTO listings (title, price, seller, description, time, featured)
VALUES (?, ?, ?, ?, ?, 0);
SELECT #listingid:=LAST_INSERT_ID();
INSERT INTO pictures (listid, primarypic)
VALUES (#listingid, 1);
COMMIT;
While this statement works fine when I put it in directly using phpMyAdmin (substituting the ? marks), it seems to fail when I call
$stmt = $mysqli->prepare("statement");
Replace "statement" with the above statement. The fact that it fails before getting to the bind_param of the $stmt leaves me to believe that it is not a problem with the parameters, but rather the query.
Here is the exact error, if it helps:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO listings (title, price, seller, description, time, featured) ' at line 2
Thanks in advance for your help!

I don't think mysqli can handle compound statements like that (especially since there is a separate commit() function). Instead of START TRANSACTION; at the beginning and COMMIT; at the end, you'd do $mysqli->autocommit(false); before the query and $mysqli->commit(); when you're done.

The problem is that you can only "prepare" a single SQL statement -- you are trying to prepare five SQL statements here.
One way to do what you want is to create a stored procedure.
From mysqli_prepare() documentation:
Prepares the SQL query, and returns a statement handle to be used for further operations on the statement. The query must consist of a single SQL statement.

Related

Mysql Prepared Statement Fails - sql query with more than one statement [duplicate]

I would like to know if i can prepare one mysqli statement that executes multiple queries:
mysqli->prepare(query1 ...1,2,3 param...; query2...4,5 param...);
or
mysqli->prepare(insert into ...1,2,3 param...; insert into...4,5 param...);
and after all
mysqli->bind_param("sssss", 1, 2, 3, 4, 5);
In that way it make error: Call to a member function bind_param() on a non-object in...
$stmt = $sql->getQueryPrepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?); INSERT INTO process (id_user, idp) VALUES (?,?);");
$stmt->bind_param("ssssss",$id, $username, $pw, $email, $id, $idp);
$stmt->execute();
$stmt->close();
A prepared statement can only execute one MySQL query. You can prepare as many statements as you want in different variables:
$stmtUser = $sql->prepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?)");
$stmtProc = $sql->prepare("INSERT INTO process (id_user, idp) VALUES (?,?);");
And then execute them later. If you want to ensure that neither one is ever run unless both are able to run, then you need to look into transactions, like Thomas said.
Also, a general tip: "call to member function on a non-object" is the standard error you get when prepare() fails and so $stmt isn't actually a prepared statement object. It usually means you need to look for an error in your prepare() statement rather than anything later.
No, a single call to the mysqli prepare() function cannot prepare multiple queries at once. You can, however, prepare more than one query for execution by using different variables. The documentation for this function is available here.
It also looks like you are trying to setup a transaction, which is a different question than you asked. If that's what you really want to know, then you'll need to provide more information about your database setup and probably more specifics about the use case you are trying to solve.

SQL Update a whole table with new data

I am running a query every 15 minutes to retrieve new data from an API and store this data in my database.
So every 15 minutes I would like to store the new data in the table and get rid of the all old data in that table.
I am currently using the following method:
$sql = "DELETE FROM self_user_follower
INSERT INTO self_user_follower (username, profile_picture, full_name, user_id, last_updated)
VALUES (:query_username, :query_profile_picture, :query_full_name, :query_user_id, :query_last_updated)";
But it gives me the following error:
Array
(
[0] => 42000
[1] => 1064
[2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO self_user_follower (username, profile_picture, full_name, user_id, l' at line 2
)
query_error
Is this the best way to do it or is there a nicer and cleaner way to do this?
If you want to put two SQL queries into one statement string, you have to
separate them with a semi-colon (;)
use the function mysqli_multi_query which supports multiple queries.
Unless you have a very good reason, modify your code so that it executes each query separately. MySQLi offers transaction support if you need that.*
The reason why you need a separate function is instructive; as mentioned in the docs:
An extra API call is used for multiple statements to reduce the likeliness of accidental SQL injection attacks. An attacker may try to add statements such as ; DROP DATABASE mysql or ; SELECT SLEEP(999). If the attacker succeeds in adding SQL to the statement string but mysqli_multi_query is not used, the server will not execute the second, injected and malicious SQL statement.
*: Actually, I'm not even sure the multi_query will execute both queries in the same transaction - I'm just guessing for your reason to use a multi-query.
Multiple statements should be terminated by semi colon
Try this
$sql = "DELETE FROM self_user_follower;
INSERT INTO self_user_follower
(username, profile_picture, full_name, user_id, last_updated)
VALUES (:query_username, :query_profile_picture, :query_full_name, :query_user_id,
:query_last_updated)";

MySQL query isn't working

The following code gives me an error "1064 You have an error in your SQL syntax;"
$this->mysqli->query("START TRANSACTION;
UPDATE Balances
SET balance={$left}
WHERE user='{$user}';
INSERT INTO Bought (user, orderid) VALUES ('{$user}', {$id});
COMMIT;");
I just can't understand why this is happening, because every command if it's used separately from others works perfect.
Execute each part as a single query when using query(), or use multi_query()

bind param in php for insert query before run execute function

I don't get the bind param in php. Why must use bind but not just execute the query directly? is it because the query format is an array?
Assuming by the bind_param() function you're using mysqli extension. There is no clear answer to "Why can't you just execute the query itself?" except this one.
You're not using a simple query in this case, but you are creating a prepared statement. Prepared statements as Wikipedia states are parameterized form of queries.
So you can't execute a query which is missing parameters, in this case you're probably executing this query :
INSERT INTO people (first_name, last_name, bio, created) VALUES (?, ?, ?, YOUR_TIME_FUNCTION)
As you can notice three parameters are missing, so you can't possibly execute that query in that state. Instead, if you have a static query you can use the mysqli_query() function, which won't accept parameters since it expects an executable query.

Placeholder For SQLite table In PHP

I have a query I would like to use that I would like to be reused for other select queries.
Is it possible to have a select query like this:
SELECT * FROM ? WHERE id = ?;
And then bind the values like this:
$stmt->bindValue(1, $table, PDO::PARAM_STR);
$stmt->bindValue(2, $id, PDO::PARAM_INT);
The problem is when I do this I get this $database->errorInfo() from a PDOException
HY000 1 near "?" syntax error.
I have tried taking out the table placeholder and it does work. Is it possible to do it my way or do I need to have separate functions?
Short answer: NO.
Long answer:
Refer to the PDO::prepare manual. There is a statement: This must be a valid SQL statement for the target database server. This means that your DB backend have to support prepared statement syntax that you use.
As far as I know, neither mysql, nor any other DB does not allow binding variables to occur in FROM clause. The reason for that lays deep in the concept of prepared statement. Prepared statement is being prepared inside the DB when you are calling prepare. This means that DB planner builds a plan for the query, so it can be executed multiple times with different parameters without building it again and again. To build a plan, planner needs to know affected tables, functions called, opportunities to use different fetch and join strategies (index scans/nested loops/etc.) and so on.
So, you cant 'bind' table name into prepared statement at the moment you want it to run, because DB needs table names at the moment when you prepare the statement. That's why you receive that message: DB requires all table names to be present in the preparing query.

Categories