My goal is sql-escaping in bulk-insert query.
Eg:
INSERT INTO log VALUES (0,5,-7,'str'), (4,0,0,'str'), (0,0,0,'str');
The code inserts in table about 100-200 records each 30 seconds. (Log pooling).
I didn't find way to use PreparedStatement for bulk-insert, so i had to manually build that query through StringBuilder.
But i have no idea how to escape strings, don't really much want apply something like kludge-fixes (Quotes escaping through regex-replace etc).
Is there any handy way?
Two ways so far i know.
1st Way
Its insert record one by one
final String sql = "INSERT INTO tablename(columnname) Values(?)";
PreparedStatement statement = connection.prepareStatement(sql);
while (condition) {
statement.setString(1,value);
statement.executeUpdate();
}
2nd way
It inserts all record as bulk insert
final String sql = "INSERT INTO tablename(columnname) Values(?)";
PreparedStatement statement = connection.prepareStatement(sql);
while (condition) {
statement.setString(1,value);
statement.addBatch();
}
statement.executeBatch();
You need to use PreparedStatement and possibly batch insert. See http://www.exampledepot.com/egs/java.sql/BatchUpdate.html
Related
Im writing a java program and I have a SQL statement that currently is outputting wrong:
so the code is:
String sql = "SELECT Name from Users WHERE Name LIKE "+t;
and the Output is:
SELECT Name from Users WHERE Name LIKE David
But I need it to be with single quotes how can I add that to be like:
SELECT Name from Users WHERE Name LIKE 'David'
how can I add those quotes?
Many thanks for the help
This is a very common mistake. I'm guessing you are using Statement class to create your query and executing it.
I'd like to suggest that you use prepared statements. It'll since your issue and help you with further issues.
PreparedStatement ps = yourconn.prepareStatement("select name from users where name like ?");
ps.setString(1,yoursearchedusername);
ResultSet rs = ps.executeQuery();
This will add your quotes. Plus it will prevent from sql injection attacks in future.
Your current query will also cause issues of your actual query has ' or ? Or any other sql wild card. Prepared statement avoids all these issues and helps with performance by having the sql already compiled and stored at db layer (if enabled)
Use a prepared statement to prevent sql injections.
String searchedName = "cdaiga";
String sql = "SELECT Name from Users WHERE UPPER(Name) LIKE '%?%'";
PreparedStatement preparedStatement = dbConnection.prepareStatement(sql);
preparedStatement.setString(1, (searchedName!=null? searchedName.toUpper(): ""));
// execute the SQL stetement
preparedStatement .executeUpdate();
ResultSet rs = preparedStatement.executeQuery();
// print the results if any is returned
while (rs.next()) {
String name= rs.getString("Name");
System.out.println("name: " + name);
}
Note that a case insensitive search would be appropriate.
I'm trying to execute following SQL query where it tries to find results that matches the column2 values ending with abc
PreparedStatement stmt = conn.prepareStatement("SELECT column1 FROM dbo.table1 WHERE column2 LIKE ?");
stmt.setString(1, "%" +"abc");
But it returns nothing even though there is a matching value. This only happens with SQL Server. Same query with informix database returns correct results. Anyone has an idea about what causing this to behave differently?
Is this due to an issue in how PreparedStatement creates the SQL query for SQL Server?
Edit
I found out this happens when the data in the column which i perform the like contain space. eg: when the column contains "some word" and if i perform the search by stmt.setString(1, "%" + "word"); it won't return a matching result but if i perform the same on for "someword" it would return the matching result
SQL Server accepts wild characters in the LIKE clause within the single quotation marks, like this ''.
A sample SQL query:
SELECT NAME FROM VERSIONS WHERE NAME LIKE 'Upd%'
The query above will yield you results on SQL Server. Applying the same logic to your Java code will retrieve results from your PreparedStatement as well.
PreparedStatement stmt = conn.prepareStatement("SELECT NAME FROM VERSIONS WHERE NAME LIKE ?");
stmt.setString(1, "Upd%");
I've tested this code on SQL Server 2012 and it works for me. You need to ensure that there are no trailing spaces in the search literal that you pass on to your JDBC code.
Though as a side note, you need to understand that a wildcard % used in the beginning, enforces a full table scan on the table which can deteriorate your query performance. A good article for your future reference.
Hope this helps!
i have same problem,i have done with the CONCATE function for this.
PreparedStatement ps = con.prepareStatement(
"SELECT * FROM analysis WHERE notes like CONCAT( '%',?,'%')";
ps.setString(1, notes);
ResultSet rs = ps.executeQuery();
Is it possible to use PreparedStatement for several statements?
E.g., I mean
if
String sql = "INSERT INTO OR INGNORE ... ; UPDATE ... ; INSERT INTO ...";
this
PreparedStatement pre = conn.prepareStatement(sql);
//...
pre.executeUpdate();
executes only first statement "INSERT INTO OR INGNORE ... (until semicolon).
Is it possible to execute all at once?
Is it possible to execute all at once?
this might depend on the implementation of the JDBC driver by the database vendor but in general I would not expect that to work.
String[] query = { "insert into Gericht (classification,date,name,preisExtern,preisIntern) values (?,?,?,?,?)",
"test" };
PreparedStatement stmt;
for (String str : query) {
stmt = c.prepareStatement(str);
stmt.addBatch();
}
stmt.executeBatch();
here is an example on how to use batch. if its not what you want, please tell me so.
as wished:
#XtremeBaumer how about when the parameters in prepared statement change? how can you change it dynamically?
Answer:
you can't. if you want several different queries to be executed at once, you can only use fixed statement, otherwise your code will be very large, and then you can do it manually by setting the parameters and adding it to a batch. batches are good if you have 1 query that gets different parameters and you want to add all at once
I am using PreparedStatement to execute queries for mysql database. I have written something like following:
String createQuery = "create table FEATURE(ID varchar(15) not null, ?, ?, ?)";
preparedStatement = connect.prepareStatement(createQuery);
//replacing question marks in prepared statement
int i =1;
for(Map.Entry<String,Boolean> entry: featureBool.entrySet()){
String col_final = "`"+entry.getKey()+"`"+" varchar(5)";
preparedStatement.setString(i, col_final);
}
The problem I am facing is when this query is being executed, the single quotes are being appended to the beginning and ending to the string which is replacing ? in createQuery. Can please someone help me out because I am stuck?
For e.g., if col_final = "Feature-1 varchar(5)" then in preparedStatement it is becoming 'Feature-1 varchar(5)'.
Prepared statements are meant to be used for DML (Insert, delete, update) or DQL (Select).
Create table is DDL, Prepared statement are not meant for that. Please use statement instead and dynamically create DDL statement in java.
I have two method for update:
String query = "update mytable set name = 'new_value' where id ='20' ";
Connection conn;
PreparedStatement pState;
try {
conn = DriverManager.getConnection(dbUrl, "root", "2323");
pState = conn.prepareStatement(query);
pState.executeUpdate();
} catch (SQLException sql) {
sql.printStackTrace();
}
OR:
String query = "update mytable set name = ?" + "where id = ?";
Connection conn;
PreparedStatement pState;
int s;
try {
conn = DriverManager.getConnection(dbUrl, "root", "2323");
pState = conn.prepareStatement(query);
pState.setStringt(1, "new_value");
pState.setString(2, "20");
s = pState.executeUpdate(); // if s = 1 then update done successfully
} catch (SQLException sql) {
sql.printStackTrace();
}
Both methods update database record correctly, Which is better?
Second approach is good practice to avoid SQL Injection attacks.
And following is enough to construct query String, another + concatenation is not required.
String query = "update mytable set name = ? where id = ?";
I would say the second approach.
You aren't returning anything, so why create a result set and go down that path?
Edit:
Even after your comment, I would still use the second template. It's more flexible. Additionally, it's faster. The PreparedStatement is pre-compiled in the database which allows the database to execute a parametric query using the statement faster than a normal query. This won't happen if you use string concatenation (like in your first example).
See: http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
Additionally, from that page:
The main feature of a PreparedStatement object is that, unlike a
Statement object, it is given a SQL statement when it is created. The
advantage to this is that in most cases, this SQL statement is sent to
the DBMS right away, where it is compiled. As a result, the
PreparedStatement object contains not just a SQL statement, but a SQL
statement that has been precompiled. This means that when the
PreparedStatement is executed, the DBMS can just run the
PreparedStatement SQL statement without having to compile it first.
Although PreparedStatement objects can be used for SQL statements with
no parameters, you probably use them most often for SQL statements
that take parameters. The advantage of using SQL statements that take
parameters is that you can use the same statement and supply it with
different values each time you execute it.
The second way is more faster if you use frequently the same query. Depends of the database vendor, the query is cached and the efficiency is higher than that using flat sentences. But all that depends on the implementation of the JDBC driver and the services provided by the database.
See more in Using Prepared Statements in the The Java Tutorials.