当行匹配或不匹配时插入或更新数据

时间:2018-10-31 04:15:32

标签: c# sql-server database

我有桌子ProjectTemplateSection

    [ProjectID] [int] 
    [ProjectTemplateID]
    [SectionID] [int]
    [IsActive] [bit] 
    [SectionOrderNumber] [int] 

具有以下示例数据:

  ProjectID  TemplateCloneId    SectionCloneId IsActive SectionOrderNumber
 -----------------------------------------------------------------------
    1                   1               1         1         4
    1                   1               2         0         2
    1                   1               3         1         3

我们有相互关联的项目,模板和部分模块

  • 一个模板将包含多个部分
  • 一个项目将映射一个模板

当用户将模板分配给项目时,projectid,templateid和sectionid将插入ProjectTemplateSection。

我需要以下澄清的建议

  • 如果用户进入并编辑模板的部分,例如删除部分并添加新部分。如果节和模板之间存在任何映射,则IsActive标志应为false。如果没有映射,则应插入。

我应该对所选模板的现有映射进行选择查询 &获取记录并与新映射进行比较&为新记录插入&更新旧映射,即将IsActive标志设为false

请提出哪种方案是这种情况的最佳解决方案

1 个答案:

答案 0 :(得分:0)

尝试使用Oct 31 11:18:00 dbuser /usr/sbin/cron[94330]: (dbuser) CMD (mysqldump -udbuser -pdbpassword mydb > /backups/mydb.`date +")

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 适用于SQL Server2017。对于其他版本的SQL Server,您可以找到用户定义的拆分函数。例如-T-SQL split string

测试:

STRING_SPLIT

作为变体,您可以使用表参数:

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

如何使用它:

DECLARE @Table dbo.TypeForProjectTemplateSection

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

您可以从C#中使用它:

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