MySQL inputting TINYINT syntax [duplicate] - php

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 5 years ago.
I created TINYINT columns in my MySQL database to interpret boolean variables, which based on whether checkboxes are checked or not in the html store the values (0 for false, everything else for true) in the DB. But it won't update the values when the php file is called. Is there something wrong with my SQL? Are TINYINTs inputted as below? Simply with a 0 and a 1?
<?php
include_once("createConnection.php");
session_start();
$checkbox = $_POST['name'];
$checked = $_POST['checked'];
$currentUser = $_SESSION['validUser'];
if($checked=='yes'){
$request='UPDATE projectDB.Members
SET :name=1 WHERE username=:currentUser';
$preparedStatement = $bdd->prepare($request);
$preparedStatement->bindParam(':name', $checkbox, PDO::PARAM_STR);
$preparedStatement->bindParam(':currentUser', $currentUser, PDO::PARAM_STR);
$preparedStatement->execute();
}
else{
$request='UPDATE projectDB.Members
SET :name=0 WHERE username=:currentUser';
$preparedStatement = $bdd->prepare($request);
$preparedStatement->bindParam(':name', $checkbox, PDO::PARAM_STR);
$preparedStatement->bindParam(':currentUser', $currentUser, PDO::PARAM_STR);
$preparedStatement->execute();
}
?>

Normally you want to parameterize your queries like this when you're taking user input. Your problem is that the user input (or at least potential user input) you're taking in is a column name rather than a value. PHP is converting your query to something like this:
UPDATE projectDB.Members
SET 'name'=1 WHERE username='currentUser'
Which doesn't do what you want it to (it's telling SQL to update a string called 'name' instead of update a column called name).
You still run a risk here if you don't sanitize your data - you basically have two options:
Have a whitelist of acceptable column names in your code; verify that the incoming string matches an entry in that whitelist exactly, if so use it as a column name. The disadvantage here is that you have column names in your data model strewn about your code and HTML. e.g.:
$chkcols['name1'] = true;
$chkcols['name2'] = true;
$chkcols['name3'] = true;
...
if ($chkcols[name] == true) ...;
or
Come up with a different data model, maybe something like EAV, where you don't have to deal with dynamic column names. Disadvantage here is that EAV can be a bit of an antipattern in SQL. This might use a query something like:
UPDATE projectDB.Members SET Enabled = 1 WHERE name=:name AND username =:currentUser; you could, alternatively to an EAV model, have a column that has preferences or a bitmask/list of some sort (but again, this is a SQL antipattern in that you're trying to pack in multiple pieces of information in a single column.

Related

How to add a possble value to a MySQL SET type in php, without know the current values

Hi everybody and sorry for my english.
I have the column "example" that is a SET type.
I have to make a php page where you can add values to that column.
First of all I need to know what is just in "example", to prevent the adding of an existing value by a control. Second of all I need to add the new value.
Here's what I had thinked to do.
//I just made the connection to the db in PDO or MySQLi
$newValue=$_POST['value']; //I take the value to add in the possible values from a form
//Now I have to "extract" all the possible values. Can't think how.
//I think I can store the values into an array
$result=$sql->fetch(); //$sql is the query to extract all the possible values from "example"
//So now i can do a control with a foreach
foreach($result as $control){
if ($newValue == $control){
//error message, break the foreach loop
}
}
//Now, if the code arrives here there isn't erros, so the "$newValue" is different from any other values stored in "example", so I need to add it as a possible value
$sql=$conn->query("ALTER TABLE 'TableName' CHANGE 'example' 'example' SET('$result', '$newValue')"); //<- where $result is the all existing possible values of "example"
In PDO or MySQLi, it's indifferent
Thanks for the help
We can get the column definition with a query from information_schema.columns
Assuming the table is in the current database (and assuming we are cognizant of lower_case_table_names setting in choosing to use mixed case for table names)
SELECT c.column_type
FROM information_schema.columns c
WHERE c.table_schema = DATABASE()
WHERE c.table_name = 'TableName'
AND c.column_name = 'example'
Beware of the limit on the number of elements allowed in a SET definition.
Remove the closing paren from the end, and append ',newval').
Personally, I don't much care for the idea of running an ALTER TABLE as part of the application code. Doing that is going to do an implicit commit in a transaction, and also require an exclusive table / metadata lock while the operation is performed.
If you need a SET type - you should know what values you add. Otherwise, simply use VARCHAR type.

SQL - change an existing row

I'm using PHP in order to create a website where managers have access and review forms that employees have submitted. In the reviewing PHP file, I have created two buttons which basically approve or disapprove the form. After they click on one of the buttons, they are being redirected to another PHP file which actually inserts into the MySQL Database a change in a column I named 'processed'. It changes 0 which is unprocessed to 1, which is processed. The table I am referring to has columns such as formid, fullname, department and other job related stuff, as well as the 'processed' column which allows the managers to see if there is a pending form to be reviewed.
My problem is that I have no idea how to actually allow MySQL to find the proper row and change only the cell with the name 'processed' from 0 to 1 without having to insert every cell again. Here's what I have tried till now:
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "INSERT INTO carforms (processed) where aboveid='$id' and processed='0' and teamformid=$teamformid
VALUES ('0')";
}
else if (isset($_POST['disapproved'])) {
//todo
}
How do I tell SQL to only find the specific row I want and change only one column which is processed?
Also, do I always have to type every column name when I use the INSERT INTO command?
Thanks in advance.
Use the Below code it'll work for you.
$id = $_SESSION[id];
$fullname = $_SESSION[fullname];
$teamformid = $_SESSION[teamformid];
if (isset($_POST['approved'])) {
$sql = "UPDATE `carforms` SET processed = '1' WHERE `aboveid` = '".$id."' AND `teamformid` = '".$teamformid."'";
}
Try:
"UPDATE carforms SET processed = 1 WHERE aboveid = $id AND teamformid = $teamformid"
From what I have interpreted from your question, it seems like you need to use the MySQL UPDATE command. This will update any existing rows.
For example, let's say you have a table called 'forms', consisting of a Primary Key 'form_id' and a field named 'processed'.
If we want to change the value of 'processed' to '1', we would run...
UPDATE forms SET processed = 1 WHERE form_id = [whatever number the form is];
Obviously this only works where the form (with a form_id) exists already
There is no "INSERT...WHERE" in SQL.
To change an existing record there are 2 options, REPLACE or UPDATE. The former will create the record if it does not already exist and has similar syntax to INSERT. UPDATE uses the WHERE clause to identify the record(s) to be changed.
Using REPLACE is tricky. It needs to work out whether it should INSERT a new record or UPDATE an existing one - it does this by checking if the data values presented already exist in a unique index on the table - if you don't have any unique indexes then it will never update a record. Even if you have unique indexes just now, the structure of these may change over time as your application evolves, hence I would recommend NOT using REPLACE for OLTP.
In your question you write:
where aboveid='$id' and processed='0' and teamformid=$teamformid
(it would have been helpful if you had published the relevant part of the schema)
'id' usually describes a unique identifier. So there shouldn't be multiple records with the same id, and therefore the remainder of the WHERE clause is redundant (but does provide an avenue for SQL injection - not a good thing).
If the relevant record in carforms is uniquely identifed by a value for 'id' then your code should be something like:
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
But there's another problem here. There are 3 possible states for a record:
not yet processed
declined
approved
But you've only told us about 2 possible states. Assuming the initial state is null, then the code should be:
$action=0;
if (isset($_POST['approved'])) {
$action=1;
}
$id=(integer)$id;
$sql = "UPDATE carforms SET processed = $action WHERE aboveid=$id";
if ($id &&
(isset($_POST['disapproved']) || isset($_POST['approved']))
) {
// apply the SQL to the database
} else {
// handle the unexpected outcome.
}

PHP, PDO binding dynamic number of values into the statement

I need effective some solution for the following issue:
For some reason that would be too much time-consuming to explain properly, I need a PDO prepare statemnt sorta looking this way:
'SELECT field, another field, blabla FROM table WHERE some_foreign_id = first_val AND the_same_foreign_id = second_val AND again_the_same_id = third val ......'
and Id wish to fill the values with an array of unknown size, that depends on how many fields in that foreign table fits to a certain category in yet another table.
So the querstion is: is it even possible or should I give it up and find some naive walkaround?
Thanks in advance!
Mac
You can pass an array of values into stmt ->execute($array); The only tricky part would be getting the number of question marks to enter.
$foreign_ids = array(foreign_id_1, foreign_id_2, foreign_id_3); //etc
$input_list = substr(str_repeat(',?', count($foreign_ids)), 1); //this gets you the correct number of ? to use for your query
// if you need add another value to the parameters you can use array_push($foreign_ids,$your_other_param);
$stmt= $dbh->prepare("
SELECT field, another_field
WHERE some_foreign_id = ($input_list)");
$stmt->execute($foreign_ids);
It should be possible. You'll need to generate your query dynamically with question marks for parameters, and then bind with an array at the point of execution.
See example 3 on the PDO::execute page of the PHP docs.

Dynamic lead capture script

I'm creating a dynamic lead capture script.
The form passes the table name, and the rest of the post data.
I'm looking for a way to collect all the post inputs and insert that into a MySQL table without knowing the input names since each 'lead' script is different and contains different fields.
The table is already created and contains all the columns necessary for the input.
Any clean ideas?
Cheers!
A quick solution is to serialize an array of your validated post data. This will convert it into a string for storing in your Database.
You can unserialize that string to convert it back into a manageble array.
http://php.net/manual/en/function.serialize.php
The biggest downside is not having the full SQL support that you would have otherwise, by putting data into separate database fields.
I would use a combination of both techniques by putting consistant data like names, email into their own fields and unknown data into another field.
--
Try index identification (if you don't know the specific names):
$data = array_values($_POST);
$name = $data[0];
$email = $data[1];
$etc = $data[2];
--
Generate SQL string from data. Remember be vigilant with validation and ideally you should use Mysqli bind params to correcly build your query string.
foreach($_POST as $input_name => $input_value){
//do validation here
//match columns here
if($input_name=='name') $cleaned[$input_name] = $input_value;
}
$values_csv = '"'.implode('","',$cleaned).'"';
$sql = "INSERT INTO table_name VALUES ($values_csv);";

mysql if word match statement

how do i save the data, if
1) the word match Pros, it will be saved to t_pros column
2) the word that not match Pros, it will be saved to t_others column
i heard i can use mysql CASE statement, but dont know how to use it?
table pro:
id t_pros t_others
------------------------
1 Pros 1x
2 Pros 2x
3 voucher
<input type="text" id="t_pros">
$db->query("INSERT INTO pro(t_pros,t_others) VALUES($t_pros, $t_pros)");
So in each row only one of the two columns ever has a value?
In that case, how about:
$column = (preg_match('/^Pros/i', $_POST['t_pros'])) ? 't_pros' : 't_others';
$t_pros = mysql_real_escape_string($_POST['t_pros']);
$db->query("INSERT INTO pro($column) VALUES ($t_pros)");
That is, pick which column based on whether the value begins with 'Pros' or not (just as you indicated), and then just insert into that column, using MySQL's default value (normally NULL) for the other.
First, your input field needs the attribute name="t_pros".
Secondly, this code is open to SQL Injection - read up on it.
The query might look like this:
INSERT INTO pro(t_pros,t_others) VALUES(IF($t_pros = 'Pros', 'Pros', NULL), IF($t_pros = 'Pros', NULL, $t_pros))"
But again, this is not safe. Use mysql_real_escape_string around all variables in your SQL query, or use prepared statements.
if ($t_pros == 'Pros')
$t_pros_col = $t_pros;
else
$t_others_col = $t_pros;
$db->query("INSERT INTO pro(t_pros,t_others) VALUES($t_pros_col, $t_others_col)");

Categories