Sp_executesql, вызывающий EXEC, не работает с необязательными параметрами

Я работаю с SQL Server 2014 и пытаюсь выполнить (динамическую) хранимую процедуру из структуры сущностей.

Моя хранимая процедура имеет следующие входные параметры:

@Username          NVARCHAR(100),
@Number            DECIMAL,
@PageIndex         INT = 1,
@PageSize          INT = 20,
@Field1            NVARCHAR(12) = NULL,
@Field2            NVARCHAR(60) = NULL,
@Field3            NVARCHAR(60) = NULL,
@Field4            NVARCHAR(60) = NULL,
@Field5            NVARCHAR(60) = NULL,
@Field6            NVARCHAR(60) = 'ABC',
@Field7            NVARCHAR(4)  = 'ABC',
@IsCountOnly       BIT = 0,
@IsFilterOnly      BIT = 0

EF генерирует следующий запрос (полученный с помощью профилировщика SQL) на основе параметров, которые я добавил в свой массив, но обратите внимание, что я добавляю только те, которые мне нужны, поскольку большинство из них являются необязательными.

exec sp_executesql 
N'EXEC MySp @Username, @Number, @IsCountOnly', 
N'@Username nvarchar(100), Number decimal(6,0), @IsCountOnly bit', 
@Username=N'[email protected]', @Number=12345, @IsCountOnly=1

Когда я передаю @Username, @Number, которые являются обязательными, а затем передаю @IsCountOnly, моя хранимая процедура выполняется, но возвращает неправильные результаты, поскольку кажется, что значение, переданное через @IsCountOnly, обрабатывается как @PageIndex, а не @IsCountOnly.

Обратите внимание, что если я вызову EXEC непосредственно в SQL Server Management Studio:

EXEC    [dbo].[MySp]
@Username = N'[email protected]',
@Number = 12345,
@IsCountOnly = 1
GO

Он работает так, как ожидалось.

Чтобы проверить, была ли проблема в этом, я включил все параметры в exec sp_executesql N'EXEC ..., и это сработало, как и ожидалось, но кажется излишним определять все параметры, когда в некоторых сценариях нужны только некоторые из них.

Это ошибка в SQL при работе с exec sp_executesql и EXEC или я что-то не так делаю??

Спасибо.

ОБНОВЛЕНИЕ-1:

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

Вы делаете это неправильно (извините). Вместо этого используйте EXEC MySp @Username = @Username, @Number = @Number, @IsCountOnly = @IsCountOnly. Это сбивает с толку, но ваш синтаксис фактически передает параметры по порядковому номеру, просто заполняя эти порядковые значения параметрами самого параметризованного оператора EXEC.

Jeroen Mostert 27.06.2019 13:26

Ни один из параметров не указывает, какой параметр они передают, поэтому они основаны на порядковой позиции, а не на имени переменной. Третий параметр в вашей SP — @PageIndex, поэтому @IsCountOnly (которое является переданным третьим значением) будет рассматриваться как значение для @PageIndex; а остальные будут иметь значение по умолчанию. Это похоже на ошибку сопоставления в коде вашего приложения.

Larnu 27.06.2019 13:26
«когда я передаю null для необязательных параметров, на самом деле не используются предоставленные значения по умолчанию» Значение по умолчанию для параметра используется, когда параметр опущен, а не при передаче NULL. NULL все еще значение, просто неизвестное.
Larnu 27.06.2019 13:57

@JeroenMostert ты был в ударе! Быстро изменил мою функцию, которая создает список полей для моих необязательных полей, чтобы включить одно и то же поле, и это сработало сразу! Спасибо

Thierry 27.06.2019 15:20
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
4
676
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать именованные параметры:

N'EXEC MySp @Username=@Username, @Number=@Number, @IsCountOnly=@IsCountOnly''

Я не генерирую этот код. Entity framework есть и это моя проблема. поскольку он генерирует запрос как «exec sp_executesql N'EXEC....», как упоминается в вопросе, который вызывает проблему. Это вызов, который у меня есть на моем уровне данных: DbContext.Database.SqlQuery("EXEC MySP @Username, @Number, " + optionalParameters, parameterList.ToArray()) где необязательные параметры — это просто дополнительные устанавливаемые @Field, а список параметров содержит массив SqlParameters.

Thierry 27.06.2019 13:39

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

Thierry 27.06.2019 13:43

К сожалению, это не работает. так как sp_executesql ожидает передачи параметров.

Thierry 27.06.2019 13:52

@Thierry: см. этот вопрос, чтобы узнать больше о том, как конкретно работает EF.

Jeroen Mostert 27.06.2019 14:01

Как заявил @JeroenMostert, использование параметров имени является решением. Спасибо еще раз.

Thierry 27.06.2019 15:21

Другие вопросы по теме