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
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.
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.
I have an HTML form that allows users to type in a word and hit submit. This action sends the submitted word to a database table entitled 'word' which gives it an auto-incremented id and a timestamp for each submission.
I'm trying to prevent the database table from updating with duplicate word entries, and i'm also trying to incorporate prepared statements while doing this.
I have done a fair amount of research on this, but nothing I can find is helping me sort out the required syntax to pull this off. This submission got me close (MySQL: Insert record if not exists in table) but I cannot for the life of me figure out how to incorporate prepared statements in this solution that utilize bindvalue. I think my issue deals with preparing the statement before binding my values, but if that's the case I feel like I don't understand how to pull of the prepared statement.
I'm admittedly very new to all of this, so any and all solutions for improvement are welcome. Thanks. Here is the PHP and SQL code I have pieced together to get this working. Followed by that is the error message I receive.
if (!empty($_POST['word'])) {
try {
$sql = 'INSERT INTO word SET
wordname = :wordname,
worddate = now()
SELECT * FROM (SELECT :wordname) AS tmp
WHERE NOT EXISTS (SELECT wordname from word where wordname = :wordname) LIMIT 1';
$s1 = $pdo->prepare($sql);
$s1->bindValue(':wordname', $_POST['word']);
$s1->execute();
}
catch (PDOException $e) {
$error = 'Error submitting batch of forms.'.$e->getMessage();
include 'error.html.php';
exit();
}
}
Error submitting batch of forms.SQLSTATE[42000]: Syntax error or access violation: 1064 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 'SELECT * FROM (SELECT wordname) AS tmp WHERE NOT EXISTS (SELECT wordname from word ' at line 4
Thanks once again.
Add a unique index to your wordname column, then you can just use a basic INSERT ... VALUES statement.
$sql = 'INSERT INTO word (wordname, worddate) VALUES (:wordname, now())';
With this query, your current bindValue code should work.
Based on the error you're currently getting, your PDO connection is already configured to throw exceptions, so your code will generate an PDOException if you try to insert a duplicate value for wordname. You can catch that specific error and respond accordingly. (This would be one of the "certain scenarios" referred to in that answer I linked.)
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"
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