Php mysql statement with set and select - sql

I have a weird problem, when i use the query on phpmyadmin, it works. but when i use using a php script it returns an error.
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in
I tried to troubleshoot and discovered that the problem lies with the set statement.
this is my example code.
$sql = 'set #rank=0; select * from user;';
Please help somebody.

First Run
$sql = set #rank=0;
it will store value of rank
then run:
select * from user;
In sort you need to run both queries separately .
set statement stores values. that can be used by next executing query,
like code below :
$sql ="SET #id:=0";
$Executives=$DB->exec($sql);
$sql = "SELECT #id:=#id+1 as id,pes.* FROM profile_executive_summary as pes where profile_id=".$pid;
$Executives=$DB->fetchAssoc($sql);

See what mysql_error returns after you run mysql_query('...'). That might help. In general, mysql_query only permits one query. You can't separate them by newlines or semicolons. mysqli will do it for you though.

Related

Dynamically change project used in a SQL query

I am using BigQuery, Standard SQL, and I want to dynamically change parts of the FROM clause, such as the project id. I have been looking for a solution for this the last 3 years - the problem has been that parameters cannot be used as inputs in the FROM clause. The benefit would be to create a stored procedure, where the project id can be passed in as an argument and can query the appropriate project. The projects would have the same datasets and table names - this would be our way of building a Master query for easy development and implementation. Instead of changing 15 clients' views, we can change the Stored Procedure once and it will push out the changes to all clients' views. However, I have always gotten hung up on dynamically changing the FROM clause!
For example:
DECLARE ProjectId STRING DEFAULT 'test_project';
SELECT col_1 FROM `#ProjectId.Dataset.Table`;
would always error out due to parameters not being able to be used in the FROM clause. However, I saw a related post on using dynamic SQL to overcome this obstacle. I've been looking into the EXECUTE IMMEDIATE function within BigQuery, as this is what has been cited to be a solution. From that post I attempted to implement in several ways:
Attempt #1:
DECLARE ProjectId STRING DEFAULT 'test_project';
EXECUTE IMMEDIATE CONCAT(
"SELECT * FROM ", #ProjectId, ".DataSet.`Table` " )
^ This gives an error "Query error: Undeclared query parameters at [2:19]"
Attempt #2:
EXECUTE IMMEDIATE CONCAT(
"SELECT * FROM ", #ProjectId, ".DataSet.`Table` " )
USING 'my-project' as ProjectId, 'my-dataset' as DataSet;
^ which gives the error "Query error: Undeclared query parameters at [1:19]"
Third and final attempt was to try declaring the parameter within the EXECUTE IMMEDIATE:
EXECUTE IMMEDIATE CONCAT(
"DECLARE ProjectId STRING DEFAULT 'test_project'; ",
"SELECT * FROM ", #ProjectId, ".DataSet.`Table` " )
USING 'my-project' as ProjectId, 'my-dataset' as DataSet;
^ which, you guessed it, results in the same error "Query error: Undeclared query parameters at [1:19]"
I am reaching out to see if anybody has had success with this? I see the value in the Dynamic SQL statements, and have read the documentation and some examples, but it still doesn't seem to work when trying to dynamically change the FROM clause. Any help is much appreciated, willing to try whatever is thrown out - excited to learn what can be done!
Just remove #:
DECLARE ProjectId STRING DEFAULT 'test_project';
EXECUTE IMMEDIATE CONCAT(
"SELECT * FROM ", ProjectId, ".DataSet.`Table` " )

SQL select query not working with variable parameter in my servelets

i'm trying to execute following line of code with my servelet in netbeans:
ResultSet rs = stmnt.executeQuery("select * from ZEE.WORDCOUNT where WORD =" + searchTxt);
where searchTxt is String variable.
but it says "Column 'zeeshan' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join . . . . ".
it really works fine, if i provide the hardcoded value instead of variable, as:
ResultSet rs = stmnt.executeQuery("select * from ZEE.WORDCOUNT where WORD= 'zeeshan'");
i'm not getting, what i'm missing?
You are missing the single quotes around the sql string you are constructing. So this should work:
ResultSet rs = stmnt.executeQuery("select * from ZEE.WORDCOUNT where WORD ='" + searchTxt+"'");
Please note that constructing SQL statements in this way is really dangerous, because it opens your application up for SQL injection attacks. Use bind parameters instead.
This will also allow better caching of parsed statements on many rdbms's.

Wildcard, '%', within ColdFusion cfscript query LIKE statement?

Is it possible to use a wildcard in a SQL LIKE statement within a ColdFusion cfscript query?
An example that doesn't work:
local.q = new Query();
local.q.setDatasource(variables.dsn);
local.q.addParam(name='lastname', value='%' & arguments.lastname, cfsqltype="cf_sql_varchar");
local.qString = 'SELECT name FROM users WHERE lastname LIKE :lastname';
local.q.setSQL(local.qString);
local.result = local.q.execute().getResult();
I also tried these, which didn't work:
local.qString = 'SELECT name FROM users WHERE lastname LIKE %:lastname';
local.qString = "SELECT name FROM users WHERE lastname LIKE '%:lastname'";
UPDATE:
I am using MS SQL Server 2008.
The query works fine within SQL Server Mgmt Studio... I think it has something to do with how to format the query within cfscript tags?
Yes, it is possible. You're setting it in the param, which is correct. I'm not sure why it's not working with you.
I did the following and it worked.
var qryArgsCol = {};
qryArgsCol.datasource = variables.datasource;
qryArgsCol.SQL = "
SELECT ID
FROM Users
WHERE LastName LIKE :searchStringParam
";
var qryGetID = new query(argumentCollection=qryArgsCol);
qryGetID.addParam(name="searchStringParam", value="%" & searchString, cfsqltype="cf_sql_varchar");
qryGetIDResult = qryGetID.execute().getResult();
There's a response here from Adam Cameron, which was apparently deleted by an overzealous mod.
Rather than repeat what he says, I've just copied and pasted (with emphasis added to the key parts):
Just to clarify that the syntax you tried in your first example does work. That is the correct approach here. To clarify / explain:
The <cfquery> version of the example you have would be along the lines of:
<cfqueryparam value="%foo">
So in the function version, the param would be ? or :paramName and the value of the param would continue to be "%foo".
The % is part of the param value, not the SQL string.
So given that "doesn't work" for you, it would help if you posted the error, or whatever it is that causes you to think it's not working (what your expectation is, and what the actual results are). Then we can deal with the actual cause of your problem, which is not what you think it is, I think.
Does the query work fine as a <cfquery>?
Depending on the dbms used, that single and double quotes may be interpreted when the sql statement is run. What dbms are you using? Your statement now doesn't select for the value in the variable, but for any user whose lastname is "lastname". It should be something like:
lastname like '%#lastname#'
Just remember that you ultimately need to see what CF gives the DB server. In this instance, you can try this mockup to get close and find the same error in SSMS by messing with the quotes/value in the param declaration:
declare #param1 varchar(max) = '%Eisenlohr';
SELECT name FROM users WHERE lastname LIKE #param1
I just ran into the same problem as the original poster where it "wasn't working" and I didn't get any results from the query of queries.
The problem for me is that the wildcard search is case-sensitive.
local.q = new Query();
local.q.setDatasource(variables.dsn);
local.q.addParam(name='lastname', value='%' & LCase(arguments.lastname), cfsqltype="cf_sql_varchar");
local.qString = 'SELECT name FROM users WHERE LOWER(lastname) LIKE :lastname';
local.q.setSQL(local.qString);
local.result = local.q.execute().getResult();
So what I did was made sure the incoming argument was lower case and made sure the comparing field in the SQL was lower case as well and it worked.
Use like this.
local.q = new Query();
local.q.setDatasource(variables.dsn);
local.q.addParam(name="lastname", cfsqltype="cf_sql_varchar",value='%ARGUMENTS.lastname' );
local.qString = 'SELECT name FROM users WHERE lastname LIKE :lastname';
local.q.setSQL(local.qString);
local.result = local.q.execute().getResult();
I would suggest using the CFQuery tag instead of attempting to run queries within CFScript. Unless you REALLY know what you are doing. I say this because the CFQuery tag has some built-in functionality that not only makes building queries easier for you but may also protect you from unforeseen attacks (the SQL injection type). For example, when using CFQuery it will automatically escape single-quotes for you so that inserting things like 'well isn't that a mess' will not blow up on you. You also have the benefit of being able to use the CFQueryParam tag to further battle against SQL injection attacks. While you may be able to use the CFQueryParam functionality within CFScript it is not as straight forward (at least not for me).
See this blog post from Ben Nadel talking about some of this.
So in CFQuery tags your query would look something like this:
<cfquery name="myQuery" datasource="#variables.dsn#">
SELECT name
FROM users
WHERE lastname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%:#arguments.lastname#" maxlength="256" />
</cfquery>

SQL Injection: is this secure?

I have this site with the following parameters:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc
I use the values of each of the parameters as a value in a SQL query.
I am trying to test my application and ultimately hack my own application for learning purposes.
I'm trying to inject this statement:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc' or 1=1 --
But It fails, and MySQL says this:
Warning: mysql_fetch_assoc() expects parameter 1 to be resource,
boolean given in /home/dir/public_html/pagination.php on line 132
Is my application completely free from SQL injection, or is it still possible?
EDIT: Is it possible for me to find a valid sql injection statement to input into one of the parameters of the URL?
The application secured from sql injection never produces invalid queries.
So obviously you still have some issues.
Well-written application for any input produces valid and expected output.
That's completely vulnerable, and the fact that you can cause a syntax error proves it.
There is no function to escape column names or order by directions. Those functions do not exist because it is bad style to expose the DB logic directly in the URL, because it makes the URLs dependent on changes to your database logic.
I'd suggest something like an array mapping the "order" parameter values to column names:
$order_cols = array(
'time' => 'comment_time',
'popular' => 'comment_score',
... and so on ...
);
if (!isset($order_cols[$_GET['order'])) {
$_GET['order'] = 'time';
}
$order = $order_cols[$_GET['order']];
Restrict "sc" manually:
if ($_GET['sc'] == 'asc' || $_GET['sc'] == 'desc') {
$order .= ' ' . $_GET['sc'];
} else {
$order .= ' desc';
}
Then you're guaranteed safe to append that to the query, and the URL is not tied to the DB implementation.
I'm not 100% certain, but I'd say it still seems vulnerable to me -- the fact that it's accepting the single-quote (') as a delimiter and then generating an error off the subsequent injected code says to me that it's passing things it shouldn't on to MySQL.
Any data that could possibly be taken from somewhere other than your application itself should go through mysql_real_escape_string() first. This way the whole ' or 1=1 part gets passed as a value to MySQL... unless you're passing "sc" straight through for the sort order, such as
$sql = "SELECT * FROM foo WHERE page='{$_REQUEST['page']}' ORDER BY data {$_REQUEST['sc']}";
... which you also shouldn't be doing. Try something along these lines:
$page = mysql_real_escape_string($_REQUEST['page']);
if ($_REQUEST['sc'] == "desc")
$sortorder = "DESC";
else
$sortorder = "ASC";
$sql = "SELECT * FROM foo WHERE page='{$page}' ORDER BY data {$sortorder}";
I still couldn't say it's TOTALLY injection-proof, but it's definitely more robust.
I am assuming that your generated query does something like
select <some number of fields>
from <some table>
where sc=desc
order by comment_time
Now, if I were to attack the order by statement instead of the WHERE, I might be able to get some results... Imagine I added the following
comment_time; select top 5 * from sysobjects
the query being returned to your front end would be the top 5 rows from sysobjects, rather than the query you try to generated (depending a lot on the front end)...
It really depends on how PHP validates those arguments. If MySQL is giving you a warning, it means that a hacker already passes through your first line of defence, which is your PHP script.
Use if(!preg_match('/^regex_pattern$/', $your_input)) to filter all your inputs before passing them to MySQL.

Updating email addresses in MySQL (regexp?)

Is there a way to update every email address in MySQL with regexp? What I want to do is to change something#domain.xx addresses to something#domain.yy. Is it possible to do with SQL or should I do it with PHP for example?
Thanks!
You can search for a REGEXP with MySQL, but, unfortunately, it cannot return the matched part.
It's possible to do it with SQL as follows:
UPDATE mytable
SET email = REPLACE(email, '#domain.xx', '#domain.yy')
WHERE email REGEXP '#domain.xx$'
You can omit the WHERE clause, but it could lead to unexpected results (like #example.xxx.com will be replaced with #example.yyx.com), so it's better to leave it.
UPDATE tableName
SET email = CONCAT(SUBSTRING(email, 1, locate('#',email)), 'domain.yy')
WHERE email REGEXP '#domain.xx$';
I would rather do it with PHP, if possible. Mysql unfortunately does not allow capturing matching parts in regular expressions. Or even better: you can combine the two like this, for example:
$emails = fetchAllDistinctEmailsIntoAnArray();
# Make the array int-indexed:
$emails = array_values($emails);
# convert the mails
$replacedEmails = preg_replace('/xx$/', 'yy', $emails);
# create a new query
$cases = array();
foreach ($emails as $key => $email) {
# Don't forget to use mysql_escape_string or similar!
$cases[] = "WHEN '" . escapeValue($email) .
"' THEN '" . escappeValue(replacedEmails[$key]) . "'";
}
issueQuery(
"UPDATE `YourTable`
SET `emailColumn` =
CASE `emailColumn`" .
implode(',', $cases) .
" END CASE");
Note that this solution will take quite some time and you may run out of memory or hit execution limits if you have many entries in your database. You might want to look into ignore_user_abort() and ini_set() for changing the memory limit for this script.
Disclaimer: Script not tested! Do not use without understanding/testing the code (might mess up your db).
Didn't check it, since don't have mysql installed, but seems it could help you
update table_name
set table_name.email = substr(table_name.email, 0, position("#" in table_name.email) + 1)
+ "new_domain";
PS. Regexp won't help you for update, since it only can help you to locate specific entrance of substring in string ot check whenever string is matches the pattern. Here you can find reference to relevant functions.