我有一个基本的SQL Server删除脚本:
Delete from tableX
where colA = ? and colB = ?;
在tableX
中,我没有任何指示顺序ID或时间戳的列;只是varchar
。我想删除插入的最新条目,并且我无法访问插入脚本中的行号。 TOP
不是一个选项,因为它是随机的。此外,这个特定的表没有主键,并且它不是设计不佳的问题。有什么方法可以做到这一点吗?我记得mysql能够调用像max(row_number)
这样的东西,还有一些类似于限制的东西。
答案 0 :(得分:2)
ROW_NUMBER
也存在于SQL Server中,但必须与OVER (order_by_clause)
一起使用。所以......在你的情况下,除非你想出另一种排序算法,否则你不可能。
编辑:(来自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