Привет и спасибо за чтение!
Мне было интересно, как лучше всего инкапсулировать логику хранимых процедур с использованием метода SQL на основе множеств.
Например, у меня есть приложение для ввода продукта, которое я разрабатываю. Пытаясь ограничить дублирование кода, я создал хранимую процедуру AddItem, которая создает новый продукт в таблицах продуктов. Недостатком является то, что для использования этой процедуры в ситуации, которая требует добавления группы продуктов, я вынужден использовать курсор или цикл WHILE для выполнения процедуры по типу «FOR EACH». Это приводит к очень низкой производительности на больших наборах предметов.
Конечно, я мог бы жестко закодировать операторы INSERT в вызывающей процедуре, но это заставляет меня чувствовать себя странно, потому что весь смысл в том, чтобы иметь возможность изменить (в одном месте) логику «добавления элемента». Поэтому, если столбец изменился, я должен был помнить, чтобы изменить все операторы INSERT во всех местах, которые его используют. Я просто подумал, что должен быть лучший способ сделать это, и любой совет будет оценен.
EDIT:
Совершенно верно, я должен привести пример кода. Вот содержимое процедуры AddItem, которая выполняется в базе данных MS SQL2005:
ALTER PROCEDURE [dbo].[AddItem]
@ProjectNumber int,
@ItemName varchar(255),
@SupplierID int,
@SKUType int,
@Store varchar(3),
@Category varchar(4),
@AddedBy varchar(255),
@ParentSKU varchar(255) = NULL,
@SetNumber int = NULL,
@NewItemNumber int OUTPUT
AS
SET NOCOUNT ON
DECLARE @DiscontinuedStatus bit
BEGIN TRY
BEGIN TRAN
SET @NewItemNumber = 0
INSERT INTO ProductEntry.dbo.Items
(ProjectNumber, SetNumber, SKUType, Store, Category, AddedBy, ParentSKU, EntryTime)
VALUES(@ProjectNumber, @SetNumber, @SKUType, @Store, @Category, @AddedBy, @ParentSKU, CURRENT_TIMESTAMP)
SET @NewItemNumber = SCOPE_IDENTITY()
IF @SKUType = 1
BEGIN
SET @DiscontinuedStatus = 1
END
ELSE
BEGIN
SET @DiscontinuedStatus = 0
END
INSERT INTO ProductEntry.dbo.ItemInfo
(ItemNumber, ItemName, Discontinued)
VALUES (@NewItemNumber, @ItemName, @DiscontinuedStatus)
INSERT INTO ProductEntry.dbo.ItemSupplierInfo
(ItemNumber, SupplierID)
VALUES(@NewItemNumber, @SupplierID)
INSERT INTO ProductEntry.dbo.ItemWebInfo
(ItemNumber)
VALUES(@NewItemNumber)
INSERT INTO ProductEntry.dbo.ItemTags
(ItemNumber)
VALUES (@NewItemNumber)
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH
Мне нужна процедура, которая добавляет несколько элементов одновременно (с номерами больше 1000), и при использовании курсора производительность очень плохая. Добавление группы из 800 продуктов занимает более минуты, и от этого становится только хуже.
EDIT:
Чтобы дополнительно прояснить решение, приложение позволяет элементы, которые имеют отношения родитель-ребенок. При добавлении нового родительского элемента пользователь выбирает из списка параметров, и набор дочерних элементов создается на основе набора параметров.
Например, пользователь может создать продукт под названием «Awesome Boot» с набором опций Colors = "Brown, Black", Size = "10M, 11M, 12M", ToeStyle = "SteelToe, SoftToe" - это будет создать набор из 12 предметов. Очевидно, вы можете увидеть, как это может возрасти в геометрической прогрессии, учитывая, что большинство ботинок имеют около 36 размеров, несколько цветов и стилей ног, а также другие варианты. Это может привести к родительскому элементу с большим количеством дочерних элементов.
Я полагаю, что одним из решений было бы объединение всей информации об элементах в одну таблицу "Элементы", что устраняет необходимость хранения одной и той же IDENTITY в нескольких таблицах. Мне нравится удобство логического разделения связанных данных на разные таблицы. Может быть, я пытаюсь взять свой пирог и съесть его тоже!
Спасибо! :)