【问题标题】:Sequence database field and query for updating sort order用于更新排序顺序的序列数据库字段和查询
【发布时间】:2009-07-03 00:11:34
【问题描述】:

我想让我的应用程序的用户定义多个(比如说)电子邮件地址。然后我想给他们重新排列这些地址的能力,所以主地址在最上面,次要在下等等。

假设我在数据库中有一个 UserEmailAddresses 表,该表链接用户 (UserId) 和电子邮件地址 (EmailAddressId)。

1) 我应该为保存这些电子邮件地址排序顺序的字段使用什么数据类型(int、float 等)?

2) 当用户重新排列他们的位置时,什么样的查询可以有效地改变这些序列号?一定要修改多条记录吗?

(我使用 C# 和 Linq,但欢迎使用伪代码)。

【问题讨论】:

    标签: c# linq-to-sql database-design types


    【解决方案1】:

    您需要添加一个整数字段来存储电子邮件地址的排序顺序。

    随着新电子邮件地址的添加,它们会被分配下一个排序顺序 ID。如果一个地址需要在现有地址之上进行排序,我将使用更新语句来更新排序顺序 ID 大于所需排序顺序索引的所有电子邮件地址,然后更新重新排序的电子邮件地址以具有所需的排序顺序索引。

    Table Schema
    -----------------------
    EmailID INT primary Key //Auto increment
    EmailAddress Varchar(N)
    SortOrderIdx INT //This would control your display order
    UserID INT //This would be the owner of this particular email list
    
    Email Create Statement
    -----------------------
    SELECT @NewSortOrdrIdx = MAX(SortOrderIdx)+1
    FROM EmailTable 
    WHERE UserId = @UserID
    
    INSERT INTO EmailTable (EmailAddress, SortOrderIdx, UserID)
    VALUES (@EmailAddress, @NewSortOrdrIdx, @UserID)
    
    Email Reorder Statement
    -----------------------
    UPDATE EmailTable
    SET SortOrderIdx = SortOrderIdx + 1
    WHERE SortOrderIdx >= @desired_Sort_Order_Idx AND UserID = @UserID
    
    UPDATE EmailTable
    SET SortOrderIdx = @desired_Sort_Order_Idx
    WHERE EmailID = @resorted_Email_ID AND UserID = @UserID
    
    Email Select Statement
    -----------------------
    SELECT EmailAddress 
    FROM EmailTable
    WHERE UserID = @UserID
    ORDER BY SortOrderIdx ASC
    

    【讨论】:

    • 我想我也需要在添加新地址之前查询最大的序列号。看来我是在用这种方式标记数据库......这只是这个功能的价格吗?
    【解决方案2】:

    这是一个简单的设计,简化了“碰撞”的处理。您只需要更新一行即可使用此方法:

    UserEmailAddresses Table
    ------------------------
    YourPKHere        <whatever you have, identity?>
    UserId            <whatever you have>
    EmailAddressId    <whatever you have>
    DisplaySeq        INT
    LastChgDate       datetime
    
    
    SELECT * FROM UserEmailAddresses ORDER BY DisplaySeq ASC, LastChgDate DESC
    

    编辑示例代码

    DECLARE @UserEmailAddresses table
    (
         YourPKHere        int identity(1,1) primary key
        ,UserId            int
        ,EmailAddressId    varchar(100)
        ,DisplaySeq        INT
        ,LastChgDate       datetime
    )
    
    --existing data
    INSERT INTO @UserEmailAddresses values (1,'one@one.com',1,'1/1/2009')
    INSERT INTO @UserEmailAddresses values (1,'two@two.com',2,'2/2/2009')
    INSERT INTO @UserEmailAddresses values (1,'three@three.com',3,'3/3/2009')
    INSERT INTO @UserEmailAddresses values (2,'one2@one2.com',1,'1/1/2009')
    INSERT INTO @UserEmailAddresses values (2,'two2@two2.com',2,'2/2/2009')
    
    --application updates one row, no locking or blocking
    update @UserEmailAddresses set DisplaySeq=1,LastChgDate=getdate() where UserId=1 and EmailAddressId='two@two.com' --could say WHERE YourPKHere=n, but you don't give your complete table schema
    
    
    --display the emails in proper order, with displayable continuous row numbers
    SELECT 
        *, ROW_NUMBER() over(partition by UserId order by DisplaySeq ASC,LastChgDate DESC) AS ActualDuisplaySeq
        FROM @UserEmailAddresses
        WHERE UserId=1
    
    --display the e-mails in proper order
    SELECT * FROM @UserEmailAddresses Where UserId=1 ORDER BY DisplaySeq ASC, LastChgDate DESC
    

    【讨论】:

    • 这相当聪明...但是,假设我更改了两个地址,因此它们是“顶部”地址,每个地址的 DisplaySeq 为 1,但区分它们的时间不同。现在,假设我想将第三个地址放在 #2 位置(在前两个位置之间)......我看不出有任何方法可以用你的提案来做到这一点。
    • 这取决于您的用户界面。如果您显示一个表格,其中每个电话号码都在其自己的行中,并让他们在文本框中输入排序值,并且他们希望同时具有多个重复值,它将按照您的描述进行排序。但是,如果他们以唯一的方式输入它们,则没有问题。如果您希望程序修复序列顺序,则需要始终运行额外的更新。
    猜你喜欢
    • 2015-02-25
    • 1970-01-01
    • 2019-02-22
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多