I am converting an existing program from JDBC-ODBC Bridge to UCanAccess. It has been working for years. The Java program writes to an MDB file. After conversion, one Insert command stopped working.
It throws "net.ucanaccess.jdbc.UcanaccessSQLException: unexpected token: [".
After some experimentation I determined that the problem is caused by three columns that include apostrophes in their names. Example: [Sched'd PO Place Date]. Apparently JDBC-ODBC Bridge did not care but UCanAccess does.
I am somewhat trapped with the existing MDB structure or I'd simply rename the fields. But there is no telling how many downstream reports could be broken if I did that. The MDB is used for Ad Hoc reporting.
Here is a simplified SQL Select version of the problem. It throws the same error as the Insert.
String cJD = "net.ucanaccess.jdbc.UcanaccessDriver";
String cS = "jdbc:ucanaccess://C:/MosAll/mosall.mdb";
String uid = "";
String pw = "";
String sql4 = "select [Sched'd PO Place Date] from [Tier 1] ";
Class.forName(cJD);
Connection con = DriverManager.getConnection(cS, uid, pw);
PreparedStatement pstmt4;
pstmt4 = con.prepareStatement(sql4);
pstmt4.execute();
Is there a way to "escape" the apostrophes or reconfigure ucanaccess so that the driver can execute them?
This issue has been fixed in UCanAccess 2.0.9.4.
Previous answer:
I have been able to recreate the issue with UCanAccess version 2.0.9.3.
select [Sched'd PO Place Date] ...
fails, but for now simply omitting the '
select [Schedd PO Place Date] ...
works okay. Interestingly, using backticks instead of square brackets
select `Sched'd PO Place Date` ...
also produces the exception
net.ucanaccess.jdbc.UcanaccessSQLException: unexpected token: [
With luck this will get fixed in a future release of UCanAccess.
have you tried table, columns names between `` (they not apostrophe but the one next to ~), the \' may work, and finally the JDBC standard way is to define the escape character at the end of the query:
String sql4 = "select [Sched\'d PO Place Date] from [Tier 1] { escape '\'}"
You may want to try the one above also with ``instead of []
Finally, your last resource is "select *" and extract the right column yourself
Related
I want to insert a data using JDBC, whenever I execute the program then it shows me some Mysql error:
Insert statement:
String sql = "INSERT into books(name, isbn, author, category, desc, published) VALUES('"+name+"','"+isbn+"','"+author+"','"+category+"', '"+desc+"','"+book_published+"')";
I am trying to convert the string to date here using :
String yr = year.getSelectedItem().toString();
String mn = month.getSelectedItem().toString();
String dy = day.getSelectedItem().toString();
String book_date = yr+"-"+mn+"-"+dy;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd",
Locale.ENGLISH);
try{
Date book_published = df.parse(book_date);
}catch(...){...}
and it shows me error like :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'desc, published) VALUES('skd flakj','klsdjf askj','kl jasdklfj kl','kls djfklj f' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
Please help me figure out what is the problem here.
Your code is prone to SQL injection attacks due to use of normal query statements. To secure your query use preparedstatement.
As per your query issue, DESC is a reserved word. So you can't use it as column name.View this for complete list of reserved words.
desc is a reserved word for MySQL, which means u can just use it plainly.
To use it without getting an error from MySQL, u should use ` surround the reserved word.
Ps: u SQL statement may suffer from SQL injection if using user-inputed parameters, attackers can use it to get control of ur system.Maybe u should try to hv a look on this one.
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
desc is not a particularly good column name because it's a reserved word in MySQL. I'm not sure if this is the only issue here but you may want to try surrounding desc with ticks, like so:
String sql = "INSERT into books(`name`, `isbn`, `author`, `category`, `desc`, `published`) VALUES('"+name+"','"+isbn+"','"+author+"','"+category+"', '"+desc+"','"+book_published+"')";
It's good practice anyway.
Edit: and as others have mentioned, prepared statements are safer when saving untrusted input to a database.
I have some problem trying to implement a simple JDBC query into a Java application.
So I have the following query:
SELECT D.*
FROM coda_tx c, documenti_tx d
WHERE C.FK_TIPO_DOC = 99
AND C.FK_STATO = 1
AND C.FK_PIVA_MITTENTE = '05779711000'
AND C.PK_CODA = D.PFK_CODA
AND C.CANALE='STA'
If I run it into Oracle SQL Developer it run well and I obtain 2 records as result.
So I have to implement this query into a DAO class of my application in which I definied the following method:
public void getListaFatturePDF(String partitaIva) {
System.out.println("INTO ottieniListaFatturePDF()");
Blob blobPdf;
String sql;
StringBuffer sb = new StringBuffer();
sb.append("SELECT D.*");
sb.append("FROM coda_tx c, documenti_tx d");
sb.append("WHERE C.FK_TIPO_DOC = 99");
sb.append("AND C.FK_STATO = 1");
sb.append("AND C.PK_CODA = D.PFK_CODA");
sb.append("AND C.CANALE='STA'");
sb.append("AND C.FK_PIVA_MITTENTE = '");
sb.append(partitaIva);
sb.append("';");
sql = sb.toString();
try {
statment = connection.createStatement();
ResultSet rs = statment.executeQuery(sql);
System.out.println("ResultSet obtained");
} catch (SQLException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
The problem is that when I try to perform the previous method is thrown the following SQLException:
java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30)
at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:762)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111)
at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309)
at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422)
at DAO.FatturaDAO.getListaFatturePDF(FatturaDAO.java:43)
at mainPkg.Main.main(Main.java:74)
Why? I think that maybe is something wrong in the SQL syntax but I am not sure about it (because if I perform the query into Oracle SQL Developer it works fine) What am I missing? How can I fix it?
Tnx
executeQuery() automatically adds a semicolon to a statement when executing it.
Change the line sb.append("';"); to sb.append("'");.
Also you'll need to add spaces at the end or at the beginning of each line, your statements are invalid otherwise.
Add a white space at the end of each line so that the keyword on the next line is not clumped with it, e.g.:
sb.append("SELECT D.* ");
instead of
sb.append("SELECT D.*");
and also remove the trailing semicolon.
This is how it worked for me:
See the aligned query SELECT, FROM, UNION, etc keywords must be compatible along with the queries.
Also, see the white/very thin lines going down along these keywords. Re-aligning worked for me. Lastly, I removed the ; at the end.
All I am mentioning about .SQL files. This might be the same issue in regular java class as well.
The semi colon was the culprit, for some reason the SQL with the ; at the end did not work in my sprint boot service.
Once I removed it, it worked fine
Java DB2 Sql command throws an error if i have a ' in my String i tried to replace it with a escape sequence but it would not work on the DB2 end any help ? I want the ' to be present in the String.
Error
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-10, SQLSTATE=42603, SQLERRMC=', DRIVER=3.63.123
Java
String FUNC_VP = "Chris O'Connor/Henry/George";
String myQuery = "SELECT DISTINCT(VICE_PRES) FROM EMP_HC WHERE FUNC_VP ='"+funcvp_name.replace("'", "/'")+"'";
Use a PreparedStatement and its setParameter() methods. It will handle things like escaping for you, and you'll never have to wonder how a particular database might handle things. It also prevents SQL injection, so there's no good reason not to use it.
Try
String FUNC_VP = "Chris O''Connor/Henry/George";
To escape an apostrohe on DB2 it seems you have to use two apostrophes
I have Oracle DB 11g Enterprise Edition and I want to create a table by reading the sql script from a file.Through java code I am reading following sql script from a file and storing it in a String sqlBlock:
CREATE SEQUENCE VerHist_SeqNum
START WITH 1
INCREMENT BY 1;
CREATE TABLE VerHist
(
SequenceNumber NUMBER(10,0) NOT NULL,
SQLFileName VARCHAR2(100) NOT NULL,
STATUS VARCHAR2(10) NOT NULL,
AppliedDate DATE NOT NULL,
DateCreated DATE
DEFAULT (SYSDATE),
DateUpdated DATE
DEFAULT (SYSDATE),
CONSTRAINT PK_VerHist PRIMARY KEY( SequenceNumber ),
CONSTRAINT UC_VerHist_SQLFileNa UNIQUE( SQLFileName )
);
CREATE OR REPLACE TRIGGER VerHist_SeqNum_TRG
BEFORE INSERT
ON VerHist
FOR EACH ROW
BEGIN
SELECT VerHist_SeqNum.NEXTVAL INTO :NEW.SequenceNumber
FROM DUAL;
END;
When I execute this query it gives
java.sql.SQLException: ORA-00911: invalid character\n
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at
oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743) at
oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:207) at
oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:946)
at
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1168)
at
oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1687)
at
oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1653)
Following is my code to execute the sql block:
Statement stmt = conn.createStatement();
String sqlBlock = //"this contains the content of the file (it contains \n charters)";
stmt.execute(sqlBlock);
Is the newline charter invalid here, if yes, how to get this working otherwise?
Please note that when I copy paste the contents of this file and run the script through Oracle SQL Developer it runs fine.
I think the \n reference is a red-herring, and an artefact of how the error is being logged. You're trying to run two SQL statements, separated by a semi-colon, in one execute. That is not allowed. The semi-colon is a statement separator in SQL*Plus, not in SQL, and will generate an ORA-00911 even with a single statement. And execute has to be a single statement.
If you were doing DML you could wrap the statements in a PL/SQL block and execute that, but since this is DDL you can't do that unless you resort to dynamic SQL, which is going to be overly complicated and messy for what you're trying to do.
You need to put each statement in a separate file (without the trailing semi-colon on the create sequence; you still need it on the create trigger because there it is ending the trigger's PL/SQL block, not acting as a statement separator - confusing, I know), and read and execute them separately. Then each execute has a single statement, and will be much happier.
As an aside, you don't need to select your sequence value into your variable in 11g; you can now do it like this:
CREATE OR REPLACE TRIGGER VerHist_SeqNum_TRG
BEFORE INSERT
ON VerHist
FOR EACH ROW
BEGIN
:NEW.SequenceNumber := VerHist_SeqNum.NEXTVAL;
END;
When you copy paste the contains of the file to browser. Browser will treat \n as new line.
Whereas for the code /n is character only.
Try to replace \n with single space and then run it will work
sqlBlock = sqlBlock.replaceAll("\n"," ");
Remove the \n from the query. If you want the query to be formatted in sql developer, you can select the query and press Ctrl+F7
My clienet(android) sends user details in the user form and my servlet just enters those details into to the database(postgre sql). I tried to give to do a sql injection attack by giving ;DELETE FROM tbl_name; in the username field.
But postgresql just treats it as a value and enters it as the username. How do I do the SQLINjection attack. (I have not done any sort of checking in the postgre sql or the servlet).Does it mean that postgresql is SQLInjection attack resistant?
I am using the following statements to insert the data:
String insert ="insert into userdetail(username,id,sno) values('"+username+"','"+userid+"','"+no+"')";
Statement stmt = conn.createStatement();
stmt.executeUpdate(insert);
The username contains ;DELETE FROM userdetail;.
I have tried the following also:
');DELETE FROM userdetail;
But it fives the following error:
org.postgresql.util.PSQLException: ERROR: unterminat
ed quoted string at or near "');"
Position: 1
I have also tried this:
','',');DELETE FROM userdetail;
This gives the following error:
17:36:46,828 INFO [STDOUT] org.postgresql.util.PSQLException: ERROR: unterminat
ed quoted string at or near "''');"
Position: 38
but does not delete the records of the table. How do I make it delete the tables records?
The key trick is that the complete statement string must
do something innovative
be still valid SQL
So far the answers have omitted the second part. But an invalid SQL statement will abort the transaction and hence most likely does nothing at all. If you set autoCommit to true that attack may be easier.
But this string should to the trick in a "clean" way:
foo', '42', '42'); delete from userdetail; --
Note: The resulting string is this (line breaks only for better reading):
insert into userdetail(username,id,sno) values('foo', '42', '42');
delete from userdetail;
-- ','21','21')
Both the INSERT part is complete and correct (assuming no unique index collisions of course) and also the DELETE is correct. The potentially offending rest is masked by the trailing SQL comment --.
hat type of attack that you are describing - even if you get the use of single quotes "correct" - will not work with PostgreSQL
It does not work because the JDBC driver does not allow to run more than one statement in a single Statement.execute() call.
It will throw an error ("invalid character" pointing to the ;)
(Sorry, this is only true for Oracle)
There are other scenarios that would work with a badly written application.
Assuming the application is checking the username/password like this (note that this is a very simplified example!)
String sql = "SELECT count(*) FROM users WHERE username = '";
sql += username;
sql += "' AND password = '";
sql += pwd;
sql += "'"
then a possible attack could be to enter the value:
' or 1=1 or '' = '
into the password field.
This would wind up with the following generated SQL
SELECT count(*) FROM users WHERE username = 'arthur'
AND password = '' or 1=1 or ''=''
Which would always be true and one could login without a password.
Try ', '', '');DELETE FROM tbl_name; to delete your table.
In simplest case, you can give ' as user name and your server should give you an error.
Besides, there is no SQL injection resistant database because SQL injection happens because of poorly coded server-side (CGI) script and not because of database weaknesses.