how to use php method like "explode" in sql - php

I am trying to get some data, and in the table, there is a field named "sysload". However, it is a var(string) type. The data in it is like "0.0, 0.2, 0.5",three numbers split by comma. However, in the sql, I only need the last number(in this example:0.5) to compare in "where". So how can I use it ? My code:
$termquery=mysql_query("SELECT a.terminal FROM terminal_server_log a
inner join
(
SELECT terminal, MAX(timestamp) timestamp
FROM terminal_server_log
group by terminal
) b on (b.terminal=a.terminal and a.timestamp=b.timestamp)
WHERE explode(',', sysload)[2]>$number");
The last line is the most important one, i want to compare with '$number', but it seems i cannot use 'explode'. Thanks

You can probably use regular expressions to match the last element of your sysload column: https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-instr
Look also at CAST() function, as the extracted substring should be converted to a numeric value to allow comparison with a number.

PHP functions will not work inside SQL queries.
You can remove this filter from your query and filter at the php side, or you can make a custom explode function using some mysql string functions.
In this link has an example: (I didn't check if it's working)
Equivalent of explode() to work with strings in MySQL

Related

How to write MySQL Query in Laravel 5 without using PHP String function?

I need to eliminate the specific prefix of a string by default on getting value from the database.
In MySQL, i can use the following,
SELECT RIGHT('abc3',1) -- Results in "3"
SELECT RIGHT('abc3',2) -- Results in "c3"
But, how can i use same process in Laravel eloquent?.
Or any other solutions are available for remove the prefix of a string while retrieve from database in laravel.
I know trim will eliminate, but only spaces.
ex.
property_color
property_size
Here i need to extract "property_".
expect.
color
size
Is it possible in laravel, in without using PHP String function.
Only on Direct eloquent Operation.
Thanks in Advance !
That's what I would do:
$arrayData = DB::select(DB::raw("SELECT RIGHT('abc3',1) ")):
you can pass array of parameter to bind values:
DB::select(DB::raw(" SQL QUERY "),$paramsArray);
You have to use raw queries within your builder like
$results = YourRepo::where(DB::raw("SELECT SUBSTRING('property_color',9)") , 'LIKE', "%property_xxx%");
keep in mind that substring is slow.

SQL-injection with binding of an array to =ANY() condition

It assumed a more complex query with multiple bindings so please don't guide me to use the things like implode(',',$ids), (?,?,?) or PDO possibilities for this example.
The question is to clarify a possibility of the SQL-injection of this specific method.
There is parameter 1,2,3 in the url http://localhost/executeSql/1,2,3.
The parameter is passed by binding into = ANY operator as the string representation of the array '{1,2,3}' of PostgreSQL 9.3.
The php-code on Laravel 5.1:
public function executeSql($ids)
{
$ids='{'.$ids.'}';
$condition = 'WHERE id = ANY(:ids)';
$sql="SELECT id FROM (VALUES (1),(2),(3)) AS t(id) $condition";
DB::select($sql,[':ids'=>$ids]);
}
The result is the query:
SELECT id FROM (VALUES (1),(2),(3)) AS t(id) WHERE id = ANY('{1,2,3}')
That's works well untill the parameter contains integers only.
If the parameter is 1,2,3+ the QueryException occurs:
Invalid text representation: 7 ERROR: invalid input syntax for integer: "3+"
Can it be considered a proper protection to avoid SQL-injection?
As far as I understand from the documentation here and here , ANY convert the string you pass into an array and then use the operator (=) to compare each value in the array for one that would match.
In this case, I think pgsql do a little more: it has seen the lvalue (id) is of type integer, so it expect an array of integers. Since 3+ is not an integer, you have this one.
You should probably inspect the content of ids array (using filter_var and like) to ensure you have only integer values.
Since you definitively want the query to run with unintended result, this fails as a proper SQL injection because ANY checks its input and the query fails before running.
If however pgsql comes with a facility to build an array of integer from range, like {1:999999999999}, then you probably have a problem because the query will match a lot whole more rows.

MySQL query String contains opposite

MySQL query String contains
Hello, I am trying to make an mysql query that looks for a column value that contains a string from a master string I set. So if my master string is '1234567', I would like it to return any results with column values that have '1','2', etc... The above link was as close as to what I can find but I need it comparing in the opposite direction.
eg.:
WHERE '%{$needle}%' LIKE `column`
You are a little vague about where the various values are being stored (your text uses terms like "master string" but the sample code uses different names).
You can do what you want using regexp. Here is an example:
select 'abcd6efg' regexp concat('.*[', '1234567', '].*')
To be honest, regex is different from like in one important respect. regex returns true if any part of the left string matches, whereas for like the entire string has to match. So, the following also works:
select 'abcd6efg' regexp concat('[', '1234567', ']')
I like to put the explicit wildcards in to avoid mistakes when switching between the two.
You can look up the documentation for regular expressions here.
How about
WHERE ? LIKE CONCAT('%', `column`, '%')
where ? is a placeholder having a bound parameter with your master value (1234567) because you are using the PDO or MySQLi extension, right?
You're most certainly not using the deprecated MySQL extension, surely.

Why MySQL fetches record even if it doesn't match the ID?

I just discovered this, I use MySQL as my database.
When i do something like:
$query = $this->db->where('id', '6rubbish')->get('posts', 1);
it generates and executes this SQL:
SELECT *
FROM (`posts`)
WHERE `id` = '6rubbish'
LIMIT 1
The surprising thing is that it actually fetches the post with the ID 6.
I find this very vulnerable in same cases because i'm trying to exactly match the ID, not to do a LIKE query.
Any ideas?
Yes.
Read Type Conversion in Expression Evaluation
Use intval() PHP function to extract the integer part of the variable
Or use is_int to exclude any variable that is not a pure integer
But the origin of the problem is that your query generator library doesn't understand the variable types, PHP being a dynamic typed language doesn't help too.
I don't know what library you're using, maybe there is an option to tell that you're passing an int? It should protect you from SQL injection, I hope, try with:
$query = $this->db->where('id', "don't")->get('posts', 1);
and see if the generated SQL has the single quoted escaped (doubled or preceded by backslash).
That is because SELECT 6 = '6rubbish' will give you true, and your id is number type.
Your id field is, no doubt, a numeric data type.
When MySQL evaluates expressions, it converts operands to compatible types (see docs).
'6rubbish' (a string) gets converted to 6 (a number) and, hence, you get a match.

Using Array "Keys" In a MySQL WHERE Clause

I have a data set that is generated by a Zip Code range search:
$zips:
key -> value
11967 -> 0.5
11951 -> 1.3
The key is the Zip Code (Which I need to query the Database for), and the value is the miles from the user entered zip code. I need to take the key (Zip Code) and search the database, preferably using a MySQL query similar to my current one:
$getlistings = mysql_query("SELECT * FROM stores WHERE zip IN ($zips)");
The other alternative is to change the array somehow in my code. I tried looking in code for where the array is generated originally but I couldn't find it. Any help would be greatly appreciated!! Thanks :)
You could convert the array keys to a SQL-compatible string. For example:
'11967', '11951'
and then use the string in the query.
Since the SQL query doesn't know what a php array is and there's no good way (that I know of) to extract just the keys and surround them in quotes, so this may be your best bet.
EDIT: As Ionut G. Stan wrote (and gave an example for), using the implode and array_map functions will get you there. However, I believe the solution provided will only work if your column definition is numeric. Character columns would require that elements be surrounded by apostrophes in the IN clause.
array_keys should be what you're looking for.
$zip = array_keys($zips); # gives you simple array(11967, 11951);
implode(', ', $zip); # results in: '11967, 11951'
Cannot comment the other answers, so one additional remark from my side. Depending on the country you are in and what you do with the data... In Germany there are ZIP-Codes starting with "0" so you should make sure that you either do not store them as numerical value if you want to compare them to other data (e.g. ZIP <-> geocoord-mappings) or make sure that you convert them to int everywhere and use filtering on the output.
Old ZIP codes had four numbers, new ones have five. So displaying a new ZIP with four numbers because the leading 0 is missing will lead to confusion.
Regarding use of a temporary table i would say it depends on the size of the table and how many zip codes are used in the query.
This should do it:
// array_map sanitizes the data
$zip_codes = implode(', ', array_map('intval', array_keys($zips)));
$getlistings = mysql_query("SELECT * FROM stores WHERE zip IN ($zip_codes)");
For best performance, you should create a temporary table, fill it with your ZIP codes and query like this:
SELECT *
FROM stores
JOIN temptable
ON zip = tempvalue
Of course this will be more efficient only if you ZIP column is indexed.
I just want to throw in that the previous code snippets gave me some syntax errors and the database just spitted out one entry instead of all relevant data. The following snippet worked for me:
implode("','", $zipNumbers);

Categories