Django: Use variable names instead of %s - mysql

Im passing multiple parameter into a raw sql statement, for each parameter im using %s
Is it possible to use the variable name instead of multiple %s
Example:
man = "John"
wife = "Jane"
query = "SELECT * FROM person WHERE name = %s and wife = %s"
cursor.execute(query, [man, wife])

Is it a model you are querying?
Looking at the docs explaining the raw() manager
raw() automatically maps fields in the query to fields on the model.
this should be as easy as:
Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')

DB API 2.0 defines following parameter styles
'qmark' Question mark style,
e.g. '...WHERE name=?'
'numeric' Numeric, positional style,
e.g. '...WHERE name=:1'
'named' Named style,
e.g. '...WHERE name=:name'
'format' ANSI C printf format codes,
e.g. '...WHERE name=%s'
'pyformat' Python extended format codes,
e.g. '...WHERE name=%(name)s'
Now, not all databases implement all of them. Check if DB engine you're using does support pyformat.

Related

how to select rows where a specific string column matches at least one value inside a json array?

SELECT name FROM accounts WHERE Name in ("name1","name2");
the values are being sent inside a json array
["name1","name2"]
currently i just convert the array into json string and remove the first and last characters
"name1","name2"
but could i just keep the array intact? i tried json_contains
SELECT name FROM accounts WHERE JSON_CONTAINS(name,'["name1","name2"]');
my understanding as to which why that didn't work is because name column isn't json string array
Core issue is you can't "prepare" flex statements without some sort of preprocessing.
Generally you'll want to do input validation etc, on the application side regardless, and then use some sort of pre-constructor if you're not using an ORM.
ie:
$values = ["name1", "name2"];
// Validation should happen here
$inputs = substr(str_repeat("?,", count($values)), 0, -1);
$bind = str_repeat("s", count($values));
$sqli = "SELECT name FROM accounts WHERE Name in ($inputs);";
...
$stmt->bind_param($bind, ...$values);
...
You can use the same principal for PDO as well, but regaredless you're gunna want to handle the validation layer on the application side, and there is no "easy" way to inject "IN" statements into prepared SQL.

ValueError("unsupported format character 'A' (0x41) at index 185",)

I am trying to execute a query which lists certain values of my db that match the inputs of my html search form. I want it to do the search even if some of the form inputs are empty inputs.I am using Python 3.4 and my query is something like this:
query=("select DISTINCT val1,val2,val3,val4 from tab1,tab2 WHERE tab1.val1=tab2.val1 AND onoma LIKE '%' AND epitheto LIKE '%' AND (val4 between % AND %)" )
data =(d1, d2, d3 ,d4)
c.execute("SET NAMES utf8")
c.execute(query,data)
the error I get is this:
ValueError("unsupported format character 'A' (0x41) at index 185",)
Please, if you know how i can fix this, i would really appreciate it. I'm a begginer with databases.
Thanks in advance
Placeholders for parameters are spelled %s, not %:
query = """
select DISTINCT val1,val2,val3,val4 from tab1,tab2
WHERE tab1.val1=tab2.val1 AND onoma LIKE %s AND
epitheto LIKE %s AND
(val4 between %s AND %s)
"""
data = ('%{}%'.format(d1), '%{}%'.format(d2), d3 ,d4)
c.execute(query, data)
Note that you should not add quotes around placeholders (leave those to the database driver), and for a LIKE query, you need to add the wildcards to the parameter value. I used str.format() here to put % wildcards before and after each value. A LIKE query without wildcards (so % or _) may as well just use = equality tests.

How to search a json encoded value in a mysql column?

I have stored some extra form data as json in a mysql column (extraData).
Example data
{"1":{"name":"sadsdaf ","surname":"sdafa","occupation":"sdaas","email":"dsasdaf#asdf.nl","barcode":"052355491"},"2":{"name":"sadafd","surname":"sdafa","occupation":"sddaf","email":"sda#daf.nl","barcode":"052355492"}}
I would like to do a search query which also does a search for the barcode stored in the json encoded field? So not only this
$sql = "SELECT name FROM visitors WHERE barcode = '".$barcode."'";
But also
$sql = "SELECT name FROM visitors WHERE barcode = '".$barcode."' OR extraData = '".$barcode."'";
What do I need to do to extraData so the variable barcode is checked and I get the corresponding name, surname etc?
SELECT TRIM(BOTH '"' FROM SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(V.extraData,'"name":', -1),',',1),'}',1)
FROM visitors V
WHERE V.extraData LIKE '%"barcode"%'
AND :barcode = TRIM(BOTH '"' FROM SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(V.extraData,'"barcode":', -1),',',1),'}',1);
the LIKE '%"barcode"%' filters the rows with the field extraData containing barcode values
the :barcode means to be the value to match, the TRIM is to get rid of the extra double quotes , the nested SUBSTRING_INDEX searchs for:
the text starting at the end of the first match of '"barcode":' up to
the next match of ',' (if there are more key/values) up to the next
match of '}' (if it's the last key/value at that level)
keep in mind that if you find that a certain key/val is always present in every row and is accessed everywhere you should consider adding an extra field to the table/data model and create an index out of it (ie. name, surname).
the values retrieved must be decoded "always".
"Einstürzende Neubauten" is stored as "Einst\u00fcrzende Neubauten"
doing search and compare numbers are "ok", like in the example (the trim double quotes sometimes would not be necesary as if you json_encode an integer var it will be stored as "number":99 ). but fractional numbers would be stored depending on the locale "1,5" / "1.5"
search and compare strings are more tricky: you have to "jsonencode" the value to match
"https://www.google.com" is stored as "https:\/\/www.google.com"
check your data normalization skills.
check your optimization skills
use an online tool to see how your data will be encoded

Rails: Querying with an Array

I have the following method which creates and then executes an SQL query:
def edition_authors(edition, authors)
query_string = "contributor_type = ? AND author = ?"
for i in 1..authors.length - 1
query_string += " OR author = ?"
end
return edition.contributors.where(query_string, 'Author', authors)
end
The last line is the one I'm having trouble with. I want the 'authors' array to somehow turn into a set of strings. For instance, if the authors array contained ['James Joyce', 'Cory Doctorow', 'Cormac McCarthy'], I'd like that last line to read like:
return edition.contributors.where(query_string, 'Author', 'James Joyce', 'Cory Doctorow', 'Cormac McCarthy')
How could I accomplish this?
Depends which rails and which ruby you are using,
ActiveRecord already has this functionality in Rails 3: Model.where(:my_field => ['Author', 'James Joyce', 'Cory Doctorow', 'Cormac McCarthy'])
arr.map{|v| v.to_s.inspect} will get you a comma separated list
arr.join(',') will give you a comma separated list, no quotes.
Then you can use this string however you wish.
Try this:
Instead of using a big bunch of ORs, use a SQL IN clause, and
then use Array#join to supply the values
So:
.where("contributor_type = ? AND author IN (?)", 'Author', authors.join("','"))
should do the trick, with some caveats: string values in a SQL IN clause need to be single quoted and comma separated SELECT * FROM fubar WHERE blah IN ('foo','bar','baz'); I think Rails is clever about knowing how to quote things, so look in the Rails log to see what SQL is being generated if you're getting an error.
Also, since your values may contain single quotes (Georgia O'Keefe) I am not sure if Rails is smart enough to escape these for you when used in this manner.
Bonus tip: make sure there's an index on the Author column. This is an expensive query, in general.

passing string in a query to MySQL database in MATLAB

I am using MySQL with MATLAB, and I want to get a name from user, and pass it to the table in mySQL, but it is rejecting a variable name in place of string
var_name=input('enter the name:');
mysql('insert into table (name) values (var_name)');
Any suggestions?
FIRST read the comments to this question - you don't want to shoot yourself in the foot with a mysql injection security problem. You have been warned. Now, to solve your current problem, without addressing the security risk of the whole approach when it comes to building SQL queries, read on...
In principle Amro has already posted two solutions for you which work, but since you have not accepted it I'll explain further.
Your problem is that you are not telling MATLAB which parts of your query it should interpret as a literal string, and which parts it should interpret as a variable name. To solve this, you can just end the literal string where appropriate, i.e. after the opening brackets, and then start them again before the closing brackets.
In between those literal strings you want to add the contents of your variables, so you need to tell MATLAB to concat your literal strings with your variables, since the mysql command probably expects the whole query as a single string. So in essence you want to take the string 'insert into table(' and the string saved in the variable name and the string ') values (' and so on and glue them into one big string. Amro and Isaac have shown you two solutions of how to do this without much explanation:
horzcat('insert into table (', name, ') values (', var_name, ')')
uses the function horzcat, while
['insert into table (' name ') values (' var_name ')']
uses the fact that MATLAB treats strings as arrays of characters so that you can just use square brackets to form a large array containing the strings one after the other.
The third solution, offered by Amro, is a bit more sublte:
sprintf('insert into table (%s) values (%s)',name,var_name)
It tells the function sprintf (which is made for that purpose) "take the string which I supply as first parameter and replace occurences of %s with the strings I supply as the following parameters. This last technique is in particular useful if you also need to insert numbers into your string, because sprintf can also convert numbers to string and allows fine control over how they are formatted. You should have a close look at the help page for sprintf to know more :-).
Try this instead:
mysql(['insert into table (' name ') values (' var_name ')']);
or even:
mysql(sprintf('insert into table (%s) values (%s)',name,var_name));
I believe the problem you are having is the same as the one in this other question. It sounds like you want to create a command string that itself contains a ' delimited string, which would require you to escape each ' with another ' when you create your command string (note the first example in this string handling documentation). Note also you may want to use the 's' option for the INPUT function:
var_name = input('Enter the name: ','s'); %# Treats input like a string
commandString = sprintf('insert into table (name) values (''%s'')', var_name);
%# Note the two apostrophes --^
mysql(commandString);
If I were to enter Ken for the input, the string commandString would contain the following:
insert into table (name) values ('Ken')
And of course, as others have already mentioned, beware injection vulnerabilities.