#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. спасибо за это. Я надеялся, что есть более простой способ. Это определенно рабочее решение.