I am using MySQLi in php to prevent SQL Injection with my table.
I have the following SQL command that works perfectly if input into phpMyAdmin.
INSERT INTO UsageData (MyID) SELECT * FROM (SELECT 'USER') AS tmp WHERE NOT EXISTS ( SELECT MyID FROM UsageData WHERE MyID = 'USER') LIMIT 1
Essentially it is intended to insert a new row with MyID as 'USER' if such a row does not already exist.
I have tried to do this with php like so
$query1 = "INSERT INTO UsageData (MyID) SELECT * FROM (SELECT ?) AS tmp WHERE NOT EXISTS ( SELECT MyID FROM UsageData WHERE MyID = ? ) LIMIT 1";
if ($statement1 = $database->prepare($query1)) {
$statement1->bind_param("ss", $inID, $inID);
$statement1->execute();
$statement1->close();
} else {
echo "Incorrect SQL 1\n";
echo "Query: ".$query1."\n";
echo $database->error."\n";
}
However this always results in the echoing of "Incorrect SQL". The error mentioned is "No tables used".
I have a SQL request sent right after it in the PHP that works perfectly but this one for some reason does not.
What am I doing incorrectly?
Okay, I'm going to assume that you've done the work to properly set up the database handler by doing something like $database = new pdo(...);
I'm a little foggy as to what happens when you put assignment statements inside the as an if condition. I would advise you to do the assignment before the if-else block and then test to see if ($statement1 === false) (testing for equivalence, not just equality) for an error. Otherwise, you can enclose $database->prepare(...) in a try-catch block as it emits a PDOException if something goes wrong like this:
try {
$statement1 = $database->prepare($query1);
} catch (PDOException $e) {
die("PDO Exception: " . $e->getCode() . ": " . $e->getMessage());
}
Related
Using PHP PDO with this SQL statement
SELECT count(*) FROM my_table;
returns an INTEGER with Postgres and a STRING with Sqlite3. That is, if there is one row in the table, Postgres returns (int)1 and Sqlite returns '1'.
Is this as intended, or is this a bug?
[edit to add below]
In case you want to follow along at home, here's a demonstration script I threw together. I actually encountered this when my PHPUnit tests passed (using in-memory Sqlite as a test fixture) and but my application failed using the production Postrgres database.
<?php
function connect($dsn)
{
try {
$pdo = new \PDO($dsn);
}
catch (\PDOException $e) {
echo 'New PDO failed: ' . $e->getMessage() . PHP_EOL;
exit;
}
return $pdo;
}
function doQuery($pdo, $sql)
{
if ( ($result = $pdo->query($sql)) === false) {
echo "'$sql' failed: " . print_r($pdo->errorInfo(), true) . PHP_EOL;
}
return $result;
}
$pgo = connect('pgsql:host=localhost;dbname=postgres');
$sqo = connect('sqlite::memory:');
doQuery($pgo, 'DROP TABLE IF EXISTS public.foo');
doQuery($pgo, 'CREATE TABLE public.foo ( ii int )');
doQuery($pgo, 'INSERT INTO public.foo VALUES (42)');
doQuery($sqo, "ATTACH DATABASE ':memory:' AS public;") or die();
doQuery($sqo, 'DROP TABLE IF EXISTS public.foo');
doQuery($sqo, 'CREATE TABLE public.foo ( ii int )');
doQuery($sqo, 'INSERT INTO public.foo VALUES (42)');
$pgResult = doQuery($pgo, 'SELECT COUNT(ii) FROM foo');
echo 'Postgres: ';
var_dump($pgResult->fetchColumn());
echo 'Sqlite3: ';
$ltResult = doQuery($sqo, 'SELECT COUNT(ii) FROM foo');
var_dump($ltResult->fetchColumn());
This is a side effect of sqlite not having datatypes. Or rather, having what they call the dynamic type system. But quite interestingly
SELECT TYPEOF(b) FROM ( select count(*) as b from my_table) a;
produces integer as the output! So clearly something is being lost in translation from sqlite to php. However it doesn't really matter because in php '1' + 2 gives 3. Because let's not forget, PHP is also a dynamic typed system.
Reported and accepted as a PHP PDO bug:
https://bugs.php.net/bug.php?id=72798
I'm having the problem of mySQL not recognizing the session user when I select data from a table. Can someone please point me in the correct position on what I need to do to fix this?
$sql1="SELECT * FROM `Bookings` WHERE `username`={$_SESSION['user']}";
This is what my code looks like, but it never fetches the data and just remains blank.
First you should check if $_SESSION['user'] is initialized or has any value.
Second, it is better to assign the session user to a variable, so as to avoid some ugly issues related to escaping quotes, in the future. Don't just directly dump your session within your mysql statement.
$user_session = $_SESSION['user'];
$sql1="SELECT * FROM `Bookings` WHERE `username`= $user_session";
#Edit:
as #Dann pointed out, it's must better and safer to user prepared statement, with either the mysqli/pdo API. Here is a simple example in PDO.
First you have to connect to your database:
try {
$db = new \PDO("mysql:host=localhost;dbname=xx;charset=utf8", "xx", "xx", [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
} catch(\PDOException $e){
echo "Error connecting to mysql: ". $e->getMessage();
}
Then simply fetch the booking as seen below.
$user_session = $_SESSION['user'];
try{
$stmt = $db->prepare("SELECT * FROM Bookings WHERE username = ?");
$result = $stmt->execute([$user_session]);
if($result){
// show booking
}
} catch(\PDOException $e){
echo "Counld not get user bookings. error: " . $e->getMessage();
}
Now your query is safer from mysql injection attacks, and connection errors will only throw exceptions, instead of showing potentially harmful errors.
You can use
$user=$_SESSION['user'];
$sql1="SELECT * FROM Bookings WHERE username= '$user'";
Hopefully This will solve your problem
I have been trying to create a PHP script that will periodically move "completed" rows from a table on my Joomla site to a different table. The query I wrote works just fine in PHPMyAdmin:
INSERT INTO my_calsgovdocs.sent_copy
SELECT * FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%';
DELETE FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%';
I attempted to translate it into some PHP code which could run inside Joomla, and I've pasted that code below. It returns an "Unexpected T_STRING" error which points to the line below which starts ->insert into, and it has now occurred to me that the script wouldn't work because "insert into" isn't a valid method name! So far I can't find an equivalent method to be used inside Joomla. This was my attempt at the code:
try
{
$db->transactionStart();
$query = $db->getQuery(true);
$query
->insert into($db->quoteName('sent_copy'))
->select('*')
->from($db->quoteName('entered_copy'))
->where($db->quoteName('Status') . ' LIKE ' . $db->quote('%Sent%') . ';')
->delete from($db->quoteName('entered_copy'))
->where($db->quoteName('Status') . ' LIKE ' . $db->quote('%Sent%'));
$db->setQuery($query);
$result = $db->execute();
$db->transactionCommit();
}
catch (Exception $e)
{
$db->transactionRollback();
JErrorPage::render($e);
}
Anyone have an idea how I can accomplish this inside Joomla? I'd prefer (as you may have noticed above) to do it in one transaction so that, if there's an error, I won't have a mess on my hands.
$db->setQuery allows being passed a query string as an argument instead of an object. See "preparing the query": https://docs.joomla.org/J1.5:Accessing_the_database_using_JDatabase
I've also suggested running two of these queries as part of the same transaction.
I unfortunately don't have a joomla installation handy to test this, please comment if you find it doesn't work.
try
{
$db->transactionStart();
$query = $db->getQuery(true);
$query1 = "INSERT INTO my_calsgovdocs.sent_copy
SELECT * FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%'";
$db->setQuery($query1);
$result1 = $db->execute();
$query2 = "DELETE FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%'";
$db->setQuery($query2);
$result2 = $db->execute();
$db->transactionCommit();
}
catch (Exception $e)
{
$db->transactionRollback();
JErrorPage::render($e);
}
You could try doing it in plain old php? Something like
$conf = JFactory::getConfig(); // load your config
try{
$link = mysqli_connect($conf->get('host'), $conf->get('user'),
$conf->get('password'), $conf->get('db'));
mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_WRITE);
mysqli_query($link, "INSERT INTO my_calsgovdocs.sent_copy
SELECT * FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%'");
mysqli_query($link, "DELETE FROM my_calsgovdocs.entered_copy
WHERE `Status` LIKE '%Sent%'");
mysqli_commit($link);
}
catch (Exception $e)
{
mysqli_rollback($link);
JErrorPage::render($e);
}
mysqli_close($link);
I'm kind of a stuck in searching for a solution.
I need to check if an input data $coupon from the form (after "post" action) equals data in the existing MySQL table called Serial, in the row $Coupon. If those two entries match i need the one in table "Serial" removed (DELETED From). In the other case I need to display an Error, maybe like echo "The coupon number you've entered is invalid".
Now i have the following code, but it doesnt do the check.
$query4="SELECT EXISTS(SELECT 1 FROM serial WHERE Coupon='$coupon')";
$result = mysql_query($query4);
if($result){
echo "Bravo!";
}
else{
"The coupon number you've entered is invalid";
exit;
}
// Delete data from mysql
$query2="DELETE FROM serial WHERE Coupon = '$coupon'";
$result = mysql_query($query2);
// if successfully insert data into database, displays message "Successful".
if($result){
echo "Some info";
}
else {
die(mysql_error());
}
Appreciate any ideas greatly!
You've created a race condition for yourself. The fact that the coupon exists when you run the SELECT statement does not mean that it will exist when you run the delete statement, especially if this is a web app, or multi-threaded/multi-process.
The DELETE statement deletes rows from tbl_name and returns a count of the number of deleted rows. This count can be obtained by calling the ROW_COUNT() function.
Run your DELETE unconditionally, then use the ROW_COUNT to see if it was there and got deleted or wasn't ever there.
First of all phase out mysql_* functionality or you have bigger problems than checking the result. Your code is vulnerable to SQL Injection. Use PDO or MySQLi instead.
Secondly, why do you need EXISTS in the first query at all?
Here is the solution in PDO:
$query = 'SELECT 1 FROM serial WHERE Coupon = :coupon';
$stmt = PDO->prepare($query);
$stmt->bindParam(':coupon', $coupon, DB::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
//query 2
$query2 = "DELETE FROM serial WHERE Coupon = :coupon";
$stmt2 = PDO->prepare($query2);
$stmt2->bindParam(':coupon', $coupon, DB::PARAM_STR);
if ($stmt2->execute()) {
echo 'Success';
} else {
echo 'Unable to Delete';
}
} else {
echo 'Selected Coupon Is Invalid';
}
OR MORE SIMPLY IN ONE QUERY:
$query = 'DELETE FROM serial WHERE coupon = :coupon';
$stmt = PDO->prepare($query);
$stmt->bindParam(':coupon', $coupon, DB::PARAM_STR);
if ($stmt->execute()) {
echo 'Success';
} else {
echo 'failure, invalid coupon';
}
You can actually just do SELECT 1 FROM serial...
Then:
$result = mysql_query($query4);
if (mysql_num_rows($result)) {
If it returns a row, you know it exists. You can also add LIMIT 1 to the query to make it faster.
By the way, your code is vulnerable to injection. You should use properly parameterized queries with PDO or mysqli.
Following up from mluebke's answer:
// Delete data from mysql
$query="DELETE FROM serial WHERE Coupon = '$coupon'";
mysql_query($query);
//Did we delete something?
if (mysql_affected_rows()) {
echo "Bravo!";
}
else{
"The coupon number you've entered is invalid";
exit;
}
http://www.php.net/manual/en/function.mysql-affected-rows.php
http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_row-count
I am trying to create a duplicate username checker and I am thinking this is probably the way to do it correct me if im wrong. Basically I want the username the user input to be stored in a variable called userName and then use that variable to check and see if there are any LIKE rows in the database and if so return a count of 1 or more to a variable named $count I would then have an IF ELSE statement that would either yell at the user or let them continue. I have run into a problem using the LIKE statement. I think my syntax could be wrong since I have been trying several different methods but still no luck.
Main Code
<?php
require 'DB.php';
$userName = "tes";
echo $userName;
try{
$stmt = $conn->prepare('SELECT COUNT(*) FROM `CLL_users` WHERE `user_name` LIKE "% . ":userName" . "');
$stmt->bindValue(':userName', $userName);
$stmt->execute();
$count = $stmt->fetchColumn();
return $count;
echo $count;
} catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}
?>
It appears you're trying to do string concatenation in MySQL using invalid syntax. Try this:
'SELECT COUNT(*) FROM `CLL_users` WHERE `user_name` LIKE CONCAT("%",:userName)'
You can probably use = instead of LIKE. The SQL syntax in itself isn't case-sensitive. I think you might be able to set up your database so that certain tables are case sensitive but I know for a fact through usage that no tables in my own MySQL database are. If you're unsure it's easy to try, just run a select with a username you know is in there but write it with different casing.
Just do a select WHERE 'user_name'=$entered_username, if you get one or more don't add the new user, if not go ahead. You could of course mark the user_field as unique, that way you'd know for sure you won't have duplicates, might be something worth looking at.
Try to use this select:
("SELECT COUNT(*) FROM CLL_users WHERE user_name LIKE "% . "'".$userName."'");