试图创建一个有点通用的查询方法

时间:2012-03-27 21:53:25

标签: c# .net sql oracle parameterized-query

我想要的不仅是用参数替换存储在列中的值,还要替换表名,列名等,所以我试过这个:

    // Can get any string value based on any string key with this function
    public string GetValForKeyVal(string ATable, string AKeyVal, string AColumnToQuery, string AColumnToReturn) {
        String qry = "SELECT :ColOfInterest FROM :TableToQuery WHERE :KeyValColumn = :KeyVal";
        OracleCommand cmd = new OracleCommand(qry, con);
        cmd.CommandType = CommandType.Text;
        OracleParameter opColOfInterest = cmd.Parameters.Add("ColOfInterest", OracleDbType.Varchar2,
          AColumnToReturn, ParameterDirection.Input);
        OracleParameter opTableToQuery = cmd.Parameters.Add("TableToQuery", OracleDbType.Varchar2,
          ATable, ParameterDirection.Input);
        OracleParameter opKeyValColumn = cmd.Parameters.Add("KeyValColumn", OracleDbType.Varchar2,
          AColumnToQuery, ParameterDirection.Input);
        OracleParameter opKeyVal = cmd.Parameters.Add("KeyVal", OracleDbType.Varchar2,
          AKeyVal, ParameterDirection.Input);
        return cmd.ExecuteScalar().ToString();
    }

...但是得到,"ORA-00903 invalid table name"

所以,我尝试用C#方式做的事情:

    public string GetValForKeyVal(string ATable, string AKeyVal, string AColumnToQuery, string AColumnToReturn) {
        String qry = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}", AColumnToReturn, ATable, AColumnToQuery, AKeyVal);
        OracleCommand cmd = new OracleCommand(qry, con);
        cmd.CommandType = CommandType.Text;
        return cmd.ExecuteScalar().ToString();
    }

......但实际上,"ORA-00904 "WHYAMINOTQUOTINGTHEDOT"."EXE": invalid identifier"

也失败了

我是在吠叫错误的树,还是只是用错误的方法来制作猫?

在古代(Delphi),您可以通过将其包含在QueryStr()之类的内容中使字符串安全传递到数据库引擎。 C#/Oracle是否有类似的辅助函数?

1 个答案:

答案 0 :(得分:4)

您无法使用参数替换Oracle中的表名和列名。从数据库角度使用参数化查询的主要好处之一是Oracle可以解析一次查询(生成查询计划等),然后使用不同的参数值执行多次。如果一个或多个列发生更改,则需要对查询进行新的硬解析,以使其无法成为绑定变量。

您能解释一下您正试图解决的问题吗?您想要编写可以查询任意表的任意列的代码似乎很不寻常 - 这通常意味着您有许多不同的表存储相同的基本数据类型,在这种情况下您通常会更好通过重新审视数据模型的规范化来实现。如果要确定特定的表名称或列名是否可以从SQL注入的角度安全地传递到数据库,可以使用DBMS_ASSERT package,但此时只需查询{{1}即可。对于指定的表名和列名,以查看数据库中ALL_TAB_COLUMNS中是否实际存在列AColumnToReturnAColumnToQuery