Question

I wanted to replace not just values stored in columns with parameters, but table names, column names, etc., so I tried this:

    // 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();
    }

...but get, "ORA-00903 invalid table name"

So, I tried doing in the C# way:

    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();
    }

...but that too failed, in fact with, "ORA-00904 "WHYAMINOTQUOTINGTHEDOT"."EXE": invalid identifier"

Am I barking up the wrong tree, or simply using the wrong way to filet a cat?

In olden times (Delphi), you could make a string safe for passing to the DB engine by encasing it in something like QueryStr(). Is there an analogous helper function for C#/Oracle?

Was it helpful?

Solution

You can't use parameters to replace table names and column names in Oracle. One of the major benefits of using parameterized queries from the database perspective is that Oracle can parse the query once (generating the query plan among other things) and then execute it many times with different parameter values. If the table or columns change, that requires a new hard parse of the query so it would not be eligible to be a bind variable.

Can you explain a bit more about the problem you're trying to solve? It seems unusual that you'd want to write code that could query an arbitrary column of an arbitrary table-- that generally implies that you have a number of different tables that store the same basic sort of data in which case you would generally be better served by revisiting the normalization of your data model. If you want to determine whether a particular table name or column name is safe to pass to the database from a SQL injection standpoint, you could use the DBMS_ASSERT package but at that point you might be better served just querying ALL_TAB_COLUMNS for the specified table name and column name to see whether there are actually columns AColumnToReturn and AColumnToQuery in ATable in the database.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top