Синтаксическая ошибка SQL, но объединенный текст прекрасно работает в Datagrip - PullRequest
0 голосов
/ 24 октября 2019

Я пытаюсь выполнить запрос, но я получаю сообщение об ошибке при его запуске.

Однако я использую Intellij и когда я использую конкатенацию строк копирования в функцию буфера обмена и запускаю запросв блоке данных запрос выполняется нормально (после ввода параметров)

Я получаю сообщение об ошибке: «ОШИБКА: синтаксическая ошибка в или около« tstoredarticle »\ n Позиция: 199»

Я нахожу немного странным, что это показывает, что после изменения строки произошла смена строки, но кроме этого я не вижу, в чем дело.

Какие могут быть проблемы, которые могут вызвать такую ​​проблему?

мой запрос в 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

1 Ответ

1 голос
/ 24 октября 2019

Не используйте конкатенацию строк с динамическими текстовыми значениями для построения оператора SQL.

Например, если текстовые значения предоставляются пользователем, вы оставляете себя уязвимым для SQL-инъекции атак, позволяющих хакерам украсть ваши данные и удалить ваши таблицы.

Но у вас также есть проблемы с получением текстовых значений в кавычках и экранированием правильно.

Вместо этого используйте 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-инъекций и синтаксиса SQLошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...