I have an sql query that uses boolean fulltext search:
SELECT
*,
MATCH (job_title) AGAINST ('"product manager"' in boolean mode) AS title_relevance_exact,
MATCH (job_description) AGAINST ('"product manager"' in boolean mode) AS description_relevance_exact,
MATCH (job_title) AGAINST ('product manager' in boolean mode) AS title_relevance_part,
MATCH (job_description) AGAINST ('product manager' in boolean mode) AS description_relevance_part
FROM
jobs
WHERE
MATCH(job_title, job_description) AGAINST ('product manager') AND
date_posted >= now() - INTERVAL 30 DAY
ORDER BY
job_title LIKE 'product manager' DESC,
title_relevance_exact DESC,
description_relevance_exact DESC,
title_relevance_part DESC,
description_relevance_part DESC
LIMIT 300;
i.e. the quotation and speech marks in '"product manager"' is important to the query.
When I run this query as a spring jdbc prepared statement, I have to do some work arounds to get the string formatted correctly since if I have '?', jdbc doesnt recognise this as a parameter:
String queryPrepared =
"SELECT\n" +
" *,\n" +
" MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_exact,\n" +
" MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_exact,\n" +
" MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_part,\n" +
" MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_part\n" +
"FROM\n" +
" jobs\n" +
"WHERE\n" +
" MATCH(job_title, job_description) AGAINST (?) AND\n" +
" date_posted >= now() - INTERVAL 30 DAY\n" +
"ORDER BY\n" +
" job_title LIKE ? DESC,\n" +
" title_relevance_exact DESC,\n" +
" description_relevance_exact DESC,\n" +
" title_relevance_part DESC,\n" +
" description_relevance_part DESC\n" +
"LIMIT 500;";
String param1 = String.format("'\"%1$s\"'", searchValue);
String param2 = String.format("'%1$s'", searchValue);
List<Map<String, Object>> resultPrepared = jdbcTemplate.queryForList(queryPrepared,
new Object[] {param1, param1, param2, param2, param2, param2});
But the correct result isnt produced from the query, the results are not in the expected order. I can only assume that this happens because of the formatting in the prepared statement parameters. But I can't see what the query looks like after adding the parameters, how can I debug this?
You need to remove the single quotes from your value. Single quotes in SQL delimit a string literal in the query string. When you set a parameter value, you only need to set the string value without the single quotes.
So, if you want to replace the literal '"product manager"' with a parameter, then you use ? in your query (so, without single quotes), and set the value "product manager" (again, without single quotes), which as a Java string literal is "\"product manager\"".
Using single quotes in the value passed as a parameter would be the equivalent of using the SQL String literal '''"product manager"'''.
Related
I am new to using SQL2O with MySQL, but I am having a weird problem, where different queries return same results. Is SQL2O returning me cached results?
My code looks like this:
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY :order :sequence "+
"LIMIT :from, :limit";
int limit = 5;
int startIndex = (page-1)*limit;
String sequence = "DESC";
try(Connection con = sql2o.open()) {
if(order.contains("-")){
order = order.replace("-", "");
sequence= " ASC";
}
Query query= con.createQuery(sql)
.addParameter("from", startIndex)
.addParameter("limit", limit)
.addParameter("order", order)
.addParameter("sequence", sequence);
List<ReportA> result = query.executeAndFetch(ReportA.class);
con.close();
The 4 parameters always change, but the output remains the same. I have verified the queries in mysql workbench, the data is different, but SQL2O returns me the same set of data. Am I missing something?
Your query is invalid. It wont compile and throw an Sql2oException on execution.
The problem is, basically, that you can use parameters only for values, not for table names, column names or other keywords like "ASC". Changing those would change the structure of the query.
It's possible to construct queries with variable structure by good old string concatenation, i.e.
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY " + order " " + SEQUENCE +
"LIMIT :from, :limit";
and then
query(sql)
.addParameter("from", from)
.addParameter("limit", limit)
.executeAndFetch(...)
"MERGE INTO NT_PROPERTY ntProp USING ( " +
"SELECT * FROM NT_PROPERTY ) " +
"VALUES " +
"('minDPTObjectId'," + minDPTObjectId + ", 'Starting DPT Object Id') " +
"('maxDPTObjectId', " + maxDPTObjectId + ", 'Ending DPT Object Id') " +
"vt (NAME, VALUE, NOTE) " +
"ON ( ntProp.NAME = vt.NAME ) " +
"WHEN MATCHED THEN " +
"UPDATE SET VALUE = vt.VALUE "+
"WHEN NOT MATCHED THEN " +
"INSERT (NAME, VALUE, NOTE) VALUES (vt.NAME, vt.VALUE, vt.NOTE)";
Well I'm getting a missing ON keyword error and with no clue what so ever, also is there any other way to make it less clumsy
Help is very much appreciated.
The problem is that your MERGE syntax is incorrect. Your statement takes the form of:
MERGE INTO nt_property ntprop
USING (SELECT * FROM nt_property)
VALUES (...)
vt (...)
ON (ntprop.name = vt.name)
WHEN MATCHED THEN
UPDATE ...
WHEN NOT MATCHED THEN
INSERT ...;
but it should be of the form:
MERGE INTO target_table tgt_alias
USING source_table_or_subquery src_alias
ON (<JOIN conditions>)
WHEN MATCHED THEN
UPDATE ...
WHEN NOT MATCHED THEN
INSERT ...;
Why do you have the VALUES and vt clauses between your using and your on clauses? That's the incorrect syntax. Also, whilst you can use select * from tablename in the using clause, you could just use the tablename directly, since you're selecting all columns and all rows.
MERGE INTO NT_PROPERTY D
USING (SELECT * FROM DUAL ) S
ON (D.NAME = 'minDPTObjectId')
WHEN MATCHED THEN UPDATE SET D.VALUE = '1234'
WHEN NOT MATCHED THEN INSERT (NAME, VALUE, NOTE)
VALUES ('maxDPTObjectId', '1111', 'Ending DPT Object Id') ;
I'm trying to organize a search function on the site, using the Spring-jdbc NamedParameterJdbcTemplate.
public List<PhoneEntry> searchPhoneEntries(String search, String username) {
String SQL = "select * from entries, users where users.enabled=true " +
"and entries.username=:username " +
"and concat(secondName, firstName, patronymic, mobile, tel, " +
"address, entries.email) like ('%:search%')";
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("username", username);
params.addValue("search", search);
return jdbcTemplate.query(SQL, params, new PhoneEntryMapper());
}
But I get an empty list and have no any error.
When using a simple concatenation:
"...like '%" + search + "%'";
it working properly, but as I understand it is not safe.
I tried also add '%' symbols in parameter:
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("username", username);
params.addValue("search", "'%" + search + "%'");
return jdbcTemplate.query(SQL, params, new PhoneEntryMapper());
But it doesn't work too.
The solution is to add the parameter without quotes
params.addValue("search", "%" + search + "%");
and in the SQL string write
String sql = "... like :search";
Your first approach ('%:search%') did not work since named parameters are not recognized within string literals.
The second approach params.addValue("search", "'%" + search + "%'"); did not work since now the quotes were part of the like string, therefore asking Mysql to look for strings which start and end with a quote and contain the search term.
I am trying to do a SalesForce query from Java, and I want to insert the current date and time into the query. However, I also want to add a wildcard for title, and the percent for the wildcard is being interpreted as a format specifier and giving an error.
String soqlQuery = new String.format("SELECT Id, Title, CreatedDate "
+ "FROM FeedItem "
+ "WHERE title like '%ven%' and createdDate %s ", timeOfLastQuery);
I was able to just use string concatenation to get around the problem, but I would like to know if there is a way to do create a query string that contains a wildcard specifically using formatted strings.
You can escape them with another % like
String soqlQuery = new String.format("SELECT Id, Title, CreatedDate "
+ "FROM FeedItem "
+ "WHERE title like '%%ven%%' and createdDate %s ", timeOfLastQuery);
Suppose I have an execquery statement like this:
db1.execSQL("insert into "+TABLE_NAME+" values('"name"')");
where name is a string variable which contains an apostrophe. For example:
name = "tom's database";
In this case, I get an SQLITEexception near this statement. I am certain that this is because of that single quote.
How to modify this such that the statement does not cause a crash and the name get stored in the db with the single quote intact?
I read online that every such single quote has to be prefixed by another single quote.
Can someone provide the code for the same?
Duplicate question. Check How to escape unsupported character in SQLite on Android?
Use
String escapedName = DatabaseUtils.sqlEscapeString(name);
db1.execSQL("insert into "+TABLE_NAME+" values('" + escapedName + "')");
See http://developer.android.com/reference/android/database/DatabaseUtils.html#sqlEscapeString%28java.lang.String%29
Escaping the special character in the string literal works but generally it's an error prone approach. It's better to use ? placeholder and bind arguments, like this:
db1.execSQL("INSERT INTO " + TABLE_NAME + " VALUES (?)", new String[] { name });
or use insert() with ContentValues which does essentially the same.
You forgot:
To double the string apostrophes (since a apostrophes are the SQL string delimiters).
To add the + in the INSERT string to properly add the variable.
So, I'd change the above INSERT statement to:
db1.execSQL("INSERT INTO " + TABLE_NAME + " VALUES ('" + name.replace("'", "''") + "')");
You can use "PrepareStatement" to avoid problems
SQLiteStatement p = db1.compileStatement("insert into "+TABLE_NAME+" values(?)");
p.bindString(1, name);
p.execute();
Other form:
ContentValues values = new ContentValues();
values.put("name", name);
db1.insert(TABLE_NAME, null, values);