2016-12-05 144 views
0

我写了一个存储过程中插入姓名和电子邮件地址:如何返回值1存储过程

CREATE PROCEDURE [dbo].[usp_Referral_Email] 
    @user_key varchar(36), 
    @name nvarchar(100),  
    @email nvarchar(500), 
    @result int output 
AS 
BEGIN 
    DECLARE @username Nvarchar(500) 
    DECLARE @useremail Nvarchar(500) 
    DECLARE @CusrsorID CURSOR 

    SET @CusrsorID = CURSOR FOR 
     SELECT Value,Value1 
     FROM ufn_split_string(@name,@email) 

    OPEN @CusrsorID 

    FETCH NEXT FROM @CusrsorID INTO @username, @useremail 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     declare @user nvarchar(36) 

     begin try 
     begin transaction trans_Referral_Email  

      IF NOT EXISTS (SELECT 1 FROM dbo.C_User_Credentials 
          WHERE email = @useremail) 
      BEGIN 
       IF NOT EXISTS (SELECT 1 FROM dbo.Referral_Email 
           WHERE R_Email = @useremail) 
       BEGIN 
        INSERT INTO dbo.Referral_Email (CFK_C_UP_key, R_Name, R_Email) 
        VALUES (@user_key, @username, @useremail)    

        SET @result = 1 
       END 
       ELSE 
       BEGIN 
        SET @result = 0 
       END 
      END 
      ELSE 
      BEGIN 
       SET @result = 0 
      END 

      COMMIT transaction trans_Referral_Email 
     end try 
     begin catch 
      rollback transaction trans_Referral_Email 
      set @result=ERROR_MESSAGE() 
     end catch 


     FETCH NEXT FROM @CusrsorID INTO @username, @useremail 
    END 

    CLOSE @CusrsorID 
    DEALLOCATE @CusrsorID 
END 

作为一个例子,我将通过价值

  1. @name = ramesh,suresh,rahul
  2. @email = [email protected],[email protected],[email protected]

在插入之前,我们检查条件电子邮件地址是否存在,假设电子邮件地址存在,它将不会插入表中。 现在我的问题是我会通过例子来解释。 [email protected][email protected]是新的电子邮件地址,这两个电子邮件地址都将插入到表,以便返回值是 [email protected]已在表中存在,因此它会插入到表所以返回值将是和输出@返回值将为但我们插入了2个电子邮件地址,所以我需要@返回值应为1作为输出

所以我的问题是,如果在电子邮件地址的任何地方插入到表中,如果一个电子邮件地址,还插入输出应该@收益率= 1

+0

你看过MERGE()吗?它似乎非常适合这类问题。与@@ ROWCOUNT配对 – scsimon

+0

为什么在这个世界上你使用这样的循环来插入数据?这应该是一个基于集合的方法。这让我怀疑你的分配器是否也是一个基于循环的解决方案。这里有一些更好的替代环路分离器。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings –

回答

1

你需要的是被称为“锁”(过时)或作为flag variable,并且是很常见的。

一个标志变量(在这种情况下,@result)应该在循环之外初始化,然后在出现条件时(在这种情况下插入一条记录)进行设置。跳过任何后续记录时,不应触摸该变量。这样它就起到了一种或门的作用。

像这样:

CREATE PROCEDURE [dbo].[usp_Referral_Email] 
    @user_key varchar(36), 
    @name nvarchar(100),  
    @email nvarchar(500), 
    @result int output 
AS 
BEGIN 
    DECLARE @username Nvarchar(500) 
    DECLARE @useremail Nvarchar(500) 
    DECLARE @CusrsorID CURSOR 

    SET @CusrsorID = CURSOR FOR 
     SELECT Value,Value1 
     FROM ufn_split_string(@name,@email) 

    OPEN @CusrsorID 

    FETCH NEXT FROM @CusrsorID INTO @username, @useremail 
    SET @result = 0 --<--- Will stay 0 until one or more rows are inserted 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     declare @user nvarchar(36) 

     begin try 
     begin transaction trans_Referral_Email  

      IF NOT EXISTS (SELECT 1 FROM dbo.C_User_Credentials 
          WHERE email = @useremail) 
      BEGIN 
       IF NOT EXISTS (SELECT 1 FROM dbo.Referral_Email 
           WHERE R_Email = @useremail) 
       BEGIN 
        INSERT INTO dbo.Referral_Email (CFK_C_UP_key, R_Name, R_Email) 
        VALUES (@user_key, @username, @useremail)    

        SET @result = 1 --<--- Will stay 1 for the rest of its lifespan, even if other rows are not inserted 
       END 
      END 

      COMMIT transaction trans_Referral_Email 
     end try 
     begin catch 
      rollback transaction trans_Referral_Email 
      set @result=ERROR_MESSAGE() 
     end catch 


     FETCH NEXT FROM @CusrsorID INTO @username, @useremail 
    END 

    CLOSE @CusrsorID 
    DEALLOCATE @CusrsorID 
END 

通知我已经删除了一堆的ELSE条件,因为你当一个记录被跳过不需要做任何事情。

0

您要处理/插入几个用户1存储过程调用,并且不能使用单个输出INT字段为多个用户返回插入状态。

更好地在应用程序级别拆分@name和@email参数,并传递给您的(修改过的)存储过程只有一对名称和电子邮件。然后,您必须多次从应用程序级别为每个名称/电子邮件对调用spT。

如果您仍然希望为批量用户插入使用单个spT,则必须将每个插入状态记录到临时表或表变量中,然后在spT结束时您必须从该临时表或表中选择SELECT变量。

这种方式在应用程序级别,您将有一行状态返回每个名称/电子邮件输入对。

但我个人建议你实际上改变你的spT,每个名字/电子邮件对被调用一次。这是一个更好,更干净的方法。

HTH