SQL Exception : Unexpected Token - UCanAccess - java

I'm trying to create a new MS Access table from a Java program. The SQL query is below. I get an error saying:
net.UcanacessSQLException:UCAExc:::4.0.1 unexpected token: REQ-MTI
PreparedStatement prepStmt;
String createStmt = "CREATE TABLE [" + tableName + "] ([Test_Case_ID] CHAR (20) PRIMARY KEY, [Test_Name] CHAR (120),"
+ " [Test_Description] CHAR (100), [Req-MTI] CHAR (15), [Req-Card_ID] CHAR (50), [Req-H19] CHAR (20));";
prepStmt = conn.prepareStatement(createStmt);
prepStmt.executeUpdate();
I can't use underscores instead of the hyphen. I've tried putting all the table names in square brackets, quotations, ect, but nothing seems to be working. I've taken the generated string and pasted it into a MS Access query and it creates the table fine there.
Any help would be appreciated. Thanks!

I was able to sort-of reproduce your issue under UCanAccess 4.0.2. It seems to be getting confused by the spaces following the CHAR keyword. I could get the code to run if I specified the fields as, e.g., CHAR(20) instead of CHAR (20).
Edit re: question update
I was able to reproduce the issue under UCanAccess 4.0.1. The workaround is to use a Statement instead of a PreparedStatement to execute the DDL. (It's not even necessary to remove the spaces as described above, at least under 4.0.1.)

If column names contain any characters except letters, numbers, and underscores, the name must be delimited by enclosing it in back quotes (`)
so try changing your column name to :
`Req-MTI`

Related

Java program to transfer from SQL database to another in java : column field = reserved word

I am trying to run my java program, in which I have to transfer data from a DB to another one.
Well, the program works but one of the column field is named "public", and when I'm trying to transfer that data using jdbc, it crashes with the following statement:
"incorrect syntax near from keyword 'public'".
I've tried to load the column field as [public], (public), `public` works in SQL syntax but not in the program, since it has to check equivalence for "public", so "'public' is returning false.
Some code sample when i load the datas :
String publicDb = iArboFromExtranet.get(i).getString("public");
Some code sample when i transfer it :
private static final String PUBLIC = "public";
IArbo.set(PUBLIC, Strings.nullToEmpty(publicVar))
By the way, i cant rename the fields since i'm working for IT services industry. Its not our database
Since you're using a framework to generate your SQL, and you use a reserved word as a column name, you have a (tough?) choice to make:
Update the implementation of IArbo to quote reserved words (or all names).
Don't use IArbo.
Don't use a reserved word as a column name.
It looks like you're building SQL insert and/or update queries. Quote everything, so if the database field is MyField and the table is MyTable your query should have "MyTable" and "MyField" for this particular field. In Java you can build the string by escaping the double quote with a backslash:
queryString = "insert into \"MyTable\" (\"MyField\"...) values ('whatever'...)";

"UcanaccessSQLException: unexpected token" when column name contains apostrophe

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

Special characters in SQLiteDatabase android

I am at the verge of finishing my first android app. But I am stuck wondering something about saving special characters in SQLite Database.
When I take data from a edit view and put that data into my database, I am able to input all the special characters without handling anything.
for eg.
EditText editText1 = (EditText) findViewById(R.id.user_name);
String name = editText1.getText().toString();
db.execSQL("INSERT INTO DETAILS VALUES('" + name + "');");
Now the PROBLEM
even if I input ), (, ", * or any other special character, its able to insert that data
BUT as soon as I enter ' (apostrophe), there is an error(Log shows syntax). I have read almost every question related to special characters on stackoverflow but still I am not able to understand that even using ( or ) or " should generate a syntax error, same as in the case of apostrophe. Then why does it happen. Even though it works for me, but I am curios. Also what is the best way to escape these special characters ?
Thanks in advance
Do not use execSQL() for this!
SQLiteDatabase.insert() will build the statement for you, and also avoid any problem with special characters in the parameters.
ContentValues values = new ContentValues();
values.put("FIELD_NAME", name);
db.insert("DETAILS", null, values);
To understand what is happening, just check what is the resulting SQL statement from adding the parameter:
name = Scarlett -> INSERT INTO DETAILS VALUES('Scarlett'); (Ok)
name = O'Hara -> INSERT INTO DETAILS VALUES('O'Hara'); (Wrong)
Since the apostrophe is the string delimiter in SQL, there is one 'O' string plus Hara' which is not a valid token. In this case it just produces an error, but a maliciously crafted string could produce valid SQL which does unintended things.
That's why concatenating strings is a VERY BAD PRACTICE (TM) when writing SQL statements, as it can lead to SQL Injection. Remember the story of Bobby Tables!
To enter an apostrophe, you have to double it ('').
Because an apostrophe is a special character which delimits SQL strings.
So:
String sql = "INSERT INTO DETAILS VALUES('" + name + "')";
db.execSQL(sql.replaceAll("'", "''"));
Even better, you could bind your parameter:
db.execSQL("INSERT INTO DETAILS VALUES (?)", new String[]{name});
The ? is replaced and converted by the parameter passed as new String[]{name}
So, you don't even have to care about the ' characters in your string.
To answer the question in your comments:
A valid SQL String might be:
'This is an apostrophe: ''; this is a quote: "; this is an asterisk: *, ...'

newline charter \n gives "java.sql.SQLException: ORA-00911: invalid character\n" Oracle 11g

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

how to create user defined table (table name is in a string ) in oracle using java

how to create user defined table (table name is in a string ) oracle using java
String Tablename="student";
stmt=con.prepareStatement("create table"+Tablename+"(name varchar(12),class varchar(12))");
stmt.executeUpdate();
with out string i.e user defined table name it works fine:
stmt=con.prepareStatement("create table student (name varchar(12),class varchar(12))");
but the above listed versions which takes string as user name shows following error
java.sql.SQLException: ORA-00901: invalid CREATE command
Leave spaces before and after the table name, please.
Your original code resulted in this SQL command getting executed:
create tableMyTablename(name varchar(12),class varchar(12))
And in that, the tableMyTablename was not comprehensible for the DB...
Correctly:
stmt=con.prepareStatement("create table "+Tablename+" (name varchar(12),class varchar(12))");
Also, a few notes:
Java naming: variable names start with lowercase letters
this (preparing the statement) doesn't really make sense. It is not reusable to have a statement that can only create the same structure for a table.
it is wise to avoid the + to concatenate Strings, and other objects' string representations... It may have very unexpected results, even compile errors...
logging: in such situations, it is always wise to log the created SQL commands. Even a (yuck!) System.out.println(); is better than nothing...
Put a space after "create table" i.e.
"create table "
Your statement was being evaluated as create tablestudent...

Categories

Resources