我正在为不同类型的数据库生成SQL代码。为了动态地执行此操作,SQL脚本的某些参数存储在变量中。
一个这样存储的参数是某些查询的比较表达式。 假设我有一个带有Name,DateOfBirth和Gender列的Dogs表,那么我在变量中有比较表达式,例如:
string myExpression = "Gender=1";
string myExpression2 = "Gender=1 AND Name='Bucky'";
然后我会构建以下SQL字符串:
string mySqlString = "SELECT * FROM "dbo"."Dogs" WHERE " + myExpression;
问题是,对于Oracle语法,我必须引用列名(如上面的dbo.Dogs所示)。所以我需要从存储的表达式创建一个字符串,如下所示:
string quotedExpression = "\"Gender\"=1";
有这么快的方法吗?我想在比较符号上拆分字符串,但后来我会剪切符号本身,它也不会在复杂的条件下工作。我可以遍历整个字符串,但这将包括许多要检查的条件(比较符号可以是多个字符(<>)或关键字(ANY,ALL等)),我宁愿避免很多循环。
答案 0 :(得分:1)
IMO这里的问题是尝试将myExpression
/ myExpression2
用作裸SQL字符串。除了是一个巨大的SQL注入漏洞之外,它还会导致像您现在看到的问题。当我需要这样做时,我将过滤器表达式视为DSL,然后我将其解析为AST(使用类似修改后的分流码算法 - 尽管还有其他方法可以做到)。所以我最终得到了
AND
=
Gender
1
=
Name
'Bucky'
现在我可以走那棵树(访客模式),看着每一个。 1
看起来像一个整数(int.TryParse
等),因此我们可以添加一个带有该值的参数。 'Bucky'
看起来像一个字符串文字(通过引号),因此我们可以添加一个基于字符串的参数,其值为Bucky
(实际值中没有引号)。另外两个是非引用字符串,因此它们是列名。我们根据我们的模型(白名单)检查它们,并应用任何必要的SQL语法,例如转义 - 也许是别名(在DSL中它可能是Name
,但在数据库中是XX_Name2_ChangeMe
。如果在模型中找到列
是的,这更复杂,但它会让你安全和理智。
可能有些库已经可以为你做表达式解析(到AST)。