Can java String.format handle replacing ? instead of %s - java

I'm using
db.execSQL("INSERT INTO table SELECT NULL WHERE '1'=?;",new String[]{"1"});
db.execSQL("INSERT INTO robot_active_variables\n" +
"SELECT NULL, ravs._id,str,val\n" +
"FROM ( SELECT 'is_answer' AS str, ? AS val\n" +
"UNION ALL SELECT 'is_setting', ?\n" +
"UNION ALL SELECT 'is_val', ?\n" +
"UNION ALL SELECT 'is_group_actions', ?\n" +
"UNION ALL SELECT 'is_lone_action', ?\n" +
"UNION ALL SELECT '_id', ?\n" +
"UNION ALL SELECT 'val', ? ) v\n" +
"join robot_active_variables_super ravs on ravs._id not in (select _id_parent from robot_active_variables);",new String[]{"1", "0", "0", "0", "0", String.valueOf(idAnswer), "0"})
And I want to use log.v to output the sql inserts.
1 What's it called to replace %s with String array, and what's the name for replacing '?' with String array? I noticed this strategy very often in c but never knew what's it called or how to google it.
2 Can formatter or any other method do the above replacements directly?
What i tried:
v1: Log.v("custom log.v call " , sql + bindArgs));
but i had to copy paste every var into the "?"
v2: Log.v("custom log.v call " , String.format(sql.replaceAll("\\?","%s"),bindArgs));
but then some queries didn't work, it seems that numbers are converted to text, ie: 'select 1=?' with new String[]{"1"} will give false because it becomes 'select 1="1"'
v3: Log.v("custom log.v call " , String.format(sql.replaceAll("\\?","\"%s\""),bindArgs));
works quite well

v2: Log.v("custom log.v call " , String.format(sql.replaceAll("\\?","%s"),bindArgs));
but then some queries didn't work, it seems that numbers are converted to text, ie: 'select 1=?' with new String[]{"1"} will give false because it becomes 'select 1="1"'
v3: Log.v("custom log.v call " , String.format(sql.replaceAll("\\?","\"%s\""),bindArgs));
works quite well
Either of these solutions is fine. Note that in the first version, you should still use the original string when executing the query, not the formatted one. As you noted, the formatted version of your query will convert all types to a String. This will allow the SQL engine to use the correct types and correct quoting to avoid SQL injection.

Related

SQL MERGE to update or insert values into same table

"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') ;

Mysql query with In clause regex

I have a SQL query like this:
"select f.filterid as filtename, f.id as filtertext " +
"from filter f " +
"where group_Id = '" + id +"' " +
"OR groupIds like '%." + id + ".%' ";
And I want to pass a list of ids to this query to make performance better. I don't know whether REGEX works with in an IN clause. And I tried the below one which is not working and not sure what to use in case of REGEX.
"select f.filterid as filtename, f.id as filtertext from filter f " +
"where group_Id in ("+StringUtils.join(ids, "','")+")" +
"OR groupIds in ("+StringUtils.join(ids, "','")+")"";
Thanks.
I would recommend to use the Query#setParameter to achieve this, if you are using JPA you can easily supply your ids list in the setParameter.
But for your current resolution you may try the below changes.
Not sure if your group_Id column expects integer or string datatype, well I will propose changes for either of the cases.
If it expects String - You are missing the starting " ' " change your code as below
If it expects integer type - You should not wrap your comma separator with " ' ", remove them as below
"select f.filterid as filtename, f.id as filtertext from filter f " + "where group_Id in ("+StringUtils.join(ids, ",")+")" + "OR groupIds in ("+"'"+StringUtils.join(ids, "','")+"'"+")";
Trying running this query and see if you get the desired resultset
Perhaps the problem lies in the use of method StringUtils.join.
you can edit your sql like the following code.
select f.filterid as filtename, f.id as filtertext from filter f where group_Id in ('groupA_id', 'groupB_id', 'groupC_id')
if your ids is {"groupA_id", "groupB_id", "groupC_id"}, then
"select f.filterid as filtename, f.id as filtertext from filter f where group_Id in (" + "'" + StringUtils.join(ids, "','") + "'" +")"
Try Something like this:
Query query = session.Query("select f.filterid as filtename, f.id as filtertext from filter f where group_Id in :list");
query.SetParameterList(":list", ListOfIds);

How to introduce % in SQL consult in java

I'm trying to set a sql query like this:
SELECT id
FROM example_table
WHERE agent not like '%example'
I tried that in SQL Developer and works fine, but in Java I don`t get what I want to:
String= "%example"
(...)
query=""
+ "SELECT id"
+ "FROM example_table"
+ "WHERE agent not like ?"
(...)
pst.setString(n++, String);
(...)
I don't get any error but the query doesn't give the result I want, I think the point is that setting the String is not compatible with "%".
Thank you in advance
EDIT:
SOLUTION:
String= "example"
(...)
query=""
+ "SELECT id"
+ "FROM example_table"
+ "WHERE agent not like **concat('%', ?)"**
(...)
pst.setString(n++, String);
(...)
That simple :)

Get data for past 7days and if no data for particular day return 0

I would like to get data for the past 1week(7 days), with all days included. When there is no data for particular day, a zero should be returned.
This is what i have so far
"SELECT DATE(date) AS created_date, SUM(quantity) AS total_amount " +
"FROM milk_collection " +
"WHERE DATE(date) > DATE_SUB(DATE(NOW()), INTERVAL 30 DAY) " +
"GROUP BY created_date";
The problem is this query does not return zero(0) if no records for that day are found.
This is a classic application for a "calendar table". To get zero values for certain key values you need to ensure those key values appear in a table that you can left-join to the values table.
Create a table containing one row per date:
create table calendar ( cal_date date );
Then populate it with all dates in the range you're interested in. Finally left-join it to milk_collection on the date column in your query. This will guarantee you have at least one row per date in the selected range, with null in the quantity column for dates having no data.
Thanks to #Jim Garrison for his guide, i was able to come up with a query that does exactly what i want. Hope this post will help someone with similar problem and save them time.
SQL
"SELECT DATE(D) AS temporary_date, SUM(IFNULL(quantity,0)) AS total_amount, DATE(date) AS created_date "+
"FROM "+
"( SELECT DATE_SUB(NOW(), INTERVAL D DAY) AS D "+
" FROM (SELECT 0 as D "+
"UNION SELECT 1 "+
"UNION SELECT 2 "+
"UNION SELECT 3 "+
"UNION SELECT 4 "+
"UNION SELECT 5 "+
"UNION SELECT 6 ) AS D ) AS D "+
"LEFT JOIN milk_collection ON DATE(date) = date(D) "+
"GROUP BY temporary_date ORDER BY D ASC ";
Try this, I am not sure if this works as I am not with my system that has MySQL installation
"SELECT DATE(date) AS created_date, SUM(IFNULL(quantity,0)) AS total_amount " +
"FROM milk_collection " +
"WHERE DATE(date) > DATE_SUB(DATE(NOW()), INTERVAL 30 DAY) " +
"GROUP BY created_date";

Query in Java - Subquery gone wrong or what?

I'm having a problem with this query of mine. I've spent almost an hour trying to correct it but still getting an error.
Heres my code:
sql = "INSERT INTO tbl_case \n" +
"(Case_ID, Employee_ID, Patient_ID, Chief_Complaint, Date) \n" +
"VALUES \n" +
"(\n" +
" '',\n" +
" 'EMP0001',\n" +
" '(SELECT Patient_ID from tbl_patient WHERE ID_no = '"+getPatient_ID()+"')',\n" +
" '"+txtcc.getText()+"',\n" +
" '"+time+"'\n" +
")";
dp.sop("Query 'Create Case': "+sql);
dp.Insertion(sql);
Note: dp stands for a class I inherited the methods from. dp.Selection is a simple executeQuery I made for retrieving data. dp.Insertion is for updating.
Here is the output of the query in String:
Query 'Create Case': INSERT INTO tbl_case
(Case_ID, Employee_ID, Patient_ID, Chief_Complaint, Date)
VALUES
(
'',
'EMP0001',
'(SELECT Patient_ID from tbl_patient WHERE ID_no = '10000201117')',
'Head Ache',
'2016-01-30 09:55:27'
)
and the error is a mysql syntax error near:
'10000201117)',
'Head Ache',
'2016-01-30 10:07:08'
)' at Line 7
anyone spotted whats wrong? I'm using mysql from xampp.
Since (SELECT Patient_ID from tbl_patient WHERE ID_no = '10000201117') is in single quotes you might want to try putting 10000201117 in double quotes.
For example:
'(SELECT Patient_ID from tbl_patient WHERE ID_no = "10000201117")'
I don't think you need to surround the SELECT statement with quotes.
As it is now, this part '(SELECT Patient_ID from tbl_patient WHERE ID_no = ' is interpreted as a value instead of part of a query.
Try: (SELECT ...) instead of '(SELECT ...)'

Categories