Dynamically add parameter to a 'IN' clause in a query? - sql

I am attempting to query an MS Access DB with C#
Static query is -
Select FieldID , CDGroups.CDGroupID , Priority
from Fields , CDGroups
where Fields.CDGroupID = CDGroups.CDGroupID
and Fields.FieldID in ('f1','f2','f3')
order by Priority
I need to replace f1,f2.. FieldID from fieldIdList(List<string> fieldIdList) which contains all these fields
How can I go about it?

The correct way would be to use SQL parameters.
To do this, you need to loop through your list and create one parameter per list item - in the SQL string and in your query's list of SQL parameters.
Take a look at this answer to a similar question:
How to pass sqlparameter to IN()?

var listId= string.Join(",", fieldIdList.Select(m => string.Format("'{0}'", m)));;
then
"Field.FieldID in (" + listId+ ")

I used following code:
StringBuilder sb = new StringBuilder();
foreach (string fieldId in fieldIdList)
{
sb.Append("'" + fieldId + "',");
}
string fieldList = sb.ToString().TrimEnd(',');
string queryString =
"Select FieldID , CDGroups.CDGroupID , Priority from Fields , CDGroups where Fields.CDGroupID = CDGroups.CDGroupID and Fields.FieldID in (" + fieldList + ") order by Priority";

Try this query -
SELECT CDGroupID FROM fields
WHERE FieldID IN ('f1', 'f2', 'f3')
GROUP BY CDGroupID
HAVING(COUNT(DISTINCT FieldID)) >= 3
It will show a list of CDGroupID that have 'f1','f2' and 'f3' at least. If you want to show ones that have just 'f1','f2' and 'f3', then change WHERE condition to 'HAVING(COUNT(DISTINCT FieldID)) >= 3'.

Related

how can join two query in PostgreSQL

I want to join two querys into one query.
What retrieved in the first query is a tables with column of resourceindex that sorts ascending:
String loadRates = "SELECT * FROM ratings WHERE userindex="
+ uindex
+ " ORDER BY rank DESC";
And in the second query, what should retrieved is rows of resourceindexes:
String loadResources = "SELECT * FROM resourceinfo WHERE resourceindex = "
+ rs.getInt("resourceindex");
How can I combine these into a single query?
Do not use old style join but use the keyword join.
Never ever write an SQL string like that with concatenation of parameters but use parameters instead.
"SELECT * FROM public.resourceinfo"
+ " inner join public.ratings ON ratings.resourceindex = resourceinfo.index"
+ " WHERE ratings.userindex = $1" +
+ " ORDER BY ratings.rank DESC;";
How you would apply the parameters depend on the language you are using which you didn't tag.
EDIT: If you meant it would also filtered by a resourceindex parameter then add it too as:
AND resourceinfo.index = $2

How to compare with the string when the same string received in different order in SQL

How to compare with the string when the same string received in different order?
Eg: in my table there is two columns named as "meaning","Relevant name"
column data type is in varchar
meaning - Relevant name
food - snacks;choco;chips
input - " choco;chips;snacks "
output - "food"
how this type string will be compared?Could anyone suggest any idea
Putting CSV data in a column is bad; relational databases aren't designed to be treated that way. Have multiple rows for your values:
Meaning|RelName
food |snacks
food |choco
food |chips
And split your input when querying:
SELECT DISTINCT Meaning FROM t WHERE RelName IN ('choco','chips','snacks')
The split and query formation should be done in your frontend language
Do not use string concatenation to build your SQL with values, i.e. this naive way (c# syntax):
//this is bad - forming a list of values by replacing ; with',' and concatting
//into anotehr sql string
strSQL = "SELECT DISTINCT Meaning FROM t WHERE RelName IN ('" + input.Replace(";", "','") + "')";
Do use parameters together with string concatenation:
//this is good
//declare the base sql stub
sqlCommand.CommandText = "SELECT DISTINCT Meaning FROM t WHERE RelName IN (";
//split the input into values
var foods = input.Split(';');
//for each value
for(int i = 0; i < foods.Length; i++){
//add a bit to the sql with a new parameter named
sqlCommand.CommandText += "#param" + i + ",";
//add a parameter name and value to match the just-added parameter
sqlCommand.Parameters.AddWithValue("param" + i, foods[i]);
}
//the sql ends with a comma; a syntax error. trim it and put a ) to close the IN
sqlCommand.CommandText = sqlCommand.CommandText.TrimEnd(',') + ")";

Query to retrieve all row data for supplied column name

I am using Eclipse and Oracle SQL Developer. My connections are all set up. I am trying to query my database in SQL Developer by passing in a column name as a variable.
For example, I just want to use something similar to this statement:
select * from CUSTOMERS;
but allow CUSTOMERS to be a variable where I can pass in any table name.
Currently this pulls all column names from given column name and connection:
final String query = "select column_name from all_tab_columns"
+" where owner = ?"
+" and table_name = ?";
try {
headers = DAO.useJNDI(jndi)
.setSQL(query)
.input(1, host)
.input(2, tableName)
.list(String.class);
I want to do the same thing but with rows. Does anyone know how to do this? This is what I am thinking about so far:
final String sql = "select *"
+ " from table_name"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, host)
.input(2, tableName)
.list(DatabaseCompareDto.class);
The main focus is the SQL statements. I know everything else works.
If I'm reading your question correctly, I think what you want is to replace the first table_name in your SQL with ?, then add an additional .input( 1, tableName) :
final String sql = "select *"
+ " from ?"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, tableName)
.input(2, host)
.input(3, tableName)
.list(DatabaseCompareDto.class);
You can't pass the table name as a parameter. Instead of wasting your energy on such an alleged generic solution, use or create a small templating engine which allows you to replace the table name in your query before sending it to the database.

Order of JSON returned by ORMLite?

I'm new to web services and trying to query some tables using ORMLite, it doesn't support join statements so I'm using a raw query. I was wondering if there is a way to specify how the JSON is returned. What I have right now is:
Dao<CodesModel,String> CodesDao = DaoManager.createDao(connectionSource, CodesModel.class);
GenericRawResults<String[]> rawResults =
CodesDao.queryRaw(
"select r.CodeA, s.SubCodeA, r.CodeB, s.SubCodeB " +
"from CodesTable r JOIN SubCodesTable s ON s.CodeA = r.CodeA " +
"where SubCodeB = '" + b_sub + "' AND r.CodeB = '" + b_code + "'");
And the results are returned as a String[] and always seem to be in the order of
[CodeA, SubCodeA, CodeB, SubCodeB]
but I have only tested this locally and can't find in the documentation what determines the order for variables in the array that is returned.
The results are ordered that way because that is the order in which you specified them in the select statement. If you want the results ordered in a different way, reorder them in your query.
If anyone is looking for a way to know column names when using "select *" you can also use "getColumnNames()" on the rawResults object and they will always be in the order that the results are. Examples
//The result is returned as a GenericRawResults object
List<String[]> results = rawResults.getResults();
String[] columns = rawResults.getColumnNames();
JSONObject obj = new JSONObject();
if(results.size()>0)
{
obj.put(columns[0], results.get(0)[0]);
obj.put(columns[1], results.get(0)[1]);
obj.put(columns[2], results.get(0)[2]);
obj.put(columns[3], results.get(0)[3]);
}

Update multiple rows with WHERE clause

I am trying to update multiple rows at once (SQL Server 2005). Previously I was updating a single row with this query:
UPDATE dbo.My_Users
SET MyUserId = #MyUserId
WHERE EmailID = #EmailId
Now #EmailId will have comma-separated EmailIds.
How can I modify the script to update multiple rows? I have seen some examples which make use of UNION ALL. But they are mostly to insert multiple records without where clause.
A similar question was answered in Parameterize an SQL IN clause
The same idea can be applied here:
declare #EmailIds varchar = '|email1#test.com|email2#test.com|';
UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE #EmailIds LIKE '%|' + EmailID + '|%';
Though this does not contain a comma-separated list, the delimiter could easily be changed to a pipe-character. The caveat here is, the more data that exists in the table and the more email addresses that are in the #EmailIds list, the slower (much slower) this query can become.
Using C#, I would actually recommend the second example in the above-mentioned question where the list is expanded to create a query similar to:
UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE EmailID IN (#email1, #email2);
C# to implement (a modified version of the example in the question above):
string[] emails = new string { "email1#test.com", "email2#test.com" };
string sql = "UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE EmailID IN ({0});"
string[] emailParams = emails.Select((s, i) => "#email" + i.ToString()).ToArray();
string inClause = string.Join(",", emailParams);
using (SqlCommand cmd = new SqlCommand(string.Format(sql, inClause))) {
for(int i = 0; i < emailParams.Length; i++) {
cmd.Parameters.AddWithValue(emailParams[i], emails[i]);
}
}
You could use dynamic SQL
exec('UPDATE dbo.My_Users SET MyUserId = ' + cast(#MyUserId as varchar) + ' WHERE EmailID in (' + #EmailIds + ')')