SQL Syntax Error Exception when trying to insert row into table

为君一笑 提交于 2019-11-29 15:42:06

Two problems in your code:

  1. SQL statements don't need semicolon ; at the end. It will make the code fail.

  2. The code is prone to SQL Injection and is hard to maintain. Use a PreparedStatement instead:

This should be the working code:

String sql = "INSERT INTO MyAlbums VALUES (?, ?, ?, ?, ?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
if(album instanceof CDAlbum) {
    pstmt.setString(1, "CD");
    CDAlbum cdAlbum = (CDAlbum)album;
    pstmt.setString(4, cdAlbum.getArtist());
    pstmt.setString(5, cdAlbum.getTracks());
}
if(album instanceof DVDAlbum) {
    pstmt.setString(1, "DVD");
    DVDAlbum dvdAlbum = (DVDAlbum)album;
    pstmt.setString(4, dvdAlbum.getDirector());
    pstmt.setString(5, dvdAlbum.getPlotOutline());
}
pstmt.setString(2, album.getTitle());
pstmt.setString(3, album.getGenre());
pstmt.executeUpdate();

The big difference between plain string concatenation and this approach for your case is that PreparedStatement parameters will escape any ' and " and other characters for you.

XKCD #327 (http://xkcd.com/327/)

Use a PreparedStatement!

May I suggest:

try (final PreparedStatement preparedStatement = con.prepareStatement(sql)) {
    if (album instanceof CDAlbum) {
        CDAlbum cdAlbum = (CDAlbum) album;
        preparedStatement.setString(1, "CD");
        preparedStatement.setString(2, cdAlbum.getTitle());
        preparedStatement.setString(3, cdAlbum.getGenre());
        preparedStatement.setString(4, cdAlbum.getArtist());
        preparedStatement.setString(5, cdAlbum.getTracks());
    } else if (album instanceof DVDAlbum) {
        DVDAlbum dvdAlbum = (DVDAlbum) album;
        preparedStatement.setString(1, "DVD");
        preparedStatement.setString(2, dvdAlbum.getTitle());
        preparedStatement.setString(3, dvdAlbum.getGenre());
        preparedStatement.setString(4, dvdAlbum.getDirector());
        preparedStatement.setString(5, dvdAlbum.getPlotOutline());
    }
    dvdAlbum.getPlotOutline();
}

This prevents any possibility of weird values in the data causing the query to fail. Also note that I use a try-with-resources construct, this will always close the resources. Your current code has a memory leak if there is an error in the query - the exception will be thrown and the close() calls with be skipped. You have this issue in many places, when you read the file, when you open the connection, etc...

I have also changed your if...if to an if...else if as I suppose it's unlikely that a CDAlbum would also be a DVDAlbum. A naming note - acronyms in class names are best expressed as words - DvdAlbum rather than DVDAlbum.

Further I would suggest that you learn about method overloading as well as polymorphism. Any use if instanceof in your code is a sure sign of code smell.

Although the whole idea of storing completely disparate data in the same table is a sure sign of design problems. Further, fields like tracks - surely that needs to be another table?!

It is probably "Don't cry for me, Argentina". Do you see it?

You can breach security with wrong values.

Best use a prepared statement:

    String sql = "INSERT INTO MyAlbums(Title, Genre, X, Y) VALUES (?, ?, ?, ?, ?)";
    try (Statement statement = connection.createPreparedStatement(sql)) {
        if(album instanceof CDAlbum) {
            CDAlbum cdAlbum = (CDAlbum)album;
            statement.setString(1, "CD");
            statement.setString(2, cdAlbum.getTitle());
            statement.setString(3, cdAlbum.getGenre());
            statement.setString(4, cdAlbum.getArtist());
            statement.setString(5, cdAlbum.getTracks());
        } else if(album instanceof DVDAlbum) {
            DVDAlbum dvdAlbum = (DVDAlbum)album;
            statement.setString(1, "DVD");
            statement.setString(2, dvdAlbum.getTitle());
            statement.setString(3, dvdAlbum.getGenre());
            statement.setString(4, dvdAlbum.getDirector());
            statement.setString(5, dvdAlbum.getPlotOutline());
        }
        int updateCount = statement.executeUpdate();
        System.out.println("Album Added! (" + updateCount + " Records updated)");
    }

I have added some column names as good measure for future changes to the table scheme. And updateCount should give 1 for addition.

The try-with-resources closes statement irrespective of thrown exception / return / break.

P.S. "Don't" is probably the culprit, the apostrophe ends the quoted text, and that t appears in your error message.

sql = "INSERT INTO MyAlbums VALUES ('DVD', '" + dvdAlbum.getTitle() + "', '" + dvdAlbum.getGenre() + "','" + dvdAlbum.getDirector() + "', '" + dvdAlbum.getPlotOutline() + "');";

I don't think two ; required. Better to debug the code and take the SQL query and test in DB.

You need to escape any ' character in your cdAlbum.getTitle(), cdAlbum.getGenre(), cdAlbum.getArtist(), cdAlbum.getTracks() strings.

Better yet, use prepared statement and it will handle this for you and as a bonus you won't be vulnerable to SQL injection.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!