String truncation when using PreparedStatement and SetString with SQL Server - java

I'm trying to use PreparedStatement and setString to insert data into a TEXT field of a SQL Server DB. The statement is something like this:
PreparedStatement p = con.prepareStatement("insert into comments(comments) VALUES (?)");
p.setString(1, comment);
The insert is working correctly but being truncated after 200-some characters. An error is not thrown. I can't find reference to this being the case anywhere else. It's definitely coming from the Java side, I've tested longer inserts into the SQL db directly.
Ideas? Is there a way I could convert the string to a different data type maybe?

Related

Is it safe to use JDBC setString() to store CLOB data type with Oracle database?

I have a need to store a large string into Oracle database the length of which would be at most 10000 bytes. I understand that there is some configuration in Oracle 12c that can increase the 4000 byte limit of varchar2. But I do not have the option to use that configuration.
So I am inclined to use the CLOB data type. I have no previous experience in using CLOB. So I have my concerns.
I saw the following on SO
Java: How to insert CLOB into oracle database
I did not want to use any oracle package to handle the CLOB type. My question is, is the following safe enough for my purpose?
To store:
try {
String myclobstring = "xx ........";
String sql = "Insert into mytable (clobfield) values (?)";
Statement stmt = conn.prepareStatement(sql);
stmt.setString(1, myclobstring);
.
.
}
To Retrieve:
try {
String sql = "select clobfield from mytable";
stmt = conn.createStatement();
ResultSet result = stmt.executeQuery(sql);
String s = result.getString ("clobfield');
.
.
}
You can create the CLOB as a String, though using a stmt.setCharacterStream might be a bit better for something very large. Here is an example I found that shows this nicely:
Storing Clobs
You can also use the java.sql.Clob if you're wanting to not use the Oracle specific code.
From Oracle's documentation on CLOB
Use the java.sql.Clob and create the CLOB with the connection's createClob function.
I thought I will post an answer as I did not see an explicit answer. So far setString()/setString() is storing up to 10K characters into the CLOB field. I am getting back what I am storing without a problem.
I did see the following related SO post that gives me a bit more confidence.
How to use setClob() in PreparedStatement inJDBC

Prepared Statement effect against SQL Injection

For example, I have the code below:
import java.sql.*; ...
public void main (string[] args){
try {
Class.forName („COM.ibm.db2.jdbc.net.DB2Driver“);} catch (ClassNotFoundException e) {//error handling}
try {
String url = "jdbc:db2://host:6789/myDB2"
Connection con = DriverManager.getConnection(url, "login", "password");
PreparedStatement pStmt = con.prepareStatement("UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=?"
pStmt.setInt (1, 35);
pStmt.executeUpdate();
pStmt.setString (1, args[0]);
pStmt.executeUpdate();
con.close();
} catch (SQLException e) { //error handling}
}
Presumably we have the table like:
+--------+----------+-----------+
|PNR |Name |Salary |
+--------+----------+-----------+
|34 |Tim |20000 |
+--------+----------+-----------+
|35 |John |45000 |
+--------+----------+-----------+
I have a difficult time predicting what will happen if:
args[0]="35 OR Salary<100000"
Doesn't the setString command replace args[0] with 35 OR Salary < 100000 and then all the salary record gets doubled?
Server-Side Prepared Statements
SQL parameters help to avoid SQL injection because the value of the parameter is not combined with the SQL query at all. The SQL query with parameter placeholders is sent to the MySQL server, where it is parsed and analyzed. It does things like check that you wrote valid SQL syntax, that the tables and columns you reference exist, and you have the right privileges to access those tables and columns.
This is why parameters can't be used for table names or column names or other syntax. Because the validation occurs when the parameters are still left as placeholders. The value of the parameters is sent later, so the validation must assume a parameter must replace only a single scalar value in your SQL query.
After this point, the query is stored internally in the MySQL server as non-textual data structures. It is no longer in SQL, it's just a number of internal objects in the MySQL code. The places where you had used ? become query elements that MySQL knows need to be supplied with values before it can execute the query.
When you run pStmt.executeUpdate() the values of the variables you bound to the parameters are sent to the MySQL server. They are filled into the placeholders in the non-textual representation of the query.
This way, the parameter values are not combined until after the parsing is done, therefore there's no way for the content of the parameter to change the SQL syntax. It affects the SQL query only like a single string would, as if there were a type of quote delimiter that could not be broken by unmatched quote characters in the parameter content.
Query parameters are a reliable way to protect against SQL injection.
Emulated Prepared Statements
Some drivers implement an "emulated" prepared statement. This means it does nothing with the SQL query you pass to prepareStatement(), except save the SQL string in the JDBC driver (on the client-side). It does not send the SQL query to the server at this time.
Then when you run executeUpdate() your variables are interpolated into the parameter placeholders in the SQL string, and the full string is sent to the server. Then the MySQL server parses the combined SQL query, with parameter values and all. MySQL Server can't even tell which values were literal values in the original SQL query versus which were combined as parameters. They all appear as literal values to the parser.
In this case, you have to trust that the JDBC driver does correct escaping, so quotes and other characters inside your parameter content can't mix up the SQL parser. The driver should be well-tested to handle all cases, like special character sets, and hex-encoded quote characters and other ways to trick it.
That won't cause SQL injection issues. It will translate to:
UPDATE PERS SET Salary=Salary*2.0 WHERE PNR='35 OR Salary<100000'
The inserted quotes will save you from SQL injection. I am simplifying a bit. JDBC implementation determines how exactly PreparedStatement translates to a real SQL query. It doesn't necessarily actually translate it to the above SQL. But this is one way it can prevent attacks.
Careful, though. If you use user input to create your SQL, you sill still be susceptible to SQL injection. As long as you use user inputs only to call .setXYZ() params, you'll be safe from it.

SQL Query works in workbench but gives syntax error in java

I ran the query in both sql Workbench and in the executeUpdate() method in java:
in Workbench:
INSERT INTO recentsearches (name) VALUES ("blah");
in java:
statement.executeUpdate("INSERT INTO recentsearches (name) VALUES (\""+name+"\""));
Assuming name = "blah". But I get a syntax error from running the query in java, I've already checked the string value for name. It definitely comes up as "blah", and I didn't forget the speech marks around string values, yet I still get a syntax error.
The error I get in my console is:
check the manual that corresponds to your MySQL server version for the
right syntax to use near '' at line 1
Try to use:
"INSERT INTO recentsearches (name) VALUES("+name+")";
My advice, use PreparedStatement because it has:
-Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.
-Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the values

Inserting variables with SQL in Java

I'm writing a webpage that takes input from a form, sends it through cgi to a java file, inserts the input into a database through sql and then prints out the database. I'm having trouble inserting into the database using variables though, and I was wondering if anyone would be able to help me out.
String a1Insert = (String)form.get("a1");
String a2Insert = (String)form.get("a2");
This is where I get my variables form the form (just believe that it works, there's a bunch more back end but I've used this before and I know it's getting the variables correctly).
String dbURL = "jdbc:derby://blah.blahblah.ca:CSE2014;user=blah;password=blarg";
Connection conn = DriverManager.getConnection(dbURL);
Statement stmt = conn.createStatement();
stmt.executeUpdate("set schema course");
stmt.executeUpdate("INSERT INTO MEMBER VALUES (a1Insert, a2Insert)");
stmt.close();
This is where I try to insert into the databse. It give me the error:
Column 'A1INSERT' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'A1INSERT' is not a column in the target table.
If anyone has any ideas that would be lovely ^.^ Thanks
java.sql.Statement doesn't support parameters, switching to java.sql.PreparedStatement will allow you to set parameters. Replace the parameter names in your SQL with ?, and call the setter methods on the prepared statement to assign a value to each parameter. This will look something like
String sql = "INSERT INTO MEMBER VALUES (?, ?)";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1, "a1");
stmt.setString(2, "a2");
stmt.executeUpdate();
That will execute the SQL
INSERT INTO MEMBER VALUES ('a1', 'a2')
Notice the parameter indexes start from 1, not 0. Also notice I didn't have to put quotes on the strings, the PreparedStatement did it for me.
Alternatively you could keep using Statement and create your SQL string in Java code, but that introduces the possibility of SQL injection attacks. Using PreparedStatement to set parameters avoids that issue by taking care of handling quotes for you; if it finds a quote in the parameter value it will escape it, so that it will not affect the SQL statement it is included in.
Oracle has a tutorial here.

Insert an email address into MySQL using a java application

I am trying to insert an email address into a MySQL using a java application. The problem I am having is that the "#" character is causing a MySQLSyntaxErrorException. I try to insert the email address as a String. How do i fix this?
String insert = "INSERT INTO customer_tbl(name, email) VALUES (?,?)";
PreparedStatement ps = con.prepareStatement(insert);
ps.setString(1,"name");
ps.setString(2,"freddy#slabbinck.net");
ps.executeUpdate();
A prepared statement let you use placemarkers, which can be set to anything and is not parsed by the SQL parser. As an added bonus, this makes you also immune for SQL injection.
Parameterize your query using a PreparedStatement. This way you do not have to worry about manual string escaping and are less vulnerable to SQL injection attacks.
Try to use PreparedStatement like in this example: http://www.exampledepot.com/egs/java.sql/InsertPs.html

Categories