SQL syntax error when concatenating query string - java

try(Connection dbConnection = DBConnectionManager.getIntakeConnection();
PreparedStatement preparedStmtSetMaxStrikeId = dbConnection.prepareStatement(
"SELECT MAX(strike_id) FROM strike WHERE 'SELECT p.party_type_id,"
+ "p.csa_score,p.party_tn,p.rec_create_date,"
+ "s.strike_id, s.strike_date, s.strike_level, s.strike_status,
s.appealable,s.appeal_status,s.rec_change_date,s.event_id,
s.is_email_processed,s.policy_id"
+ "FROM strike s "
+ "INNER JOIN parties p"
+ "ON p.party_id = s.party_id"
+ "WHERE p.account ='"+appealStatus.getSubscriberId()
+"'AND strike_status = '"+OCIRISConstants.STRIKE_STATUS_ACTIVE+"' ");)
The error is below.
Integers in the error are subscriber ids.
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 '0957936101205'AND strike_status = 'ACTIVE'' at line 1

The error message says:
near '0957936101205'AND strike_status = 'ACTIVE'' at line 1
It's actually identifying the 0 following the ', which ends the text literal started in the first line, because this is bad SQL:
SELECT MAX(strike_id) FROM strike WHERE '...'0957936101205'AND strike_status = 'ACTIVE'
-- ^^ BAD
Here is the code annotated with comments:
try(Connection dbConnection = DBConnectionManager.getIntakeConnection();
PreparedStatement preparedStmtSetMaxStrikeId = dbConnection.prepareStatement(
"SELECT MAX(strike_id) FROM strike WHERE 'SELECT p.party_type_id,"
// ^ What is this? Even without ' it makes no sense
// ^ But it STARTS A TEXT LITERAL
+ "p.csa_score,p.party_tn,p.rec_create_date,"
+ "s.strike_id, s.strike_date, s.strike_level, s.strike_status, s.appealable,s.appeal_status,s.rec_change_date,s.event_id,s.is_email_processed,s.policy_id"
+ "FROM strike s "
// ^ Missing space, but it's in a text literal so doesn't matter
+ "INNER JOIN parties p"
+ "ON p.party_id = s.party_id"
// ^ Missing space, but it's in a text literal so doesn't matter
+ "WHERE p.account ='"+appealStatus.getSubscriberId()
// ^ Missing space, but it's in a text literal so doesn't matter
// ^ END TEXT LITERAL from first line
// ^ error complains about inserted value 0957936101205
+"'AND strike_status = '"+OCIRISConstants.STRIKE_STATUS_ACTIVE+"' ");)
// ^ Starts a new text literal
// ^ Missing space, but it's in a text literal so doesn't matter
// ^ end text literal
// ^ would complain about inserted value ACTIVE
// ^ Dangling '
Also, you shouldn't be using string concatenation to build the SQL, since it'll cause syntax errors and leave you susceptible to SQL Injection attacks, allowing hackers to steal your data and delete your tables.
Assuming the initial SELECT MAX( ... WHERE ' is in error, here is a cleaned up version, formatted for clarity:
String sql = "SELECT p.party_type_id, p.csa_score, p.party_tn, p.rec_create_date" +
", s.strike_id, s.strike_date, s.strike_level, s.strike_status" +
", s.appealable, s.appeal_status, s.rec_change_date, s.event_id" +
", s.is_email_processed, s.policy_id" +
" FROM strike s" +
" INNER JOIN parties p ON p.party_id = s.party_id" +
" WHERE p.account = ?" +
" AND strike_status = ?";
try (Connection conn = DBConnectionManager.getIntakeConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, appealStatus.getSubscriberId());
stmt.setString(2, OCIRISConstants.STRIKE_STATUS_ACTIVE);

The specific syntax error there is saying that there should be a space before the AND on the last line of the query:
+"' AND strike_status // ... etc
^ Insert a space here
However, you have several other problems there, e.g. you have not got spaces around line breaks, e.g.
+ "INNER JOIN parties p"
+ "ON p.party_id = s.party_id"
would become
+ "INNER JOIN parties pON p.party_id = s.party_id"
You should insert more spaces appropriately, either at the start or end of each line.
There are other syntax errors like WHERE 'SELECT. You need to check all of your syntax very carefully.
Also: concatenating values into prepared statements somewhat defeats the point of prepared statements. See the Javadoc for examples of how to use them correctly.

Related

TO_DATE in Oracle JDBC PreparedStatement giving invalid identifier

I am a bit baffled by this as I'm sure I have done it a hundred times but from this snippet of JDBC prepared statement:
"SELECT {0} FROM " +
"(select a.* " +
"from TABLE a " +
"inner join TABLE p ON " +
"and p.AS_OF_DT = TO_DATE(?, 'yyyyMMdd')";
...
pStmt.setString(1, dateAsString);
I am getting
java.sql.SQLSyntaxErrorException: ORA-00904: "YYYYMMDD": invalid identifier
I can reproduce the error in TOAD by removing the quotes around YYYYMMDD.
What do I need to do inside the prepared statement String to prevent this?
I have tried
playing with the upper/lowercase of YYYYMMDD
Ensuring the dateAsString is in the right format
Escaping the quotes like ''YYYYMMDD'' and '''YYYYMMDD'''

error in java about SQLsyntax while query works correctly in MySQL

while creating a program for a store that lists his assortment in a txt-file getting his information from a database from MySQL(phpMyAdmin), I always get the same error in netbeans while running the file. Netbeans show this error: "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 '.....' at line 1". my Query is correct, i've checked over a hundred times in MySQL and it gives always the right tables. also in java i've checked my code plenty of times.
i've googled it and find some other people with some similar issues but none of the proposed solutions work for my project. i've entered extra quotation marks (because I forget them). here's my code:
String Lijst = "";
Connection con = null;
try
{
con = getConnection();
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
String sql = "SELECT ArtikelWinkel.Artikelnummer, Artikel.Naam, Artikel.Prijs, Artikel.GekregenPunten, ArtikelMetBonus.MinimumAantalGekocht, ArtikelMetBonus.BonuspuntenVerdiend, PuntenInwisselbaarArtikel.PrijsInPunten, PuntenInwisselbaarArtikel.MinimumGeldbedrag "
+ "FROM ArtikelWinkel LEFT OUTER JOIN Artikel ON Artikel.Artikelnummer=ArtikelWinkel.Artikelnummer "
+ "LEFT OUTER JOIN ArtikelMetBonus ON ArtikelWinkel.Artikelnummer=ArtikelMetBonus.Artikelnummer "
+ "LEFT OUTER JOIN PuntenInwisselbaarArtikel ON ArtikelWinkel.Artikelnummer=PuntenInwisselbaarArtikel.Artikelnummer"
+ "WHERE ArtikelWinkel.Naam='" + naamWinkel + "'";
ResultSet srs = stmt.executeQuery(sql);
Lijst = "Naam Winkel - Artikel - Artikelnummer - Prijs - Gekregen punten per artikel - "
+ "min. # kopen om bonus te verdienen - # bonuspunten verdiend - min. bedrag kopen om prijs in punten \n";
while(srs.next())
{
Lijst +="\t\t"+ naamWinkel +" - "+srs.getString("Artikel.Naam")+" - "
+srs.getString("ArtikelWinkel.Artikelnummer") +" - "+srs.getString("Artikel.Prijs")
+ " - "+srs.getString("Artikel.GekregenPunten") +" - " +srs.getString("ArtikelMetBonus.MinimumAantalGekocht") +
" - "+srs.getString("ArtikelMetBonus.BonuspuntenVerdiend") + " - " +srs.getString("PuntenInwisselbaarArtikel.MinimumGeldbedrag")+ "\n";
}
con.close();
they were also people that suggested te let out the sql between the brackets in the statement: ResultSet srs = stmt.executeQuery(sql); I found that very unlogical and it gave an error too.
Some people thought I may had a connection problem but i have other methods in my class that work perfectly with my connectionMethod.
Any suggestions? thank you very much
You didn't put space before WHERE at SQL query.
String sql = "SELECT.. .."
...PuntenInwisselbaarArtikel.Artikelnummer"
+ "WHERE ArtikelWinkel.Naam='" + naamWinkel + "'"; |_ put space here.
There is no space between Artikelnummer and your WHERE clause, change your query like this and try again:
+ "LEFT OUTER JOIN PuntenInwisselbaarArtikel ON ArtikelWinkel.Artikelnummer=PuntenInwisselbaarArtikel.Artikelnummer"
+ " WHERE ArtikelWinkel.Naam='" + naamWinkel + "'";

SQL Query Will Not Execute SQLite, Java

Problem Synopsis:
When attempting to execute a SQL query in Java with a SQLite Database, the SQL statement fails to return from the execute() or executeQuery() method. In other words, the system "hangs" when executing this SQL statement.
Question:
What am I doing wrong to explain why the ResultSet never "returns?"
TroubleShooting
I tried to narrow the problem and the problem seems to be with the Java execute() or executeQuery(). A ResultSet never seems to return. For example, I tried executing exactly the same query directly in SQLite (that is, using a SQLite DB manager). The query (outside Java) executes in about 5ms and returns the valid result set.
NOTE: No exception is thrown. The system merely seems to "hang" and becomes unresponsive until a manual kill. (waiting more than 10 minutes.)
Code:
I heavily edited this code to make the problem simpler to see. (In production, this uses Prepared Statements. But, the error occurs in both methods--straight Statement and prepared Statement versions.)
Basically, the SELECT returns a single DB item so the user can review that item.
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT d1.id, d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
Configuration:
Java 6,
JDBC Driver = Xerial sqlite-jdbc-3.7.2,
SQLite 3,
Windows
Update
Minor revision: as I continue to work with this, adding a MIN(d1.id) to the beginning of the SQL statement at least returns a ResultSet (rather than "hanging"). But, this is not really what I wanted as the MIN obviates the LIMIT function.
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT MIN(d1.id), d1.id,
d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
What a messy SQL statement (sorry)! I don't know SQLite, but why not simplify to:
SELECT DISTINCT md.id, md.sourcefullfilepath, md.sourcefilepath, md.sourcefilename,
dc.classificationid, dc.classid, dc.userid
FROM MatterDataset md
LEFT JOIN DocumentClassification dc
ON dc.documentid = md.id
AND (dc.classid = 1 OR dc.classid = 2 )
AND dc.userid < 0
LEFT JOIN PrivilegeLog pl
ON md.id = pl.documentparentid
AND md.matterid = pl.matterid
WHERE pl.privilegelogitemid IS NULL
AND md.matterid = \'100\'
ORDER BY md.id LIMIT 1 ;
I was uncertain whether you wanted to LEFT JOIN or INNER JOIN to DocumentClassification (using LEFT JOIN and then put requirements on classid and userid in the WHERE statement is - in my opinion - contradictory). If DocumentClassification has to exist, then change to INNER JOIN and put the references to classid and userid into the WHERE clause, if DocumentClassification may or may not exist in your result set, then keep the query as I suggested above.
I went back and started over. The SQL syntax, while it worked outside Java, simply seemed too complex for the JDBC driver. This cleaned-up revision seems to work:
SELECT DISTINCT
MatterDataset.id, MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath,
MatterDataset.sourcefilename
FROM MatterDataset , DocumentClassification
ON DocumentClassification.documentid = MatterDataset.id
AND MatterDataset.matterid = DocumentClassification.matterid
LEFT JOIN PrivilegeLog ON MatterDataset.id = PrivilegeLog.documentparentid
AND MatterDataset.matterid = PrivilegeLog.matterid
WHERE PrivilegeLog.privilegelogitemid IS NULL
AND MatterDataset.matterid = '100'
AND (DocumentClassification.classid = 1 OR DocumentClassification.classid = 2)
AND DocumentClassification.userid = -99
ORDER BY MatterDataset.id LIMIT 1;
A nice lesson in: just because you can in SQL doesn't mean you should.
What this statement does is essentially locates items in the MatterDataset Table that are NOT in the PrivilegeLog table. The LEFT JOIN and IS NULL syntax locate the items that are "missing." That is, i want to find items that are in MatterDataset but not yet in PrivilegeLog and return those items.

Java Regex capture any (.*) with DOTALL ignores zero-width positive lookahead

Not a regex expert, but I know enough to be dangerous, need some help with an expression I am working on. Long story short, a recent database upgrade has invalidated thousands of queries within string literals of a legacy application that I support. I am writing a few expressions to capture the majority of these and hopefully fix them programatically.
Consider the following:
Query query = session
.createSQLQuery("SELECT distinct p.userid, p.name, f.hsid, "
+ "p.vid, p.vname, p.paymentdate, p.amount "
+ "FROM vk.payment p, (select * from vs.fuser) fu, (select * from vs.fac) f "
+ "WHERE p.description = 'Check' AND "
+ "p.paymentdate >= :startDate and p.paymentdate <= :endDate AND "
+ "fu.userid = p.userid AND fu.facid = f.facid "
+ "ORDER BY p.userid");
query.setParameter("startDate", startDate);
query.setParameter("endDate", endDate);
I have the following DOTALL expression to attempt and capture simply the ugly contents of the method argument.
(?s)(?<=\.createSQLQuery\(")(.*)(?="\)\;)
I specify the DOTALL flag with (?s) a non-capturing look behind to get \.createSQLQuery\(", capture everything including line breaks with (.*), and finally a non capturing positive lookahead to stop the capture at "\)\;.
I am expecting to capture the following:
SELECT distinct p.userid, p.name, f.hsid, "
+ "p.vid, p.vname, p.paymentdate, p.amount "
+ "FROM vk.payment p, (select * from vs.fuser) fu, (select * from vs.fac) f "
+ "WHERE p.description = 'Check' AND "
+ "p.paymentdate >= :startDate and p.paymentdate <= :endDate AND "
+ "fu.userid = p.userid AND fu.facid = f.facid "
+ "ORDER BY p.userid
Instead the expression is a lot greedier than I anticipated and is capturing this:
SELECT distinct p.userid, p.name, f.hsid, "
+ "p.vid, p.vname, p.paymentdate, p.amount "
+ "FROM vk.payment p, (select * from vs.fuser) fu, (select * from vs.fac) f "
+ "WHERE p.description = 'Check' AND "
+ "p.paymentdate >= :startDate and p.paymentdate <= :endDate AND "
+ "fu.userid = p.userid AND fu.facid = f.facid "
+ "ORDER BY p.userid");
query.setParameter("startDate", startDate);
query.setParameter("endDate", endDate);
... to EOF
The thing is that without the DOTALL the expression works as expected on a single line:
Query query = session.createSQLQuery("SELECT .... ");
and captures without the remaining characters on the end...
SELECT ....
Is there some aspect of DOTALL that every regex guru seems to know that does not seem to be documented anywhere? Does DOTALL not work with positive lookahead?
I appreciate any help!
Make the * quantifier non-greedy by adding a ? after it, like so: .*?
Also why are you even using lookarounds? It can lead to undesired behavior in some cases to use them without thought like this. (And it always irritates me. (-; )
You could just use:
(?s)\.createSQLQuery\("(.*?)"\);

Problem with PrepareStatement in Java

I have created table with 3 fields language,country,install type. When I write a query to print the maximum occuring value in each of the field, I am getting a weird problem.Can anyone say the reason.Here is my code.
PreparedStatement ps1= null;
ps1 = conn.prepareStatement("desc Configuration");
ResultSet rs1=ps1.executeQuery();
while(rs1.next()) {
System.out.print(rs1.getString(1)+":");
PreparedStatement ps2= null;
ps2 = conn.prepareStatement("select ? from Configuration c1 "+
" group by language "+
" having count(*) >= all " +
" ( select count(*) from Configuration c2 "+
" group by language )");
ps2.setString(1,rs1.getString(1));
ResultSet rs2=ps2.executeQuery();
while(rs2.next())
System.out.print(rs2.getString(1));
System.out.println();
}
The output I am getting here is language:language But the output what I am expecting is
language:english like that. I am getting later output if i replace '?' with language in the prepare statement.But if i give the same with ? I am getting what ever I have given for ps2.setString.
Why is this happening. Any solutions?
? in prepared statements is not a placeholder for textual substitution, it's a parameter, therefore its value is always interpreted as data, not as an arbitrary part of query syntax.
So, in this case the actual query being executed is an equivalent of select 'language' from ....
If you need to substitute parts of the query other than data, you have to use concatenation (beware of SQL injections!):
ps2 = conn.prepareStatement("select "
+ rs1.getString(1)
+ " from Configuration c1 group by language having count(*) >= all( select count(*)from Configuration c2 group by language )");
You can't set column names using a PreparedStatement. You can only set column values.
Instead of using this approach, you will have to build the sql yourself using concatenation, for example:
String sql = "select "+ rs1.getString(1) + " from Configuration c1 group by language having count(*) >= all( select count(*)from Configuration c2 group by language)";
The '?' mark in ps2 is recognized as literal-string. Not as a column name.

Categories