I need to search a string in mysql with php. I get an error related to the spaces in the string. I an not fimilar with regex, I am not sure it that is my only choice.
example:
$ex="This and That";
$sql = 'SELECT
some_ID
FROM ' . atable. ' WHERE ' . strings. ' LIKE ' . $ex. ' AND visable=' . '1';
after executing I get an error like:
"near 'That AND visable=1' at line x"
so its probably not picking up the first two words, any suggestions?
Thanks in advance.
You are missing quotes around the string. They need to be encapsulated entirely for the query to execute properly.
Change this:
LIKE ' . $ex. ' AND
To this:
LIKE "' . $ex. '" AND
On a side note, make sure you are protecting your self against SQL injections AND make sure your query is properly escaped.
Related
We use doctrine 2 and want to write parameterised code like this:
attributes #> \'{' . $con->quote($attrId) . ':' . (int)$value . '}\'';
to have a query like this:
WHERE attributes #>'{"color":14}';
The "color" is the custom (user chosen) name of an attribute. So I feel that quote() is an appropriate function to shield it. But it wraps a parameter with single quotes, what makes the request syntax incorrect.
quoteIdentifier() function wraps with double quotes, BUT I'm not sure if it's right to use it in this context.
How to build a safe code to get the request I need?
Here is a way to do it with json_build_object and pg_exec_params:
<?php
$dbconn = pg_connect('');
$data = 'some"th\'ing';
pg_query_params($dbconn, 'SELECT json_build_object($1::text, $2::integer)', [$data, 14]);
?>
You need the explicit type casts so that PostgreSQL knows whether the argument is a string or a number.
You can include the double quotes in the string.
$attr = '{"' . $attrId . '":' . (int) $value . '}';
Don't depend on quoting to keep you safe, but instead execute the query with a method that binds the value to a prepared statement.
$statement = $con->executeQuery('SELECT * FROM your_table WHERE attributes #> ?', [$attr]);
I have a PHP program that will either INSERT a new row, or UPDATE the existing one if it's already there. When running on a browser, it returns errors.
But, the actual call runs OK on phpMySQL - no error reported and row is updated.
"Errormessage: 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 '"updated", `conditions` =" ",' at line 1.
Code to connect to mySQL and make the update or insert is very simple
require_once ('mysqli_connect.php');
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error($dbcon);
exit ;
}
Then I make the actual body of the call, which produces variable $call containing this (example is for UPDATE):
UPDATE `deal` SET `deal_lotus_source` = "updated", `conditions` =" ", `termsnotes` = " ", `walkprovision` = " ", `sector` = "Application Software", `industry` = "Airconditioning", `tgt` = "Bcd", `acq` = "E", `dtstart` = "2015/03/08" , `dtclose` = "2015/03/23", `dtexdivtgt` = "2015/03/17", `dtexdivacq` = "2015/03/17", `dtexdivtgtexp` = "2015/03/17", `dtexdivacqexp` = "2015/03/17", `acq` = "E",`stat`= "Closed",`acqtype`= "Domestic",`dealtype`= "Acquisition of Private Company Cash-Stoc",`analyst`= "Fred Blogs",`tgttkr`= "ABC",`tgtx`= "C",`tgtprec`= "$",`tgtpret`= "1",`tgtshrout`= "2",`acqtkr`= "D",`acqx`= "F",`acqprec`= "$",`acqpret`= "3",`acqshrsout`= "4",`dlvalue`= "5",`eacls`= "Actual",`tgtlaw`= "",`acqlaw`= "",`tgtbank`= "",`acqbank`= "",`tgtshrsoutfd`= "6",`acqshrsoutfd`= "7",`tgtdebt`= "8",`acqdebt`= "8",`suppress`= "0",`pricingp`= "",`terminate`= " ",`divstattgt`= "",`divstatacq`= "",`divfreqtgt`= "Quarterly",`divfreqacq`= "Quarterly",`divcurrtgt`= "$",`divcurracq`= "$",`divamttgt`= "0.000",`divamtacq`= "0.000", `cos` = "", `mot` = "" WHERE deal_id =578
and the code to update (or insert) is
if (!mysqli_query($dbcon, $call)) {
printf("Errormessage: %s\n", mysqli_error($dbcon));
die;
}
Any ideas?
You have to use single quotes arround the values:
UPDATE `deal` SET `deal_lotus_source` = 'updated', `conditions` =' ', `termsnotes` = ' ', `walkprovision` = ' ', `sector` = 'Application Software', ...
Quotes in PHP can be confusing, because depending on which type of quote you use there are (different rules](http://www.trans4mind.com/personal_development/phpTutorial/quotes.htm). The most important things (in this case) to keep in mind are these 2:
* If you have a variable ($var) inside double-quotes ("$var") then it will get substituted (your string will now contain value) whereas if it is in single-quotes ('$var') then it will NOT get substituted (it remains in your string as $var)
* If you are need single-quotes as part of your string then use double-quotes around the string. ("I don't like contractions and I can't bear to use them.") If you need double-quotes as part of your string then use single quotes to surround the string. ('He said, "Hello, Dear!" and she slapped him.')
You are using double quotes (note the values you want to compare conditions and termsnotes and etc. to) but you are going to want to change to single-quotes inside the string so you can surround the whole thing with double-quotes. This also has the advantage of allowing you to use variables inside it.
$call = "UPDATE `deal`
SET `deal_lotus_source` = 'updated',
`conditions` =' ',
`termsnotes` = ' ',
`walkprovision` = ' ',
...
`mot` = ''
WHERE deal_id =578";
Note that the only double-quotes in that whole line of code are the ones at the very beginning and ending of the string. If you want to put a double-quote inside the string then you would have to put a backslash in front of it.
One very important step when you are constructing a query in a string (especially if you are getting errors with it) is to actually look at it. Use echo "call=<pre>$call</pre><br />\n"; and then look very carefully at all your quotes and etc. You can actually copy/paste the results of this echo into phpMyAdmin and see if the actual query works in your sql tab - this is a great test.
In summary, quotes in PHP are very consistent and very powerful, but they do have the potential to change your string during the process of assigning the string to a variable. It's very important to verify that the string after assignment is the string that you expect.
how to search a string in a row in php? I wrote this code:
$filterQuery .=' LIKE %' . $db->Quote(JString::strtolower($filter) . '%');
it works in mysql to search string with: LIKE '%stringtosearch%'
why it doesn't work in php?
As already noted, you forget the quotes around the %...% part. BUT, MySQL is not case sensitive by default so you can probably remove the JString call unless you've specifically configured your MySQL server to be case-sensitive. The alternative usage could then be simplified to:
$filterQuery .=' LIKE ' . $db->quote('%' . $filter . '%');
Note, however, that if you are using user input, SQL wildcards could result in a DOS attack (the user could include addition % and _ characters in the filter string). To prevent this, you'd use a format like:
$filterQuery .=' LIKE ' . $db->quote('%' . $db->escape($filter, true) . '%');
and that will escape the filter itself (and allow you to search for real underscores or % characters). This is how the core code handles this case as shown here:
https://github.com/joomla/joomla-cms/blob/staging/administrator/components/com_content/models/articles.php#L285
Note: #Andrew Eddie gives a better answer above
$filterQuery .=' LIKE ' . $db->quote('%'. JString::strtolower($filter) . '%');
Because your bracketed code adds in quotes around your string, do this instead...
$filterQuery .=" LIKE '%" . strtolower($filter) . "%'");
Remember you will need to sanitise/escape your data before querying the database
if it works like LIKE '%stringtosearch%' then add ''s before and after %'s like so
$filterQuery .= " LIKE '%" . $db->Quote(JString::strtolower($filter) . "%' ");
^ ^
I generally understand the idea behind escaping quotes using backslashes and alternatively using backslashes to escape so that you can have backslashes in your strings and so forth, but I've run in to a problem trying to pass a query through odbc_exec() and using a table-valued function and I just cannot seem to get it to stop giving me
SQL error: [Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark after the character string '0000005'.
This is what it looks like when I hard code the variables:
$query = 'SELECT '.$csvCriteria.", googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('1','1','northbound','0006009','00000050370A2P000004','00060041270B2P000070','1')";
This works fine. Note that $csvCriteria hasn't given me any problems. This is what I want it to look like:
$query = 'SELECT '.$csvCriteria.", googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('".$stepNum."', '".$segMarker."', '".$prevDirection."', '".$rdNoA."', '".$re_1."', '".$re_2."', '".$directionA."')";
However I keep getting errors around $re_1 and $re_2 (the error I've put in at the top of this).
I've tried multiple variations of what I think may work, such as:
$query = 'SELECT '.$csvCriteria.", googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('".$stepNum."','".$segMarker."','".$prevDirection."','".$rdNoA.'\',\''.$re_1.'\',\'00060091100B1P000030\',\'1\')';
But I am neither expertly proficient at this, nor do I know if I'm missing something blatantly obvious. Just absolutely stuck and need a hand!
I can not reproduce your error:
The SQL in question is:
SELECT csvcriteria,
googstep,
segment,
prevailingdirection
FROM jselectorcsvcreator('1', '1', 'northbound', '0006009',
'00000050370A2P000004', '00060041270B2P000070', '1');
Placing the data in variables such as:
$csvCriteria = 'csvCriteria';
$stepNum = 1;
$segMarker = 1;
$prevDirection = 'northbound';
$rdNoA = '0006009';
$re_1 = '00000050370A2P000004';
$re_2 = '00060041270B2P000070';
$directionA = 1;
Using the first line of code, which works and using the one that doesn't work both return the exact same thing:
$correct = 'SELECT ' . $csvCriteria . ", googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('1','1','northbound','0006009','00000050370A2P000004','00060041270B2P000070','1')";
$query = 'SELECT ' . $csvCriteria . ", googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('" . $stepNum . "','" . $segMarker . "','" . $prevDirection . "','" . $rdNoA . "','" . $re_1 . "','" . $re_2 . "','" . $directionA . "')";
echo $correct . "\n";
echo $query . "\n";
var_dump($correct === $query);
The response is (CodePad):
SELECT csvCriteria, googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('1','1','northbound','0006009','00000050370A2P000004','00060041270B2P000070','1')
SELECT csvCriteria, googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('1','1','northbound','0006009','00000050370A2P000004','00060041270B2P000070','1')
bool(true)
My guess is that $csvCriteria or any of the variables at hand have errors.
I would highly recommend looking at the echoed query of $query in an SQL Formatter (Select MS ACCESS)
$query = 'SELECT '.$csvCriteria.", .....
should be
$query = 'SELECT '.$csvCriteria.', ......
Try using
$query = "SELECT $csvCriteria, googStep, Segment, PrevailingDirection FROM jSelectorCSVCreator('$stepNum','$segMarker','$prevDirection','$rdNoA','$re_1','00060091100B1P000030','1')";
This is much simpler without need of all the escapes.
As it turns out I was attempting to pass a string that looked like this "0000000\000X00X0\0000000" and it wasn't working so well. I decided to use stripslashes() so I could pass the variable more easily and work with it once it was in SQL. Turns out stripslashes() doesn't work like that. I used str_replace() instead and it now works fine.
I got sick of writing queries in my PHP as:
"WHERE '" . Database::escape($var) . "'";
The escape() function just calls mysql_real_escape_string() - but it's there so I can extend support to other databases later.
Having to single quote strings in the query was making my code more cluttered. So my idea was to create an other function in my database class to 'prepare' a variable for a query:
static public function prepare($var)
{
if (is_object($var) || is_array($var) ) {
return " '" . Database::escape(serialize($var)) . "' ";
} else if (is_bool($var)) {
return ' ' . (int)$var . ' ';
} else if (is_int($var)) {
return ' ' . $var . ' ';
} else if (is_string($var) || is_float($var)) {
return " '" . Database::escape($var) . "' ";
} else {
throw new Exception('Unsupported variable type [' . gettype($var) . ']');
}
}
Now the benefit here is that, I don't need to worry about which variables I pass to a query. However it raises two questions:
Am I handling each variable type properly?
For what reason (if any) should I not do this?
Yes, just use parameterised queries and it will Just Work. That is the right solution, and it's not terribly tricky.
In PHP, use PDO to do this, its API is much more sane than mysql_ or mysqli_ and moreover, it can throw exceptions on errors and do other nice things.
You probably shouldn't be doing this. Here's why: mysqli::prepare or PDO::prepare
As for your function itself, what happens if you have something stored in a string (say "5") that you want to store as an int? It'll still quote it anyway.
You are looking for a) pepared statements and b) a database abstraction layer (like PDO).
What you are trying to do on your own has been solved already, you should not roll your own implementation.
If you go down that road you'll notice that this:
"... WHERE '" . Database::escape($var) . "'"
is pointless and dangerous. A clear separation of SQL code and parameters requires you to be more explicit and gets you on the safe side against SQL injection the same time:
"--- WHERE SomeField = ?" /* the parameter (?) will be filled elsewhere */
It's worth noting that true vendor-independence in the database field is somewhere between hard and impossible, depending on your needs and priorities. So trying to write portable SQL could turn out as an exercise in futility unless you are willing to sacrifice a lot. For MySQL it starts even with the LIMIT clause, which you will find impossible to port to, say, SQL Server.
You can try
$sql = "SELECT * FROM SomeTable WHERE userid = '{Database::prepare($userid}'";
to alleviate the typing issues. Though my suggestion is that if you are accepting inputs from a form, why not setup Database::prepare() to run through the $_REQUEST or $_POST to clean them up, or spit out a copy?
This is how I do it:
$safe_post = InputCleaner::clean($_POST);
$sql = "SELECT * FROM table WHERE userid = {$safe_post['userid']}";