Passing an operator as a parameter to odbc_execute() - php

I am taking my first tentative steps into prepared statements (and falling flat on my face).
Previously, I built the following from $_GET and echoed it back - the code was working fine and it returned what I expected from my simple test database.
SELECT * FROM edit_box WHERE (tag="9") AND (text="mango") ORDER BY time_stamp DESC
and when I try to code it using a prepared statement, even if I don't use $_GET but just hard-code the values from the previous, my code looks like this
$odbc_query = OdbcPrepare('SELECT * FROM edit_box WHERE (tag="?")' .
' AND (text ? "?") ORDER BY time_stamp DESC');
$odbcResult = odbc_exec($odbc_query, array('9', '=', 'mango'));
var_dump($odbcResult);
I get NULL.
Obviously a beginner mistake, but I stare at it and still don't say d'oh!
What am I doing wrong?

You cannot do this --
AND (text ? "?")
Parameters, like this, can usually only be passed for actual values - and in some cases identifiers...
To do what you want you need to interpolate the '=' inline into the SQL statement...
Kind of, like this --
$logical_operator = '=';
$sql = SELECT * FROM edit_box WHERE (tag=\"?\") AND (text $logical_operator \"?\") ORDER BY time_stamp DESC');
$odbc_query = OdbcPrepare($sql);
$odbcResult = odbc_exec($odbc_query, array('9', 'mango'));

Related

% (joker) does not work in my sql query with IN operator

I am reading out a database table, and excluding some rows with given values in a column.
But i cant get the query to get the right number for me. I suspect it still counts the kampanje_xxxxx rows. I use % to exclude.
$sql =
"SELECT *
FROM salg
WHERE
fnr='$fnr'
AND kategori NOT IN ('tilbehor', 'servicekontrakt', '%kampanje%')
AND dato BETWEEN '$fdato' AND '$tdato'"
;
$kjor = mysqli_query($connect, $sql);
$faste .= mysqli_num_rows($kjor). ", ";
The IN comparison operator takes list of values, it does not recognizes wildcards such as %. So your assumption that it still counts the kampanje_xxxxx rows is correct, since MySQL is actually searching for a litteral '%kampanje%' value.
You would need to create a separate LIKE condition to check the column againts the value that contains the wildcard. I believe that your query can be expressed as follows :
SELECT *
FROM salg
WHERE
fnr='$fnr'
AND kategori NOT IN ('tilbehor', 'servicekontrakt')
AND kategori NOT LIKE '%kampanje%'
AND dato BETWEEN '$fdato' AND '$tdato'
you should use OR not like and avoid wild char in IN set of values
"SELECT *
FROM salg
WHERE fnr='$fnr'
AND ( kategori NOT IN ('tilbehor', 'servicekontrakt')
OR NOT LIKE concat('%','kampanje','%') )
AND dato BETWEEN '$fdato' AND '$tdato'";
anyway you should avoid the use of php var in sql .. you are at risk for sqliject .. try take a look at ypour db driver for prepared statements and binding param
for see error eventually try show the exact erro message using
if (!$kjor) {
printf("Errormessage: %s\n", $connect->error);
}

Searching through JSON data in MySQL in PHP

The last time I have posted a question about searching JSON data using PHP. After testing the script I wanted to try something else. Using MySQL to search through the data. Since it is faster than looping everything using a PHP script.
I was writing the script in PhpMyAdmin and that has generated the next PHP script for me. But somewhere there is a bug (sad)
"SELECT *
FROM `bigtree_pages`
WHERE `resources` like \'%\"XNCatDesc\": \"%?%\' and `resources` like \'%\"Brand\": \"%?%\' and `resources` like \'%\"ItemDesc\": \"%?%\'"
I want to give three values. The Categorie, the brand, and the ItemDesc (the name). But this throws an error.
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near '\'%"XNCatDesc": "%'41'%\' and resources like \'%"Brand":
"%'none'%\' and `reso'
To be honest, I don't really know where I have to put my % sign.
For example. I have this in my JSON "Brand": "Bullet",
The value needs to be Brand (since we are searching on the Brand) and the brand is Bullet. What is the best way to write this query?
To use a parameter inside a LIKE expression in a prepared query, you need to form the entire expression and use that as the parameter. Otherwise you run into issues as you have with the insertion of quotes into your value. If you are using mysqli, try something like this (assuming your connection is called $conn and the values you want to search for are called $categorie, $brand and $itemdesc):
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE `resources` like ? and `resources` like ? and `resources` like ?");
$search_categorie = "%\"XNCatDesc\": \"%$categorie%\"";
$search_brand = "%\"Brand\": \"%$brand%\"";
$search_itemdesc = "%\"ItemDesc\": \"%$itemdesc%\"";
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();
However the problem you will run into is that because of the % surrounding the search values (e.g. $brand) in the query, when searching for brand = X you could match for example
"Brand": "Y", "Other Value": "contains an X"
So instead you should use regular expressions e.g.
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE `resources` rlike ? AND `resources` rlike ? AND `resources` rlike ?");
$search_categorie = '"XNCatDesc":[[:space:]]+"[^"]*' . $categorie;
$search_brand = '"Brand":[[:space:]]+"[^"]*' . $brand;
$search_itemdesc = '"ItemDesc":[[:space:]]+"[^"]*' . $itemdesc;
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();
If you are running MySQL 5.7 or later, this is better done using the inbuilt JSON_EXTRACT function:
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE JSON_EXTRACT(`resources`, '$.XNCatDesc') LIKE ? and
JSON_EXTRACT(`resources`, '$.Brand') LIKE ? and
JSON_EXTRACT(`resources`, '$.ItemDesc') LIKE ?");
$search_categorie = "%$categorie%";
$search_brand = "%$brand%";
$search_itemdesc = "%$itemdesc%";
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();

PDO adds the apostrophe to the mySQL query

After years of reading it's time to ask first question :)
My problem is that after migrating the code from mySQLi to PDO we have got a problem as it seems PDO adds the apostrophes to the query.
PHP code goes like that:
$sort = $_GET['sort']; << table column name (mySQL VARCHAR only columns)
....
$query = 'SELECT * FROM table WHERE xxx > 0';
$query .= ' ORDER BY :sort ASC ;';
$qry_result= $db->prepare($query);
$qry_result->execute(array(':sort'=>$sort));
mysqli version went smoothly but now queries (mysql log file) looks like this:
SELECT * FROM table where xxx > 0 ORDER BY 'SORT_VAR_VALUE' ASC;
^ 2 problems ^
So the table is NOT sorted, as sort order (from mySQL point of view) is wrong.
phpinfo() does not get any results for search on "magic" nor "quotes" btw.
Any idea ??
The placeholders in PDO statements are for values only. If you want to add actual SQL to the query you need to do it another way.
First, you should sanitize $sort and surround it with backticks in the query.
$sort = preg_replace('/^[a-zA-Z0-9_]/', '', $sort);
Then you could double quote the query string and PHP will replace $sort with it's value for you:
$query = "SELECT * FROM table WHERE xxx > 0 ORDER BY `$sort` ASC";
Or you could replace it with preg_replace like so:
$query = 'SELECT * FROM table WHERE xxx > 0 ORDER BY `:sort` ASC';
$query = preg_replace('/:sort/', $sort, $query, 1);
I would use the preg_replace method because it allows you to reuse the query if you assign the results from preg_replace to another variable instead of overwriting the original variable.
by default pdo binds values as strings.
To fix this you will want to check that the column is actually a valid name and then add it to the query, you can do it the following way:
function validName($string){
return !preg_match("/[^a-zA-Z0-9\$_\.]/i", $string);
}
if(validName($sort)){
$db->prepare("SELECT * FROM table where xxx > 0 ORDER BY $sort ASC");
}
With PDO it's not possible to bind other things that variables in the WHERE statement. So you have to hard code the names of the columns you order by.
See How do I set ORDER BY params using prepared PDO statement?
or Can PHP PDO Statements accept the table or column name as parameter? for further explanations.

passing variable with multiple values seperated by comma to sql statement through PHP

I've looked all over the interwebs, and cannot find that simple answer I'm looking for - possibly because it doesn't exist, but.. possibly because I don't know the correct terms to search for.
ok, so, i've got a variable - it's actaully a key value pair in an array that i'm passing into my function. the key is args[comments_mentioned] and the value is dynamically generated for me - it's ALWAYS going to be number, separated by commas (i.e. 1,2,3,4,5)
so, just to be super clear:
$args[comments_mentioned] == "1,2,3,4"; //could be any amount of number, not just 1,2,3,4,5
i'd like to pass this into a sql statement as a variable to use in an "IN" clause, like so:
$sr_sql = <<<SQL
SELECT *
FROM $wpdb->commentmeta
WHERE meta_value = %s
AND comment_ID in ($args[comments_mentioned])
ORDER BY meta_id DESC
SQL;
Then, Prepare it using the wordpress prepare and get results
$sr_query = $wpdb->prepare( $sr_sql, $args[user_id]) );
//receive the correct sql statement, and plug 'er in.
$sr_comment_rows = $wpdb->get_results($sr_query);
and run my foreach loop:
foreach ($sr_comment_rows as $sr_comment) {
$sResults .= 'do something with $sr_comment';
}
now, i realize the code above won't work - i can't just pass the variable in there like that. BUT, i can't pass it as a string (%s), because it wraps it in '1,2,3,45', and so it looks for the entire string, and not each number. I can't pass it as an int (%d), because of the commas...
In other posts, they mentioned create a temp table or variable, but, i'm not sure if that's the correct way to do it in mysql, or how to reference it once I do.
so, how do I do this? preference for actual code that works ;)
Thank you for reading and helping out!
One option, if you cannot normalize your data, is to enclose your string in commas such that it be ",1,2,3,4," and then you could do:
AND LOCATE( CONCAT(',',comment_ID,',') , ($args[comments_mentioned]) )
which will match if it finds a eg. ',3,' in ',1,2,3,4,' (Using 3 as an example)
I believe this should be enough:
$params = $args[comments_mentioned];
$table = $wpdb->commentmeta;
$sr_sql = "
SELECT *
FROM $table
WHERE meta_value = %s
AND comment_ID in ($params)
ORDER BY meta_id DESC
";
It will be result something like:
SELECT *
FROM table_on_variable
WHERE meta_value = %s
AND comment_ID in (1,2,3,4)
ORDER BY meta_id DESC
If your mainly issue is regarding the in clause, so you will not have problems if you use double quotes and single variable as illustrated above.

Building stored procedures with if/else statements?

I'm trying to convert regular query building to stored procedures. I do not know the best way to go about this, with "building" a query. Not sure how to explain, so i will give an example. My example is in PHP, but the concept is the same in any language.. example should be simple enough.
if($somevar){
$w .= " AND SomeVar = '$somevar' ";
}
if($anothervar){
$w .= " AND AnotherVar = '$anothervar' ";
}
$sql = "SELECT * FROM MyTable WHERE Title = 'test' " . $w;
So basically if both of those have a value, then the SQL would be:
SELECT * FROM MyTable WHERE Title = 'test' AND SomeVar = 'blah' AND
AnotherVar = 'blah'
Because there's four possible variations of this query, what would be the best way to "build" this query using stored procedures?
Heres the other three possibilities:
SELECT * FROM MyTable WHERE Title = 'test' AND AnotherVar = 'blah'
SELECT * FROM MyTable WHERE Title = 'test' AND SomeVar = 'blah'
SELECT * FROM MyTable WHERE Title = 'test'
Do I pass both variables via BIND to a SP, then in the SP do the IF/ELSE statements.
If so, could someone provide me with an example on how to do this in the SP?
Or, is there some other way of handling this?
Thanks!
Edit: The MySQL will be converted to MSSQL from regular queries, to stored procedures
Edit 2:
based on Joe Stefanelli's comment, i think this is the answer to my question, any thoughts?
CREATE PROCEDURE testSP
#somevar varchar(50),
#anothervar varchar(50)
AS
SELECT * FROM MyTable WHERE Title = #title
AND ((SomeVar = #somevar AND #somevar IS NOT NULL) OR (#somevar IS NULL))
AND ((AnotherVar = #anothervar AND #anothervar IS NOT NULL) OR (#anothervar IS NULL))
MySQL does not support dynamic SQL in stored procedures. If you can get by with a prepared statement, you'd be good to go, but otherwise you may want to split your logic into separate procedures.
Also take a look at this SO question.

Categories