When add query parameters for dapper in a loop,like this:
if (model.UserGroupId != null && model.UserGroupId.Count>0)
{
var list = model.UserGroupId;
sql += " and ( CHARINDEX(','+#group_id+',',','+mem.group_id+',')>0 ";
paras.Add("group_id", list[0].Trim());
for (var i = 1; i < list.Count(); i++)
{
string data = "#group_id" + i;
sql += " or CHARINDEX('," + data+ ",',','+mem.group_id+',')>0 ";
paras.Add(data, list[i].Trim());
}
sql += " )";
}
it does not report errors, but the query results are incorrect. I can't use dynamic # as a result of searching data. How can I solve this problem?
If I use this it can search correctly:
if (model.UserGroupId != null && model.UserGroupId.Count > 0)
{
var list = model.UserGroupId;
sql += " and ( CHARINDEX(','+#group_id+',',','+mem.group_id+',')>0 ";
paras.Add("group_id", list[0].Trim());
for (var i = 1; i < list.Count(); i++)
{
// string data = "#group_id" + i;
sql += " or CHARINDEX('," + list[i].Trim() + ",',','+mem.group_id+',')>0 ";
// paras.Add(data, list[i].Trim());
}
sql += " )";
}
But it has SQL injection problems.
var list = model.UserGroupId;
sql += " and ( CHARINDEX(','+#group_id+',',','+mem.group_id+',')>0 ";
paras.Add("group_id", list[0].Trim());
for (var i = 1; i < list.Count(); i++)
{
**sql += " or CHARINDEX(','+#group_id"+i+"+',',','+mem.group_id+',')>0 ";
paras.Add("#group_id" + i, list[i].Trim());**
}
sql += " )";
it can search rightly
Related
I need to run a solve three times. Every time solve needs to have different input from different columns of a tuple. That is why I need to access the loop variable with in the OPL as a parameter and need to change that parameter with every loop. Please suggest how to do that in ODM OPL.
(I am able to do it when running a standalone model with a physical .dat file by introducing a int in dat file and changing its values with each loop, but same is not possible when running through an ODM application).
You can do this using a scripting main() function:
.dat file:
param = 0; // This value is actually never used
.mod file:
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int param = ...;
dvar float x;
minimize x;
subject to { x >= param; }
main {
thisOplModel.generate();
var def = thisOplModel.modelDefinition;
var data = thisOplModel.dataElements;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
opl.end();
}
}
The scripting code modifies the data before creating a new model in each iteration. You have a more elaborate version of code like this in the cutstock_main.mod example that ships with CPLEX.
What Daniel wrote works fine. If you do not want to have the non necessary .dat file you could write
sub.mod
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int param = ...;
dvar float x;
minimize x;
subject to { x >= param; }
and then in another model that will be the main one:
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
main {
thisOplModel.generate();
var src = new IloOplModelSource("sub.mod");
var def=new IloOplModelDefinition(src);
var data = new IloOplDataElements();;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
opl.end();
}
}
which will give
Round 0: 1, 1
Round 1: 2, 2
and
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int solutions[0..1];
main {
thisOplModel.generate();
var src = new IloOplModelSource("sub.mod");
var def=new IloOplModelDefinition(src);
var data = new IloOplDataElements();;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
thisOplModel.solutions[i]=opl.x.solutionValue;
opl.end();
}
writeln(thisOplModel.solutions);
}
to address your next question about populating tables
which gives
Round 0: 1, 1
Round 1: 2, 2
[1 2]
I have a prepared statement in my application and it takes 3 minutes to give an results. However, same query i have executed in sql developer and it only takes less than 0.1 seconds to give the results. I have done research on this throughout last week and I couldn't find a proper solution. Here is my code.
public List<ResponseDto> loadData(RequestDto request) throws SQLException {
List<ResponseDto> responseDto = new ArrayList<>();
int sortBy = request.getSortBy();
String sql = "SELECT *" +
"FROM (SELECT r.*, ROWNUM RNUM, COUNT(*) OVER () RESULT_COUNT " +
" FROM (SELECT *" +
"FROM" +
" (SELECT r.VALUE_4," +
" r.DATE," +
" r.ID," +
" r.AMOUNT," +
" r.TO_AGENT_ID," +
" r.FROM_AGENT_ID," +
" a.NAME," +
" r.VALUE_2," +
" r.VALUE_1," +
" r.STATUS," +
" r.VALUE_3," +
" r.TEXT" +
" FROM MY_TABLE r" +
" INNER JOIN AGENT a " +
" ON a.AGENT_ID=r.TO_AGENT_ID" +
" WHERE r.STATUS = 1 " +
" AND r.ID IN" +
" (SELECT T.ID FROM TEST_TABLE T" +
" INNER JOIN AGENT af" +
" ON af.AGENT_ID = T.FROM_AGENT_ID " +
" INNER JOIN AGENT at" +
" ON at.AGENT_ID=T.TO_AGENT_ID" +
" WHERE T.FROM_AGENT_ID=?";
StringBuilder sbQuery = new StringBuilder(sql);
if (request.getToAgentId() != 0) {
sbQuery.append(" AND T.TO_AGENT_ID = ? ");
} else if (request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
sbQuery.append(" AND UPPER(at.NAME) like UPPER( ? ) ");
}
String secondPart =
" AND T.STATUS = 1" +
" AND TO_DATE(T.DATE) BETWEEN TO_DATE(?, 'yyyy-MM-dd') AND TO_DATE(?, 'yyyy-MM-dd')" +
" ) " +
" or r.VALUE_3=?";
sbQuery.append(secondPArt);
if (sortBy == 1) {
sbQuery.append(" ORDER BY a.NAME ");
} else if (sortBy == 2) {
sbQuery.append(" ORDER BY r.AMOUNT ");
} else if (sortBy == 3) {
sbQuery.append(" ORDER BY r.VALUE_4 ");
}
if (request.getSortingOrder() == 1) {
sbQuery.append("DESC ");
} else if (request.getSortingOrder() == 2) {
sbQuery.append("ASC ");
}
sbQuery.append(" )) R)" +
"WHERE RNUM between ? and ?");
String sqlq = sbQuery.toString();
log.info(sqlq);
try(Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement(sbQuery.toString()) ) {
con.setAutoCommit(false);
String nameParam = "%" + request.getQueryParam() + "%";
pstmt.setLong(1, request.getFromAgentId());
if (request.getToAgentId() != 0) {
pstmt.setLong(2, request.getToAgentId());
} else if(request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
pstmt.setString(2, request.getQueryParam());
}
pstmt.setString(3, request.getFromDate());
pstmt.setString(4, request.getToDte());
pstmt.setString(5, request.getQueryParam());
pstmt.setLong(6, request.getFromIndex());
pstmt.setLong(7, request.getToIndex());
responseDto = helperMethod(pstmt);
con.commit();
} catch (SQLException e) {
log.error(e.getMessage());
throw e;
}
return responseDto;
}
public List<MyDto> helperMethod(PreparedStatement pstmt) throws SQLException {
List<MyDto> myDtoList = new ArrayList<>();
try( ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
MyDto myDto = new MyDto();
myDto.setValue4(rs.getLong("VALUE_4"));
myDto.setDate(rs.getDate("DATE"));
myDto.setTransactionId(rs.getLong("ID"));
myDto.setAmount(rs.getLong("AMOUNT"));
myDto.setToAgentId(rs.getLong("TO_AGENT_ID"));
myDto.setFromAgentId(rs.getLong("FROM_AGENT_ID"));
myDto.setName(rs.getString("NAME"));
myDto.setValue2(rs.getLong("VALUE_2"));
myDto.setValue1(rs.getLong("VALUE_1"));
myDto.setStatus(rs.getInt("STATUS"));
myDto.setValue3(rs.getString("VALUE_3"));
myDto.setText(rs.getString("TEXT"));
myDtoList.add(myDto);
}
}catch (Exception ex){
log.error(ex.getMessage());
throw ex;
}
return myDtoList;
}
As I said, same query works with in milliseconds. I really don't know what i am doing wrong here.
Any help would be grateful !
This is not a direct answer, but may hopefully point you in the right direction. First off, depending on your conditionals, there are different variations of what SQL is executed. I would try the following:
Edit the select string and embed a unique comment in it so we can find it in the next step. Example : "select /*mytest*/ * from ..."
Execute your program. Then locate the query in the v$sqlarea such as: select sql_id from v$sqlarea where instr(sql_fulltext,'mytest') > 0;
using the sql_id value from Step #2, execute SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('sql_id',0));
this will show you the execution plan, and hopefully you will see the difference maybe a full table scan is happening or index not getting used. etc. Do similar steps for the direct sql query that is faster and see what the differences are.
Can anyone help me understand why this below would not remove named cals. It seems to work fine until the very last line where it does the save. I don't get any exceptions or error messages.
When i look in QV Management console under System>Licenses i still see the ones that were supposed to be removed (Named user CALs)
Client Build Number: 11.20.13314.0
QMSClient Client;
string QMS = "http://localhost:4799/QMS/Service";
Client = new QMSClient("BasicHttpBinding_IQMS", QMS);
string key = Client.GetTimeLimitedServiceKey();
ServiceKeyClientMessageInspector.ServiceKey = key;
List<ServiceInfo> MyQVS = Client.GetServices(ServiceTypes.QlikViewServer);
Client.ClearQVSCache(QVSCacheObjects.All);
CALConfiguration myCALs = Client.GetCALConfiguration(MyQVS[0].ID, CALConfigurationScope.NamedCALs);
List<AssignedNamedCAL> currentNamedCALs = myCALs.NamedCALs.AssignedCALs.ToList();
List<int> indexToRemove = new List<int>();
int cnt = 1;
for (int i = 0; i < currentNamedCALs.Count; i++)
{
if ((currentNamedCALs[i].QuarantinedUntil < System.DateTime.Now)
&& (currentNamedCALs[i].LastUsed < DateTime.Now.AddDays(daysFromToday)))
{
Console.WriteLine("[" + cnt + "] " + currentNamedCALs[i].UserName +
"; Last used: " + currentNamedCALs[i].LastUsed);
indexToRemove.Add(i);
cnt++;
}
}
Console.WriteLine();
for (int i = indexToRemove.Count; i > 0; i--)
{
if (currentNamedCALs[indexToRemove[i - 1]] != null)
{
currentNamedCALs.RemoveAt(indexToRemove[i - 1]);
}
}
Console.WriteLine("\nDone");
myCALs.NamedCALs.AssignedCALs = currentNamedCALs;
Client.SaveCALConfiguration(myCALs);
The following code works fine from within Oracle's SqlPlus (using Oracle 11.2.02.0g) however when I connect with and ODBC connection via C# code, I get told I have an invalid character.
Since the single quote didn't work in SQLplus, I'm assuming the characters that are consider invalid by ODBC are the double quotes. I've tried braces '{' and brackets '[' but still get the same error -> ERROR [HY000][Oracle][ODBC][Ora]ORA-00911:invalid character <-
Any help would be much appreciated. I still don't understand why SQL statements would be interpreted differently because of the connection type.
CREATE USER "AD1\EGRYXU" IDENTIFIED EXTERNALLY;
Error if ran alone that states the username conflicts with another user or role name. It does create the user in the database.
C# Code is below.
private void button1_Click(object sender, EventArgs e)
{
string happy = "";
string sql1 = "";
string sql2 = "";
string sql3 = "";
string sql4 = "";
string column;
int rownum = -1;
bool frst = false;
string dirIni = "\\\\ramxtxss021-f01\\hou_common_013\\globaluser\\";
string fileIni = "add_users.sql";
string transIniFullFileName = Path.Combine(dirIni, fileIni);
System.Data.Odbc.OdbcConnection conn = new System.Data.Odbc.OdbcConnection();
num_users = (usrdetails.Count > 0);
if (regions && num_users)
{
using (StreamWriter sw = new StreamWriter(transIniFullFileName))
{
for (int y = 0; y < usrdetails.Count; y++)
{
switch(usrdetails[y].add_del.ToUpper())
{
case "A":
sql1 = "CREATE USER \"" + usrdetails[y].userID.ToUpper() + "\" IDENTIFIED EXTERNALLY;";
sql2 = "GRANT EDMROLE TO \"" + usrdetails[y].userID.ToUpper() + "\";";
sql3 = "INSERT INTO MD_SITE_USER VALUES(generate_key(5), (select user_id from MD_SITE_USER where user_name = '" +
usrdetails[y].group + "') , {" + usrdetails[y].userID.ToUpper() + "}, " + usrdetails[y].seclev +
", '" + usrdetails[y].username.ToUpper() + "', 'U', '" + usrdetails[y].isext.ToUpper() + "', 'N');";
sw.WriteLine(sql1);
sw.WriteLine(sql2);
sw.WriteLine(sql3);
break;
case "D":
sql2 = "DELETE MD_SITE_APP_ACTION_OWNER WHERE user_id in (SELECT user_id FROM MD_SITE_USER where user_name = ‘"+ usrdetails[y].userID + "’+ and user_or_group = ‘U’);";
sql3 = "DELETE FROM MD_SITE_USER where user_name = ‘"+ usrdetails[y].userID + "’ and user_or_group = ‘U’;";
sql4 = "DROP USER "+ usrdetails[y].userID + " FROM USERS;";
sw.WriteLine(sql2);
sw.WriteLine(sql3);
sw.WriteLine(sql4);
break;
default:
MessageBox.Show("Add/Delete command argument not recognized for user\r\n" + usrdetails[y].userID + " \r\n Argument -> " + usrdetails[y].add_del);
break;
}
}
sw.Close();
}
for (int x = 0; x < region.Count; x++)
{
OdbcCommand command = new OdbcCommand();
conn.ConnectionString = "Driver={Oracle in OraClient11g_home1};" +
"Dbq=" + region[x].dbname +
";Uid=" + region[x].username + ";Pwd=" + region[x].password + ";";
try
{
string cmdTexts = File.ReadAllText(transIniFullFileName);
conn.Open();
using (conn)
{
command.Connection = conn;
command.CommandText = cmdTexts;
command.ExecuteNonQuery();
OdbcDataReader dr = command.ExecuteReader();
Form6.dataGridView2.AutoGenerateColumns = false;
if (!frst)
{
for (int i = 0; i < dr.FieldCount; i++)
{
column = dr.GetName(i);
Form6.dataGridView2.Columns.Add("col" + i, column);
Form6.dataGridView2.Columns[i].FillWeight = 1;
}
frst = true;
}
rownum++;
dataGridView1.Rows.Add();
dataGridView1.Rows[rownum].Cells[0].Value = "Results for Region -> " + Form5.region[x].dbname;
dataGridView1.Refresh();
while (dr.Read())
{
rownum++;
Form6.dataGridView2.Rows.Add();
for (int i = 0; i < dr.FieldCount; i++)
{
column = dr.GetValue(i).ToString();
Form6.dataGridView2.Rows[rownum].Cells[i].Value = column;
}
}
Form6.dataGridView2.Refresh();
Form6.dataGridView2.Show();
Form6.Show();
}
conn.Close();
Form6.dataGridView2.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("Error Message: " + ex.Message);
}
}
}
else
{
if (!regions)
happy = "Error - You have not selected any regions.\r\n";
else
happy = "Regions are now selected.\r\n";
if (!num_users)
happy = happy + "Error - You have not entered any users.\r\n";
MessageBox.Show(happy);
}
File.Delete(transIniFullFileName);
}
Don't use ";" (semi-colon) in the command text..
The command text within ODBC or ODP should be a command, e.g. not a set of commands, therefore - ";" is not relevant, and is an invalid character.
it appears you are trying to run a script..
if that is your intent, it should be padded with a "begin" and "end" for the code to be able to run:
BEGIN
INSERT...;
DELETE ...;
END;
(refer to http://www.intertech.com/Blog/executing-sql-scripts-with-oracle-odp/ for more info)
Last thing - if you want to run a "create user" (or any other DDL) from within an anonymous block or a procedure you need to run it with "execute immediate" syntax:
BEGIN
execute immediate 'CREATE USER test IDENTIFIED EXTERNALLY';
END;
This is what I tried doing..
public void printArray()
{
for(int i = 0; i<size; i++)
{
System.out.println("arr[" + i + "] = " + arr[i]);
}
}
this is what I get:
-arr[0] = Papa Bill
-arr[1] = Ali Baba
-arr[2] = Ming the Merciless
-arr[3] = Grandpa
-arr[4] = Tornado
-arr[5] = null
I need it to print with out null...
Just add a check for null in your for loop:
if ( arr[i] != null ){
System.out.println("arr[" + i + "] = " + arr[i]);
}