I want to set the ArtikelAnzahl (the number of article) in the database to the term, which I will get from my Java GUI.
So the SQL command string should look like:
"update warenliste set Anzahl=Anzahl+"anzahl"where Artikel_ID="+arikel_ID;
where:
warenliste is the table and Anzahl is a comlum which should get updated.
the number of article in the DB should be added to the number which we will get from the GUI.
Is this command right? I just learned SQL yesterday and unfortunately am not yet good at it.
public void setArtikelAnzahl(int anzahl, int arikel_ID) {
try {
String query = "update warenliste set Anzahl=Anzahl+"anzahl"where Artikel_ID="+arikel_ID;
rs= st.executeQuery(query);
}
catch(Exception e) {
System.out.println(e);
}
}
The SQL part
The SQL part of the query seems fine if artikel_id and anzahl are both numeric (and that it's anzahl and not artikeanzahl).
Let's instantiate the statement for an imaginary article 1 and a quantity of 27:
update warenliste set Anzahl=Anzahl+27 where Artikel_ID=1;
If you test this here with the following schema, it will work out fine:
create table warenliste (artikel_ID numeric,
bezeichnung varchar(100),
anzahl numeric);
insert into warenliste values (1,"Schraubenzieher", 1050);
insert into warenliste values (2,"Hammer", 10347);
The Java part
But there are a couple of problems in the Java part. First, you need to correct the statement to make the Java code compile. You also need to add missing spaces in the result string:
String query = "update warenliste set Anzahl=Anzahl+"+anzahl+" where Artikel_ID="+arikel_ID;
^ ^ ^
Since you're not too familiar with SQL yet, I'd suggest to display the query string before you execute it. Just to verify that it matches your expectations.
Now if ariktel_id is a string, and not a numeric, you may have to add the missing quotes around in the query string around the variable.
It's not required, but I'd recommend that when you build the query string, you use uppercases in the SQL statements. This will facilitate reading the java code, especially when you'll have SQL strings mixed with java variables like here.
Related
I'm having issues dealing with the single quote while using it in a prepared statement in JAVA via Oracle JDBC.
Let's say we have a table Restaurant with a column restaurant_name with 1 value : Jack's Deli
I want to use a simple prepared statement query like this:
String result = "Jack\'\'s Deli"
String sqlStatement = "select * from Restaurant where restauraunt_name like ? escape '\\' ";
PreparedStatement pStmt = conn.prepareStatement(sqlStatement);
pstmt.setString(1, result);
The result shows 0 returned values, however when I directly search the query in the database (ORACLE) it works fine and retrieves the result. (Oracle uses two single quotes as an escape for the first)
I am thinking that the value is not being passed properly to the database. Or there is some other formatting issue.
The point of prepared statements is that you don't need any escaping.
.setString(1, "Jack's Deli") will get it done.
There is a select query that I am executing with DB2 JDBC. I am using Prepared Statement to pass in the value for the parameter. The column length of that parameter in the database is 12 so everything works fine until the length of the value is 12 and then it fails. Throws an exception with the error message as in the title. I did some searching and found an explanation in the following link http://www-01.ibm.com/support/docview.wss?uid=swg21319477 and the resolution mentioned in there is as below
Resolving the problem
Add additional client side validation code to prevents queries, with values that are larger than the allowed maximum length to be ran.
I don't want to do this. Why wouldn't the query just return back with no results. Any idea how do I go about this?
EDIT
String sql = "select student_id, student_name from student where student_id = ?";
try (Connection connection = DBUtils.GetConnection)
{
try (PreparedStatement statement = connection.prepareStatement(sql))
{
statement.setString(1, student_id);
ResultSet result = statement.executeQuery();
while (result.next())
{
//...
}
}
}
Even though I do not recommend doing it: We had a similar problem and found that - at least in our case -, if you really want that empty result, you can use a native SQL query instead of the prepared statement. Apparently, it is the argument binding for the prepared statement which runs into the argument validation. The native query (which you would have manually constructed using your arguments) seemed to sidestep this validation, and just returned an empty result.
(For completeness' sake: If really manually constructing your SQL query from given arguments, be sure to know what you are doing, validate your arguments, and specifically beware of SQL injection.)
The correct answer here would be what #Gaius Gracchus offers up as an alternative suggestion in his comment to #Hans's answer. You try/catch the SQLException, gather its SQL State (always better than an SQL Code), and handle/throw a custom exception to indicate invalid input to the client. An empty result set (even though that is what the OP desires) is not accurate. The only other real alternative is to increase the size of the column or procedural input/input-output (not likely).
try {
// sql bind or execute
}
catch (SQLException e) {
String sqlState = e.getSQLState();
if (sqlState != null && sqlState.equals("22001")) {
throw new CustomException("Invalid input, etc");
}
throw e;
}
update <table> set url="http://www.google.com?a=1&something=so"
If I'm updating directly my string is updated till ?a=1 from & it is eliminating. can any one help me in this if my url contains any special symbol and how I need to update. I'm working from java
To avoid problems with string values consider using PreparedStatement and its setString method which will generate proper query with escaped values (if needed).
So try with
PreparedStatement ps = con.prepareStatement("update table set url=?");
// +----------------------------------------------------^
// | represents where we should put value
ps.setString(1, "http://www.google.com?a=1&something=so");
//then execute this statement
use this:-
update [table_name] set url='http://www.google.com?a=1'||'&'||'something=so'
here we are concatenating &, so that it does not create problem while update.
FYI.. if we have & in the string we try to update, oracle consider string following & as a parameter whose value it thinks as if it will be provided at run time, that is the reason why it was troubling you.
For some sql statements I can't use a prepared statment, for instance:
SELECT MAX(AGE) FROM ?
For instance when I want to vary the table. Is there a utility that sanitizes sql in Java? There is one in ruby.
Right, prepared statement query parameters can be used only where you would use a single literal value. You can't use a parameter for a table name, a column name, a list of values, or any other SQL syntax.
So you have to interpolate your application variable into the SQL string and quote the string appropriately. Do use quoting to delimit your table name identifier, and escape the quote string by doubling it:
java.sql.DatabaseMetaData md = conn.getMetaData();
String q = md.getIdentifierQuoteString();
String sql = "SELECT MAX(AGE) FROM %s%s%s";
sql = String.format(sql, q, tablename.replaceAll(q, q+q), q);
For example, if your table name is literally table"name, and your RDBMS identifier quote character is ", then sql should contain a string like:
SELECT MAX(AGE) FROM "table""name"
I also agree with #ChssPly76's comment -- it's best if your user input is actually not the literal table name, but a signifier that your code maps into a table name, which you then interpolate into the SQL query. This gives you more assurance that no SQL injection can occur.
HashMap h = new HashMap<String,String>();
/* user-friendly table name maps to actual, ugly table name */
h.put("accounts", "tbl_accounts123");
userTablename = ... /* user input */
if (h.containsKey(userTablename)) {
tablename = h.get(userTablename);
} else {
throw ... /* Exception that user input is invalid */
}
String sql = "SELECT MAX(AGE) FROM %s";
/* we know the table names are safe because we wrote them */
sql = String.format(sql, tablename);
Not possible. Best what you can do is to use String#format().
String sql = "SELECT MAX(AGE) FROM %s";
sql = String.format(sql, tablename);
Note that this doesn't avoid SQL injection risks. If the tablename is a user/client-controlled value, you'd need to sanitize it using String#replaceAll().
tablename = tablename.replaceAll("[^\\w]", "");
Hope this helps.
[Edit] I should add: do NOT use this for column values where you can use PreparedStatement for. Just continue using it the usual way for any column values.
[Edit2] Best would be to not let the user/client be able to enter the tablename the way it want, but better present a dropdown containing all valid tablenames (which you can obtain by DatabaseMetaData#getCatalogs()) in the UI so that the user/client can select it. Don't forget to check in the server side if the selection is valid because one could spoof the request parameters.
In this case you could validate the table name against the list of available tables, by getting the table listing from the DatabaseMetaData. In reality it would probably just be easier to use a regex to strip spaces, perhaps also some sql reserved words, ";", etc from the string prior to using something liek String.format to build your complete sql statement.
The reason you can't use preparedStatement is because it is probably encasing the table name in ''s and escaping it like a string.
I am working a Airsoft application.
I'm trying to add records to a MS Access Database via SQL in Java. I have established a link to the database, with the following:
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
ResultSet rs = stmt.executeQuery("SELECT * FROM AirsoftGunRentals");
tblRent.setModel(DbUtils.resultSetToTableModel(rs));
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I am using Ucanaccess to access my MS database. It is reading the database and is displaying to a JTable. However, I need to create three JButtons to add, delete and update the table. I have tried to code the add button, and I have tried to add a record, but it crashes and gives me errors.
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent)"+
"VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
ResultSet rs = stmt.executeQuery(Query);
JOptionPane.showMessageDialog(null, "Success!");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I have attempted all three, hoping for a result. But am still getting big errors. The only difference between the buttons is that one adds, one deletes and one updates the table. Other then that, the code is the same, minus variables.
As Brahim mentionned it, you should use stmt.executeUpdate(Query) whenever you update / insert or delete data. Also with this particular query, given your String concatenation (see end of line), there is no space between the ")" and the "VALUES" which probably causes a malformed query.
However, I can see from your code that you are not very experienced with such use-cases, and I'd like to add some pointers before all hell breaks loose in your project :
Use PreparedStatement instead of Statement and replace variables by placeholders to prevent SQL Injection.
The code that you are using here is extremely prone to SQL injection - if any user has any control over any of the variables, this could lead to a full database dump (theft), destruction of data (vandalism), or even in machine takeover if other conditions are met.
A good advice is to never use the Statement class, better be safe than sorry :)
Respect Java Conventions (or be coherent).
In your example you define the String Query, while all the other variables start with lower-case (as in Java Conventions), instead of String query. Overtime, such little mistakes (that won't break a build) will lead to bugs due to mistaking variables with classnames etc :)
Good luck on your road to mastering this wonderful language ! :)
First add a space before the quotation marks like this :
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent) "+
" VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
And use stmt.executeUpdate(Query); instead of : stmt.executeQuery(Query);in your insert, update and delete queries. For select queries you can keep it.
I managed to find an answer on how to add, delete and update records to a MS Access DB. This is what I found, after I declared the connection, and the prepped statement. I will try to explain to the best I can. I had to add values individually using this:
(pstmt = Prepped Statement Variable)
pstmt.setWhatever(1,Variable);
And it works fine now. I use the same method to delete and update records.
This is the basic query format:
String SQLInsert = "INSERT INTO Tbl VALUES(NULL,?,?,?,?)";
The NULL in the statement is the autonumber in the table. and .setWhatever() clause replaces the question marks with the data types. Thus manipulating the database.
Thank you everyone for all your contributions. It helped a lot, and made this section a lot more understandable.