I have a table with 6 columns.
1.ID (number)(PK)
2.USER_ID (number)
3.ROLE_ID (number)
4.CREATED_TS (date)
5.CREATED_BY (VARCHAR2)
6.ACTIVE_IND (VARCHAR2)
I am inserting data via a POST REST API Call in that table. I am firing a query in Java Repository.
public UserRoles save(final UserRoles u) {
final String insertQuery = "INSERT INTO VEB_USER_ROLES(ID, USER_ID, ROLE_ID, CREATED_TS, CREATED_BY, ACTIVE_IND) " +
"VALUES(VEB_USER_ROLES_SEQ.NEXTVAL, ?, ?, ?, 'PROD_MASTER', 'Y')";
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(insertQuery, new String[]{"ID"});
ps.setLong(1, u.getUserId());
ps.setLong(2, u.getRoleId());
ps.setDate(3, new java.sql.Date(System.currentTimeMillis()));
return ps;
}
}, keyHolder);
return u;
}
The query is working fine and the data is been inserted.I just want to add a check if same UserID and RoleID exists it should not insert.
for eg in the DB I have Userid '1' and roleId '1' and I send the same values ie userid '1' and role id '1' it should not get inserted.
Can anyone guide me regarding this.
Create a UNIQUE constraint on the two columns: USER_ID and ROLE_ID
ALTER TABLE yourtablename ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
Examples: Status on Insertion-
-- succeeds:
INSERT yourtablename(USER_ID, ROLE_ID) VALUES(1, 22);
-- succeeds:
INSERT yourtablename(USER_ID, ROLE_ID) VALUES(2, 23);
-- fails:
INSERT yourtablename(USER_ID, ROLE_ID) VALUES(1, 23);
If its not possible to ALTER the DB structure, you can check this also by your code:
- Before inserting new record check USER_ID & ROLE_ID exists in DB.
Use a select query & check whether a similar record exists.
Its just a idea, please make it working for you, if required:
$exists = SELECT COUNT(*) no_of_similar_records FROM yourTableName WHERE USER_ID = $USER_ID AND ROLE_ID = $ROLE_ID
If it has a value the do not INSERT again.
So here we do not need a DB update on structure.
This may help you..
Couple of ways to handle this
Add unique constraint on the table on columns Userid, Roleid or,
Do a SELECT before trying to insert to check if they already exists or,
Use merge into insert when NOT MATCHED
Related
I want to use jdbcTemplate to create table based on another table under condition. I have postgres database. When I execute this and pass parameter:
String SQL = "create table test as (select * from users where countryId =?)";
jdbcTemplate.update(SQL, new Object[] {3})
I receive table test with all columns from users table but with no rows.
However, when I execute this:
String SQL = "create table test as (select * from users where countryId =3)";
jdbcTemplate.update(SQL)
I receive test table with rows where countryId = 3, so that is what I was expecting to receive in the first solution.
Your passing of the bind variable is not correct, but it does not play any role.
You simple can not use a bind variable in a data definition statement as you immediately see in the triggered error
Caught: org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL
[create table test as (select * from users where countryId =?)];
SQL state [72000]; error code [1027];
ORA-01027: bind variables not allowed for data definition operations
So you have two options, either concatenate the statement (which is not recommended due to the danger of SQL injection)
or split the statement in two parts:
// create empty table
sql = "create table test as (select * from users where 1 = 0)";
jdbcTemplate.update(sql)
// insert data
sql = "insert into test(countryId, name) select countryId, name from users where countryId =?";
updCnt = jdbcTemplate.update(sql, new SqlParameterValue(Types.INTEGER,3));
Note that in the insert statement you can see the correct way of passing an interger value of 3 as a bind variable.
You can follow below approach as well:-
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)");
List<Object[]> employeeIds = new ArrayList<>();
for (Integer id : ids) {
employeeIds.add(new Object[] { id });
}
jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds);
Here you may query with 2 operations to avoid SQL injection.
You are using method update from jdbcTemplate in a wrong way.
Try with this:
String SQL = "create table test as (select * from users where countryId = ?)";
jdbcTemplate.update(SQL, 3);
CREATE TABLE:
CREATE TABLE tests (id SERIAL PRIMARY KEY, "name" VARCHAR);
UPSERT:
INSERT INTO tests (id, "name")
VALUES (?, ?)
ON CONFLICT (id) DO UPDATE
SET "name" = EXCLUDED."name";
The problem is that it never executes the UPDATE part because SERIAL type resolves all conflicts - it just inserts existing records as new records with new ids (nextval) instead of updating them.
I am trying to implement a "Save All Records" function. It should update existing records and insert new ones if they do not exist.
The algorithm I imagined:
connection.setAutoCommit(false);
for (Test test : tests)
{
statement = connection.prepareStatement("INSERT INTO tests (id, \"name\") VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET \"name\" = EXCLUDED.\"name\";");
statement.setInt(1, test.getId());
statement.setString(2, test.getName());
statement.execute();
}
connection.commit();
I want to write an insert query using preparedStatement. Inside it I want to put a selection query. I did the following but I get: You have an error in your SQL syntax
protected final String createStudentQuery = " INSERT INTO student (student_id, ed_level) VALUES (SELECT MAX(user_id) FROM user WHERE usertype ='Student' , ?)";
and then
stmt5 = conn.prepareStatement(createStudentQuery);
stmt5.setString(1, ed_level);
stmt5.executeUpdate();
All the declarations(connection, statement) have been made.
There are 2 values that needs to be inserted, student_id and ed_level . But in your select statement there is only one value, MAX(user_id). You have to also add the value for ed_level in the select query.
Also, your query should be:
INSERT INTO <TABLE_1> (COLUMN_1, COLUMN_2,...) SELECT COLUMN_1, COLUMN_2,... FROM <TABLE_2> WHERE <CONDITION>
I have modified the query to something like this:
INSERT INTO student (student_id, ed_level) VALUES ((SELECT MAX(user_id) FROM user WHERE usertype ='Student') , ?)
Hope this helps.
I am inserting into a table from my jdbc program,
like this
PreparedStatement ps = con.prepareStatement(sqlqry);
ps.setInt(1,dto.getInstall_id());
ps.setString(2, dto.getDashboard_name());
ps.setString(3, dto.getDashboard_type());
ps.setString(4, dto.getDashboard_image());
But in the table i have column say D_ID which in is primary key and i dont want o insert the D_ID from my program into table because the same id might be already exist. So for avoiding the PK_CONSTRAINT I am not inseting it.
But when i try this i am getting this error.
ORA-01400: cannot insert NULL into ("TESTDB"."TESTATBLE"."D_ID")
So how can i solve this problem, Any alternative like if i insert D_ID from the program my JDBC program the D_ID column should dynamically generate id's in the table.
I am banging my head for this. Please help!
You should create that ID using a sequence. So for each ID column that you have, you create a corresponding sequence:
create table testatble
(
d_id integer not null primary key,
install_id integer not null,
dashboard_name varchar(100)
... more columns ....
);
create sequence seq_testatble_d_id;
You can use it like this:
// note that there is no placeholder for the D_ID column
// the value is taken directly from the sequence
String sqlqry =
"insert into testatble (d_id, install_id, dashboard_name) " +
"values (seq_testatble_d_id.nextval, ?, ?)";
PreparedStatement ps = con.prepareStatement(sqlqry);
ps.setInt(1,dto.getInstall_id());
ps.setString(2, dto.getDashboard_name());
... more parameters ...
ps.executeUpdate();
That way the id will be generated automatically.
If you need the generated ID in your Java code after the insert, you can use getGeneratedKeys() to return it:
// the second parameter tells the driver
// that you want the generated value for the column D_ID
PreparedStatement ps = con.prepareStatement(sqlqry, new String[]{"D_ID"});
// as before
ps.setInt(1,dto.getInstall_id());
ps.setString(2, dto.getDashboard_name());
... more parameters ...
ps.executeUpdate();
// now retrieve the generated ID
int d_id = -1;
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) // important!
{
d_id = rs.getInt(1);
}
rs.close();
More on sequences in the Oracle manual: http://docs.oracle.com/cd/E11882_01/server.112/e26088/pseudocolumns002.htm#SQLRF00253
You should use Auto Increment number for ID(I Oracle you can use sequence). You can do this at the link:
Create ID with auto increment on oracle
You should also read this. If there is a sequence to your ID then here you can read information about that.
How can I insert into table1 like: INSERT INTO table1 (description) VALUES ('Some test description here'); and have it return the automatically incremented ID so that I can then insert a row into table2? The description is not guaranteed to be unique. I am using a Java PreparedStatement to insert the value currently with execute()
I have the following table structure:
CREATE TABLE table1 (
table1ID INTEGER NOT NULL AUTO_INCREMENT,
description VARCHAR(255) NOT NULL,
CONSTRAINT PK_table1 PRIMARY KEY (table1ID)
);
CREATE TABLE table2 (
table1ID INTEGER NOT NULL,
personID INTEGER NOT NULL,
CONSTRAINT PK_table2 PRIMARY KEY (table1ID, personID)
);
ALTER TABLE table2 ADD CONSTRAINT FK_table1_table2
FOREIGN KEY (table1ID) REFERENCES table1 (table1ID);
ALTER TABLE table2 ADD CONSTRAINT FK_table2_person
FOREIGN KEY (personID) REFERENCES person (personID);
run this query right after the insert completes succesfully: SELECT LAST_INSERT_ID()
Try this:
PreparedStatement st = con.prepareStatement(
"Insert into table1 (name) values ('test desc')",
Statement.RETURN_GENERATED_KEYS);
st.executeUpdate();
ResultSet rs = st.getGeneratedKeys();
if(rs.next())
{
int data = rs.getRow();
int id = rs.getInt(1);
}
Observe values of data & id.
You don't need to fire insert & select queries separately.