首页 > 解决方案 > 存储过程 - 游标 - 为记录字段赋值并在游标末尾选择

问题描述

我将联系人对象列表 ( List<Contact>) 从 C# 传递给 SQL Server 存储过程:

在此处输入图像描述

为了捕获这个列表,我在 SQL Server 中使用了用户定义的表类型,如下所示:

在此处输入图像描述

现在在我的存储过程中,我需要做以下事情。

  1. 通过传递给存储过程的联系人列表循环(光标)
  2. 如果tblContact数据库中的表有当前电子邮件地址的记录(当前联系人记录/迭代),则需要获取该tblContact记录ContactId并将其分配给当前Contact迭代记录;否则使用该电子邮件地址(不存在)向 tblContact 插入一条新记录,并将其 contactId 值分配给当前联系人记录/迭代 tblContact 字段(因为 contactId 是 TblContact 的主键,我可以这样做

    SET @contactId = (SELECT SCOPE_IDENTITY()); 
    

    )。

  3. 最后选择修改后的联系人记录

我需要一些帮助来实现上面列出的第二步,这是我到目前为止所写的,

ALTER PROCEDURE [dbo].[UpdateMailjetDetails] 
    @contacts Contact READONLY
AS
BEGIN
    SET NOCOUNT ON;

    -- 1. Loop (cursor) though contacts list passed to stored procedure
    DECLARE @contactEmail varchar(1000);

    DECLARE cur CURSOR FOR 
         SELECT Email FROM @contacts

    OPEN cur    
    FETCH NEXT FROM cur INTO @contactEmail; 

    WHILE @@FETCH_STATUS = 0 
    BEGIN
        DECLARE @contactId INT = (SELECT TOP(1) ContactId 
                                  FROM tblContact 
                                  WHERE EmailAddress = @contactEmail);

        IF (@contactId != '')
        BEGIN           
            SELECT 'Exists - ' + CONVERT(VARCHAR, @contactId);

        -- 2 assign contact Id to current contact.TblContactId
    END
    ELSE
    BEGIN
        INSERT INTO tblContact (EmailAddress, DateCreated) 
        VALUES (@contactEmail, GETDATE()); 

        SET @contactId = (SELECT SCOPE_IDENTITY()); 
        -- 2 new @contactId value to current contact.TblContactId 
    END

    FETCH NEXT FROM cur INTO @contactEmail;
END

CLOSE cur    
DEALLOCATE cur

-- 3
SELECT * FROM @contacts
END

这就是我执行存储过程的方式:

DECLARE @return_value int
DECLARE @input Contact;

INSERT INTO @input (Email, [Name], TblContactId, CompanyId, TblContactCompanyId) 
VALUES ('a@a.com', 'a', null, null, null),
       ('b@a.com', 'b', null, 1, 1),
       ('a@gmail.com', 'aa', null, 1, 1),
       ('b@hotmail.com', 'bb', null, 1, 1)


EXEC @return_value = [dbo].[UpdateMailjetDetails]
                     @contacts = @input

SELECT 'Return Value' = @return_value
GO

因此,如上所述,在执行存储过程之后,它需要打印所有带有它的联系人记录TblContactId(现有的或新插入的)值。

对此非常感谢任何帮助或指导。谢谢。

标签: sql-servertsqlstored-procedurescursoruser-defined-types

解决方案


如果我理解正确,您想获取输入电子邮件地址的列表,如果该电子邮件地址尚不存在,则将任何输入到目标表中,然后在目标表中输出原始地址列表及其相应数据?您根本不需要光标,以下应该可以满足您的需要,并且可能会表现得更好:

CREATE PROC dbo.UpdateMailjetDetails (
    @contacts dbo.Contact READONLY
)
AS

INSERT INTO dbo.tblContact (EmailAddress, DateCreated)
SELECT c.Email, SYSDATETIME()
FROM @contacts c
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.tblContact t
    WHERE t.EmailAddress = c.Email
);

SELECT c.Email, t.[Name], t.tblContactId, c.CompanyId, t.CompanyId AS tblContactCompanyId
FROM @contacts c
    LEFT OUTER JOIN dbo.tblContact t ON t.EmailAddress = c.Email;

我的一些假设在这里可能略有偏差,但这应该作为一个起点。请注意,如果您对目标表中的电子邮件地址列没有唯一约束,那么最后的结果可能包含比您最初提供的行更多的行,因为可能有多个匹配行。请注意,如果要执行其他操作,例如如果行存在则更新,则可以将插入语句替换为合并语句。


推荐阅读