Страницы

Поиск по вопросам

вторник, 16 июля 2019 г.

Дефолтное значение для табличного типа

Использую в хранимке табличный тип:
CREATE PROCEDURE dbo.p_TestProc @UID INT =0, @RequredID StringTableType READONLY
Где StringTableType табличный тип определяемый следующим образом:
CREATE TYPE dbo.StringTableType AS TABLE ( StrValue VARCHAR(50) COLLATE Cyrillic_General_CI_AS NULL )
Вопрос: Как сделать параметр @RequredID необязательным?
Или, как альтернатива: Как определить для @RequredID значение по умолчанию? (не пустое, а скажем чтобы таблице была одна строка со значением "EMPTY")


Ответ

Переменные табличного типа итак необязательны.
Можно вызвать:
exec dbo.p_TestProc @UID = 1
в этом случае @RequiredID примет значение пустой таблицы.
Значение по умолчанию, насколько мне известно, задать нельзя, т.е. написать что-то типа
CREATE PROCEDURE dbo.p_TestProc ( @UID INT = 0, @RequiredID StringTableType READONLY = VALUES ('EMPTY') )
не выйдет.
Если нет возможности контролировать вызов процедуры, то можно внутри кода процедуры вместо входного параметра попробовать использовать дополнительную переменную того же табличного типа, в которую перекладывать данные из входного параметра, или инициализировать её по необходимости значениями по-умолчанию. Примерно так:
ALTER PROCEDURE dbo.p_TestProc ( @UID INT = 0, @RequiredID StringTableType READONLY ) as begin set nocount on;
declare @NormalizedID StringTableType;
if exists (select 1 from @RequiredID) insert into @NormalizedID (StrValue) select StrValue from @RequiredID; else insert into @NormalizedID (StrValue) values ('EMPTY');
-- далее по коду использовать @NormalizedID вместо @RequiredID -- ... end
Хотя, конечно такое перекладывание данных не слишком изящно и несколько снизит производительность.
Если же вы контролируете вызов, то оптимальнее всё же задать умолчания до вызова процедуры, а не внутри неё.
В SQL коде это будет примерно так:
declare @uid int; declare @tableParam dbo.StringTableType;
select @uid = ID from SomeTable where ...;
insert into @tableParam (StrValue) select SomeValue from SomeOtherTable where ...;
if not exists (select 1 from @tableParam) insert into @tableParam (StrValue) values ('EMPTY');
exec dbo.p_TestProc @uid, @tableParam;
Если же это внешний вызов, то, например, на C# это будет выглядеть примерно следующим образом:
class StringTableType : DataTable { public StringTableType() { Columns.Add("StrValue", typeof(string)); }
public static StringTableType GetDefault() { var def = new StringTableType(); def.Rows.Add("EMPTY");
return def; } }
void Call_p_TestProc(int? uid, StringTableType t) { SqlCommand cmd = new SqlCommand("dbo.p_TestProc");
cmd.Parameters.AddWithValue("@UID", uid ?? (object)DBNull.Value);
cmd.Parameters.Add( new SqlParameter("@tableParam", SqlDbType.Structured) { TypeName = "[dbo].[StringTableType]", Value = t == null || t.Rows.Count == 0 ? StringTableType.GetDefault() : t });
//execute cmd }

Комментариев нет:

Отправить комментарий