what's different between '".$string."' and '$string" on MySQL Querys - mysql

what's different between below two query's on '".$string."' and '$string'
SELECT * FROM users WHERE UserName='".$USERNAME."' AND Pass='".$PASS."'
/* AND */
SELECT * FROM users WHERE UserName='$USERNAME' AND Pass='$PASS'
if different what's better for security ? strings always secure on input but just for above differents
EDIT:
I use above querys on PHP JUST and need it on it

In PHP, at least, there is absolutely no difference between the two -- they do the exact same thing. Both are equally vulnerable to SQL injection.

There is no difference between them in your case.
But you'll see a difference if the string you're concatenating does not contain special chars (such as ') :
$b = 'b';
$string = "a" . $b . "c";
Is not equivalent to :
$b = 'b';
$string = "a$bc";
Because PHP will look for $bc variable. But this is equivalent to :
$b = 'b';
$string = "a{$b}c";
As well as your example is equivalent to :
SELECT * FROM users WHERE UserName='{$USERNAME}' AND Pass='{$PASS}'
But take care, the single quotted string :
$b = 'b';
$string = 'a{$b}c';
will be litteraly read as a{$b}c.
Finally, as #duskwuff warns, you should be aware of sql injections.

Related

Is it possible to insert sql query in php array value?

for($count = 0; $count < count($_POST["item_sub_category"]); $count++)
{
$data = array(
':item_sub_category_id'
=> SELECT r_name FROM Repair where r_id = $_POST["item_sub_category"][$count]
);
$query = "INSERT INTO Repairlog (description,visitID) VALUES (:item_sub_category_id,'1')";
$statement = $connect->prepare($query);
$statement->execute($data);
}
As far as concerns, your code won't work. The SQL query that you are passing as a parameter will simply be interpreted as a string.
You could avoid the need for a loop by taking advantage of the INSERT INTO ... SELECT ... syntax. The idea is to generate an IN clause that contains all values that are in the array, and then run a single query to insert all records at once.
Consider:
$in = str_repeat('?,', count($_POST["item_sub_category"]) - 1) . '?';
$query = "INSERT INTO Repairlog (description,visitID) SELECT r_name, 1 FROM Repair WHERE r_id IN ($in)";
$statement = $connect->prepare($query);
$statement->execute($_POST["item_sub_category"]);
Note: it is likely that visitID is an integer and not a string; if so, then it is better not to surround the value with single quotes (I removed them in the above code).
TLDR; No.
Your question can be re-framed as: Can I write SQL code in php. The answer is NO. You can write the SQL code within a String type variable (or parameter) in php.
This is a general rule for any programming language, you cannot have multiple languages within the same file, as the language parser will not be able understand which syntax is that.
In order to embed a different language in another language, you need some kind of separator that will define when the new language or special type will start and when it will end.

mathematical operator as a variable in mysql query

I am wondering if it is possible to use a mathematical operator for a variable in a prepared mysql statement? I have written what I think it would look like below (albeit it doesn't work, I get "Call to a member function bind_param() on a non-object").
$result = $mysqli->prepare("SELECT t.column FROM table t WHERE t.value ( ? ) ( ? );");
$result->bind_param('ss', $operator, $value);
$result->execute();
I am using this along with an if statement that changes the operator value based on if a radio button is checked on the greater or less than value. Like below.
if (isset($_POST["abovebelow"]) && $_POST["abovebelow"] == "Above"){
$operator = ">";
}
elseif (isset($_POST["abovebelow"]) && $_POST["abovebelow"] == "Below"){
$operator = "<";
}
elseif (!isset($_POST["abovebelow"])){
$operator = "=";
}
You have only 2 variables in your query string but you bind 3 values, so that isn't right in the first place.Then you shouldn't add the operator like that, better do like this:
if (isset($_POST["abovebelow"]) && $_POST["abovebelow"] == "Above"){
$operator = ">";
}
elseif (isset($_POST["abovebelow"]) && $_POST["abovebelow"] == "Below"){
$operator = "<";
}
elseif (!isset($_POST["abovebelow"])){
$operator = "=";
}
$result = $mysqli->prepare("SELECT t.column FROM table t WHERE t.value".$operator." ? ;");
$result->bind_param($value);
$result->execute();
The short answer is, "No, you can't do that."
The long answer is, "No, you can't do that." Among other reasons is that the complier must be able to parse the complete query, which means it must know the operators at parse time.
Emil Borconi suggests a good work-around, that you could insert the operator into the text of the query, and then prepare it.
No, it's not possible. Placeholders in a prepared statement are only allowed in places where expressions are allowed. So you can't use a placeholder for a table or column name, and you can't use it for syntactical elements like operators.
If you need to substitute those things dynamically, you need to use string operations in PHP, not prepared statement placeholders.

Select or Return "field" names from a query (not table) in MySQL

I have a Dynamic Pivot in MySQL (see this question: MySQL "Multi-Dimensional?" Dynamic Pivot)
I want to know the Column/As/Field names as if it were a table and I queried INFORMATION_SCHEMA (which if this was a REAL table, would be easy enough: MySQL query to get column names?).
But, I can find no question or reference to a function or SELECT option to get the Column/As/Field names from a query. Is this possible? If so, how?
Using Perl to access MySQL (http://dbi.perl.org/).
So, flipping this around... we know the fixed columns. So, if we use the same basic query that creates the Pivot to begin with, we can get a GROUP_CONCAT of the names.
SET #sql = NULL;
SELECT GROUP_CONCAT(qrv.req_name) INTO #sql
FROM (SELECT qrt.req_name FROM qual_requirment_values qrv JOIN qual_requirment_types qrt ON qrt.id = qrv.req_type_id) qrv;
SET #sql = CONCAT('r.rank,r.member_type,im.name,qrv.grouping,', #sql);
SELECT #sql;
This can then be split into an array and used.
Seems like the long way around, but in the absence of something else it will work for my application. Seems horribly inefficient! :)
The better answer, thanks to #OllieJones. The Data Base Interface used to access MySQL should provide a way.
In my case (Perl), the answer is here: http://www.perlmonks.org/?node_id=264623
my $sql = ... [some query];
my $sth = $dbh->prepare($sql);
$sth->execute();
my $field_name_arrayref = $sth->{NAME};
Further to the answer, this is the full method within my MySQL package. do() is our generic DBI method that returns queries in an AoA. Adapting that method to create do_fieldNames();
## Tested Method
sub do_fieldNames {
my ($self, $sql, $has_results) = #_;
my ($sth, $rv, #row, #query_results);
## Execute the SQL statement
$sth = $$self->prepare($sql);
$rv = $sth->execute or &error(3306, __LINE__, __FILE__, $sql, $$self->errstr);
return undef unless $rv > 0;
## SOLUTION >> Field Name arrayref, part of the standard included DBI Perl Module
my $field_name_arrayref = $sth->{NAME};
## Parse the results
if ($has_results || $sql =~ /^select/i) {
while (#row = $sth->fetchrow_array) {
push #query_results, [ #row ];
}
}
## Return results
return (\#query_results, $field_name_arrayref) ;
}

Using a hash value in a simple mysql query (perl)

Can someone help me figure out the correct syntax of
for (my $i = 0; $i <=3; $i++)
{
$store = qq(INSERT INTO main (creator_name,relationship)
VALUES("$data{creatorname}",$data{"relationship$i"}) );
The problem lies with $data{"relationship$1"}. I'm looping because I have 'relationship1', 'relationship2', and 'relationship3' in my data hash. I didn't want to go through 3 separate mysql queries to get the job done so I'm trying to loop over it.
Any pointers?
EDIT:
Thanks for your help with pointing me towards placeholders. It's not working as placeholders and it looks like it's because of
$sth->execute($data{creatorname},$data{relationship},"DATE_ADD(NOW(), INTERVAL $interval)"
I have a DATE_ADD now that I'm using, it doesn't look like it likes to be used as a placeholder.
As pointed out by mob and Bill, if possible it is best to use place holders, but that's not the reason your code is not working.
It is not working because you are trying to do two levels of variable interpolation in one string: first interpolate $i into "relationship$i", then interpolate $data{"relationship$i"} into the larger string quoted with qq. They will not nest like that.
This would work:
for (my $i = 0; $i <=3; $i++)
{
my $relationship = $data{"relationship$i"}
$store = qq(INSERT INTO main (creator_name,relationship)
VALUES("$data{creatorname}",$relationship ) );
As #mob says, you should use query parameters instead of fighting with how to interpolate variables directly into strings.
$store = qq(INSERT INTO main (creator_name, relationship) VALUES (?, ?));
$st = $dbi->prepare($store);
for (my $i = 0; $i < 3; $i++)
{
$st->execute($data{creatorname}, $data{"relationship$i"});
}
Advantages of using parameters:
Easier to code, without worrying about awkward string interpolation.
Slightly better for performance, because the SQL statement is parsed once, instead of repeatedly during each loop iteration.
Safer with respect to application security; good defense against SQL injection.
Re your comment:
An SQL parameter can be used only in place of a single scalar value. Not an expression, or a table name or column name, or a list of values, or SQL keywords. Basically, any value you pass for the parameter value will be treated as though you had put quotes around it (there are some nuances to that, but it gives you the approximate idea).
Given the expression you described, I'd write the code like this:
$store = qq(INSERT INTO main (creator_name, relationship, complicated_column)
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL ? HOUR)));
$st = $dbi->prepare($store);
for (my $i = 0; $i < 3; $i++)
{
$st->execute($data{creatorname}, $data{"relationship$i"}, $interval);
}
Re answer from #harmic:
This is awkward to reply to another answer by adding to my own answer, but I wanted to share a code test that demonstrates the "double-interpolation" does in fact work.
$ cat test.pl
$i = 1;
$data{"key$i"} = "word";
$s = qq(string with parentheses ($data{"key$i"}));
print $s, "\n";
$ perl test.pl
string with parentheses (word)
The output of running this Perl script shows that the interpolation worked.
It's a bit hard on the eyes, but if you always have three rows to enter you could do it all in one execute():
my $sth = $dbh->prepare(<<'__eosql');
INSERT INTO main (time_column, creator_name, relationship)
SELECT NOW() + INTERVAL ? HOUR, -- placeholder for $interval
?, -- $data{creatorname}
relation
FROM (SELECT ? AS relation -- $data{relationship1}
UNION ALL
SELECT ? -- $data{relationship2}
UNION ALL
SELECT ?) d -- $data{relationship3}
__eosql
$sth->execute($interval, #data{qw(creatorname relationship1 relationship2 relationship3)});
That uses a hash slice to pull the values out of %data.

MYSQL Search by arrays

Got a question for you all...
What would be the best way to search my table by array, that has an array in the table.
EG:
$var = (1,4,7,9,14)
$Query = "SELECT * FROM business_listings WHERE category IN ($var)";
'category' would have 4,27,89,101
How can I get this to match if one of the numbers in the $var matches one of the numbers in the table.
If your database column is a list of comma separated values, and you're searching for one value in that list, then you're in a different situation.
If your category column contains the text value 410,406,149,152, like you commented below, and you're searching for fields whose category contains 152, then you'll need to use MySQL's FIND_IN_SET() function.
If you have to check multiple values, then you need to use more than one FIND_IN_SET. If you read the documentation, you'll see that the first argument for FIND_IN_SET must be a single string, not a string list (it can't contain a comma). Use the following instead:
$var = "401,320,152";
$items = explode(",", $var);
foreach ($items as &$i) {
$i = "FIND_IN_SET('" . $i . "', `category`)";
}
$search = implode(" OR ", $items);
unset($i);
$query = "SELECT * FROM business_listings WHERE " . $items;
This will output:
SELECT * FROM business_listings WHERE
FIND_IN_SET('401', `category`) OR
FIND_IN_SET('320', `category`) OR
FIND_IN_SET('152', `category`)
The above script will work even if $var contains only one value.
Finally, as tadman mentioned, since we're getting into queries that can be tricky to build with prepared statements, you need to make sure you're escaping and sanitizing your input properly. For an example, if $var is being retrieved from the user somehow, then before you modify it in any way, you need to escape it with mysqli_real_escape_string():
$var = $mysqli->real_escape_string($var);
Assuming that $mysqli is your open MySQLi connection.
Hope this helps!