Alright, So I am trying to make a query that searches the table PRIV for any columns that were selected in the checkboxs that = Yes or No.
Here is the code.
if(isset($_POST['submit']))
{
$fini = $_POST['chk'];
$fila = $_POST['ends'];
$qMarks = str_repeat('?,', count($fini) - 1) . '?';
$stmt = $con->prepare("SELECT * FROM priv WHERE `$qMarks` = `$fila`");
$stmt->execute($fini);
while($myR=$stmt->fetch(PDO::FETCH_ASSOC))
{
echo $myR['ident'];
echo "<br>";
}
}
As you can see, $fini represents the checkboxs in an array form that were selected.. the possible numbers in $fini are op1, op2 all the way through op24
$fila represents a simple Yes or No Selector..
For instance.. If I was to select checkbox 2 and 3 then $fini array would be op2, op3 and if I selected enabled on the selector then $fila would be Yes
This is the error I am getting.
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column ''op1'' in 'where clause'' in
It's saying unknown columns op1.. Which makes no sense because I have columns op1 - op24
Could someone please help me with this.
The error message shows that the 'op1' column (with quotes) is being looked for, which obviously does not exist. The quotes are there because you passed these values as string parameters.
But that could never work. Parameters are intended to pass literal values, not column names.
The thing you want to do does not go well with parameters. Instead I would suggest the following code. Comments should clarify each step:
// Generate array of valid column names
$columns = array_map(function ($i) { return "op$i"; }, range(1,24));
// Ensure the provided data is acceptable -- remove what is not:
$fila = $_POST['ends'] == 'Yes' ? 'Yes' : 'No'; // only Yes or No are allowed
$fini = array_intersect($columns, $_POST['chk']); // only real column names are allowed
// You need to treat the case when no checkboxes are checked:
if (count($fini) == 0) die("You need to check at least one checkbox.");
// Make $fila also an array with just as many elements as $fini, and wrap
// each value (Yes or No) in quotes:
$fila = array_fill(0, count($fini), "'$fila'");
// turn both arrays into comma-separated strings, and compare tuples
$sql = "SELECT * FROM priv
WHERE (" . implode(',', $fini) . ") = (" . implode(',', $fila) . ")";
$stmt = $con->prepare($sql);
$stmt->execute(); // no parameters
// ... etc...
Considerations
It is not so good practice to design a database table with 24 columns which serve a similar purpose. Instead you should normalise your database, and put these values in rows instead of in columns.
Related
I am trying to find a match in two different columns using input from two different form fields in a PHP form. I am referencing the two string variables that are input into the form in my mysql code, but it is returning an error:
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 'MATCH (abcdef) AGAINST name' at line 1
I have tried a few variations of the syntax, but with no success.
$name = mysql_real_escape_string($_POST['studentname']);
$num = mysql_real_escape_string($_POST['studentnum']);
$qw = "SELECT name FROM students MATCH ($name) AGAINST name";
$qw1 = "SELECT studentnum FROM students MATCH ($num) AGAINST studentnum";
$namematch = mysql_query($qw) or die(mysql_error());
$nummatch = mysql_query($qw1) or die(mysql_error());
if (($namematch || $nummatch) == FALSE) {
die('Name or student number do not match those on record');
}
I believe you have your parameters backwards in the MATCH clause. You have:
$qw = "SELECT name FROM students MATCH ($name) AGAINST name";
Instead it should be:
$qw = "SELECT name FROM students MATCH (name) AGAINST $name";
In other words, MATCH (column) AGAINST (parameter), not the other way around.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html#function_match
try this, use in_array to match array:
while($row = mysqli_fetch_array($qw)){
$namematch[] = $row['name'];
}
while($row2 = mysqli_fetch_array($qw)){
$nummatch[] = $row['studentnum'];
}
if(in_array($name,$namematch)){
echo 0;
}else{
echo 1;
}
*NOTE Please avoid to use mysql. I suggest use MYSQLi rather than use MYSQL. Just FYI.
First off, you are missing WHERE in your SQL statements.
Second, you have your arguments in MATCH and AGAINST reversed. MATCH should be given the column names as arguments.
E.g.
SELECT name FROM students MATCH ($name) AGAINST name
should be
SELECT name FROM students WHERE MATCH (name) AGAINST ('$name')
and similarly adjust your second query.
Im trying to create a php page where logged in users can update their profile.
Ive found an example Im trying to stick to:
I receive the POST from the update form:
$id=$_SESSION['id'];
$info1=mysql_real_escape_string($_POST['info1']);
$info2=mysql_real_escape_string($_POST['info2']);
$info3=mysql_real_escape_string($_POST['info3']);
The sql query to update the profile
$query=mysqli->query("UPDATE profiles SET
info1=IF('$info1' = '', info1, '$info1'),
info2=IF('$info2' = '', info2, '$info2'),
info3=IF('$info3' = '', info3, '$info3')
WHERE id='$id'");
How does this short IF statement work?
I dont want to update the column if there is no input - is that what it does?
How would i add some criteria to the inputs? like length of the string etc.
So, to clarify from Benio's answer which explains the IF() condition, in effect it is saying that for each column you are trying to update,
if the incoming $variable value is blank, replace the column with what it already had (ie: to not destroy it just because a blank value came in). If there IS something other than blank (the other half of the IF() function), update the column with what the $variable is...
and obviously you have 3 different $ variables for each column of info1, 2, 3.
IF(CONDITION, STATEMENT if CONDITION is true) for 2 arguments
IF(CONDITION, STATEMENT if CONDITION is true, STATEMENT if CONDITION is false) for 3 arguments
$sql = sprintf('UPDATE %s SET', $table);
$rowdata = null;
foreach ($rows as $field => $value) {
$rowdata[] = sprintf('%s = %s', $field, $value); // Escape the $value here!
}
$sql .= sprintf(' %s', implode(', ', $rowdata));
So enter your table name in $table and the data that you want to add as key-pair values in an associative array called $rows and you will end up with your query in $sql
I have a piece of code that looks like this:
// get media table columns
$media_columns = $this->many( "SHOW COLUMNS FROM media;" );
$media_fields = array(); // array to filter out unnecessary col data
$pk_name = 'ignore_this';
foreach( $media_columns as $col ) {
$field = $col['Field'];
if( $field !== $pk_name ) {
array_push($media_fields, '`'.$field.'`');
}
}
$fields_str = "(".implode(",", $media_fields).")"; // put in string
// we will be overriding the campaign_uid with parent_uid
$insert_str = str_replace("`campaign_uid`", "'$parent_uid'", implode(',', $media_fields) );
// duplicate draft media, pointing to parent campaign
$this->none(
"INSERT INTO media ".
"$fields_str ".
"SELECT $insert_str ".
"FROM media WHERE `campaign_uid`='$campaign_uid' "
);
Which throws an error:
exception 'Exception' with message 'ADO Error: Unknown column 'margin-left' in 'field list' { INSERT INTO media (`ignore_this`,`nonprofit_uid`,`campaign_uid`,`meta_id`,`image_name`,`url`,`type`,`subtype`,`mark`,`last_updated`,`deleted`,`margin-left`,`margin-top`)
SELECT `ignore_this`,`nonprofit_uid`,'XXXXXX',`meta_id`,`image_name`,`url`,`type`,`subtype`,`mark`,`last_updated`,`deleted`,`margin-left`,`margin-top` FROM media
WHERE `campaign_uid`='XXXXXXXXXXX }'
Before you ask about the funky sql wrapper functions: don't. I've inherited a mess of a codebase from my predecessor, and am largely locked into using his functions.
For the same reason, we have hyphens in the mysql column names. Because it's margin-left that fails, I suspect that this is the problem, but there's enough hard-coded references to that column name all over the place the refactoring isn't a very attractive option.
The funny part is, I'm pulling the field names directly from a SHOW COLUMNS call, and escaping them with ticks. I don't understand how the column can't be found if it was just read from the DB a second ago.
Any help is appreciated.
Don't use show columns. That was never really intended for how you're using it. Use the information_schema meta-db instead:
select COLUMN_NAME
from information_schema.COLUMNS
where (TABLE_SCHEMA='name of db') AND (TABLE_NAME = 'name of your table')
Simple question I guess, but a fundamental one and I'm not sure of the best practice.
So let's say that I have a database with some IP addresses that I want to display to the user.
Is this a good/secure way/practice?
//--> CONNECT TO DB, etc
$db_query = 'SELECT ip,'
."FROM table "
."GROUP BY ip ";
$result = $db_conn->query($db_query);
echo 'Found '.$result->num_rows.' records';
if($result->num_rows > 0) {
while($row = $result->fetch_array(MYSQLI_BOTH))
{
//POPULATE A HTML TABLE/WHATEVER WITH THE INFO
}
}
I'm mostly concerned about this: $result->num_rows > 0 and this: fetch_array(MYSQLI_BOTH)
I'm asking because I read somewhere that num_rows > 0 can usually mean trouble depending on the situation, for example a user login. In that case I suppose it would num_rows == 1 right?
And also, I haven't fully understood the difference between MYSQLI_BOTH and other forms of fetching.. If you could simple explain them to me and when to use them I would be grateful.
What do you think?
I would add a check to ensure your query was executed OK - and if not output the error :
$result = $db_conn->query($db_query);
// check for error - output the error
if (!$result) {
$message = 'Invalid query: ' . mysqli_error() . "\n";
$message .= 'Whole query: ' . $db_query;
die($message);
}
echo 'Found '.$result->num_rows.' records';
Other than that ... looks OK
EDIT:
To explain MYSQLI_BOTH, the options are MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH ->
MYSQLI_ASSOC = Associative array so the value of the rows can be accessed using $row['column']
MYSQLI_NUM = Numeric array so the values of the rows are accessed using a number $row[n] where n is the number of the column (0 based)
MYSQLI_BOTH = can use both to access values of row either $row[n] or $row['column']
EDIT2:
There is also a function for checking the number of returned rows :
if(mysqli_num_rows($result) == 0){
echo "Sorry. No records found in the database";
}
else {
// loop you results or whatever you want to do
}
EDIT3:
php.net has some excellent docs for the MY_SQLI extension
Two things:
If you only need an associative array, then don't use fetch_array(). Use fetch_assoc().
There's no need to concatenate the query like that, you could use something like:
$sql = "
SELECT
ip
FROM
table
";
This helps with large queries with multiple options in the WHERE clause or JOINs. It's quicker to type out, and you can quickly copy and paste it for checking in phpMyAdmin and the like.
I'd like to create a query in MySQL that has an optional value. When the value is specified the query is filtered by that value, when the value is not all rows are returned. Here's the idea:
public function doQuery($item = 'ANY_VALUE') {
$query = "SELECT * FROM table WHERE item = ?";
db->fetchAll($query,array($item))
...
}
doQuery(); // Returns everything
doQuery($item='item1'); // Returns only rows where item = 'item1'
Is there an easy way to do this without creating two query strings depending on the value of $item?
As far as I know, no such "any" placeholder exists.
If you can use LIKE, you could do
SELECT * FROM table WHERE item LIKE '%'
if you can append a condition, you could nullify the item clause like this:
SELECT * FROM table WHERE item = ? OR 1=1
(won't work in your example though, because you are passing "item" as a parameter)
That's all the options I can see - it's probably easiest to work with two queries, removing the WHERE clause altogether in the second one.
This would probably work, but I*m not sure whether it's a good idea from a database point of view.
public function doQuery($item = 'ANY_VALUE') {
$query = "SELECT * FROM table WHERE item = ? OR 1 = ?";
db->fetchAll($query,array($item, ($item == 'ANY_VALUE' ? 1 : 0))
...
}
Better way to do this is first generate sql query from the parameter you need to bother on, and then execute.
function doQuery($params) {
$query = 'SELECT * FROM mytable ';
if (is_array($params) // or whatever your condition ) {
$query .= 'WHERE item = ' . $params[0];
}
$query .= ' ;';
// execute generated query
execute($query);
}
You cannot get distinct results without giving distinct query strings.
Using $q = "... WHERE item = '$item'" you DO create distinct query strings depending on the value of $item, so it is not that different from using
$q = "..." . ($item=='ANY_VALUE' ? something : s_th_else);.
That said I see two or three options:
use function doQuery($item = "%") { $query = "SELECT ... WHERE item LIKE '$item'"; ...}
But then callers to that function must know that they must escape a '%' or '_' character properly if they want to search for an item having this character literally (e.g. for item = "5% alcoholic solution", giving this as argument would also find "50-50 sunflower and olive oil non alcoholic solution".
use function doQuery($item = NULL) { $query = "SELECT ..."; if ($item !== NULL) $query .= " WHERE item = '$item' "; ...} (where I use NULL to allow any other string or numerical value as a valid "non-empty" argument; in case you also want to allow to search for NULL (without quotes) you must choose another "impossible" default value, e.g., [], and you must anyway use a distinct query without the single quotes which however are very important in the general case), or even:
use function doQuery($item = NULL) { if($item === NULL) $query = "SELECT ..."; else $query = "SELECT ... WHERE item = '$item' "; ...}, which is more to type but probably faster since it will avoid an additional string manipulation (concatenation of the first and second part).
I think the 2nd & 3rd options are better than the first one. You should explain why you want to avoid these better solutions.
PS: always take care of not forgetting the quotes in the SQL, and even to properly escape any special characters (quotes, ...) in arguments which can depend on user input, as to avoid SQL injections. You may be keen on finding shortest possible solutions (as I am), but neglecting such aspects is a no-no: it's not a valid solution, so it's not the shortest solution!