【问题标题】:Stored Procedure/SQL script that allows me to add a record to a table允许我向表中添加记录的存储过程/SQL 脚本
【发布时间】:2017-12-07 20:18:59
【问题描述】:

我有 2 个表,一个包含所有电子邮件数据,另一个包含所有特定成员电子邮件数据,如果已阅读电子邮件,则其中一个会创建一行。 一旦成员阅读了一封电子邮件,它就会添加到 Member_email_read 表中(该表是根据所有阅读的电子邮件创建和填充的)。

我正在尝试(批量)设置所有要阅读的消息(这将填充 Member_email_read 表),但我可以一次添加一条 (请参阅下面的存储过程),我无法批量添加它们。

这两个表是电子邮件,它保存了系统中每封电子邮件的记录。另一个表格是成员已阅读的所有电子邮件的表格。每次一封电子邮件 被读取一条记录被添加到 Member_email_read 表中。它们在 message_id 上关联(并且两者都应该使用相同的 user_id)。两张表如下-

SELECT [member_email_id]
  ,[member_email_FK_message_id]
  ,[member_email_FK_user_id]
  ,[member_email_status]
  ,[member_email_read_datetime]
  ,[member_email_delete_datetime]
FROM [MemberData].[dbo].[Member_email_read]



SELECT[message_id]
  ,[email_catlogue_num]
  ,[email_FK_user_id]
  ,[Email_time]
  ,[email_content]
  ,[Email_created_date]
FROM [MemberData].[dbo].[Email]

要将所有消息(对于某个用户)设置为未读,我要做的就是从该表中删除该用户的每条记录,这可以通过以下方式完成:

DELETE FROM [MemberData].[dbo].[Member_email_read]
WHERE [member_email_FK_message_id_FK_user_id] ='2';

我基本上是在寻找这个删除的反面。

我创建了一个存储过程,允许将一个特定的电子邮件设置为读取,但是此存储过程(执行时)需要成员输入 email_id、message_id、user_id、状态、read_datetime 和 delete_datetime。

CREATE PROCEDURE [dbo].[set_member_email_to_read]

@member_email_id int,
@member_email_FK_message_id int,
@member_email_FK_user_id int
@member_email_status varchar(1),
@member_email_read_datetime dateTime,
@member_email_delete_datetime dateTime

as
if not exists (Select * from [dbo].[Member_email_read] where [member_email_FK_message_id] = @member_email_FK_message_id) begin
insert into [dbo].[Member_email_read]
    (
       [member_email_FK_message_id]
      ,[member_email_FK_user_id]
      ,[member_email_status]
      ,[member_email_read_datetime]
      ,[member_email_delete_datetime]
  )
  values
  (
        @member_email_FK_message_id,
        @member_email_FK_user_id
        @member_email_status,
        @member_email_read_datetime,
        @member_email_delete_datetime
  )


SELECT Convert(int,SCOPE_IDENTITY()) As InsertedID

end else begin
    update [dbo].[Member_email_read] set
   [member_email_FK_message_id]         =   @member_email_FK_message_id
  ,[member_email_FK_user_id]            =   @member_email_FK_user_id
  ,[member_email_status]                =   @member_email_status
  ,[member_email_read_datetime]         =   @member_email_read_datetime
  ,[member_email_delete_datetime]       =   @member_email_delete_datetime

where [member_email_FK_user_id] = @member_email_FK_user_id
if (@@ERROR = 0) begin
    SELECT Convert(int,@member_email_FK_user_id) As InsertedID
end
end
GO

我希望创建一个允许我输入的存储过程(或通用 SQL 脚本) 一个 user_id,然后允许该用户的所有电子邮件从未读更改为已读(填充 Member_email_read 表)。

【问题讨论】:

  • 你考虑过触发器吗?
  • 是否有您想要的默认statusemail_read_datetime 是当前时间戳,delete_datetimenull
  • 不确定是否使用触发器,以前没有真正使用过它们。在这种情况下它将如何工作?
  • 状态可以只是新的或读取 email_read_datetime 和 delete_datetime 可能为空 - 这之前已经工作过
  • 我认为您不需要为此使用触发器,但 MERGE 语句应该允许您从电子邮件表批量插入/更新到已读电子邮件表。不过,我质疑这张桌子的设计。为什么不在同一个电子邮件表中有一个read_datetime 字段?

标签: sql sql-server database


【解决方案1】:

您可以尝试使用MERGEinsert/update 从您的Email 表执行到您的Member_email_read 表中:

MERGE [MemberData].[dbo].[Member_email_read] AS tgt  
USING (
    SELECT message_id, user_id, 'R', null, CURRENT_TIMESTAMP
    FROM [MemberData].[dbo].[Email] 
    WHERE user_id = @UserId
) AS src (MessageId, UserId, Status, ReadDate, DeleteDate) 
ON (
    tgt.member_email_FK_message_id = src.message_id
    AND tgt.member_email_FK_user_id = src.user_id
)  
WHEN MATCHED THEN   
    UPDATE SET tgt.member_email_status = src.Status,
               tgt.member_email_read_datetime = src.ReadDate,
               tgt.member_email_delete_datetime = src.DeleteDate
WHEN NOT MATCHED THEN  
    INSERT (member_email_FK_message_id, member_email_FK_user_id, 
            member_email_status, member_email_read_datetime, member_email_delete_datetime)  
    VALUES (src.MessageId, src.UserId, src.Status, src.ReadDate, src.DeleteDate)
;

这应该可行,尽管正如我在上面的评论中提到的,你应该重新考虑你的表格设计,只需添加一个 read_datetimedelete_datetime(如果你真的需要的话,可能是一个 status 列)到你的Email 表,而不是拥有一个完整的单独表来保存标识删除状态的记录。

【讨论】:

  • 感谢@gmiley 这个解决方案运行良好。我会更改表的架构,但它是我继承的大型数据库的一部分。
  • 我已经实现了上面的 SQL 脚本,它大部分工作得很好......但是我如何确保 member_email_FK_message_id(电子邮件表)与 message_id(member_email_read 表)的值相同似乎有为不同的 user_id 创建重复记录。我认为作为“tgt.member_email_FK_message_id = src.message_id”,这将确保只有 1 条记录而不是重复的。因此,并非所有电子邮件都被添加,因此并非所有电子邮件都被标记为未读......任何想法@gmiley?谢谢
  • @Needabitofhelp 这作为一个新问题可能会更好,如果您想发布它并给我链接,我将非常乐意提供帮助。在新博文中,提供两个表结构和示例数据,说明您遇到的问题。
  • 我在这个问题上开了一张新票,贴在这里 - stackoverflow.com/questions/47942262/…@gmiley
猜你喜欢
  • 2013-05-06
  • 1970-01-01
  • 2018-03-09
  • 2012-11-06
  • 2019-03-17
  • 2018-02-03
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
相关资源
最近更新 更多