Параметры Oracle в запросах .net sql — ORA-00933: команда SQL не завершена должным образом

#sql #oracle #odp.net

#sql #Oracle #odp.net

Вопрос:

Я пытаюсь создать предложение where для передачи в качестве параметра команде Oracle, и это оказывается сложнее, чем я думал. Что я хочу сделать, так это создать большой запрос where на основе пользовательского ввода из нашего приложения. Запрос where должен быть единственным параметром для инструкции и будет содержать несколько условий AND , ИЛИ в нем. Этот код здесь работает, однако это не совсем то, что мне нужно:

 string conStr = "User Id=testschema;Password=pass12341;Data Source=orapdex01";
Console.WriteLine("About to connect to Database with Connection String: "   conStr);
OracleConnection con = new OracleConnection(conStr);
con.Open();
Console.WriteLine("Connected to the Database..."   Environment.NewLine   "Press enter to continue");
Console.ReadLine();

// Assume the connection is correct because it works already without the parameterization
String block = "SELECT * FROM TEMP_VIEW WHERE NAME = :1";

// set command to create anonymous PL/SQL block
OracleCommand cmd = new OracleCommand();

cmd.CommandText = block;
cmd.Connection = con;

// since execurting anonymous pl/sql blcok, setting the command type
// as text instead of stored procedure
cmd.CommandType = CommandType.Text;

// Setting Oracle Parameter
// Bind the parameter as OracleDBType.Varchar2 
OracleParameter param = cmd.Parameters.Add("whereTxt", OracleDbType.Varchar2);
param.Direction = ParameterDirection.Input;

param.Value = "MY VALUE";

// Get returned values from select statement
OracleDataReader dr = cmd.ExecuteReader();

// Read the identifier for each  result and display it
while (dr.Read()) 
{
    Console.WriteLine(dr.GetValue(0));
}

Console.WriteLine("Selected successfully !");
Console.WriteLine("");

Console.WriteLine("***********************************************************");

Console.ReadKey();
  

Если я изменю приведенные ниже строки на желаемый тип результата, то получу сообщение об ошибке «ORA-00933: команда SQL не завершена должным образом».:

 String block = "SELECT * FROM TEMP_VIEW :1";
...
...
param.Value = "WHERE NAME = 'MY VALUE' AND ID = 5929";
  

Мой вопрос в том, как мне выполнить добавление моего большого запроса where динамически, не вызывая этой ошибки?

Ответ №1:

К сожалению, простого способа добиться этого нет.

Одна вещь, которую вам нужно будет понять при использовании параметризованного SQL в целом, заключается в том, что параметры привязки могут использоваться только для значений, таких как строки, числа или даты. Вы не можете поместить в них биты SQL, такие как имена столбцов или WHERE предложения.

Как только база данных получит текст SQL, она попытается проанализировать его и выяснить, является ли он допустимым, и она сделает это, не обращая внимания на значения параметра bind. Он не сможет выполнить SQL без всех значений.

Строка SQL SELECT * FROM TEMP_VIEW :1 никогда не может быть допустимой, поскольку Oracle не ожидает, что значение будет немедленно следовать FROM TEMP_VIEW .

Вам нужно будет создать свой SQL в виде строки, а также одновременно создать список параметров привязки. Если вы обнаружите, что вам нужно добавить условие в столбец NAME , вы добавляете WHERE NAME = :1 в строку SQL и параметр с именем :1 и значением, которое вы хотите добавить. Если вам нужно добавить второе условие, вы добавляете AND ID = :2 к строке SQL параметр с именем :2 .

Надеюсь, следующий код должен объяснить немного лучше:

 // Initialise SQL string and parameter list.
String sql = "SELECT * FROM DUAL";
var oracleParams = new List<OracleParameter>();

// Build up SQL string and list of parameters.
// (There's only one in this somewhat simplistic example.  If you have
// more than one parameter, it might be easier to start the query with
// "SELECT ... FROM some_table WHERE 1=1" and then append
// " AND some_column = :1" or similar.  Don't forget to add spaces!)
sql  = " WHERE DUMMY = :1";
oracleParams.Add(new OracleParameter(":1", OracleDbType.Varchar2, "X", ParameterDirection.Input));

using (var connection = new OracleConnection() { ConnectionString = "..."})
{
    connection.Open();

    // Create the command, setting the SQL text and the parameters.
    var command = new OracleCommand(sql, connection);
    command.Parameters.AddRange(oracleParams.ToArray());

    using (OracleDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            // Do stuff with the data read...
        }
    }
}
  

Комментарии:

1. спасибо за это. Я надеялся, что есть более простой способ. Это определенно рабочее решение.