在不使用datetime或ID的情况下删除SQL Server中的最新条目

时间:2015-07-08 14:40:55

标签: sql-server delete-row

我有一个基本的SQL Server删除脚本:

Delete from tableX 
where colA = ? and colB = ?;

tableX中,我没有任何指示顺序ID或时间戳的列;只是varchar。我想删除插入的最新条目,并且我无法访问插入脚本中的行号。 TOP不是一个选项,因为它是随机的。此外,这个特定的表没有主键,并且它不是设计不佳的问题。有什么方法可以做到这一点吗?我记得mysql能够调用像max(row_number)这样的东西,还有一些类似于限制的东西。

3 个答案:

答案 0 :(得分:2)

ROW_NUMBER也存在于SQL Server中,但必须与OVER (order_by_clause)一起使用。所以......在你的情况下,除非你想出另一种排序算法,否则你不可能。

MSDN

编辑:(来自MSDN的George示例......我担心他的公司有阻止MSDN的防火墙规则)

SQL码

USE AdventureWorks2012; 
GO
SELECT ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS Row, 
    FirstName, LastName, ROUND(SalesYTD,2,1) AS "Sales YTD" 
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0;

输出

Row FirstName    LastName               SalesYTD
--- -----------  ---------------------- -----------------
1   Linda        Mitchell               4251368.54
2   Jae          Pak                    4116871.22
3   Michael      Blythe                 3763178.17
4   Jillian      Carson                 3189418.36
5   Ranjit       Varkey Chudukatil      3121616.32
6   José         Saraiva                2604540.71
7   Shu          Ito                    2458535.61
8   Tsvi         Reiter                 2315185.61
9   Rachel       Valdez                 1827066.71
10  Tete         Mensa-Annan            1576562.19
11  David        Campbell               1573012.93
12  Garrett      Vargas                 1453719.46
13  Lynn         Tsoflias               1421810.92
14  Pamela       Ansman-Wolfe           1352577.13

返回行的子集

USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
    FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;

将ROW_NUMBER()与PARTITION一起使用

USE AdventureWorks2012;
GO
SELECT FirstName, LastName, TerritoryName, ROUND(SalesYTD,2,1),
ROW_NUMBER() OVER(PARTITION BY TerritoryName ORDER BY SalesYTD DESC) AS Row
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0
ORDER BY TerritoryName;

输出

FirstName  LastName             TerritoryName        SalesYTD      Row
---------  -------------------- ------------------   ------------  ---
Lynn       Tsoflias             Australia            1421810.92    1
José       Saraiva              Canada               2604540.71    1
Garrett    Vargas               Canada               1453719.46    2
Jillian    Carson               Central              3189418.36    1
Ranjit     Varkey Chudukatil    France               3121616.32    1
Rachel     Valdez               Germany              1827066.71    1
Michael    Blythe               Northeast            3763178.17    1
Tete       Mensa-Annan          Northwest            1576562.19    1
David      Campbell             Northwest            1573012.93    2
Pamela     Ansman-Wolfe         Northwest            1352577.13    3
Tsvi       Reiter               Southeast            2315185.61    1
Linda      Mitchell             Southwest            4251368.54    1
Shu        Ito                  Southwest            2458535.61    2
Jae        Pak                  United Kingdom       4116871.22    1

答案 1 :(得分:2)

您当前的表格设计不允许您确定最新的条目。你没有要排序的字段来指示最后添加了哪条记录。

您需要从审计表中重新设计或提取该信息。如果您有一个没有审计表的数据库,您可能必须找到一个工具来读取事务日志,这将是一个非常耗时且昂贵的过程。或者,如果您知道要删除的记录的添加日期,则可以在此之前使用备份来查找添加的记录。只是因为您可能正在查看此日期之后您想要保留的记录。

如果您需要定期执行此操作而不是一次性修复一些错误数据,那么您需要正确设计数据库以包含标识字段和可能的dateupdated字段(通过触发器维护)或审计表。 (在我看来,没有包含公司所依赖信息的数据库应该没有审计表,这是为什么你永远不应该允许ORM来设计数据库的众多原因之一,但我离题了。)如果你需要知道订单记录是添加到表中,作为开发人员,您负责创建该结构。数据库只存储tehm存储的内容,如果你没有设计,那么它就不容易获得或者根本不可用

答案 2 :(得分:0)

如果(colA +'_'+ colB)无法公开,请尝试此操作。

 declare @delColumn nvarchar(250)

    set @delColumn = (select top 1   DeleteColumn from (
    select (colA +'_'+ colB)  as DeleteColumn ,
          ROW_NUMBER() OVER(ORDER BY colA DESC) as Id from tableX  
    )b
    order by Id desc
    )

delete  from tableX where  (colA +'_'+ colB) =@delColumn