Попробуйте использовать MERGE
:
CREATE TABLE TestProjectTemplateSection(
ProjectID int,
ProjectTemplateID int,
SectionID int,
IsActive bit,
SectionOrderNumber int
)
INSERT TestProjectTemplateSection(ProjectID,ProjectTemplateID,SectionID,IsActive,SectionOrderNumber)VALUES
(1,1,1,1,4),
(1,1,2,0,2),
(1,1,3,1,3)
И процедура для вставки / обновления / деактивации с помощью:
CREATE PROC SetTestProjectTemplateSection
@ProjectID int,
@ProjectTemplateID int,
@SectionID int,
@IsActive int=1,
@SectionOrderNumber int=NULL
AS
MERGE TestProjectTemplateSection trg
USING
(
SELECT
@ProjectID ProjectID,
@ProjectTemplateID ProjectTemplateID,
@SectionID SectionID,
@IsActive IsActive,
@SectionOrderNumber SectionOrderNumber
) src
ON trg.ProjectID=src.ProjectID AND trg.ProjectTemplateID=src.ProjectTemplateID AND trg.SectionID=src.SectionID
WHEN MATCHED THEN -- update IsActive and SectionOrderNumber
UPDATE SET
trg.IsActive=src.IsActive,
trg.SectionOrderNumber=ISNULL(src.SectionOrderNumber,trg.SectionOrderNumber) -- if NULL then not change it
WHEN NOT MATCHED BY TARGET THEN -- insert new row
INSERT(ProjectID,ProjectTemplateID,SectionID,IsActive,SectionOrderNumber)
VALUES(src.ProjectID,src.ProjectTemplateID,src.SectionID,src.IsActive,src.SectionOrderNumber);
GO
Демо-версия:
-- case 1 - update
EXEC SetTestProjectTemplateSection 1,1,2,1
EXEC SetTestProjectTemplateSection 1,1,2,1,111 -- set new order number
SELECT *
FROM TestProjectTemplateSection
-- case 2 - insert
EXEC SetTestProjectTemplateSection 2,1,2,1,123
SELECT *
FROM TestProjectTemplateSection
-- case 3 - deactive
EXEC SetTestProjectTemplateSection 2,1,2,0
SELECT *
FROM TestProjectTemplateSection
Я думаю, что в качестве варианта вы можете использовать STRING_SPLIT
для списка разделов (см. @ListOfSectionID
):
CREATE PROC SetTestProjectTemplateSections
@ProjectID int,
@ProjectTemplateID int,
@ListOfSectionID varchar(100), -- e.g. '1,2,3,4'
@IsActive int=1
AS
MERGE TestProjectTemplateSection trg
USING
(
SELECT
@ProjectID ProjectID,
@ProjectTemplateID ProjectTemplateID,
CAST(value AS int) SectionID,
@IsActive IsActive
FROM STRING_SPLIT(@ListOfSectionID,',')
) src
ON trg.ProjectID=src.ProjectID AND trg.ProjectTemplateID=src.ProjectTemplateID AND trg.SectionID=src.SectionID
WHEN MATCHED THEN
UPDATE SET
trg.IsActive=src.IsActive
WHEN NOT MATCHED BY TARGET THEN
INSERT(ProjectID,ProjectTemplateID,SectionID,IsActive)
VALUES(src.ProjectID,src.ProjectTemplateID,src.SectionID,src.IsActive);
GO
Но STRING_SPLIT
работает для SQL Server 2017. Для другой версии SQL Server вы можете найти пользовательскую функцию для разбиения. Например - строка разделения T-SQL
Тест:
EXEC SetTestProjectTemplateSections 1,1,'1,2,3,4',0
SELECT *
FROM TestProjectTemplateSection
В качестве варианта можно использовать параметр таблицы:
CREATE TYPE TypeForProjectTemplateSection AS table(
ProjectID int,
ProjectTemplateID int,
SectionID int,
IsActive bit,
SectionOrderNumber int
)
GO
И используйте этот тип в своей процедуре:
CREATE PROC SetTestProjectTemplateSectionFromTable
@ProjectTemplateSectionDate dbo.TypeForProjectTemplateSection READONLY -- need to use READONLY here
AS
MERGE TestProjectTemplateSection trg
USING @ProjectTemplateSectionDate src
ON trg.ProjectID=src.ProjectID AND trg.ProjectTemplateID=src.ProjectTemplateID AND trg.SectionID=src.SectionID
WHEN MATCHED THEN -- update IsActive and SectionOrderNumber
UPDATE SET
trg.IsActive=src.IsActive,
trg.SectionOrderNumber=src.SectionOrderNumber
WHEN NOT MATCHED BY TARGET THEN -- insert new row
INSERT(ProjectID,ProjectTemplateID,SectionID,IsActive,SectionOrderNumber)
VALUES(src.ProjectID,src.ProjectTemplateID,src.SectionID,src.IsActive,src.SectionOrderNumber);
GO
Как его использовать:
ОБЪЯВИТЬ @Table dbo.TypeForProjectTemplateSection
INSERT @Table(ProjectID,ProjectTemplateID,SectionID,IsActive,SectionOrderNumber)VALUES
(1,1,1,1,111),
(1,1,2,1,222)
EXEC SetTestProjectTemplateSectionFromTable @Table -- use it as parameter
SELECT *
FROM TestProjectTemplateSection
И вы можете использовать его из C #:
SqlCommand cmd = new SqlCommand("SetTestProjectTemplateSectionFromTable", con);
cmd.CommandType = CommandType.StoredProcedure;
DataTable tbl = new DataTable();
tbl.Columns.Add("ProjectID", typeof(int));
tbl.Columns.Add("ProjectTemplateID", typeof(int));
tbl.Columns.Add("SectionID", typeof(int));
tbl.Columns.Add("IsActive", typeof(bool)); // Check it because I don't remember how to use type bit here
tbl.Columns.Add("SectionOrderNumber", typeof(int));
tbl.Rows.Add(1,1,1,true,111);
tbl.Rows.Add(1,1,2,true,222);
cmd.Parameters.AddWithValue("@ProjectTemplateSectionDate", tbl);
cmd.ExecuteNonQuery();