mysql 如何处理SQL查询到一个数据库与概率的100+组合?

gxwragnw  于 2023-11-16  发布在  Mysql
关注(0)|答案(2)|浏览(112)

我有9个字段到我的用户界面,每一个都代表了我的数据库表中的一列。所以问题是,我需要覆盖所有可能的9个字段的组合,并向数据库发送特定的查询。示例:如果用户输入了2个字段,我将从DB中返回与这2个项目的组合匹配的所有项目。如果用户输入了3个字段,我从数据库中返回所有与这3个项目的组合相匹配的项目。如果你计算它们,很明显组合是100+。使用JAVA和MySQL与JDBC驱动程序,提供了保护SQL注入的Prepared语句。但是这样,我应该制作100+函数来覆盖所有组合,代码将是重复的。
如何解决:我创建了一个查询生成器,它接受用户输入的输入并创建一个SQL QUERY作为字符串。然后我使用Statement Class将其传递给DB。这样我就覆盖了所有可能的组合,但我必须自己从零开始制作SQL注入保护,通常它是一个自定义解决方案,我相信它已经解决了问题。
如果有官方的方法可以做到这一点,请让我知道!

ki1q1bka

ki1q1bka1#

SELECT table.*
FROM table
JOIN ( SELECT @column1 AS column1
            , @column2 AS column2
                 ......
            , @column9 AS column9 
       ) AS criteria ON ( table.column1 = criteria.column1 OR criteria.column1 IS NULL)
                    AND ( table.column2 = criteria.column2 OR criteria.column2 IS NULL)
                                      ..........
                    AND ( table.column9 = criteria.column1 OR criteria.column9 IS NULL)

字符串
如果用户已经为某个列输入了值,那么你就在查询中提供输入的条件,否则就提供NULL(command.Parameters.AddWithValue("@columnX", (object)value ?? DBNull.Value))。

yzuktlbb

yzuktlbb2#

你基本上有两种可能性来处理这个问题。
第一种方法使用一个带有OR条件的语句来处理缺少的条件
第二种方法使用**动态生成的语句,只包含具有给定值的 predicate **。
第一种解决方案的缺点是你得到了 * 一个 * 语句,即处理所有输入的 * 一个执行计划 *。
第二种解决方案允许根据输入选择适当的执行计划。缺点是你会遇到 * 不同数量 * 的绑定变量,这在技术上很难处理。
这里有一个由Tom Kyte推广多年的想法
为每个选择生成 predicate ,但取决于是否给出值:

column = :bind_variable -- if the value is passed

(1=1 or :bind_variable is NULL) – if no value is NOT passed

字符串
快捷逻辑消除了没有值的 predicate ,但您在准备语句中获得了绑定变量的完整数量。

三列全部通过的示例

where
col1 = :1 and
col2 = :2 and
col3 = :3

单输入示例

where
col1 = :1 and
(1=1 or :2 is NULL) and
(1=1 or :3 is NULL)

无输入示例

where
(1=1 or :1 is NULL) and
(1=1 or :2 is NULL) and
(1=1 or :3 is NULL)


这里的Oracle执行计划的第二个例子显示,只有col1 predicate 被评估,所有其他的都被丢弃。类似的是有效的PostgreSQL,我没有测试MySQL。

------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |          |     1 |    18 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TEST     |     1 |    18 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | COL1_IDX |     1 |       |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("COL1"=TO_NUMBER(:1))


对于第三个查询(无条件),以full table scan结束

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  1000K|    17M|   896   (1)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| TEST |  1000K|    17M|   896   (1)| 00:00:01 |
--------------------------------------------------------------------------

  • 因此,如果结果的基数高度依赖于选择,这种方法更适合于一种尺寸适合所有OR predicate 解决方案 *。

相关问题