java - sql 语法错误,但串联文本在 Datagrip 中运行正常

标签 java postgresql intellij-idea

我正在尝试运行查询,但运行时出现错误。

但是,我使用的是 Intellij,当我使用复制字符串连接到剪贴板功能并在 datagrip 中运行查询时,查询运行良好(输入参数后)

我收到的错误是“错误:“tstoredarticle”处或附近的语法错误\n 位置:199”

我觉得有点奇怪,它显示在 tstoredartiacle 之后有行更改,但除此之外我看不出有什么问题。

哪些问题可能会导致此类问题?

我在 intellij 中的查询如下所示:

    private ResultSet getHuaweiSqlQuery(Integer intBrandID, Integer intStorageID, Vector<Integer> vecArticleTypes, int iCurrencyID, int iContactSupplierID, int secondaryStorage, BigDecimal exchangeRate) throws SQLException {
        return Hibernate3To4Utils.getConnection(session).createStatement().executeQuery("SELECT storedarticleid, "
                + " CASE WHEN storedarticle_storageid = " + intStorageID
                + " THEN id_storedarticleid_replacement ELSE"
                + " (SELECT COALESCE(id_storedarticleid_replacement, storedarticleid)"
                + " FROM etel.tstoredarticle x"
                + " WHERE tstoredarticle.storedarticle_articleid = x.storedarticle_articleid"
                + " AND x.storedarticle_storageid = " + intStorageID + ")"
                + " END as id_storedarticleid_replacement,"
                + " articlename,"
                + " articledescription, CASE WHEN price IS NULL THEN last_innprice*" + exchangeRate
                + " ELSE price END as last_innprice, id_modelids[1] as order_modelid, storedarticleamount-amount_in_order-amount_waiting as disponibelt,"
                + " amount_in_order, amount_in_bestilling, sum(tusedarticle.amount) as ant_artikler, articleid,amount_waiting, location"
                + " FROM etel.tstoredarticle"
                + " INNER JOIN etel.tarticle as b ON storedarticle_articleid = b.articleid"
                + " LEFT JOIN etel.tusedarticle ON usedarticle_storedarticleid = storedarticleid"
                + " AND ((tusedarticle.datesnap >= CAST(now() as date)-" + LOOK_BACK_DAYS
                + " AND usedarticlefromstorage = true) OR waiting = true)"
                + " LEFT JOIN etel.torder ON usedarticle_orderid = orderid AND torder.id_serviceplaceid = " + Constants.SERVICEPLACE
                + " LEFT JOIN etel.tsupplier_price ON id_articleid = b.articleid"
                + " AND tsupplier_price.id_serviceplaceid = " + Constants.SERVICEPLACE
                + " AND tsupplier_price.id_currencyid = " + iCurrencyID
                + " AND tsupplier_price.id_contactid_supplier = " + iContactSupplierID
                + " LEFT JOIN etel.tusedarticle as last_used on storedarticleid = last_used.usedarticle_storedarticleid"
                + " AND last_used.usedarticleid = (select MAX(latest_usedarticle.usedarticleid) from etel.tusedarticle as latest_usedarticle where"
                + " latest_usedarticle.usedarticle_storedarticleid = storedarticleid)"
                + " WHERE storedarticle_storageid IN(" + intStorageID + ", " + secondaryStorage + ") AND b.id_brandid = " + intBrandID
                + " AND id_articletypeid IN (" + getStringFromArray(vecArticleTypes.toArray()) + ")"
                + " AND tstoredarticle.passive <> true"
                + " GROUP BY storedarticleid,id_storedarticleid_replacement, articlename, articledescription, last_innprice, id_modelids[1],"
                + " storedarticleamount, amount_in_order, amount_in_bestilling, articleid,price,amount_waiting, location, last_used.datesnap"
                + " ORDER BY id_storedarticleid_replacement, storedarticleid");
    }

这是使用复制字符串连接到剪贴板功能后的相同查询: (运行良好)

SELECT storedarticleid, 
 CASE WHEN storedarticle_storageid = ?
 THEN id_storedarticleid_replacement ELSE
 (SELECT COALESCE(id_storedarticleid_replacement, storedarticleid)
 FROM etel.tstoredarticle x
 WHERE tstoredarticle.storedarticle_articleid = x.storedarticle_articleid
 AND x.storedarticle_storageid = ?)
 END as id_storedarticleid_replacement,
 articlename,
 articledescription, CASE WHEN price IS NULL THEN last_innprice*?
 ELSE price END as last_innprice, id_modelids[1] as order_modelid, storedarticleamount-amount_in_order-amount_waiting as disponibelt,
 amount_in_order, amount_in_bestilling, sum(tusedarticle.amount) as ant_artikler, articleid,amount_waiting, location
 FROM etel.tstoredarticle
 INNER JOIN etel.tarticle as b ON storedarticle_articleid = b.articleid
 LEFT JOIN etel.tusedarticle ON usedarticle_storedarticleid = storedarticleid
 AND ((tusedarticle.datesnap >= CAST(now() as date)-42
 AND usedarticlefromstorage = true) OR waiting = true)
 LEFT JOIN etel.torder ON usedarticle_orderid = orderid AND torder.id_serviceplaceid = ?
 LEFT JOIN etel.tsupplier_price ON id_articleid = b.articleid
 AND tsupplier_price.id_serviceplaceid = ?
 AND tsupplier_price.id_currencyid = ?
 AND tsupplier_price.id_contactid_supplier = ?
 LEFT JOIN etel.tusedarticle as last_used on storedarticleid = last_used.usedarticle_storedarticleid
 AND last_used.usedarticleid = (select MAX(latest_usedarticle.usedarticleid) from etel.tusedarticle as latest_usedarticle where
 latest_usedarticle.usedarticle_storedarticleid = storedarticleid)
 WHERE storedarticle_storageid IN(?, ?) AND b.id_brandid = ?
 AND id_articletypeid IN (?)
 AND tstoredarticle.passive <> true
 GROUP BY storedarticleid,id_storedarticleid_replacement, articlename, articledescription, last_innprice, id_modelids[1],
 storedarticleamount, amount_in_order, amount_in_bestilling, articleid,price,amount_waiting, location, last_used.datesnap
 ORDER BY id_storedarticleid_replacement, storedarticleid

最佳答案

不要使用字符串连接与动态文本值来构建 SQL 语句。

首先,如果文本值是由用户提供的,那么您很容易受到 SQL injection 的攻击。攻击,允许黑客窃取您的数据并删除您的表。

但是在正确引用和转义文本值时也会遇到问题。

相反,请使用 PreparedStatement,将 ? 标记放置在动态值需要到达的任何位置。这是剪贴板中的字符串。

示例:您正在做:

String name = "John";
String sql = "SELECT * FROM Person WHERE name = " + name;

这会在运行时为您提供以下文本:

SELECT * FROM Person WHERE name = John

这是错误的,因为文本值需要加引号:

SELECT * FROM Person WHERE name = 'John'

你可以试试

String name = "John's Cross";
String sql = "SELECT * FROM Person WHERE name = '" + name + "'";

但这也是错误的,因为这个新文本值嵌入了引号,并且会产生:

SELECT * FROM Person WHERE name = 'John's Cross'

为了得到正确的结果,请使用 PreparedStatement:

String name = "John's Cross";
String sql = "SELECT * FROM Person WHERE name = ?";

PreparedStatement stmt = Hibernate3To4Utils.getConnection(session).prepareStatement(sql);
stmt.setParameter(1, name);
return stmt.executeQuery();

JDBC 驱动程序将处理任何所需的转义,从而保护您免受 SQL 注入(inject)攻击和 SQL 语法错误。

关于java - sql 语法错误,但串联文本在 Datagrip 中运行正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58541448/

相关文章:

java - 使用 RestTemplate 时有很多 TIME_WAIT 连接?

java - Intellij Idea 社区不断卡住,Maven 项目长时间卡在读取 pom.xml 上

Javafx:通过pane.getChildren().get(index)恢复 Pane 中包含的标签文本

ruby-on-rails - Postgres 随机停止工作(Rails,PGSQL.5432)

java - 开发javaagents时如何运行测试?

JavaFX 文本流 overflow hidden 文本(剪辑或省略号)

windows - 在 Windows 上的 R 中执行 PSQL

java - 用于生成自定义 IntelliJ toString 方法的 Velocity 模板

java - IntelliJ 将 Lombok 生成的方法突出显示为 “cannot resolve method”

postgresql - 使用比较运算符比较 postgres 中的字符串?