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;
Related
tried to enter the output value from [ Oracle DB result ] to [ insert that value in Excel ]:
enter image description here
GetExcelCode:
Fillo fillo = new Fillo();
Connection connection;
try{
connection = fillo.getConnection("C:/Users/**/DataTawn_2.xlsx");
String strQuery = "INSERT INTO DataSheet(QuotationNumber) VALUES('" + QuotNumber + "')";
Recordset recordset = connection.executeQuery(strQuery);
System.out.println(" Recordset recordset");
while (recordset.next()) {
ArrayList<String> dataColl = recordset.getFieldNames();
Iterator <String> dataIterator = dataColl.iterator();
while (dataIterator.hasNext()){
for(int i=0; i<= dataColl.size()-1;i++ ){
String Data = dataIterator.next();
String datavalue = recordset.getField(Data);
String testData= dataColl.get(i);
System.out.println(" the test data is: "+ recordset.getField(testData));
}
break;
}
}
Oracle connectivity
st.executeQuery("select * from tajcrs.policy where bus_type='CL' ");
ResultSet res = st.getResultSet();
int count = 0;
while (res.next()) {
if (con != null)
System.out.println("Print select * from tajcrs.members");
quotation= res.getInt("quotation_no");
System.out.println("quotation_no = " + quotation);
break;
//count++;
}
/**
* calling the method
*/
getexcel.selectData(quotation);
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.
Im trying to basically make a log of errors generated from a Java program and save them in an SQL table with 2 colums( Error and Date )
Try and catch sends the error to the method which should hopefully insert into database but its failing somewhere. Im new enough to Java so im not sure how to debug it properly or get more details on wahts going wrong and where
Heres the method.
public void createErrorLog(Exception error) throws SQLException{
// Error as String
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
error.printStackTrace(pw);
sw.toString(); // stack trace as a string
String errorOne = sw.toString();
System.out.println(errorOne);
// Date
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
String dateString = dateFormat.format(date);
Connection conn = null;
try {
conn = DriverManager.getConnection(CONN_STRING, USERNAME, PASSWORD);
System.out.println("Connected to database.");
String insertSaleProperty = "INSERT INTO ErrorLogs"
+ "(Error, "
+ "Time, "
+ "(?,?)";
PreparedStatement preparedStatement = conn.prepareStatement(insertSaleProperty);
preparedStatement.setString(1, errorOne);
preparedStatement.setString(2, dateString);
// execute insert SQL statement
preparedStatement.executeUpdate();
} catch (SQLException e) {
System.err.println("Cannot write to database.");
} finally {
if(conn != null){
conn.close();
}
}
}
Try the following.
String insertSaleProperty = "INSERT INTO ErrorLogs"
+ "(Error,Time) values "
+ "(?,?)";
String insertSaleProperty = "INSERT INTO ErrorLogs"
+ "(Error, "
+ "Time, "
+ "(?,?)";
Should probably be:
String insertSaleProperty = "INSERT INTO ErrorLogs "
+ "(Error, Time) "
+ "VALUES (?,?)";
I am using sql prepared statements in my application.
The statements are prepared fine and executed fine.
After that ,when I see the table, there are no entries.
Code snippet:
void DirEntTable::do_init()
{
m_insertIntoSrvrEntTable.setStatement("INSERT INTO " + tableName() + " (entKey, srvrType, serverID, serverEntID) VALUES (" + entKeyField + ", " + srvrTypeField + ", " + serverIDField + ", " + serverEntIDField + ")");
m_insertIntoSrvrEntTable.setConnection(m_db);
if ((rc = m_insertIntoSrvrEntTable.prepare()) != SQLITE_OK)
{
LOGDEBUG("DirEntTable", "insertIntoSrvrEntTable prepare failed (%d) table %s\n", rc, tableName().c_str());
}
}
eErrorT DirEntTable::insertIntoSrvrEntTable(const int entryId, const int serverType,
const std::string &serverID, const std::string &serverEntID)
{
LOGDEBUG(__FUNCTION__, "\nvalues : entryId = %d, serverType = %d, serverID = %s, serverEntID =%s\n",entryId,serverType,serverID.c_str(),serverEntID.c_str());
eErrorT rc = kNoError;
m_insertIntoSrvrEntTable.bindInt(entKeyField, entryId);
m_insertIntoSrvrEntTable.bindInt(srvrTypeField, serverType);
m_insertIntoSrvrEntTable.bindText(serverIDField, serverID);
m_insertIntoSrvrEntTable.bindText(serverEntIDField, serverEntID);
if (!m_insertIntoSrvrEntTable())
{
rc = kFuncReturnedError;
}
m_insertIntoSrvrEntTable.reset();
return rc;
}
Output:
values : entryId = 46, serverType = 2, serverID = gds0, serverEntID =gds:330
query "INSERT INTO gdsEntries (entKey, srvrType, serverID, serverEntID) VALUES (:entKey, :srvrType, :serverID, :serverEntID)"
Please help me in understanding what could be wrong.
I have the following sql statement pulling data from a stored view:
foreach (var id in insert_idlist[0])
{
mssql_con.Open();
//top 1 for duplicate removal
//slowdown?
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU = '" + id + "'";
}
I want to rewrite the sql statement to insert all ids into a single query using an IN clause or similar to speed up execution. However I am aware that IN is a relatively slow operation, so I was hoping to get some expert advice on the fastest possible way of retrieving my data.
Speed is my only concern in this question.
Please note that security is not an issue as this application is pulling all it's variables from an internal database with no direct web access.
Updated code:
try
{
//foreach (var id in insert_idlist[0])
//{
mssql_con.Open();
//top 1 for duplicate removal
//slowdown?
//var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU = '" + id + "'";
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU IN (" + insert_idlist .Select(x => "'" + x + "'") .Aggregate((x, y) => x + "," + y) + ")";
//var mssql_select = "SELECT * FROM dbo.Book5 WHERE SKU = '"+id+"'";
SqlCommand cmd = new SqlCommand(mssql_select, mssql_con);
cmd.CommandTimeout = 0;
lbl_dev.Text += "teest";
//Create a data reader and Execute the command
try
{
SqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
insert_idlist[1].Add(dataReader["supplier name"] + " " + dataReader["range description"] + " " + dataReader["item description"]);
insert_idlist[3].Add(dataReader["Sale Price"] + "");
insert_idlist[2].Add(dataReader["WebDesc"] + "");
//insert_idlist[3].Add(dataReader["id"] + "");removed
insert_idlist[4].Add(dataReader["WebDimensions"] + "");
insert_idlist[5].Add(dataReader["RRP"] + "");
insert_idlist[6].Add(dataReader["Normal Price"] + "");
insert_idlist[7].Add("482"); //add me
insert_idlist[8].Add(dataReader["ID"] + "");
lbl_dev.Text += dataReader["supplier name"] + " " + dataReader["range description"] + " " + dataReader["item description"];
lbl_dev.Text += mssql_select;
about_to_insert = about_to_insert + 1;
}
lbl_dyn_status.Text = "Record 0 of " + about_to_insert + "updated.";
dataReader.Close();
mssql_con.Close();
}
catch (Exception e)
{
lbl_dev.Text = "" + e.Message;
}
// }
}
catch (Exception e)
{
lbl_dev.Text = "" + e.Message;
}
I want to rewrite the sql statement to insert all ids into a single
query using an IN clause or similiar.
You can use INSERT INTO ... SELECT ... like so:
INSERT INTO ATable(...)
SELECT * FROM dbo.export_to_web WHERE SKU = someid;
Note that: You have to list the columns' names in the INSERT clause to match what is returned by SELECT *.
If you are on 2008 or higher, the best way to do is pass the values into a Table-Valued Parameter. I always point people to a blog post I wrote here for that.
However, IN is not necessarily a slow operation, as long as the field that you are searching is indexed appropriately - and it would almost certainly be faster than the 'connection per item' approach.
The SQL would then be something like:
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU IN (" + insert_idlist
.Select(x => "'" + x + "'")
.Aggregate((x, y) => x + "," + y) + ")";
Disclaimer - that LINQ may not be 100% spot on :)