sql-server - 存储过程 - 游标 - 为记录字段赋值并在游标末尾选择
问题描述
我将联系人对象列表 ( List<Contact>
) 从 C# 传递给 SQL Server 存储过程:
为了捕获这个列表,我在 SQL Server 中使用了用户定义的表类型,如下所示:
现在在我的存储过程中,我需要做以下事情。
- 通过传递给存储过程的联系人列表循环(光标)
如果
tblContact
数据库中的表有当前电子邮件地址的记录(当前联系人记录/迭代),则需要获取该tblContact
记录ContactId
并将其分配给当前Contact
迭代记录;否则使用该电子邮件地址(不存在)向 tblContact 插入一条新记录,并将其 contactId 值分配给当前联系人记录/迭代 tblContact 字段(因为 contactId 是 TblContact 的主键,我可以这样做SET @contactId = (SELECT SCOPE_IDENTITY());
)。
最后选择修改后的联系人记录
我需要一些帮助来实现上面列出的第二步,这是我到目前为止所写的,
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
(现有的或新插入的)值。
对此非常感谢任何帮助或指导。谢谢。
解决方案
如果我理解正确,您想获取输入电子邮件地址的列表,如果该电子邮件地址尚不存在,则将任何输入到目标表中,然后在目标表中输出原始地址列表及其相应数据?您根本不需要光标,以下应该可以满足您的需要,并且可能会表现得更好:
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;
我的一些假设在这里可能略有偏差,但这应该作为一个起点。请注意,如果您对目标表中的电子邮件地址列没有唯一约束,那么最后的结果可能包含比您最初提供的行更多的行,因为可能有多个匹配行。请注意,如果要执行其他操作,例如如果行存在则更新,则可以将插入语句替换为合并语句。
推荐阅读
- flutter - 我该如何解决这个颤振安装错误
- python - 将文本除以 2 个字符
- mongodb - MongoDB 返回所有文档(即使它们是双重的)
- amazon-web-services - 如何将使用 express 构建的 graphql api 部署到 AWS 无服务器?
- python - 如何在 django 中使用“self”/它自己的模型获取 ManyToManyField 中的对象数?
- javascript - 错误 TS2339:“特殊 []”类型上不存在属性“默认”
- apache - htaccess:我不能允许来自特定域而不是 IP 的访问
- xslt - 获取第一次出现的 XSLT 样式表
- java - -XX:+PrintCodeCacheOnCompilation 在特定文件中
- java - 如果我有任务执行器,对我的 Spring Boot 应用程序有什么影响