【问题标题】:Update or Insert records in database based on result set根据结果​​集更新或插入数据库中的记录
【发布时间】:2015-12-18 03:00:12
【问题描述】:

我有一张这样的桌子

我有另一个表 sections,其中有 6 个部分,ID 来自 1 to 6。我从用户那里获得了一个部分 ID 列表,其中提供了有关用户当前活动部分的信息。假设返回给我的列表的部分 id 如下{2,3,4,5} 用于 ID 为 1 的用户。现在我的问题是

  1. 如何将此部分 ID 列表传递给我的存储过程
  2. 我要更新的是记录的活动标志,其中部分 ID 为 1,用户 ID 为 1,因为部分 ID 列表没有条目 1
  3. 我想为用户 id 1 在同一个表中插入第 5 节的新记录,因为它在节 id 列表中返回。

谁能告诉我如何做到这一点?

我可以从以下查询中得到total section id's

select Id from sections

但不知道我会在 total list of section id's 之间迭代并比较从 C# 返回的 list of section ids

【问题讨论】:

  • @EdwinStoteler :感谢您的帮助.. 但第一步是传递 id 列表,然后还有另一部分要更改 IsActive 标志

标签: c# sql stored-procedures sql-server-2008-r2


【解决方案1】:

回答完整的问题。

1.就像我在评论中说的:Table valued parameters

首先创建一个UDTT 来存储您的部分ID,以便为存储过程输入。

CREATE TYPE [dbo].[SectionIdUDTT] AS TABLE(
    [id] int NOT NULL
)

将此 UDTT 用作存储过程的参数:

ALTER PROCEDURE [dbo].[YourSPname] @SectionId SectionIdUDTT readonly,
    @UserId INT
AS
BEGIN

为了调用此存储过程,您必须先填写 SectionIdUDTT,然后再调用存储过程。

DECLARE @SectionId AS SectionIdUDTT;

INSERT INTO @SectionId 
--your values here

EXEC YourSPname @SectionId, @UserId;

查看DataTable 类,以便从 C# 调用它。确保用户对 UDTT 具有执行权限。

2在存储过程中

将已存在但不在表值参数中的用户设置为非活动记录。

UPDATE YourTable
SET IsActive = 0
WHERE UserId = @UserId
    AND SectionId NOT IN (SELECT id FROM @SectionId)
    AND SectionId IN (SELECT Id FROM sections) --Not really needed

3在存储过程中

只需插入尚不存在的记录。我只是假设id 是一个标识列。

INSERT INTO YourTable (UserId, SectionId, IsActive)
SELECT @UserId,
    s.id,
    1
FROM @SectionId s
WHERE NOT EXISTS (
    SELECT 1
    FROM YourTable y
    WHERE y.SectionId = s.id
        AND y.UserId = @UserId
    )

我会在您的存储过程中推荐Transaction management

【讨论】:

    【解决方案2】:

    首先我创建了一个调用存储过程的方法,我向该方法传递了sections(sections table entity) 和客户 ID 的列表

    public bool SaveChatSectionUserMapping(List<Sections> lstSections, int customerId)
            {
                con = new SqlConnection(connectionString);
                bool isUpdated = false;
                try
                {
                    string xmlString = string.Empty;
                    xmlString = XMLOperations.WriteXML(lstSections);
                    SqlCommand cmd = new SqlCommand("spUpdateSections", con);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.Add("@XMLData", SqlDbType.Xml).Value = xmlString;
                    cmd.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
                    SqlParameter param = new SqlParameter();
                    param.SqlDbType = SqlDbType.Bit;
                    param.Direction = ParameterDirection.Output;
                    param.ParameterName = "@Result";
                    cmd.Parameters.Add(param);
                    con.Open();
                    cmd.ExecuteNonQuery();
                    isUpdated = (param.Value != DBNull.Value) ? Convert.ToBoolean(param.Value) : false;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (con.State == ConnectionState.Open)
                        con.Close();
                }
                return isUpdated;
            }
    

    我从xmlString = XMLOperations.WriteXML(lstSections);这一行得到的xmlString的值是这样的

    <ArrayOfSection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Sections>
        <UserId>1</UserId>
        <SectionId>1</SectionId>
        <IsActive>true</IsActive>
      </Sections>
      <Sections>
        <UserId>1</UserId>
        <SectionId>2</SectionId>
        <IsActive>true</IsActive>
      </Sections>
      <Sections>
        <UserId>1</UserId>
        <SectionId>5</SectionId>
        <IsActive>true</IsActive>
      </Sections>
    </ArrayOfSection>
    

    现在在存储过程中

    CREATE Procedure [dbo].[spUpdateSections]  
    (  
     @XMLData as XML,
     @CustomerId INT,  
     @Result int Output
    
    )  
    AS
    BEGIN
    SET NOCOUNT ON;  
        Declare @ErrorCode Varchar(100) = '',@propertyCount VArchar(100) = '',@currentCount int=1,@SectionId int, @IsActive bit
    
    Begin TRY
    
    UPDATE Sections
    SET
        IsActive = 0
    WHERE
        UserId = @CustomerId
    
    SELECT @propertyCount = convert(VARCHAR, @XMLData.query ('count(/ArrayOfSection/Sections)'))
    SET @currentCount = 1
    
         while (@currentCount<=@propertyCount)       
         Begin 
         SET @SectionId = @XMLData.value('data(/ArrayOfSection/Sections[sql:variable("@currentCount")]/SectionId)[1]', 'INT') 
         SET @IsActive = @XMLData.value('data(/ArrayOfSection/Sections[sql:variable("@currentCount")]/IsActive)[1]', 'BIT')
    
                   If Exists (SELECT *
                              FROM
                                  Sections
                              WHERE
                                  UserId = @CustomerId
                                  AND SectionId = @SectionId)
    BEGIN
           IF(@IsActive=1) 
           BEGIN 
                UPDATE Sections
                 SET
                     IsActive = 1
                 WHERE
                     UserId = @CustomerId AND
                     SectionId = @SectionId
    
            END
    END
    
    ELSE
           BEGIN
           IF(@IsActive=1) 
           BEGIN 
    INSERT INTO Sections
               ([SectionId]
               ,[UserId]
               ,[IsActive])
         VALUES
               (@SectionId,@CustomerId,1)
            END
        END
    
    SET @currentCount = @currentCount + 1 
           End 
    
           SET @Result = 1
               ErrorCode:  
               If(@ErrorCode !='')
               BEGIN
    --SELECT @BSErrorResult = doctor.GetErrorCodeDetail(@ErrorCode)
    SET @Result = 2
               END  
        END TRY        
        BEGIN CATCH     
          --Declaring Variable for formating error  
          Declare @ErrorMessage  VARCHAR(max),  
           @ErrorSeverity  INT,  
           @ErrorState   INT
    
    --SELECTING TECHNICAL ERROR   
    SELECT @ErrorMessage = error_message()
         , @ErrorSeverity = error_severity()
         , @ErrorState = error_state()
         , @ErrorMessage = @ErrorMessage + '  ' + db_name() + '  ' + ' ' + object_name(@@PROCID);   
    
          RAISERROR (  
             @ErrorMessage, -- Message text.  
             @ErrorSeverity, -- Severity.  
             @ErrorState -- State.  
               );   
         End CATCH    
    
    
    
    END
    

    另一种生成 XMl 的方法是像这样使用 XElement

    XElement xml = new XElement("Sections",
                                    from col in lstSections
                                    select new XElement("rows",
                                                   new XElement("UserId", col.UserId),
                                                   new XElement("SectionId", col.SectionId),
                                                   new XElement("IsActive", col.IsActive)));
    
                                  string  xmlString = xml.ToString();
    

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 2010-11-18
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多