2016-11-11 2 views
0

SQL Server 2016 .Net 4.5.2 C#Проверьте, чтобы увидеть, если переменная exists..inline SQL

Я говорю это с уважением, я использую базу данных Northwind, чтобы показать, что я пытаюсь добиться. Пожалуйста, никаких комментариев о базе данных Northwind. Это всего лишь пример того, что я буду делать.

Я использую ADO.Net для выполнения встроенного sql. Моя дилемма: у меня будут дополнительные параметры, которые могут быть переданы в sql-запрос. Вот C#:

var city = ""; 
var state = "tx"; 
var sqlQuery = " 
     if exists @City 
     begin 
     select * from Customers where city = @City and [email protected]; 
     end 
     else 
     begin 
     select * from Customers where [email protected]; 
     end 
    "; 

var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI"); 
conn.Open(); 
SqlCommand cmd = new SqlCommand(sqlQuery, conn); 

if (!string.IsNullorEmpty(city)) 
{ 
    SqlParameter param = new SqlParameter(); 
    param.ParameterName = "@City"; 
    param.Value   = city; 
    cmd.Parameters.Add(param); 
} 

if (!string.IsNullorEmpty(state)) 
{ 
    SqlParameter param = new SqlParameter(); 
    param.ParameterName = "@State"; 
    param.Value   = state; 
    cmd.Parameters.Add(param); 
} 

var reader = cmd.ExecuteReader(); 

Как вы можете видеть, переменный город пустой, поэтому @City параметра не будет передан запросом SQL, но переменная состояния не является пустой, так @State параметр будет передан запрос. Имейте в виду, @City не будет пустым все время. Я поставил чек в sql, чтобы узнать, существует ли @City, но это не работает. Как проверить запрос sql, если существуют @City, @State или любые другие параметры, которые могут быть переданы? Если я смогу понять эту часть, я могу справиться с тем, что нужно сделать в sql. Спасибо за любую помощь.

P.S. Я не могу использовать хранимые процедуры.

+0

Почему вы не можете использовать хранимую процедуру? Это странное ограничение. –

+0

Согласен. Моя работа наложила на меня наручники. Мы используем все встроенные sql. Я не уверен, что это возможно, чего они хотят – BoundForGlory

+0

Это абсолютно возможно. См. Мой ответ. Мне плохо, если вы работаете с такими абсурдными ограничениями. Я слышал об этом раньше, и это всегда сводится к тому, кто дезинформирован и в состоянии сделать такие широкие мандаты. Хуже всего то, что тот же человек также обычно мертв в своих ошибочных убеждениях и отказывается слушать разум. Вам либо приходится иметь дело с такой глупостью или очищать свое резюме. –

ответ

2
select * 
from 
    Customers 
where 
    [email protected] 
    AND (city = @City 
     OR ISNULL(@City,'') = '') 

Я бы порекомендовал вышесказанное, что вы можете сделать это в 1 инструкции выбора без использования методов управления ПЧ. Он будет проверять город, но он также скажет, что если @City пуст, тогда верните его в любом случае, потому что только одно из этих условий может быть истинным в то время, когда вы никогда не закончите получать результаты, которых вы не хотите. Для того, чтобы использовать метод управления вы могли бы сделать что-то вроде следующего,

IF ISNULL(@City,'') <> '' 
BEGIN 
    select * from Customers where city = @City and [email protected]; 
END 
ELSE 
BEGIN 
    select * from Customers where [email protected]; 
END 

Но опять-таки первый пример будет больше стандартного и меньше кода, так что я бы рекомендовал.

Редактировать: Вы должны передавать параметр каждый раз. В противном случае вы действительно измените инструкцию SQL в коде C#, а не в коде SQL.

Далее вы фактически передадите пустую строку НЕ значение NULL, глядя на ваше назначение var city = "";, чтобы вы могли переключиться на тест для этого.

Проблема с НЕ передавая параметр вообще - ваш оператор SQL будет использовать переменную, которую вы не объявили, если вы не добавляете значение параметра. Таким образом, стандартный способ заключается в том, чтобы всегда передавать переменную и использовать оператор SQL, такой как первый выше. ЕСЛИ вы действительно хотите сделать это по-другому, чтобы даже не пройти вообще, вам нужно будет использовать поток управления C# для создания вашей строки SQL по-разному.

Стандартный способ:

var city = ""; 
var state = "tx"; 
var sqlQuery = " 
    select * 
    from 
     Customers 
    where 
     [email protected] 
     AND (city = @City 
      OR ISNULL(@City,'') = '') 
"; 

var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI"); 
conn.Open(); 

SqlCommand cmd = new SqlCommand(sqlQuery, conn); 

SqlParameter param = new SqlParameter(); 
param.ParameterName = "@City"; 
param.Value   = city; 
cmd.Parameters.Add(param); 

SqlParameter param = new SqlParameter(); 
param.ParameterName = "@State"; 
param.Value   = state; 
cmd.Parameters.Add(param); 

var reader = cmd.ExecuteReader(); 

способ сделать это без прохождения параметра, чтобы динамически создавать свой SQL заявление через поток C# управления:

var city = ""; 
var state = "tx"; 
var sqlQuery = " 
    select * 
    from 
     Customers 
    where 
     [email protected] 
"; 

if (!string.IsNullorEmpty(city)) 
{ 
    sqlQuery += " 
      AND [email protected]"; 
} 

var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI"); 
conn.Open(); 

SqlCommand cmd = new SqlCommand(sqlQuery, conn); 

if (!string.IsNullorEmpty(city)) 
{ 
    SqlParameter param = new SqlParameter(); 
    param.ParameterName = "@City"; 
    param.Value   = city; 
    cmd.Parameters.Add(param); 
} 

SqlParameter param = new SqlParameter(); 
param.ParameterName = "@State"; 
param.Value   = state; 
cmd.Parameters.Add(param); 

var reader = cmd.ExecuteReader(); 

Чтобы расширить немного больше о том, почему вы получили must declare scalar variable @city, когда вы не прошли параметр, потому что определение параметра в C# является тем, что определяет переменную в SQL.Итак:

SqlParameter param = new SqlParameter(); 
param.ParameterName = "@City"; 
param.Value   = city; 
cmd.Parameters.Add(param); 

По сути делает это в SQL:

DECLARE @City VARCHAR(50) 
SET @City = value of city var. 

Итак, если вы пропустите этот шаг, как вы делаете, используя, если поток управления по городу вар опустить определение переменной и SQL потерпит неудачу , Таким образом, хотя значение параметра может быть необязательным, сам параметр НЕ является опцией, если он ссылается на ваш SQL-оператор.

Также обратите внимание, что вы используете неявные типы данных в определениях параметров, которые вы действительно должны явно определять тип данных!

+0

Должен объявить скалярную переменную «@City». – BoundForGlory

+0

@BoundForGlory, вы должны всегда передавать переменную погоду, это Null или Not. у вас есть еще одна проблема, хотя вы передаете пустую строку, а не null, поэтому я обновился, чтобы отразить, как это проверить. – Matt

+0

Требование i have не передает параметр, если переменная имеет значение null. Вот почему я написал код так, как я. Я даже попытался поймать попытку, но это не удалось. – BoundForGlory

0

Когда вы проходите через sql, вам сложно использовать необязательные параметры. И это действительно не помогает сделать ваш код лучше. Параметры параметров были бы полезны в хранимой процедуре, но при прохождении через запрос это гораздо больше усилий, чем того стоит. Лучший способ справиться с этим - всегда передавать параметры. Но вы можете передать DBNull и обработать это в своем запросе.

Я также настоятельно рекомендую вам начать обматывать объекты iDisposable в инструкции USING. Особенно такие вещи, как соединения и команды. Вы НЕ хотите подключать пул соединений, потому что вы случайно пропустите вызов Dispose.

Вот один из способов, которыми вы можете управлять этим типом вещей довольно чисто.

var sqlQuery = "select * 
from Customers 
where 
(
    state = @State 
    OR 
    @state is null 
) 
AND 
(
    city = @City 
    OR 
    @City is null 
)"; 

using (SqlConnection conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI")) 
{ 
    conn.Open(); 
    using(SqlCommand cmd = new SqlCommand(sqlQuery, conn)) 
    { 
     SqlParameter param = new SqlParameter(); 
     param.ParameterName = "@City"; 
     if (string.IsNullorEmpty(city)) 
     { 
      param.value = DBNull.Vale; 
     } 
     else 
     { 
      param.Value = city; 
     } 
     cmd.Parameters.Add(param); 

     SqlParameter param = new SqlParameter(); 
     param.ParameterName = "@State"; 
     if(string.IsNullorEmpty(state)) 
     { 
      param.value = DBNull.Vale; 
     } 
     else 
     { 
      param.Value = state; 
     } 
     cmd.Parameters.Add(param); 
     } 

    } 
} 
+0

Спасибо за ваш вклад, и поверьте мне, я сделал бы это, если бы у меня была компания, над которой я работаю. Это требование работы, и я не уверен, возможно ли, что они хотят от меня. – BoundForGlory

+0

Это требование работы, что вы не можете передавать параметры в свой проход через запрос каждый раз? Это просто не имеет никакого смысла. Я чувствую вашу боль и ощущаю ваше разочарование как какой-то глупый мандат от человека, находящегося у власти, и почти не понимает, как это работает. Единственное, что я могу видеть, что ваши параметры необязательны, - это создать ветвь в C# для каждой возможной комбинации и включать только параметры, относящиеся к этому пути. Поговорите о кошмаре !!! –

Смежные вопросы