简体   繁体   English

根据结果​​集在数据库中更新或插入记录

[英]Update or Insert records in database based on result set

I've a table like this 我有这样的桌子

在此处输入图片说明

I've another table sections in which there are 6 sections with id from 1 to 6 . 我还有另一个表sections ,其中有6个节,其ID从1 to 6 I get a list of section id from user which gives information about the current active section of user. 我从用户那里获得了部分ID的列表,该列表提供了有关用户当前活动部分的信息。 Suppose the list returned to me has section ids as follows {2,3,4,5} for user with id 1 . 假设返回给我的列表具有ID为1用户,其区段ID如下{2,3,4,5}所示。 Now my question is 现在我的问题是

  1. How can I pass this list of section ids to my stored procedure 如何将此部分ID列表传递给存储过程
  2. I want to update is active flag of record where section id is 1 and user id is 1 since the list of section ids doesn't have an entry of 1 我要更新的是记录的活动标志,其中段ID为1,用户ID为1,因为段ID的列表中没有条目1
  3. I want to insert a new record of section id 5 for user id 1 in same table as it is returned in list of section ids. 我想在用户ID 1的表中插入新的ID为5的记录,因为它在ID列表中返回。

Can anyone please tell me how to achieve this? 谁能告诉我如何实现这一目标?

I can get total section id's from the following query 我可以从以下查询中获取total section id's

select Id from sections

but don't know i will iterate between total list of section id's and compare the list of section ids returned from C# 但不知道我会在total list of section id's之间进行迭代,并比较从C#返回list of section idslist of section ids

To answer the complete question. 回答完整的问题。

1. Like I said in the comment: Table valued parameters 1.就像我在评论中说的: 表值参数

First create a UDTT to store your sections ids for input for the stored procedure. 首先创建一个UDTT来存储您的部分ID,以供存储过程输入。

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

Use this UDTT as a parameter for your stored procedure: 将此UDTT用作存储过程的参数:

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

In order to call this stored procedure you must first fill the SectionIdUDTT before you call the stored procedure. 为了调用此存储过程,必须先填充SectionIdUDTT,然后再调用存储过程。

DECLARE @SectionId AS SectionIdUDTT;

INSERT INTO @SectionId 
--your values here

EXEC YourSPname @SectionId, @UserId;

Take a look at DataTable class in order to call this from C#. 看一下DataTable类,以便从C#调用它。 Make sure the user has execute permissions on the UDTT. 确保用户具有对UDTT的执行权限。

2 in the stored procedure 2在存储过程中

Set the records to inactive of the user that already existed but are not in the table valued parameter. 将记录设置为不活动的用户已存在但不在表值参数中。

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 in the stored procedure 3在存储过程中

Just insert the record that not yet exists. 只需插入尚不存在的记录。 I just assume that id is an identity column. 我只是假设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
    )

I would recommend Transaction management in your stored procedure. 我建议您在存储过程中进行事务管理

First I created a method which would call stored procedure, to that method I passed a list of sections (sections table entity) and Customer Id 首先,我创建了一个将调用存储过程的方法,向该方法传递了一个sections列表(节表实体)和客户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;
        }

The value of xmlString I get from this line xmlString = XMLOperations.WriteXML(lstSections); 我从这一行获得的xmlString的值xmlString = XMLOperations.WriteXML(lstSections); is like this 就是这样

<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>

Now in stored Procedure 现在在存储过程中

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

Another way to Generate XMl would be by using XElement like this 生成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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM