Быстрый способ явной замены параметров в операторе sp_executesql? - PullRequest
1 голос
/ 27 марта 2012

Я пишу программу на C #, которая выполняет некоторые операторы select, используя параметры, переданные sp_executesql.Одна проблема, с которой я сталкиваюсь при тестировании, заключается в том, что, получаю ли я команды, выполняемые из SQL Profiler или из Watch в Visual Studio, значения параметров указываются в конце оператора, а не указываются явно встрока в запросе.В целях тестирования я хотел бы получить быстрый способ замены значений параметров на параметры.

Итак, вместо:

exec sp_executesql N'
SELECT CustomerName
FROM CustomerTable ct WITH(NOLOCK)
WHERE ct.CustomerId <> @CustomerId
AND ct.ItemId <> @ItemId
AND ct.TransactionId = @TransactionId'
,N'@CustomerId bigint,@ItemId nvarchar(1),@TransactionId nvarchar(30), @CustomerId = 3000, @ItemId = N'4', @TransactionId=N'43281'

Я хочу:

exec sp_executesql N'
SELECT CustomerName
FROM CustomerTable ct WITH(NOLOCK)
WHERE ct.CustomerId = 3000
AND ct.ItemId <> N'4'
AND ct.TransactionId = N'43281''

Пожалуйста, не обращайте слишком много внимания на синтаксис примера, так как он используется только для демонстрации концепции.Кто-нибудь знает быстрый способ сделать это?По сути, я хотел бы заменить его для целей тестирования, поскольку мне будет легче изменять условия, чтобы проверить, как они влияют на возвращаемые результаты.Буду признателен за любую помощь, которую может оказать любой.Спасибо.

1 Ответ

3 голосов
/ 27 марта 2012

Параметризация sp_executesql имеет много преимуществ, в том числе

  • Благодаря явной параметризации вы даете SQL возможность кэшировать приличные планы запросов для определенных типов
  • Параметризация помогает предотвратить такие неприятности, какАтаки SQL-инъекций, но также избавляют от необходимости избегать проблемных символов.

Так что даже если вам удастся «непараметризовать» сгенерированный sp_executesql, если вы выполните встроенный sql, план запроса может быть значительноотличается от параметризованной версии, и вам также нужно будет выполнить экранирование и т. д. (т. е. это не подойдет для тестирования яблок и яблок).

Единственная причина, по которой я могу подумать, почему вы не хотите параметризоватьсяsp_executesql будет для удобства чтения?

Редактировать : Попытка замены будет зависеть от того, какую технологию вы используете

Как предложено @mellamokb, если вы используете ExecuteReaderэто может быть довольно просто

Предполагая ваш кодбыло что-то вроде

string sqlCmd = "SELECT CustomerName 
FROM CustomerTable ct WITH(NOLOCK) 
WHERE ct.CustomerId <> @CustomerId 
AND ct.ItemId <> @ItemId 
AND ct.TransactionId = @TransactionId";

cmd.CommandText = sqlCmd;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("CustomerId", DbType.Int32, myCustomerId));
cmd.Parameters.Add(new SqlParameter("ItemId", DbType.String, myItemId));
..
cmd.ExecuteReader()

Затем вы могли бы добавить код для построения вашего тестового запроса:

string sqlMyTest = sqlCmd.Replace("@CustomerId", myCustomerId.ToString());
sqlMyTest = sqlMyTest.Replace("@ItemId", specialEscapeFunction(myItemId));
.. do something with sqlMyTest

Однако ORM, такой как Linq2SQL или EF, не был бы таким простым

customerTable.Where(c => (c.CustomerId != myCustomerId) && (c.ItemId != myItemId) && (c.TransactionId == myTransactionId))

Возможно, вам поможет такой инструмент, как LinqPad?

...