inside Moodle core, when sending a query to the database there's a call to preg_match_all looking for : (colon), in order to find query's parameters.
I have a string (inside " ") composed of digits, a colon and a letter ("102516101:t").
Of course it's not impling for a parameter. still the Moodle expects one because of the colon(:).
How can I prevent preg_match_all looking inside a Quotation mark?
or has anyone gut another idea?
According to the comments left above, you should explicity specify the variables used in your SQL statement. In other words you should not be constructing your SQL statement by hand, or the minimum required.
Example:
$sql = "SELECT * FROM {groups} WHERE name = :name";
$params = array('name' => '102516101:t');
$DB->execute($sql, $params);
You'll also note that table names are specified like this: {table_name}, they are automatically expanded with the right prefix.
Related
Newbie here. The following function works fine when $color refers to an entry in the "style" field that is numberic e.g. "5000". But if the entry is "5000B" or letters entirely, it can't find it. Is this an indexing problem?
function get_shirt_colors_by_style($color)
{
db_connect();
$query = "SELECT style,sanmar_mainframe_color,unique_key,color_square_image
FROM sanmar_products WHERE style=$color
GROUP BY style ORDER BY style";
$result = mysql_query($query);
$data = mysql_fetch_array($result);
return $data;
}
It is failing to find alphanumeric comnbinations because the string is not quoted:
$query = "SELECT style,sanmar_mainframe_color,unique_key,color_square_image FROM sanmar_products WHERE style='$color' GROUP BY style ORDER BY style";
//-----------------------------------------------------------------------------------------------------------^^^^^^^^^
Numeric values need not be quoted in a MySQL query, but string values must always be surrounded in single quotes like '5000B'.
We assume the value of $color has already been escaped against SQL injection:
// Hopefully this happened already.
// If not, do it before running mysql_query()
$color = mysql_real_escape_string($color);
Is this an indexing problem?
No its a really bad coding problem.
Non-numeric values should be enclosed in quotes - actually literal values should always be enclosed in quotes when the underlying column type is numeric - otherwise you're likely to run into performance issues. You've also got a problem with managing errors in your code - if a query containing "WHERE style=5000B" is sent to the database it will always return an error - that you have no visibility of this error means that you've got a lot of important functionality missing from your site. Indeed, since content representations whould always be validated / changed at the point where the value leaves PHP, that also implies that your code is probably wide open to SQL injection attacks.
...and then there's the database design issues evident here: 'style' implies a non-unique identifier yet you are returning a single row from your query without any explicit ordering other than on the field you've selected on (i.e. even if it were unique, its very innefficient).
try using single quotes here:
WHERE style='$color'
I need to do this query:
SELECT * FROM brands WHERE brand =`l'artigiano italiano`
Should be quite simple but it's not working.
Like all my queries I try to execute it with the following code
$myDB = Database::getConnection($target='....',$key='....');
$sqlLogo = 'SELECT * FROM brands WHERE brand =`' . $brand->merk . '`';
$resultLogo = $myDB->query($sqlLogo);
When I open the page I get the following error
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'l'artigiano italiano' in 'where clause': SELECT * FROM brands WHERE brand =`l'artigiano italiano`; Array ( ) in merken_admin_settings() (line 23 of /home/mediaspe/domains/mediaspex.be/public_html/juniorsteps/sites/all/modules/merken/merken.admin.inc)
I tried to use
WHERE brand = "..."
and
WHERE brand = `...`
but both did not work.
Any suggestions about the possible cause? I'm staring blind at the code at the moment.
You should escape anything you embed in a SQL query. As you are using PDO, you should do it with $myDB->quote():
$sqlLogo = "SELECT * FROM brands WHERE brand = '" . $myDB->quote($brand->merk) . "'";
You can use both double quotes (") and single quotes (') for enclosing your values, but not back quotes (`).
It is even better to use prepared statements:
$stmt = $myDB->prepare("SELECT * FROM brands WHERE brand = :brand");
$resultLogo = $stmt->execute(array('brand' => $brand->merk));
This way you don't have to take care of escaping.
Have you tried escaping the single quote?
"l\'artigiano italiano"
MySQL String Syntax
While all of the other answers are valid for regular mysql_* functions, if you are using PDO, you should be taking advantage of prepared statements. They were made for just this purpose.
Just escaping the single quote can do the trick but try PDO prepared statements, they help you with security too (as already discussed here)
You can do it like this:
$brand = "l'artigiano italiano";
$stmt = $db->prepare('SELECT * FROM brands WHERE brand = :brand');
$stmt->execute( array(':brand' => $brand) );
It looks like you're using Drupal. If that's so (I assume so from the way you get the database connection and obviously the tag), you should execute your query like this:
$result = db_query('SELECT * FROM {brands} WHERE brand = :brand', array(':brand' => $brand));
That's all. Note:
Use of db_query(), which will call Database::getConnection() internally. You only need to call Database::getConnection() yourself if you want to connect to another than the default connection.
Use uf curly braces ({}) for tables managed by Drupal (which means, tables installed through hook_schema() of your module). If this is an external table not related to the Drupal installation, you won't need those. The curly braces ensure that the proper table name prefix is inserted in case the drupal installation was configured with one (which is for example the case when running tests!)
You can use :placeholder syntax for the dynamic values and directly specify the value in the second argument of db_query() (or $myMD->query(), that's the same interface).
I'm trying to use odbc_prepare and odbc_execute in PHP as follows:
$pstmt=odbc_prepare($odb_con,"select * from configured where param_name='?'");
$res=odbc_execute($pstmt,array('version'));
var_dump($res); //bool(true)
$row = odbc_fetch_array($pstmt);
var_dump($row); //bool(false)
The first var_dump returns true so the execute succeeds, but there is no row returned. A row does indeed exist with the param_name = 'version'. Why is no row returned?
To make things interesting, I ran another very simple example in php using a prepared insert.
$pstmt=odbc_prepare($odb_con,"insert into tmp1 values(?,'?')");
This line, by itself, inserted a row into the database!! Surely this is just wrong? The data entered was col 1 = blank, col 2 = ?
Any advice on where to start fixing this would be appreciated, thanks.
Edit: This is in PHP 5.2.8
Try removing the single quotes from the query string and adding them to the parameter value itself:
$pstmt=odbc_prepare($odb_con,"select * from configured where param_name=?");
$res=odbc_execute($pstmt,array(" 'version'"));
var_dump($res); //bool(true)
$row = odbc_fetch_array($pstmt);
var_dump($row); //bool(false)
The single space character at the beginning of the parameter value is very important--if the space is not there, it will treat the variable as a path to a file.
From http://www.php.net/manual/en/function.odbc-execute.php:
If you wish to store a string which
actually begins and ends with single
quotes, you must add a space or other
non-single-quote character to the
beginning or end of the parameter,
which will prevent the parameter from
being taken as a file name.
when I read this paragraph
Any parameters in parameter_array which start and end with single quotes will be taken as the name of a file to read and send to the database server as the data for the appropriate placeholder.
If you wish to store a string which actually begins and ends with single quotes, you must add a space or other non-single-quote character to the beginning or end of the parameter, which will prevent the parameter from being taken as a file name. If this is not an option, then you must use another mechanism to store the string, such as executing the query directly with odbc_exec()).
It seems to me that it isn't necessary to add single quotes ' to a string, only if you really want to have the quotes as text in the DB
Therefore if I only want to insert the text, without the single quotes I would write something like that ...
see this example from odbc-prepare
http://www.php.net/manual/en/function.odbc-prepare.php
Use this example for IBM DB/2:
$q = "update TABLE set PASS=? where NAME=?";
$res = odbc_prepare ($con, $q);
$a = "secret"; $b="user";
$exc = odbc_execute($res, array($a, $b));
This would result in the following statement
$pstmt=odbc_prepare($odb_con,"select * from configured where param_name=?");
$name = "version";
$params = array($name);
$res=odbc_execute($pstmt,$params);
var_dump($res); //bool(true)
$row = odbc_fetch_array($pstmt);
var_dump($row); //bool(false)
See that I not only removed the qoutes for the value in the params array but also removed the qoutes in the SQL statement.
please give feedback if this was right
You should not enclose variables in quotes in a prepared statement:
$pstmt=odbc_prepare($odb_con,"select * from configured where param_name=?");
$res=odbc_execute($pstmt,array(" 'version'"));
should be:
$pstmt=odbc_prepare($odb_con,"select * from configured where param_name=?");
$res=odbc_execute($pstmt,array("version"));
Question marks represent parameter placeholders, the value passed is meant to represent an unescaped, unenclosed value, which will be properly escaped by the SQL interpreter.
EDIT:
Gah, ignore me, misread php.net
odbc_fetch_array accepts as it's parameter the result of odbc_execute, you seem to be passing in the prepared statement.
What DBMS are you using? The fact that the lone insert prepare statement seems to be executed against the database rather than being prepared points to either a poor implementation of php (unlikely) or the DBMS not supporting prepared sql. If the latter is the case it is possible that their way of supporting the command with out the functionality is just to execute the statement leading to the results you get. If the DBMS does support prepared statements and the php implementation handles it properly there is some kind of issue with the insert being executed which also needs some investigation.
Did you try using double quotes? i.e.
$res=odbc_execute($pstmt,array("version"));
I'm not very experienced with PDO and MySQL query..
Look at this function:
function add($mynick, $friend) {
$dbh = new PDO(DSN,USERNAME,PASSWORD);
$sth = $dbh->prepare('UPDATE pinfo SET friends=concat_ws(',' , friends, $friend) WHERE nick = :mynick');
$sth->bindParam(':mynick', $mynick);
//$sth->bindParam(':friend', $friend);
$sth->execute();
}
This function is not working:
Warning: PDO::prepare() expects parameter 2 to be array, string given in /test5.php
Fatal error: Call to a member function bindParam() on a non-object in /test5.php
I tried to blind also $fliend var, in the concat_ws, or removing all $var and bindParam; the db connection and the db table are ok.
Why is it wrong ?
If I try to use PDO with a simple UPDATE query, without concat_ws it works.
$sth = $dbh->prepare('
UPDATE pinfo
SET friends=concat_ws(',' , friends, $friend)
WHERE nick = :mynick
');
I've reformatted your query to hopefully make the error more obvious.
Don't see it?
Check out the syntax highlighting provided by SO. See how the comma in the SET is black?
The problem is that you're enclosing your SQL statement in single-quotes, but want to use single-quotes inside the query. What's really happening is that you're breaking out of the quoted argument, passing PHP a comma, then opening the quote up again, resulting in two arguments passed to prepare: 'UPDATE pinfo SET friends=concat_ws(' and then ' , friends, $friend) WHERE nick = :mynick'. This is why PHP is whining about the second argument being invalid. You need to either escape the single quotes, or use double quotes to wrap the query.
Therefore you need to:
Use double quotes here, to avoid escaping (backslashes can get overwhelmingly ugly), and
Bind $friend properly rather than let PHP interpolate it, as noted by #Ian Wood, and as your commented out code originally suggested
Thus:
$sth = $dbh->prepare("UPDATE pinfo SET friends=concat_ws(',' , friends, :friend) WHERE nick = :mynick");
$sth->bindParam(':mynick', $mynick);
$sth->bindParam(':friend', $friend);
$sth->execute();
concat_ws(',' , friends, $friend)
think thast should be
concat_ws(',' , friends, :friend)
I would however consider changing your architecture.
Just have a table of people and then a table of friends... Keep the persons details in the people table and in the friends table have two columns 'person_id' and 'friend_id' just store the ids of the connected people - you will end up with much more useful and manageable data.
as many people can have many friends you need a 'many-to-many' relationship there...
This question already has answers here:
How do I create a PDO parameterized query with a LIKE statement?
(9 answers)
Closed 3 years ago.
I am new to PHP, and am trying to learn to use PDO to connect to a test MySQL db. I have the following:
try {
$db = new PDO('mysql:dbname=MYDBNAME;host=MYHOST', 'USERNAME', 'PASSWORD');
$query = "select * from books where ? like '%?%'";
$stmt = $db->prepare($query);
$stmt->execute(array($searchtype, $searchterm));
} catch(PDOException $e) {
echo 'PDOException: ' . $e->getMessage();
}
When I try it I get the following warning:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
When I remove the like clause, and the $searchterm param, it returns the result properly. I thought -- like '%?%' -- might not be a legal way to create this query under double quotes, so I tried escaping ', which did not work. I looked around for a solution, and found that someone moved '% and %' down to where $searchterm is:
$query = "select * from books where ? like ?";
...
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\''));
I got the same result.
Any help is appreciated. Thanks!
/ UPDATE ****/
I found on example 12 of http://us3.php.net/manual/en/pdo.prepared-statements.php
Example #12 Invalid use of placeholder
<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
$stmt->execute(array($_GET['name']));
// Below is What they suggest is the correct way.
// placeholder must be used in the place of the whole value
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->execute(array("%$_GET[name]%"));
?>
I tried this, and even though I no longer get a Warning, I do not get any results. However when I execute the query directly I will get a couple of results. Any thoughts?
Don't add the quotes when binding prepared variables and dont bind the column name
$query = sprintf( "select * from books where %s like ?", $searchtype );
...
$stmt->execute(array($searchtype, '%'.$searchterm.'%'));
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\''));
This isn't how parameterised queries work. Inserted parameters act as literal strings already, you don't have to add quote delimiters around them or escape them (that's the whole point), and if you try, you're literally comparing against the string single-quote-searchterm-single-quote.
Consequently if you are (as I suspect) intending to compare a particular column against a literal string, you don't parameterise the column name. At the moment you are comparing a literal string to another literal string, so it'll either always be true or always false regardless of the data in the row!
So I think what you probably mean is:
$query= "SELECT * FROM books WHERE $searchtype LIKE ?";
$like= "%$searchterm%";
$stmt->execute(array($like));
thought naturally you will have to be very careful that $searchtype is known-good to avoid SQL-injection. Typically you would compare it against a list of acceptable column names before using it.
(Aside: there is a way of putting arbitrary strings in a schema name that you can use for a column, but it's annoying, varies across databases and there isn't a standard escaping function for it. In MySQL, you backslash-escape the backquote character, quotes and backslashes and surround the name with backquotes. In ANSI SQL you use double-quotes with doubled-double-quotes inside. In SQL Server you use square brackets. However in reality you vary rarely need to do any of this because really you only ever want to allow a few predefined column names.)
(Another aside: if you want to be able to allow $searchterm values with literal percents, underlines or backslashes in—so users can search for “100%” without matching any string with 100 in—you have to use an explicit escape character, which is a bit tedious:)
$query= "SELECT * FROM books WHERE $searchtype LIKE ? ESCAPE '+'";
$like= str_replace(array('+', '%', '_'), array('++', '+%', '+_'), $searchterm);
$stmt->execute(array("%$like%"));
The problem I see is if you had written a wrapper for PDO, then you would have to somehow handle this separately. The answer I had found and loved was write your query and concat the % to the parameter. i.e. "WHERE column like concat('%', :something, '%')"