【问题标题】:SQL Server : how to delete a row numberSQL Server:如何删除行号
【发布时间】:2018-04-18 11:01:35
【问题描述】:

我有一个 SQL Server 表(如上所示),我正在使用此命令在我的网站上的一个表中对其进行排序

SELECT * 
FROM [user]  
ORDER BY idNum DESC;

这个表(在我的网站上运行)包含我的数据库保存的所有信息(至少对于 [user] 表)

我有按钮可以从信息中删除一行(它获取我要删除的行号),如下图所示:

我想问的是有没有一种方法可以使用行号删除一行?(因为我从按钮单击中得到一个行号我只想删除该行)?

【问题讨论】:

  • 不要使用“行号”或类似的东西来删除行 - 使用 主键 唯一可靠识别每一行
  • @marc_s 我打算给出完全相同的建议。使用 rownumber 实际上会导致删除错误的条目,因为您的表数据可能会在查看它和删除您想要的行之间发生变化。
  • 你为什么不添加一个真正的行号,并将其用作主键。它会让你的生活更轻松......
  • @ppijnenburg 但是主键也可能会消失。我投票赞成通过主键删除,但这可以在某些假设下进行。
  • 如果您尝试删除已经消失的 PK,您会收到错误消息。如果您删除特定的行号,那么行号很可能仍然存在,因为行数超过了您要删除的当前行。

标签: sql asp.net sql-server database


【解决方案1】:

您可以在这里使用 CTE:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY idNum DESC) rn
    FROM [user]
)

然后使用来自 UI 的行号删除:

DELETE
FROM cte
WHERE rn = <some value from UI>;

但许多(大多数?)UI 框架,例如Angular 能够将用户的整个元数据发送到 UI。因此,您通常只需使用直接来自 UI 中的按钮的 idNum 值即可删除。正如@marc_s 刚刚评论的那样,使用主键删除是一种安全的删除方式。

【讨论】:

  • 技术上可行,但将您的内部 ID 暴露给浏览器并不是一个好主意。
  • @TheImpaler 我认为公开主键值没有任何问题。应用安全负责确保请求仅来自有效来源。
  • 即使它来自正确的 IP,您可能不是在处理浏览器,而是在处理不同的用户代理。您最终可能会从另一个用户那里删除一行。
  • @TheImpaler 我不知道你开发什么样的应用程序,但是这个问题很久以前就解决了。通常,用户必须在每个请求中提供一个身份验证令牌。只允许从他拥有的行中删除,因此即使恶意用户进行黑客攻击,他仍然永远无法删除其他人的数据。
【解决方案2】:

你可以使用ROW_NUMBER()

DELETE FROM USER
WHERE idnum IN (SELECT idnum from (SELECT idnum,ROW_NUMBER() OVER(ORDER BY 
idnum desc) AS rw FROM USER) res WHERE res.rw = @rw)

@rw 是你的行号

【讨论】:

    【解决方案3】:

    您使用row_number() 的方法完全是错误的。它不是线程安全的——可以将另一个用户添加到数据库中,从而丢弃您向用户显示的所有“行号”。天哪,用户加载页面并保持应用程序打开一周,而在用户开始删除某些内容之前,可能已经添加或删除了一堆新用户。

    从根本上说,您的表格格式不正确。它没有主键,甚至没有任何唯一约束。

    我强烈建议:

    create table Users (
        userId int identity(1, 1) primary key,
        . . .
    );
    

    这是您应该用于删除的主键。您不需要向用户显示主键,只要您可以将其与每一行关联即可。

    由于其他原因,主键很重要。通常,使用数据库是因为要存储多个表。主键是您如何将不同的表相互连接(使用外键关系)。

    【讨论】:

      猜你喜欢
      • 2023-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 2010-12-21
      • 1970-01-01
      相关资源
      最近更新 更多