Devart Oracle. Insert and returning ID - oracle

We are trying out the Devart Oracle adapter but are having problems with existing code that worked with the Oracle's DataAccess DLL. We get the following example error on command.ExecuteNonQuery():
ORA-01400: cannot insert NULL into
("DatabaseName"."table_name"."col3")
Here is some example code:
const string query = #"INSERT INTO table_name (table_name_id, col1, col2, col3)
VALUES(table_name_id_seq.nextval, :col1, :col2, :col3)
RETURNING table_name_id INTO :output_id";
OracleParameter outputParam = new OracleParameter(":output_id", OracleDbType.Long, ParameterDirection.Output);
OracleParameter[] parameters = new OracleParameter[]
{
outputParam,
new OracleParameter(":col1", OracleDbType.VarChar, col1, ParameterDirection.Input),
new OracleParameter(":col2", OracleDbType.VarChar, col2, ParameterDirection.Input),
new OracleParameter(":col3", OracleDbType.Long, col3, ParameterDirection.Input)
}
using (OracleCommand command = connection.CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
command.Parameters.AddRange(parameters);
command.ExecuteNonQuery();
int outputId = Convert.ToInt32(outputParam.Value.ToString());
}
What are we doing wrong? We are trying to insert a row using a sequence for the PK, and return the PK for that row all in one query.
Also, the query runs fine if I remove the output parameter and the returning line in the query.

Thank you for your report. We have reproduced the issue and are investigating it. As a workaround, please switch to the Direct Mode: http://www.devart.com/dotconnect/oracle/docs/?directmode.html .

Related

Oracle OJDBC MERGE Statement and Generated Keys

Does Oracle ~>12 support generated keys using a Merge statement? Some sudo code..
MERGE INTO TARGET_TABLE TRG
USING (SELECT CAST(? AS NUMBER) AS ID FROM DUAL) SRC
ON (TRG.ID = SRC.ID)
WHEN MATCHED THEN UPDATE SET....
WHEN NOT MATCHED THEN
INSERT(ID....)
VALUES(MYSEQ.NEXTVAL...)
The prepared statement is set up;
try (PreparedStatement pstmt =
connection.prepareStatement(
loadStatement(sqlName, connection, getClass()), new String[] {ID})) {
...
int inserted = pstmt.executeUpdate();
ResultSet rs = pstmt.getGeneratedKeys();
List<Long> keys = new ArrayList<>(inserted);
while (rs.next) {
rs.getLong(1);
}
return keys;
...
I have in-memory tests where the connection uses the H2 driver running the very same SQL and PreparedStatment and that returns the generated key just fine, but Oracle does not.
Reviewing the docs it would suggest it does not?
Thanks!

Insert + Select statements in one Query<T> gives ORA-00933: SQL command not properly ended

I'd like to do a simple INSERT-and-then-SELECT-it-query in one "run" with dapper, roughly like so:
var query = "INSERT INTO Table(Id, Value) Values(1, :value);" +
"SELECT Id, Value FROM Table WHERE Id = 1;"
Connection.Query<Item>(query, new { value = value});
This just gives me ORA-00933: SQL command not properly ended. If I run the exact same query (in "one run", with the params manually replaced) in Oracle SQL Developer, it runs fine.
If I split this in two, and do this:
var insert = "INSERT INTO Table(Id, Value) Values(1, :value);"
var select = "SELECT Id, Value FROM Table WHERE Id = 1;"
Connection.Execute(insert, new { value = value});
var item = Connection.Query<Item>(select);
...it works fine. I've tried removing the last semicolon (which seemed to be a thing in other questions), with no luck.
I've done this exact same thing with success in another project where I'm using SQL Server.
Using Dapper 1.42.
Can anyone see what's wrong here?
Try this. In Insert add "Returning into Clause" and declare output parameters.
var param = new DynamicParameters();
param.Add(name: "IinsValue", value: value, direction: ParameterDirection.Input);
param.Add(name: "Id", dbType: DbType.Int32, direction: ParameterDirection.Output);
param.Add(name: "Value", dbType: DbType.String, direction: ParameterDirection.Output);
Connection.Execute("INSERT INTO Table(Id, Value) Values(1, :value) returning Id,Values into :id, :value", param );
var Id = param.get<int>("Id");
var Val = param.get<String>("Value");

How to use ampersand in JDBC?

In oracle we using select * from table_name where column_name=&value in similar way how to use ampersand in JDBC?
stmt = conn.createStatement();
String sql;
sql="select emp_name from employees"+" where emp_no=?";
ResultSet rs=stmt.executeQuery(sql);
while(rs.next()){
String emp_name=rs.getString("emp_name");
System.out.println(emp_name);
}
i wrote the above code but it is not working(showing error)
Did you read the article I provided the link to?
You use the question mark ? to point out places in your query where you want to specify a parameter, and you have to use PreparedStatement. I can't test it, but it should be something like this:
// some code to obtain the Connection object
PreparedStatement stmt = null;
String yourQuery = " SELECT emp_name FROM employees WHERE emp_no = ? ";
try {
stmt = conn.prepareStatement(yourQuery);
stmt.setLong(1, 252);
ResultSet rs = stmt.executeQuery();
while(rs.next()) {
String emp_name = rs.getString("emp_name");
System.out.println(emp_name);
}
} finally {
// close the stmt etc.
}
I'd suggest using a PreparedStatement - from memory it's something like
Connection conn = getConnection();
PreparedStatement pstmnt = conn.prepareStatement("Select * from employees where emp_no =?");
pstmnt.setLong(1,emp_no);
ResultSet rs = pstmnt.executeQuery();
but the link that #Przemyslaw Kruglej high light above will almost certainly have a good example ( I haven;t read it though ... )

Comparisons of Oracle DATE column with java.sql.timestamp via JOOQ

I am using jooq to build queries for Oracle. Everything works fine except for dates:
public static void main(String[] args) throws SQLException {
java.sql.Timestamp now = new java.sql.Timestamp(new Date().getTime());
Connection con = DriverManager.getConnection(... , ... , ...);
final Factory create = new OracleFactory(con);
Statement s = con.createStatement();
s.execute("create table test_table ( test_column DATE )");
s.execute("insert into test_table values (to_date('20111111', 'yyyymmdd'))");
// -- using to_date
ResultSet rs = s.executeQuery("select count(1) from test_table where test_column<to_date('20121212', 'yyyymmdd')");
rs.next();
System.out.println(""+rs.getInt(1));
rs.close();
// -- using a preparedstatement with java.sql.timestamp
PreparedStatement ps = con.prepareStatement("select count(1) from test_table where test_column<?");
ps.setTimestamp(1,now);
rs = ps.executeQuery();
rs.next();
System.out.println(""+rs.getInt(1));
rs.close();
// -- using jooq with java.sql.timestamp
final org.jooq.Table<org.jooq.Record> table = create.tableByName("TEST_TABLE");
final org.jooq.SelectSelectStep sss = create.select(create.count());
final org.jooq.SelectJoinStep sjs = sss.from(table);
final org.jooq.SelectConditionStep scs = sjs.where(create.fieldByName("TEST_COLUMN").lessThan(now));
System.out.println(scs.toString());
rs = s.executeQuery(scs.toString());
rs.next();
System.out.println(""+rs.getInt(1));
rs.close();
s.close();
}
Gives the following output:
1
1
select count(*) from "TEST_TABLE" where "TEST_COLUMN" < '2012-12-12 19:42:34.957'
Exception in thread "main" java.sql.SQLDataException: ORA-01861: literal does not match format string
I would have thought that JOOQ would check the type of Object in lessThan(Object)
to determine whether it can come up with a reasonable conversion, but apparently it
just does an Object.toString() in this case. I also remember that I never had issues with date queries via JOOQ in MySQL (although this is a while back). What am I doing wrong?
I suspect that this issue is due to the fact that create.fieldByName() doesn't know the type of the column (hence, Object), and coerces that unknown type on the right hand side of the comparison predicate. That should be fixed in jOOQ. I have registered #2007 for this:
https://github.com/jOOQ/jOOQ/issues/2007
In the mean time, try explicitly setting the type on your field:
create.fieldByName(Timestamp.class, "TEST_COLUMN").lessThan(now)

Oracle bound variables

I'm new to working with bound variables, so I've got a small question -
I'm using an Oracle DB and ODP.NET in a .NET app, and I'm using bound variables like this
string sql = "select * from table1 where loc=:pLoc and pno=:pPno and sno=:pSno union all select * from table2 where loc=:pLoc and pno=:pPno and sno=:pSno union all
select * from table3 where loc=:pLoc and pno=:pPno and sno=:pSno";
OracleCommand _cmd = new OracleCommand(sql, DBFacade.DbConnection);
OracleParameter pLoc = new OracleParameter(":pLoc", OracleDbType.Varchar2, 3);
pLoc.Value = loc;
OracleParameter pSno = new OracleParameter(":pSno", OracleDbType.Varchar2, 10);
pLoc.Value = sno;
OracleParameter pPno = new OracleParameter(":pPno", OracleDbType.Varchar2, 18);
pLoc.Value = pno;
_cmd.Parameters.Add(pLoc);
_cmd.Parameters.Add(pSno);
_cmd.Parameters.Add(pPno);
_odaContractPrices.SelectCommand = _cmd;
I've used bound variables successfully in other sql statements (in simpler queries like "select * from table1 where column1=:param1 and column2=:param2"), but for some reason in this one it doesn't work. Can anyone explain me why ?
Thank you very much!
I'm not sure it's the source of the error but try to remove the : in the OracleParameter constructor and use
_cmd.BindByName = true;
Actually, I think that in your case, the following will suffice:
_cmd.Parameters.Add("pLoc", loc);
_cmd.Parameters.Add("pSno", sno);
_cmd.Parameters.Add("pPno ", pno);

Resources