Using PHP to execute multiple MYSQL Queries - php

I am trying to use PHP to run consecutive MYSQL statements as shown in the code snippet below (which just copies one row to another and renames the id via a tmp table).
I am getting a repeated syntax error message. I've tried numerous iterations. And the code looks like code I've researched in the PHP Manual and other myql questions on SO (which do not include the php dimension).
Can anyone shine a light on why my php syntax is incorrect?
include("databaseconnect.php");// This obviously works. Used a zillion time
$sql ="CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id
= 1;";
$sql.="UPDATE tmp SET id=100 WHERE id = 1;";
$sql.="INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100;";
if ($conn->query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
else
{
echo "Error creating table: " . $conn->error;
//close connection etc
}
PHP Message back:
Error creating table: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UPDATE tmp SET id=100 WHERE id = 1INSERT INTO event_categoriesBU SELECT * FROM t' at line 1

Don't run a bunch of queries at once. Usually the success of one depends on all the other operations having been performed correctly, so you can't just bulldozer along as if nothing's gone wrong when there's a problem.
You can do it like this:
$queries = [
"CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id = 1",
"UPDATE tmp SET id=100 WHERE id = 1",
"INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100"
];
foreach ($query as $query) {
$stmt = $conn->prepare($query);
$stmt->execute();
}
Don't forget to enable exceptions so that any query failures will stop your process instead of the thing running out of control.
The reason you don't use multi_query is because that function does not support placeholder values. Should you need to introduce user data of some kind in this query you need to use bind_param in order to do it safely. Without placeholder values you're exposed to SQL injection bugs, and a single one of those is enough to make your entire application vulnerable.
It's worth noting that PDO is a lot more flexible and adaptable than mysqli so if you're not too heavily invested in mysqli, it's worth considering a switch.

You can't execute more than one SQL statement with query($sql), you must use multi_query($sql). Your script will then become something like this:
if ($conn->multi_query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
See the documentation for a complete example.
However, note that, as other users have well explained in the comments, executing multiple queries at the same time with this method can be potentially dangerous and should be avoided when possible, especially when handling user inputs.
You have better control of the execution flow if you execute one query at a time and check its result, rather than grouping all of them in a single call.

Related

Trying to create tables with the constraints "SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0" throws error [duplicate]

I am trying to use PHP to run consecutive MYSQL statements as shown in the code snippet below (which just copies one row to another and renames the id via a tmp table).
I am getting a repeated syntax error message. I've tried numerous iterations. And the code looks like code I've researched in the PHP Manual and other myql questions on SO (which do not include the php dimension).
Can anyone shine a light on why my php syntax is incorrect?
include("databaseconnect.php");// This obviously works. Used a zillion time
$sql ="CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id
= 1;";
$sql.="UPDATE tmp SET id=100 WHERE id = 1;";
$sql.="INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100;";
if ($conn->query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
else
{
echo "Error creating table: " . $conn->error;
//close connection etc
}
PHP Message back:
Error creating table: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UPDATE tmp SET id=100 WHERE id = 1INSERT INTO event_categoriesBU SELECT * FROM t' at line 1
Don't run a bunch of queries at once. Usually the success of one depends on all the other operations having been performed correctly, so you can't just bulldozer along as if nothing's gone wrong when there's a problem.
You can do it like this:
$queries = [
"CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id = 1",
"UPDATE tmp SET id=100 WHERE id = 1",
"INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100"
];
foreach ($query as $query) {
$stmt = $conn->prepare($query);
$stmt->execute();
}
Don't forget to enable exceptions so that any query failures will stop your process instead of the thing running out of control.
The reason you don't use multi_query is because that function does not support placeholder values. Should you need to introduce user data of some kind in this query you need to use bind_param in order to do it safely. Without placeholder values you're exposed to SQL injection bugs, and a single one of those is enough to make your entire application vulnerable.
It's worth noting that PDO is a lot more flexible and adaptable than mysqli so if you're not too heavily invested in mysqli, it's worth considering a switch.
You can't execute more than one SQL statement with query($sql), you must use multi_query($sql). Your script will then become something like this:
if ($conn->multi_query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
See the documentation for a complete example.
However, note that, as other users have well explained in the comments, executing multiple queries at the same time with this method can be potentially dangerous and should be avoided when possible, especially when handling user inputs.
You have better control of the execution flow if you execute one query at a time and check its result, rather than grouping all of them in a single call.

How to use MySQL variables in PHP? [duplicate]

I am trying to use PHP to run consecutive MYSQL statements as shown in the code snippet below (which just copies one row to another and renames the id via a tmp table).
I am getting a repeated syntax error message. I've tried numerous iterations. And the code looks like code I've researched in the PHP Manual and other myql questions on SO (which do not include the php dimension).
Can anyone shine a light on why my php syntax is incorrect?
include("databaseconnect.php");// This obviously works. Used a zillion time
$sql ="CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id
= 1;";
$sql.="UPDATE tmp SET id=100 WHERE id = 1;";
$sql.="INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100;";
if ($conn->query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
else
{
echo "Error creating table: " . $conn->error;
//close connection etc
}
PHP Message back:
Error creating table: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UPDATE tmp SET id=100 WHERE id = 1INSERT INTO event_categoriesBU SELECT * FROM t' at line 1
Don't run a bunch of queries at once. Usually the success of one depends on all the other operations having been performed correctly, so you can't just bulldozer along as if nothing's gone wrong when there's a problem.
You can do it like this:
$queries = [
"CREATE TEMPORARY TABLE tmp SELECT * FROM event_categoriesBU WHERE id = 1",
"UPDATE tmp SET id=100 WHERE id = 1",
"INSERT INTO event_categoriesBU SELECT * FROM tmp WHERE id = 100"
];
foreach ($query as $query) {
$stmt = $conn->prepare($query);
$stmt->execute();
}
Don't forget to enable exceptions so that any query failures will stop your process instead of the thing running out of control.
The reason you don't use multi_query is because that function does not support placeholder values. Should you need to introduce user data of some kind in this query you need to use bind_param in order to do it safely. Without placeholder values you're exposed to SQL injection bugs, and a single one of those is enough to make your entire application vulnerable.
It's worth noting that PDO is a lot more flexible and adaptable than mysqli so if you're not too heavily invested in mysqli, it's worth considering a switch.
You can't execute more than one SQL statement with query($sql), you must use multi_query($sql). Your script will then become something like this:
if ($conn->multi_query($sql) === TRUE)
{
echo "Table row copied successfully. Do something with it";
}
See the documentation for a complete example.
However, note that, as other users have well explained in the comments, executing multiple queries at the same time with this method can be potentially dangerous and should be avoided when possible, especially when handling user inputs.
You have better control of the execution flow if you execute one query at a time and check its result, rather than grouping all of them in a single call.

PHP / mysqli: Prepared Statements with num_rows constantly returning nothing

In my test-surroundings there is a database containing some Person Information (Name, E-Mail, Adress etc.). These Informations can be inserted by anyone into the database via a form. In the background they are inserted with a parameterized INSERT into the database after submission.
What I now would like to do is to detect if some person tries to insert the same values into the database again, and if he does, not inserting the new values and instead showing an error message. (So every person name in the database is unique, there are no multiple rows linked to one name).
I had a numerous number of ideas on how to accomplish this. My first one was to use a query like REPLACE or INSERT IGNORE, but this method would not give me feedback so I can display the error message.
My second attempt was to first do a SELECT-query, checking if the row already exists, and if num_rows is greater than 0, exit with the error message (and else do the INSERT-part). For this to work I will have to use parameterized queries for the SELECT too, as I´m putting some user input into it. Figuring that parameterized queries need special functions for everything you could normally do with way less lines of code, I researched in the internet on how to get num_rows from my $statement parameterized-statement-object. This is what I had in the end:
$connection = new mysqli('x', 'x', 'x', 'x');
if (mysqli_connect_error()) {
die("Connect Error");
}
$connection->set_charset("UTF-8");
$statement = $connection->stmt_init();
$statement = $connection->prepare('SELECT Name FROM test WHERE Name LIKE ?');
flags = "s";
$statement->bind_param($flags, $_POST["person_name"]);
$statement->execute();
$statement->store_result();
$result = $statement->get_result(); //Produces error
if ($result->num_rows >= 1) {
$output = "Your already registered";
} else {
$output = "Registering you...";
}
exit($output);
After all, I can´t get why mysqli still won´t give me num_rows from my statement. Any help is appreciated, thanks in advance!
Oh, and if you guys could explain to me what I have to do to get affected_rows,that would be awesome!
EDIT: I know I could to this by using unique constraints. I also found out that I can find out if INSERT IGNORE skipped the INSERT or not. But that won´t answer my complete question: Why does the SELECT num_rows alternative not work?
ANOTHER EDIT: I changed the code snippet to what I now have. Although my mysql(i)-version seems to be 5.6.33 (I echo´d it via $connection->server_info) get_result() produces the following error message:
Fatal error: Call to undefined method mysqli_stmt::get_result() in X on line X (line of get_result)
The behaviour of mysqli_num_rows() depends on whether buffered or unbuffered result sets are being used. For unbuffered result sets, mysqli_num_rows() will not return the correct number of rows until all the rows in the result have been retrieved. Note that if the number of rows is greater than PHP_INT_MAX, the number will be returned as a string.
Also make sure that you declare ->store_result() first. Moreover the function doesn't work with LIMIT used jointly with SQL_CALC_FOUND_ROWS. If you want to obtain the total rows found you must do it manually.
EDIT:
If nothing from the suggestions does not work for you, then I would propose to rewrite your SQL query:
SELECT `Name`, (SELECT COUNT(*) FROM `Persons`) AS `num_rows` FROM `Persons` WHERE `Name` LIKE ?
This query will return the total number from your Persons table, as well as Name, if exist.

php - How to have an output of a query as the input of another on postgresql?

I'm quite new with php and databases. I want to get the query from the search and enter the information in the Order table. I used pg_copy_from() but it is not working.
$keyword = pg_escape_string($_POST['keyword']);
$result = pg_query($dbh, "SELECT i.items_id, i.name, o.price, o.store_id, o.status, o.time, o.is_cancelled, o.gifting_carts_id FROM items i, orders o WHERE o.item_id = i.item_id AND i.name = $keyword");
// Printing results in HTML
echo "<table>\n";
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
echo "\t<tr>\n";
foreach ($line as $col_value) {
echo "\t\t<td>$col_value</td>\n";
}
echo "\t</tr>\n";
}
echo "</table>\n";
// GET INFO FROM QUERY
$sql = "INSERT INTO orders (quantity, item_id, store_id) VALUES('$quantity', '$item_id', '$store_id') returning orders_id";
$result1 = pg_query($dbh, $sql);
if (!$result1) {
die("Error in SQL query: " . pg_last_error());
header("Location: error.php");
}
header("Location: success.php");
Is this correct syntax:
$line = pg_fetch_array($result, null, PGSQL_ASSOC)
echo $line["i.item_id"] . " <- Item ID \n";
$sql = "INSERT INTO orders (item_id) VALUES('$item_id') returning orders_id";
pg_copy_from doesn't do what you think
The pg_copy_from PHP function is designed for bulk inserting rows into the database using a CSV-like format, supplied as an array from PHP. You don't need it for what you're doing, and it won't work. Each of those lines is failing with an error, but you aren't checking for errors, so you're ignoring them. If you check the PostgreSQL log files you'll see the errors.
Use the pg_fetch_... functions
Instead you want pg_fetch_array (to get an array that's also indexed by name), pg_fetch_result (to get an individual field) or pg_fetch_object (to get it as a PHP object you can access with fields as column names).
Check for and handle errors
Your code fails to check pg_result_status after database calls. So it'll fail in unexpected and usually ugly ways if a database call fails.
You should check pg_result_status after each call. It should be PGSQL_TUPLES_OK for any SELECT or ... RETURNING query, and PGSQL_COMMAND_OK for commands that don't return tuples. If it's anything else, you should use pg_result_error and/or pg_result_error_field to get error details and act on it appropriately - usually logging it and reporting a generic error to the user if it's a public facing website.
SQL Injection
Your code is vulnerable to SQL injection. Imagine what happens if someone sends the keyword:
`'); DROP TABLE items; --`
See http://bobby-tables.com and the PHP manual on SQL injection. You should be using pg_query_params or PDO.
This is also likely to cause more mundane problems. For example, any text value with a single quote in it will fail to insert because it'll terminate the text field, making your SQL statement's syntax invalid.
Always use parameterized statements (often called "prepared statements" though they're actually subtly different).
Transactions, concurrency
What if two copies of this code run at the same time? Will it do the right thing?
If there's an error half way through the program, will the database be in a sensible state?
When database programming you always need to think about these things. Transactions and locking are your main tools to make sure that the results are right. I won't discuss those in detail here, but I strongly recommend taking a look at the PostgreSQL tutorial and documentation, which discusses them in detail.
ANSI joins
Please, please, please write your queries with explicit INNER JOINs. As you have bigger queries, this starts to become vital for readability. E.g.
SELECT
i.items_id,
i.name,
o.price,
o.store_id,
o.status,
o.time,
o.is_cancelled,
o.gifting_carts_id
FROM items i
INNER JOIN orders o ON (o.item_id = i.item_id)
WHERE i.name = $keyword"

Sql query problem

I have the below sql query that will update the the values from a form to the database
$sql=
"update leads set
category='$Category',
type='$stype',
contactName='$ContactName',
email='$Email',
phone='$Phone',
altphone='$PhoneAlt', mobile='$Mobile',
fax='$Fax',
address='$Address',
city='$City',
country='$Country',
DateEdited='$today',
printed='$Printed',
remarks='$Remarks'
where id='$id'";
$result=mysql_query($sql) or die(mysql_error());
echo '<h1>Successfully Updated!!.</h1>';
when i submit I dont get any errors and the success message is displayed but the database isnt updated . When i echo the $sql, all the values are set properly. and when i ech the $result i get the value 1.
can someone please tell me what am i doing wrong here??
Have you tried running the echo of $sql directly using some DB tool? It may provide a more informative error. Alternatively, if that works you may have an issue where the transaction isn't being committed. Often a connection is set to automatically commit transactions, but that may not be the case here. Try adding a commit.
And have you ever heard of SQL injection attacks?
If you have a query that is not giving the expected result or receiving an error, and the problem isn't obvious, you should generally take a look at the final query just before it's run. Try using this right before running the query:
echo $sql;
exit;
Viewing the actual query often makes it obvious what the problem is, especially when the query includes variables. If the problem still isn't obvious, you can paste the query as is into a query browser to get feedback directly from the database engine.
Interestingly, using parametrized queries, you won't get to see the parameter values, as the parameters get replaced by MySQL, not PHP, however, you'll still get to see the entire prepared query.
Also, you can see the number of affected rows from your UPDATE statement with the mysql_affected_rows() function. You could put this immediately after the query is run:
echo ("Updated records:", mysql_affected_rows());
Spaces are often forgotten when concatenating queries.
$sql = "SELECT * FROM ducks";
$sql .= "WHERE duck = 'goose'";
When echoing the above query, we see:
SELECT * FROM ducksWHERE duck <> 'goose'
I'm guessing that the WHERE clause in your UPDATE statement isn't matching an "id = '$id'".
Also, is the id column really a string? You've put single quotes around the value. MySQL will cast the string to an integer if needed, but if it's an integer, save the database some work and remove the single quotes.
try to echo $sql and run it directly in any database console, may be there is no record with id = $id
SQL Injection can be the answer. Not an intentional attack (at this moment), but if your parameters have some unexpected information like quotes or other reserved characters you can have strange results. So, try to run this SQL directly in your database administration utility.
Try doing this
"""update leads set
category="$Category",
type="$stype", etc...; """
See if that works

Categories