Я хочу загрузить список записей с возможно длинным списком имен пользователей (от одного до тысяч имен пользователей).
Не обращайте внимания на то, как выбраны имена, и предположите, что они не могут быть определены на основе существующих данных в базе данных. Это относится к SQL Server 2005.
Я специально хочу избегать , используя оператор одиночного выбора с тысячами выражений в предложении where , что привело бы к чрезмерно длинному тексту команды для объект SqlCommand (например, ...where n='bob000001' or n='bob000002' or ... or n='bob003000'
). Звучит разумно?
Я решил выполнить выбор, заполнив простую табличную переменную именами пользователей, затем выполнив выбор / объединение между табличной переменной и таблицей с пользовательскими данными.
Итак, первое, что мне нужно сделать, это заполнить табличную переменную. У меня есть некоторые проблемы здесь:
- Синтаксис T-SQL до SQL Server 2008 является многословным для вставки нескольких строк в таблицу в одном операторе, для чего требуется что-то вроде множественное выделение и объединение всех .
- Вместо того, чтобы использовать подробный синтаксис SS2005 или даже краткий синтаксис, доступный в SQL Server 2008, я вообще избегаю длинных текстов команд и просто использую несколько команд по одному соединению.
- Объявление табличной переменной в одной SqlCommand приводит к ошибке «необходимо объявить скалярную переменную», когда я пытаюсь использовать ее в последующих SqlCommands.
- Вовлечение хранимых процедур любым способом может по-прежнему включать передачу огромных строк или препятствовать сохранению переменных вне области действия хранимой процедуры. Предположим, создание хранимых процедур не вариант.
Этот третий пункт - действительно проблема, которую я пытаюсь решить сейчас. Я видел примеры, когда люди (утверждают, что) успешно объявляют и используют переменную в одном SqlCommand без ошибки. Как этого достичь при использовании нескольких экземпляров SqlCommand? Я читал, что переменные будут сохраняться для одного соединения между несколькими командами. Может ли помочь транзакция каким-либо образом?
Наконец, имейте в виду, что я не хочу использовать временные таблицы; это предложит простое решение, но оно также позволит избежать вопроса, который я задаю относительно переменных и нескольких SqlCommands; однако, если вы действительно считаете, что это лучший вариант, не стесняйтесь так говорить.
Вот фрагмент кода, который показывает, что происходит:
public static List<Student> Load( SqlConnection conn, List<StudentID> usernames )
{
//Create table variable
SqlCommand command = new SqlCommand( "declare @s table (id varchar(30))", conn );
command.ExecuteNonQuery();
//Populate a table variable with the usernames to load
command = new SqlCommand( "insert into @s (id) values (@p)", conn );
command.Parameters.Add( "@p", SqlDbType.VarChar );
int len = usernames.Count;
for (int i = 0; i < len; i++)
{
command.Parameters["@p"].Value = usernames[i].ToString();
command.ExecuteNonQuery(); //ERROR: must declare scalar variable @s
}
//Select all students listed in the table variable
command = new SqlCommand( "select StudentID, FName, LName, [etc.] from Student inner join @s on StudentID = @s.id order by StudentID", conn );
//Execute the query to get the student info from the database.
List<Student> students = new List<Student>()
using(SqlDataReader reader = command.ExecuteReader())
{
//code to load results and populate students list
}
return students;
}
Примечание: я знаю, что SqlCommand, включающий параметры, внутренне вызывает хранимую процедуру, которая обычно предотвращает сохранение переменных в нескольких SqlCommands, но первый запрос, который объявляет табличную переменную, не включает параметры (т.е. нет ссылки на команду .Parameters.AddWithValue), поэтому он должен находиться в области действия для последующих команд, которые могут вызывать хранимые процедуры.
Редактировать: Чтобы использовать временную таблицу, нужно просто изменить @
s на #
s и declare @
s table "на create table #
s, что хорошо. Можно также захотеть сбросить временную таблицу стол в конце, но это не обязательно.