#sql #sql-server #sql-server-2008
#sql #sql-сервер #sql-server-2008
Вопрос:
Я использую SQL Server 2008 R2
. У меня возникли некоторые проблемы с поиском эффективного шаблона кодирования, для SQL
которого поддерживается повторное использование кода, а также гибкость. Под повторным использованием я подразумеваю сохранение SQL
запросов в Stored Procedures
и User Defined Functions
.
Теперь, если я выберу Stored Procedures
, я пожертвую его удобством использования непосредственно в запросе. Если я выберу User Defined Functions
, я не смогу использовать DML
инструкции.
Например, предположим, что я создал, Stored Procedures
который вставляет одну запись контакта. Теперь, если у меня есть таблица, которая может выступать в качестве источника нескольких записей контактов, все, что у меня остается, — это WHILE
циклы или CURSOR
s, что явно не рекомендуется из-за его недостатков в производительности. И из-за того, что инструкции DML не разрешены в User Defined Functions
, я просто не могу использовать их для этой цели.
Хотя, если меня не интересует повторное использование кода, то вместо использования Stored Procedures
я, безусловно, могу использовать один и тот же набор запросов снова и снова, чтобы избежать циклов while.
Какому шаблону я должен следовать?
Вот аналогичный Stored Procedures
:-
ALTER Proc [dbo].[InsertTranslationForCategory]
(
@str nvarchar(max),
@EventId int,
@CategoryName NVarchar(500),
@LanguageId int,
@DBCmdResponseCode Int Output,
@KeyIds nvarchar(max) Output
)as
BEGIN
DECLARE @XmlData XML
DECLARE @SystemCategoryId Int
DECLARE @CategoryId Int
Declare @Counter int=1
Declare @tempCount Int
Declare @IsExists int
Declare @TranslationToUpdate NVarchar(500)
Declare @EventName Varchar(200)
declare @Locale nvarchar(10)
declare @Code nvarchar(50)
declare @KeyName nvarchar(200)
declare @KeyValue nvarchar(500)
select @Locale=locale from languages where languageid = @LanguageId
SET @DBCmdResponseCode = 0
SET @KeyIds = ''
select @EventName = eventName from eventLanguages
where eventID = @EventId
--BEGIN TRY
Select @SystemCategoryId=CategoryId from SystemCategories where Name=rtrim(ltrim(@CategoryName))
Select @CategoryId=CategoryId from Categories where Name=rtrim(ltrim(@CategoryName)) and EventId=@EventId
if (@str='deactivate')
Begin
Delete from Codetranslation where CategoryId=@CategoryId
Update Categories set [Status]=0, Isfilter=0 where CategoryId=@CategoryId and Eventid=@EventId
Set @DBCmdResponseCode=2
return
End
set @XmlData=cast(@str as xml)
DECLARE @temp TABLE
(
Id int IDENTITY(1,1),
Code varchar(100),
Translation varchar(500),
CategoryId int
)
Insert into @temp (Code,Translation,CategoryId)
SELECT
tab.col.value('@Code', 'varchar(200)'),
tab.col.value('@Translation', 'varchar(500)'),@SystemCategoryId
FROM @XmlData.nodes('/Data') AS tab (col)
select @tempCount=Count(*) from @temp
if(IsNull(@CategoryId,0)>0)
Begin
While (@Counter <= @tempCount)
Begin
Select @IsExists= count(sc.categoryid) from @temp t Inner Join SystemCodetranslation sc
On sc.categoryid=t.CategoryId
where ltrim(rtrim(sc.code))=ltrim(rtrim(t.code)) and ltrim(rtrim(sc.ShortTranslation))=ltrim(rtrim(t.Translation))
and t.Id= @Counter
print @IsExists
Select @Code = Code , @KeyValue = Translation from @temp where id=@counter
set @KeyName = ltrim(rtrim(@EventName)) '_' ltrim(rtrim(@CategoryName)) '_' ltrim(rtrim(@Code)) '_LT'
exec dbo.AddUpdateKeyValue @EventId,@Locale, @KeyName,@KeyValue,NULL,12
select @KeyIds = @KeyIds convert(varchar(50),keyvalueId) ',' from dbo.KeyValues
where eventid = @EventId and keyname = @KeyName and locale = @Locale
set @KeyName = ''
set @KeyValue = ''
Set @Counter= @Counter 1
Set @IsExists=0
End
End
--- Inser data in Codetranslation table
if(isnull(@CategoryId,0)>0)
Begin
print @CategoryId
Delete from codetranslation where categoryid=@CategoryId
Insert into codetranslation (CategoryId,Code,LanguageId,ShortTranslation,LongTranslation,SortOrder)
SELECT
@CategoryId,
tab.col.value('@Code', 'varchar(200)'), @LanguageId,
tab.col.value('@Translation', 'varchar(500)'),
tab.col.value('@Translation', 'varchar(500)'),0
FROM @XmlData.nodes('/Data') AS tab (col)
Update Categories set [Status]=1 where CategoryId=@CategoryId and Eventid=@EventId
End
Set @DBCmdResponseCode=1
set @KeyIds = left(@KeyIds,len(@KeyIds)-1)
END
Комментарии:
1. можете ли вы опубликовать какой-нибудь код, например, какие многократно используемые запросы вас интересуют, вместе с их типами ввода и возврата..
2. пожалуйста, покажите какой-нибудь пример (псевдо) кода и структуры
3. Можете ли вы добавить некоторую информацию о том, что делает значение SP Vcopious_SAP_Core_Translations_Prod_Events_GCO.dbo.AddUpdateKeyValue? Если я правильно вас понял, замена этого лежит в основе вашего вопроса.
4. Я не знаю внутренностей
AddUpdateKeyValue
, поскольку он создан каким-либо другим разработчиком.
Ответ №1:
Вы можете использовать параметр переменной таблицы для своих пользовательских функций.
следующий код является примером использования параметра табличной переменной в хранимой процедуре.
CREATE TYPE IdList AS TABLE (Id INT)
CREATE PROCEDURE test
@Ids dbo.IdList READONLY
AS
Select *
From YourTable
Where YourTable.Id in (Select Id From @Ids)
End
GO
Для выполнения вашей хранимой процедуры используйте следующий формат:
Declare @Ids dbo.IdList
Insert into @Ids(Id) values(1),(2),(3)
Execute dbo.test @Ids
Редактировать
Чтобы вернуть вставленный идентификатор, я не использую параметр переменной from Table. Для этой цели я использую следующий пример запроса.
--CREATE TYPE NameList AS TABLE (Name NVarChar(100))
CREATE PROCEDURE test
@Names dbo.NameList READONLY
AS
Declare @T Table(Id Int)
Insert Into YourTable (Name)
OUTPUT Inserted.Id Into @T
Select Name
From @Names
Select * From @T
End
GO
Комментарии:
1. Вы имеете в виду использовать динамический SQL?
2. Я понятия не имел, что это возможно.
3. @RaduGheorghiu. пожалуйста, сначала протестируйте это решение.
4. Таким образом будет много
TYPE
объявлений, не так ли? Я думаю, по одному для каждой процедуры вставки-обновления?5. @Prakhar Mishra. Нет. вы создаете только один тип idList (Id int) и используете этот тип для всех хранимых процедур, которым требуется параметр списка int.