insert values into table using concatenation and Varray - java

This is my code where METHODARGDATATYPE_VARRAY is a varray at 5th column in my table and first column has auto generated sequence concatenated with 't'.
String arrayElements[] = { "Test3", "Test4" };
ArrayDescriptor desc = ArrayDescriptor.createDescriptor
("METHODARGDATATYPE_VARRAY", conn);
ARRAY newArray = new ARRAY(desc, conn, arrayElements);
String sql="insert into TestCaseIDDetails values (concat('t',TestCaseID_sequence.nextval),?,?,?,?)";
PreparedStatement ps =
conn.prepareStatement (sql);
ps.setString(2,testCaseIDandDetailsBean.getClass_name()) ;
ps.setString(3,testCaseIDandDetailsBean.getMethod_name()) ;
ps.setString(4,testCaseIDandDetailsBean.getMethodReplacement()) ;
((OraclePreparedStatement)ps).setARRAY (5, newArray);
ps.execute ();
Iam trying to execute this code but again Iam getting errors as follows:
java.sql.SQLException: Invalid column index
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.OraclePreparedStatement.setARRAYInternal(OraclePreparedStatement.java:5906)
at oracle.jdbc.driver.OraclePreparedStatement.setARRAY(OraclePreparedStatement.java:5898)
at implementation.TestCaseIDandDetailsDAOImpl.addTestCaseIDandDetails(TestCaseIDandDetailsDAOImpl.java:54)
at implementation.TestCaseIDandDetailsDAOImpl.main(TestCaseIDandDetailsDAOImpl.java:134)
my tablescripts are:
CREATE or replace TYPE METHODARGDATATYPE_VARRAY AS VARRAY(20) OF varchar2(30);
create table TestCaseIDDetails(
testcaseID varchar2(20) primary key,
classname varchar2(20) not null,
methodname varchar2(20) not null,
MethodReplacement char(2) check(MethodReplacement in ('y','n')),
MethodArgDataType METHODARGDATATYPE_VARRAY);
Create sequence TestCaseID_sequence minvalue 1 start with 1 increment by 1 ;

The indexes should correspond to the indexes of the question mark placeholders in the prepared statement, not to the column numbers in the table. The index of the first question mark is 1, the second is 2, and so on. Your indexes are all off by one, should be 1 2 3 4 instead of 2 3 4 5.

Change the following
ps.setString(2,testCaseIDandDetailsBean.getClass_name()) ;
ps.setString(3,testCaseIDandDetailsBean.getMethod_name()) ;
ps.setString(4,testCaseIDandDetailsBean.getMethodReplacement()) ;
((OraclePreparedStatement)ps).setARRAY (5, newArray);
to
ps.setString(1,testCaseIDandDetailsBean.getClass_name()) ;
ps.setString(2,testCaseIDandDetailsBean.getMethod_name()) ;
ps.setString(3,testCaseIDandDetailsBean.getMethodReplacement()) ;
((OraclePreparedStatement)ps).setARRAY (4, newArray);

Related

Intersection in DB2 using INTERSECT

I have a query in DB2 that I need intersection on.
SELECT * FROM records where id = 1
intersect
SELECT * FROM records where id = 2
Now this size of ids can grow dynamically, do we have anything in DB2 that can take the list of ids as the parameter? something like
intersect in (1,2,3,4,5) so that it may consider intersection on of result set on these ids using a single query?
You can create a TABLE with the ID LIST, and then create a procedure to create dinamically the SQL Statement to Execute.
Something like this:
CREATE PROCEDURE
YOUR_PROCEDURE
(
)
LANGUAGE SQL
SPECIFIC YOUR_PROCEDURE
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
INHERIT SPECIAL REGISTERS
SET OPTION
ALWBLK = *ALLREAD ,
ALWCPYDTA = *YES ,
COMMIT = *NONE ,
CLOSQLCSR = *ENDMOD ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = *NONE ,
DLYPRP = *NO ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX ,
OUTPUT = *PRINT,
DBGVIEW = *SOURCE
BEGIN
DECLARE LAST_ELEMENT SMALLINT DEFAULT 0 ;
DECLARE FIRST_ELEMENT SMALLINT DEFAULT 1 ;
DECLARE STMT VARCHAR ( 5000 ) ;
DECLARE ID_CODE_TO_USE NUMERIC (9 , 0) ;
DECLARE ID_LIST CURSOR FOR
SELECT
ID_CODE
FROM
YOUR_TEMPORARY_TABLE ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET LAST_ELEMENT = -1 ;
OPEN ID_LIST ;
SET STMT = '' ;
SET FIRST_ELEMENT = 1 ;
FETCH_ID_LIST:
LOOP
FETCH ID_LIST
INTO
ID_CODE_TO_USE ;
-------
IF LAST_ELEMENT = -1 THEN
LEAVE FETCH_ID_LIST ;
END IF ;
-------
IF FIRST_ELEMENT= 1 THEN
SET STMT = 'SELECT * FROM RECORD WHERE ID = ' CONCAT CHAR(ID_CODE_TO_USE)
SET FIRST_ELEMENT = 0 ;
END IF ;
-------
SET STMT = 'INTERSECT SELECT * FROM RECORD WHERE ID = ' CONCAT CHAR(ID_CODE_TO_USE)
END LOOP FETCH_ID_LIST;
CLOSE ID_LIST ;
IF STMT <> '' THEN
EXECUTE IMMEDIATE STMT ;
END IF ;
END ;
Run this as is:
with ids (id) as
(
select id
from xmltable
(
'for $id in tokenize($s, ",") return <i>{string($id)}</i>'
-- the following string of IDs may be passed as a parameter
passing '1,2,3' as "s"
columns id int path 'if (. castable as xs:integer) then xs:integer(.) else ()'
)
)
, tab (id, c1, c2) as
(
values
(1, 1, 1)
, (1, 1, 1)
, (2, 1, 1)
, (2, 1, 1)
, (3, 1, 1)
, (1, 2, 2)
, (2, 2, 2)
)
select t.c1, t.c2
from tab t
join ids i on i.id=t.id
group by t.c1, t.c2
having count(distinct t.id) = (select count(1) from ids);
C1 C2
-- --
1 1
If this is not you want to have, then provide some example with source data and the exact result desired.

Inserting Data into DB ERROR: Columns of type 'VARCHAR' cannot hold values of type 'INTEGER'

I have built a DB, and now I'm writing a function which inserts data into that DB.
I guess the problem is something I don't see, the error I get is:
Columns of type 'VARCHAR' cannot hold values of type 'INTEGER'.
while I completely understand what that means I just can't get it to work.
here is my code for insertion:
public static void insertIntoCouponsDB(long COMPANY_ID, String TITLE, String START_DATE, String END_DATE, int AMOUNT, String TYPE, String MESSAGE, double PRICE, String IMAGE) throws SQLException {
Connection connection = DriverManager.getConnection(connectionString);
String sql = String.format("insert into Coupons (COMPANY_ID, TITLE, START_DATE,END_DATE,AMOUNT,TYPE,MESSAGE,PRICE,IMAGE) values (%d, '%s', '%s','%s',%d,'%s','%s',%.2f,'%s')",COMPANY_ID,TITLE,START_DATE,END_DATE,AMOUNT,TYPE,MESSAGE,PRICE,IMAGE);
PreparedStatement preparedStatement = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.executeUpdate();
ResultSet resultSet = preparedStatement.getGeneratedKeys();
resultSet.next();
int id = resultSet.getInt(1);
System.out.println("Insertion into Coupons DONE !!! New ID: " + id);
}
}
and this is the code for the tabke creation:
public static void buildCouponsDB() {
try {
Connection connection = DriverManager.getConnection(connectionString);
Statement statement = connection.createStatement();
String sql = "create table Coupons (" +
"ID bigint not null primary key " +
"generated always as identity(start with 1, increment by 1), "+
"COMPANY_ID bigint not null, "+
"TITLE varchar(50) not null, "+
"START_DATE date not null, "+
"END_DATE date not null, "+
"AMOUNT integer not null, "+
"TYPE varchar(50) not null, "+
"MESSAGE varchar(250) not null, "+
"PRICE double not null, "+
"IMAGE varchar(100) not null)";
statement.executeUpdate(sql);
System.out.println("Coupons Table has been Created Succesfully !!");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
can anybody help?
I am a begginer so sorry if its to easy of a question, but still, asking for help. Thanks in Advance.
Seems like DerbyDB does not support implicit conversion from integers to varchar datatype, like many (most?) other databases do.
A quick review of the documentation did not give any information about the implicit conversions.
There is CAST function CAST ( [ expression | NULL | ? ] AS dataType ), but from the table in the documentation it appears that the conversion from all numeric datatypes (SMALLINT, INTEGER, BIGINT, DECIMAL etc) is not supported.
Luckily thete is another [CHAR(https://db.apache.org/derby/docs/10.14/ref/rrefbuiltchar.html) function, and it seems that this function can be used to convert numeric values to varchar datatye:
Integer to character syntax
CHAR ( integerExpression )
integerExpression
An expression that returns a value that is an
integer data type (either SMALLINT, INTEGER, or BIGINT). The result is
the character string representation of the argument in the form of an
SQL integer constant. The result consists of n characters that are the
significant digits that represent the value of the argument with a
preceding minus sign if the argument is negative. The result is left
justified.
If the first argument is a SMALLINT: The length of the result is 6. If
the number of characters in the result is less than 6, then the result
is padded on the right with blanks to length 6.
If the first argument
is an INTEGER: The length of the result is 11. If the number of
characters in the result is less than 11, then the result is padded on
the right with blanks to length 11.
If the first argument is a BIGINT:
The length of the result is 20. If the number of characters in the
result is less than 20, then the result is padded on the right with
blanks to length 20.
So you must use CHAR fuction to convert numerics to VARCHAR datatype.
A quick test I've done using ij derby client showed that the above is true:
ij> connect 'jdbc:derby://localhost:1527/myDB;create=true'
> ;
ij> create table x( x integer, y varchar(20) );
0 wierszy wstawionych/zaktualizowanych/usuniŕtych
ij> insert into x values( 1,1);
BúąD 42821: Kolumny typu 'VARCHAR' nie mog╣ przechowywaŠ wartoťci typu 'INTEGER'.
ij> insert into x values( 1, cast(1 as varchar));
BúąD 42X01: B│╣d sk│adniowy: Encountered ")" at line 1, column 43.
Issue the 'help' command for general information on IJ command syntax.
Any unrecognized commands are treated as potential SQL commands and executed directly.
Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
ij> insert into x values( 1, char(1));
1 wiersz wstawiony/zaktualizowany/usuniŕty
ij> commit;
ij> select * from x;
X |Y
--------------------------------
1 |1
1 wiersz wybrany
ij>
EDIT
It seems that CAST( 1 AS CHAR ) also works, I've done a test:
ij> insert into x values( 1, cast(1 as char));
1 wiersz wstawiony/zaktualizowany/usuniŕty
ij>

how to insert array in table using JDBC insert

I am trying to insert values into a table using jdbc driver. In my table, one column is defined as array datatype.
Table as follows
CREATE TABLE userType
(
id bigserial NOT NULL, // auto Inc
type character varying,
userRole bigint[] // array
)
I am having an array in my code, which is converted from arraylist.
List<Long> ids = new ArrayList<Long>();
ids.add("1");
ids.add("2");
ids.add("3");
ids.add("4");
Long[] idArr = new Long[ids.size()];
idArr = ids.toArray(idArr);
I am using the following code to insert the data in table.
String querys = "insert into userType(type,fk_last_modified_by,userRole)"
+ " values ('Auto',1,"+ idArr+")";
Connection connections = sessionFactory.getCurrentSession().connection();
Statement stmts = connections.createStatement();
int count =stmts.executeUpdate(querys);
System.out.println("count---"+count);
connections.close();
I am getting the following error while executing the above.
org.postgresql.util.PSQLException: ERROR: syntax error at or near "["
Position: 99
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:302)
at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:196)
at com.mmf.controllers.UpdateReconcileController.save(com.mmf.controllers.UpdateReconcileController:123)
Then I just followed the solution provided by Jagdesh,
String querys = "insert into userType(type,fk_last_modified_by,userRole)"
+ " values (?,?,?)";
System.out.println(querys);
Connection connections = sessionFactory.getCurrentSession().connection();
CallableStatement stmts = connections.prepareCall(query);
stmts.setString(1, "Auto");
stmts.setInt(2, 1);
stmts.setArray(3, connections.createArrayOf("integer", idArr));
stmts.executeUpdate(querys);;
connections.close();
Now I am getting the following error,
org.postgresql.util.PSQLException: The column index is out of range: 1, number of columns: 0.
at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:53)
at org.postgresql.core.v3.SimpleParameterList.setLiteralParameter(SimpleParameterList.java:114)
at org.postgresql.jdbc2.AbstractJdbc2Statement.bindLiteral(AbstractJdbc2Statement.java:2172)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setLong(AbstractJdbc2Statement.java:1227)
at org.apache.commons.dbcp.DelegatingCallableStatement.setLong(DelegatingCallableStatement.java:252)
Can anyone point me where I am doing mistake?
Instead of above use PreparedStatement
String querys = "insert into reconcile_process (process_type,fk_last_modified_by,fk_bank_stmt_id)"
+ " values (?,?,?)";
Connection connections = sessionFactory.getCurrentSession().connection();
PreparedStatement pstmts = connections.createStatement();
pstmts.SetString("Auto");
pstmts.SetInt(1);
pstmts.setArray(3, conn.createArrayOf("integer", idArr));
pstmts.executeUpdate(querys);
insert into reconcile_process (process_type,fk_last_modified_by,fk_bank_stmt_id) values ('Auto',1,'[Ljava.lang.Long;#b318fc5')
So you cannot just + a long type to a string.
I think you want to use a PreparedStatement, not CallableStatement.
CallableStatements are used for calling a SQL function, and it has kinda weird syntax.

Get inserted row to Oracle with java

I am building a java program to insert data to my oracle database.
My problem is that I need to insert into two tables, and to reach unique rows I use in TABLE_A triggers for id before insert get next val in a sequence.
But i need the same id for the TABLE_B for connection.
( i cant get getval because what if another user uses the program... )
So I need to reach somehow that when I use executeql(sql) command in return I see what I have submit.
Now I use that I have name and date, so I select the id where name and date is the just inserted.
But its not the best because in one day I can insert more names. So now this will not unique.
like :
insert into table a ( name,date) val ( 'Ryan','2014.01.01')
id here is autoincremented by sequence
than another sql run:
inert into table_b ( id,someval) val ( select id from table_a where
name ='Ryan', date='2014.01.01, 23)
so i need something like:
system.out.println(smtp.executesql(sql).whatIinsertednow())
*than console:* '1 row insered (id,name,date) : ( 1, Ryan, 2014.01.01)
PreparedStatement prepareStatement = connection.prepareStatement("insert...",
new String[] { "your_primary_key_column_name" });
prepareStatement.executeUpdate();
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if (null != generatedKeys && generatedKeys.next()) {
Long primaryKey = generatedKeys.getLong(1);
}
I have found the answer this is perfectly works. I can insert from JAVA and its return with the key.
Full version:
CREATE TABLE STUDENTS
(
STUDENT_ID NUMBER NOT NULL PRIMARY KEY,
NAME VARCHAR2 (50 BYTE),
EMAIL VARCHAR2 (50 BYTE),
BIRTH_DATE DATE
);
CREATE SEQUENCE STUDENT_SEQ
START WITH 0
MAXVALUE 9999999999999999999999999999
MINVALUE 0;
And the Java code
String QUERY = "INSERT INTO students "+
" VALUES (student_seq.NEXTVAL,"+
" 'Harry', 'harry#hogwarts.edu', '31-July-1980')";
// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// get database connection from connection string
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:sample", "scott", "tiger");
// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
new String[] { "student_id" });
// local variable to hold auto generated student id
Long studentId = null;
// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {
// getGeneratedKeys() returns result set of keys that were auto
// generated
// in our case student_id column
ResultSet generatedKeys = ps.getGeneratedKeys();
// if resultset has data, get the primary key value
// of last inserted record
if (null != generatedKeys && generatedKeys.next()) {
// voila! we got student id which was generated from sequence
studentId = generatedKeys.getLong(1);
}
}
source : http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/
You can accomplish that by using the RETURNING clause in your INSERT statement:
INSERT INTO table_a ( name,date) val ( 'Ryan','2014.01.01') RETURNING id INTO ?

Check if number is already in field before concatenating?

I am writing a crawler that scans many urls and then puts all the words found in each webpage into a table. In this same table the ID of the url is stored. If the word is repeated in another page, the ID of the url the word was found on is concatenated with a comma separating them. So if a word appears on multiple pages, all the concatenated ID numbers in the field might look like:
2,3,6,8,9
At the moment, if the number appears multiple times on the same page, the ID number will be added each time the number is found so the URLID field might end up looking like:
2,2,2,4,7,8,8,8,8,8,9,9
Using Java is there a way I get it to check if the number exists in the field already and only add it if it is not already there? I have looked through the api but cannot seem to find a suitable way to do this. Any ideas?
Addition:
public void updateWordTable( String[] array, int urlid ) throws SQLException, IOException {
Statement stat = connection.createStatement();
String wordQuery;
String query;
for (String item : array) {
if(item.matches("[A-Za-z0-9]+")){
wordQuery = "SELECT * FROM word WHERE word = '"+item+"'";
ResultSet rs = stat.executeQuery(wordQuery);
if(!rs.next()){
query = "INSERT INTO word VALUES ('"+item+"',"+urlid+")";
stat.executeUpdate( query );
}
else {
//query = "UPDATE word SET urlid = concat(urlid, ',"+urlid+"') WHERE word = '"+item+"' ";
//query = "UPDATE word SET urlid = CASE WHEN FIND_IN_SET( '"+urlid+"', urlid ) > 0 THEN urlid ELSE CONCAT( urlid, ',', '"+urlid+"' )END WHERE word = '"+item+"' ";
String query2 = "UPDATE word SET urlid = CASE WHEN FIND_IN_SET( ?, urlid ) > 0 THEN urlid ELSE CONCAT( urlid, ',', ? )END WHERE word = ? ";
PreparedStatement pst = connection.prepareStatement( query2 );
pst.setLong( 1, urlid );
pst.setLong( 2, urlid );
pst.setString( 3, item);
int result = pst.executeUpdate();
//stat.executeUpdate( query2 );
}
}
}
stat.close();
}
... is there a way I get it to check if the number exists in the field already and only add it if it is not already there?
You can do it using JAVA, but leave that checking to MySQL as it has such search features.
Using MySQL, you can use FIND_IN_SET function on comma separated values in the column. This will solve your problem to not reprocess in JAVA to find if such id exists.
select
FIND_IN_SET( value_to_find, column_with_cs_values ) > 0 as bool_matched
from table_name
Add where condition and others if any required.
And in the JAVA code you can just read the resultset for getBoolean.
boolean idMatched = rs.getBoolean( "bool_matched" );
if( idMatched ) {
// dont update table
}
else {
// update table
}
Alternatively, you can directly update the table column.
Example:
UPDATE table_name
SET column_name_with_cs_values =
CASE WHEN FIND_IN_SET( value_to_find,
column_name_with_cs_values
) > 0 THEN column_name_with_cs_values
ELSE CONCAT( column_name_with_cs_values, ',', value_to_find )
END
-- add where etc here
;
In JAVA, you can use the above query like the following with PreparedStatement.
String query = "UPDATE word
SET urlid = CASE WHEN FIND_IN_SET( ?, urlid ) > 0 THEN urlid
ELSE CONCAT( urlid, ',', ? )
END
WHERE word = ? ";
PreparedStatement pst = con.prepareStatement( query );
pst.setString( 1, urlid );
pst.setString( 2, urlid );
pst.setString( 3, item);
int result = pst.executeUpdate();
I guess your values are stored in mysql because your question is tagged mysql. In java you can request your database with a select and check if the value is already inserted.
Or if your are not in the mysql world but only java, use a structure that give you the guartantee of unicity as a Set instead of a List.
The easiest way would be just to load those values into Set. Set will take case to have unique elements only.
The idea is whenever you store your IDs this structure should keep uniqueness. Set is the best one when we talk about Java.
If you would like to have some mechanism on database to provide uniqueness that's another story.
That's just the general tip.
If your field is a String then you can use regex
boolean exists = s.matches("(^|.*,)"+ n + "($|,.*)");
Step1: Store new url_id in temp variable.
Step2: now check this url_id existence in your table by select statement, you can do this by below query, suppose new url_id is 7:
SELECT COUNT(url_id) FROM mytable WHERE (url_id LIKE '7,%' OR url_id LIKE '%,7' OR url_id LIKE '%,7,%');
Step3: if you get any count from above query then leave it, otherwise add in your table.
I was having a project coded in pl/sql that comes across the case like yours. My variable is stored in a String and I have to check if the number was already in the String variable. I did it from using
IF instr('2,3,6,8,9,' '2,') <= 0 THEN
' Code to append the '2,'
End If
For JAVA there is something similar to instr method, String.indexOf()
http://www.tutorialspoint.com/java/java_string_indexof.htm
However note that it will return 0 if it's the first character, so probably it will be < 0
String a = "2,3,6,8,9,";
If a.indexOf(ID + ",") < 0 { // -1 equivalent to NOT FOUND
// code to append ID + ",";
}
Note I need to check on ID + "," reason is e.g.
ID = "2";
a = "20,3,6,8,9,";
It will return me 0 due to the 20. Therefore I'm using comma as a delimiter for every number found.
So after I finish append variable a, I would remove the last comma by
a = a.substring(0, a.length()-1); // this will remove the last ","
System.out.println(a); // the output should be - 2,3,6,8,9
This is using Java if your variable is stored in Java.

Categories