Insert data from arraylist to tables - java

ok, I am a newbie. I have two ArrayList and I want to insert data from the arralylist to table. one arraylist is for the table parameters to insert and other arraylist for inserting the values of the table.
I have tried searching if there was a dynamic way to insert but could not find any.
ArrayList<String> list= new ArrayList<>();
ArrayList<String> values= new ArrayList<>();
list.add("userid");
list.add("name");
list.add("email");
values.add(userID);
values.add(name);
values.add(email);
String sql = "insert into users (" + list + ") values( " + values + ")";
stmt.executeUpdate(sql);
I want to insert the data into the table. but parameters like userid should be in ''(quotes) and name should be in ''(quotes). but they are not converted automatically. is there any other way to do the same task?
IS there any way to get the data from JSON and insert into tables locally?

You should not not concatenate values like that into a SQL String. Use a PreparedStatement instead:
String sql = "insert into users (userid, name, email) values (?,?,?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
The preferred way to insert multiple rows, is to use batching
for (int i=0; i < values.size(); i++) {
pstmt.setString(i+1, values.get(i);
}
pstmt.executeUpdate();
Passing a value for a column name userid as a String seems to be wrong to begin with. Usually those are stored as integers.

You can use String.join method to compose the query:
String sql = "insert into users (" + String.join(", ", list) + ") values( '" + String.join("', '", values) + "')";
But such by-hand sql composing from raw Strings is dangerous and can be vulnerable to injection attacks. I suggest using other solutions like orm.

Related

Sql2o keep returning a same set of data although query is different

I am new to using SQL2O with MySQL, but I am having a weird problem, where different queries return same results. Is SQL2O returning me cached results?
My code looks like this:
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY :order :sequence "+
"LIMIT :from, :limit";
int limit = 5;
int startIndex = (page-1)*limit;
String sequence = "DESC";
try(Connection con = sql2o.open()) {
if(order.contains("-")){
order = order.replace("-", "");
sequence= " ASC";
}
Query query= con.createQuery(sql)
.addParameter("from", startIndex)
.addParameter("limit", limit)
.addParameter("order", order)
.addParameter("sequence", sequence);
List<ReportA> result = query.executeAndFetch(ReportA.class);
con.close();
The 4 parameters always change, but the output remains the same. I have verified the queries in mysql workbench, the data is different, but SQL2O returns me the same set of data. Am I missing something?
Your query is invalid. It wont compile and throw an Sql2oException on execution.
The problem is, basically, that you can use parameters only for values, not for table names, column names or other keywords like "ASC". Changing those would change the structure of the query.
It's possible to construct queries with variable structure by good old string concatenation, i.e.
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY " + order " " + SEQUENCE +
"LIMIT :from, :limit";
and then
query(sql)
.addParameter("from", from)
.addParameter("limit", limit)
.executeAndFetch(...)

how to query with groupBy in jdbctemplate

I'm using jdbctemplate of Spring, and I have the following query:
SELECT ?, count(*) as " + counter + " FROM data GROUP BY ?
When i'm using
List<Map<String, Object>> values = jdbcTemplate.queryForList(sql,columnName, columnName);
I get a wrong query results - I get one row with counter of 11 - which is the counter of ALL the rows in the data table. So clearly the groupBy doesn't work correctly.
I debugged the code and saw that the executed query is in fact
SELECT 'COLUMN_3', count(*) as COUNTER FROM DATA GROUP BY 'COLUMN_3'
So I suspect that the additional apostrophes are what causing the bug.
How can I solve this? (Without using simple String query - I want to use the PreparedStatement so I won't have any SQL Injection problems).
You use the sql ? placeholders only in the WHERE clause of Sql PreparedStatements such as
WHERE bossesname=?
In your case replace the ?s with java variables as in:
String columnName = "COLUMN_3";
String counter = "COUNTER";
SELECT " + columnName + ", count(*) as " + counter + " FROM data GROUP BY " + columnName
Then use a simplified form of queryForList:
List<Map<String, Object>> values = jdbcTemplate.queryForList(sql);

SQL variables in queries in Java

I want to use several times the same values.
If I use in dbForge for MySQL next query,
SET #v1 = 123, #v2='2014-04-11', #v3 = 'user1', #v4='title1';
INSERT INTO test_table (TID, CREATED, OWNER, TITLE)
VALUES (#v1,#v2,#v3,#v4)
ON DUPLICATE KEY UPDATE
CREATED=#v2, OWNER=#v3, TITLE=#v4
it correctly executes, but in Java, when I use code
final String dbQuerry = "SET #v1 = %s, #v2='%s', #v3 = '%s', #v4='%s';\n"+
"INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (#v1,#v2,#v3,#v4)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=#v2, OWNER=#v3, TITLE=#v4";
String currentQuerry = String.format(dbQuerry, t.getParam("ID"),
t.getParam("Date"),
t.getParam("User"),
t.getParam("Title"));
mDBStatement.execute(currentQuerry);
I have an exception
SQL Exception: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near 'INSERT INTO test_table (TID, CREATED, OWNER, TITLE) VALUES
(#v1,#v2,#v3,#v4) ON ' at line 2
I can use something like this
final String dbQuerry = "INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (?,?,?,?)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=?, OWNER=?, TITLE=?";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(5, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(6, t.getParam("User"));
st.setString(4, t.getParam("Title"));
st.setString(7, t.getParam("Title"));
But it looks ugly.
Is there is a way to solve this problem?
One option is to use the special VALUES() function to reference the value that would have been inserted into a column, if the INSERT had succeeded, like this:
...
ON DUPLICATE KEY
UPDATE CREATED = VALUES(CREATED)
, OWNER = VALUES(ONWER)
, TITLE = VALUES(TITLE)
The latter form in your example is preferred, using placeholders for the bind variables. What's ugly is having to supply the same value twice.
I'd recommend something like this:
final String dbQuerry = "INSERT INTO test_table (TID,CREATED,OWNER,TITLE)\n" +
" VALUES (?,?,?, ?)\n" +
" ON DUPLICATE KEY UPDATE\n" +
" CREATED=VALUES(CREATED), OWNER=VALUES(OWNER), TITLE=VALUES(TITLE)";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(4, t.getParam("Title"));
And that's not ugly. That's the normative pattern.
Using the special VALUES() function is especially useful if we're upserting more than one row, either with a VALUES clause e.g.
INSERT INTO fee (fi, fo, fum)
VALUES
(1,'doo','dah'),(2,'menom','menah'),(3,'buhdeep','uhdeepee')
ON DUPLICATE KEY
UPDATE fo = VALUES(fo)
, fum = VALUES(fum)
Or, with an INSERT ... SELECT form:
INSERT INTO fee (fi, fo, fum)
SELECT t.ay, t.bee, t.cee FROM sometable t
ON DUPLICATE KEY
UPDATE fo = VALUES(fo)
, fum = VALUES(fum)
BTW... the error being returned from the first form is the type of error we'd expect if allowMultiQueries=true is not included in the connect string. Note that enabling multiple queries per execution effectively disables a security feature.
Consider carefully the SQL text that would be generated and sent to the database with some carefully crafted values:
val = "foo'; DROP TABLE students; --"
Using a prepared statement (with static SQL text with placeholder for bind variables, as in the example above) prevents this mode of SQL injection. And disallowing multiple statements in a single execution is another way to thwart SQL injection attacks.
I believe the # variables are used in stored procedures only...
Either you define a stored procedure or you can use the second option :
final String dbQuerry = "INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (?,?,?,?)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=?, OWNER=?, TITLE=?";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(5, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(6, t.getParam("User"));
st.setString(4, t.getParam("Title"));
st.setString(7, t.getParam("Title"));

Efficient Way to insert into multiple tables at once with same columns and data types

I need to insert into three tables at once for now. But in the future I will be inserting in more than three tables.
All the three tables have same columns and same data types. So I can insert the same data into three tables as well. Currently I am inserting into one table.
I am working with new database named XpressMP. And it supports all the major SQL syntax.
public final static String INSERT_SQL = "INSERT INTO COPY"
+ "("
+ "ID, ACCOUNT) VALUES"
+ "(?, ?)";
preparedStatement = dbConnection.prepareStatement(INSERT_SQL);
preparedStatement.setString(1, id);
preparedStatement.setString(2, ACCOUNT);
What will be the best way to insert into three tables at once? It is possible to do in a SQL? Or I need to make a change in the Java code to insert into multiple tables?
You cannot parameterize the table name part. You can create String with tablename and ?, then use that string for preparedStatement.
String tablename="COPY";
public final static String INSERT_SQL = "INSERT INTO " + tablename
+ "("
+ "ID, ACCOUNT) VALUES"
+ "(?, ?)";
preparedStatement = dbConnection.prepareStatement(INSERT_SQL);
preparedStatement.setString(1, id);
preparedStatement.setString(2, ACCOUNT);

retrieve information from multiple tables

I have 3 tables, called Drivers, Offences and Points and Sofar I'm using 3 sql Strings to insert and update data in the tables
String command1 = "INSERT INTO Drivers (IDNumber, FirstName, LastName) VALUES" + drivID + FName + LName;
String command2 = "INSERT INTO Offences(IDNumber, SpeedLimit, DriverSpeed, SeatBelt, DrunkenDriving, DriversLicense) VALUES" + drivID + intspeed + intDSpeed + strSeat + strDrunk + strLicense;
String command3 = "INSERT INTO DriverPoints(IDNumber, Points) VALUES" + drivID + intpoints;
Each table is coneccted to eachother through the primary key IDNumber
Is there a way instead of having 3 Sql commands/Strings where I can have only 1 but still be able to insert and update all 3 tables?
Roughtly your query should look like this:
SELECT d.IDNumber, d.FirstName, d.LastName, o.SpeedLimit, o.DriverSpeed, o.SeatBelt, o.DrunkenDriving, o.DriversLicense, p.Points
FROM Drivers d
JOIN Offences o on (d.IDNumber = o.IDNumber)
JOIN DriverPoints p on (d.IDNumber = p.IDNumber)
WHERE (...) -- Whathever where condition you like
This will read everything.
For updating you have to perform 3 distinct updates statements or use a stored procedure or a view, but this really depends on the database you're using.
EDIT: for insert I suggest you to use PreparedStatements
String command1 = "INSERT INTO Drivers (IDNumber, FirstName, LastName) VALUES (?, ?, ?)";
PreparedStatement ps = connection.prepareStatement(command1);
ps.setInteger(1, drivID );
ps.setString(2, FName );
ps.setString(3, LName );
ps.execute();
Write a Stored Procedure.
However to make it platform independent, you should use ANSI SQL syntax.
As per BigMike's comment, you could also create a view. This will throw more light on creating a view.
You can't insert into multiple tables with one statement, so the short answer is no. You will need three statements to insert into three tables.
Also, your syntax needs to be more like:
String command1 = "INSERT INTO Drivers (IDNumber, FirstName, LastName) VALUES (" + drivID + ", " + FName + ", " + LName + ")";
Note the addition of the commas and braces.
Also, you can put all of the statements into the one query, if that is what you mean.

Categories