I tried looking on google but without luck...
I have a SELECT SQLStatement and I want to use the LIKE operator but the parameters won't work and the query give me an error
public function getUsersList(username:String):SQLStatement
{
selectRecord= new SQLStatement();
selectRecord.sqlConnection = connection;
selectRecord.text =
"SELECT id_user, username,password,profile,leg_cliente " +
"FROM userlist " +
"WHERE username like '%:username%'";
selectRecord.parameters[":username"] = username;
return selectRecord;
}
The error I got is
':username' parameter name(s) found in parameters property but not in
the SQL specified.
I solved putting the wildcard % in the parameters instead of the statement...
selectRecord.text =
"SELECT id_user, username,password,profile,leg_cliente " +
"FROM userlist " +
"WHERE username like :username";
selectRecord.parameters[":username"] = "%"+ username+"%";
The starting problem was triggered because the query was like
selectRecord.text =
"SELECT id_user, username,password,profile,leg_cliente " +
"FROM userlist " +
"WHERE username like '%:username%'";
Putting the single quote in the statement won't let the statement to set the parameter, I suppose because the parameter key (in statement.text) is seen as a text and not a parameter itself...
This is a weird issue I've been stuck with for quite some time now. One solution I've used is like this:
var statementText:String="SELECT id_user, username,password,profile,leg_cliente " +
"FROM userlist " +
"WHERE username like '%:username%'";
var params:Dictionary=new Dictionary();
params[":username"] = username;
for(var key:Object in params) {
while(statementText.indexOf(key.toString()) >= 0) {
statementText= statementText.replace(key, params[key]);
}
}
selectRecord.text = statementText;
Related
I am using the SqliteModernCpp library. I have a data access object pattern, including the following function:
void movie_data_access_object::update_movie(movie to_update)
{
// connect to the database
sqlite::database db(this->connection_string);
// execute the query
std::string query = "UPDATE movies SET title = " + to_update.get_title() + " WHERE rowid = " + std::to_string(to_update.get_id());
db << query;
}
Essentially, I want to update the record in the database whose rowid (the PK) has the value that the object to_update has in its parameter (which is returned by get_id()).
This code yields an SQL logic error. What is the cause of this?
It turned out single quotes (') within the query string being created were missing. The line should be:
std::string query = "UPDATE movies SET title = '" + to_update.get_title() + "' WHERE rowid = " + std::to_string(to_update.get_id());
Since there is no UPDATE example in the official docs on github, This is how UPDATE queries should be implemented with prepared statements and binding
#define MODERN_SQLITE_STD_OPTIONAL_SUPPORT
#include "sqlite_modern_cpp.h"
struct Book {
int id;
string title;
string details;
Book(int id_, string title_, string details_):
id(std::move(id_)),
title(std::move(title_)),
details(std::move(details_)) {}
}
int main() {
Book book = Book(0, "foo", "bar")
sqlite::database db("stackoverflow.db");
// Assuming there is a record in table `book` that we want to `update`
db <<
" UPDATE book SET "
" title = ?, "
" details = ? "
" WHERE id = ?; "
<< book.title
<< book.details
<< book.id;
return 0;
}
I want to build a SELECT statement using a list of conditions that come from the query string of a REST api. I wrote this function, but maybe it is vulnerable to SQL injection. Can someone tell me if this is vulnerable how to fix it? Perhaps I should use some kind of SQLBuilder package? or is there a way to do it with just dotNet. I'm using dotNet 4.6.1
string BuildSelect(NameValueCollection query)
{
var result = "SELECT * FROM MYTABLE";
if (query.Count == 0) return result;
var logic = " WHERE ";
foreach (string key in query)
foreach (string v in query.GetValues(key))
{
result += logic + key + " = " + v;
logic = " AND ";
}
return result;
}
Yes it is vulnerable to SQL injection attack. You could build your query to use parameters instead (you are simply using an = check only).
Since you know the tablename, that means you also know what the columns (keys) can be. Thus, you could loop your columns, if the collection has that key then add it to the where as a parameterized statement BUT value part is NOT passed as a string, you parse it to the type it should be (or let the backend do the conversion and get error if cannot be converted). In pseudocode:
List<string> clauses = new List<string>();
var result = "SELECT * FROM MYTABLE";
foreach( var col in myTable.Columns )
{
if (query.ContainsKey(col.Name))
{
clauses.Add( $"{col.Name} = #{col.Name}";
string v = query[col.Name];
command.Parameters.Add( $"#{col.Name}", col.Type).Value = typeParse(v);
}
}
if (clauses.Any())
{
result += " WHERE " + string.Join( " AND ", clauses );
}
return result;
HTH
I have following User table and repository.
User:
id;name;job;age
1;steve;nurse;33
2;steve;programmer;null
3;steve;programmer;null
Repository method:
#Query("SELECT u FROM User u WHERE ("
+ "LOWER(u.name) = LOWER(:name) AND "
+ "LOWER(u.beruf) = LOWER(:job) AND "
+ "LOWER(u.alter) = LOWER(:age))")
public List<User> findUsers(#Param("name") String name,
#Param("job") String job,
#Param("age") String age);
If I call the repository method with following parameters
String name = "steve";
String job = "programmer";
List<User> result = repository.findUsers(name, job, null); // empy list ..why ?
I get an empty list as result, although I expect to get the entities with id=2 and id=3 as result.
What am I doing wrong ? How should I change the query to get the two entities as result.
Thanks
According to the documentation this behaviour is normal there is no way to ignore null fields. using #Query method.
instead you can use the query method specifications.
more information [here][jpa documentaiton]
if you want to keep your existing method you can also go like this:
#Query("SELECT u FROM User u WHERE ("
+ "LOWER(u.name) = LOWER(:name) AND "
+ "LOWER(u.beruf) = LOWER(:job) AND "
+ "( " +
" :age is null or LOWER(u.alter) = LOWER(:age) " +
")"
)
public List<User> findUsers(#Param("name") String name,
#Param("job") String job,
#Param("age") String age);
I am trying to write a generic method to call DB records.
All works except to make the method useful I need to passing the WHERE name value too...as well as the value to match.
Something like this...
T values = db.SingleOrDefault<T>("WHERE " + name + " = #0", value);
This works but its a bit of a clunk!
string sql = "WHERE " + name + " = #0";
T values = db.SingleOrDefault<T>(sql, value);
Can this be done with different syntax?
Thanks
You can create an extension method to hide the syntax if that bothers you
public static T SingleOrDefaultWithWhere<T>(this PetaPoco.Database db, string name, object value) {
string sql = "WHERE " + name + " = #0";
return db.SingleOrDefault<T>(sql, value);
}
And then just call
T values = db.SingleOrDefaultWithWhere<T>(name, value);
I want to perform the following query using Dapper, which currently doesn't return expected results (I think it must be treating the #pName param as literal text within the single quotes?):
var q = "SELECT * FROM Users WHERE Name LIKE '#pName%'";
#pName is the param I assign a value to upon executing the query.
Things work if I just build the SQL like:
var q = "SELECT * FROM Users WHERE Name LIKE '" + name + "%'";
.. but I would prefer to use a param if possible.
I am executing the query using the following code:
o = _cn.Query<User>(q, new { pName = new DbString { Value = name, IsFixedLength = false, Length = 25, IsAnsi = true } }).ToList();
How do I got about this using Dapper?
SELECT * FROM Users WHERE Name LIKE #pName + '%'
I would like to add here another possible solution:
var results = cn.Query("SELECT * FROM Table WHERE Column LIKE #value", new { value = value + "%" });
The wildcard is inside the string var itself, and then we reference that var in the SQL. Applies to any wildcard pattern you want.