Tik*_*ani -1 sql sql-server-2008
我想要检索最近添加的客户.我没有任何列存储添加行的日期/时间,而我的主键是Cust_ID,它不是IDENTITY列,也不一定按升序输入.
这是我的表,Customer并且想象已按此顺序添加了三行:
Cust_ID Cust_Name Cust_Age
-------------------------------------
2 C 23
6 A 25
3 B 22
Run Code Online (Sandbox Code Playgroud)
在上面的例子中我想得到最后一条记录(B).SQL Server中是否有任何预定义函数将返回表的最后一行(不依赖于升序)?
Aar*_*and 14
不,SQL Server中没有预定义函数可以返回表的"最后一行".
根据定义,表是一组无序的行.想象一下,你把一堆弹珠放在一个袋子里.现在打开包,然后问别人哪个大理石先进去或最后进去.现在把它们扔到地板上,当其他人进入房间时,请问他们先敲打地板还是最后敲打地板.你不能这样做,因为没有额外的信息表明他们倒下的顺序.
SQL Server中的表也是如此.除非您添加IDENTITY列,日期时间列或触发器,或使用外部功能(如更改跟踪,CDC,审核等),否则SQL Server无法告诉您最后插入了哪一行.您可能认为只是从没有order by子句的表中选择看起来就像是以正确的顺序返回数据,这是纯粹的巧合.这是一个例子:
CREATE TABLE dbo.floobat
(
ID INT PRIMARY KEY,
n VARCHAR(16),
x CHAR(4000) NOT NULL DEFAULT ''
);
INSERT dbo.floobat(ID,n) VALUES(1,'Sparky');
INSERT dbo.floobat(ID,n) VALUES(2,'Aaron');
INSERT dbo.floobat(ID,n) VALUES(3,'Norbert'); -- <-- inserted last
SELECT ID, n FROM dbo.floobat;
Run Code Online (Sandbox Code Playgroud)
好吧,所以默认情况下,这似乎没问题.结果:
ID n
-- -------
1 Sparky
2 Aaron
3 Norbert -- < yes, this is right
Run Code Online (Sandbox Code Playgroud)
但是,让我们更改表格,您的应用程序或其他依赖于上述排序的其他内容将不知道:
CREATE NONCLUSTERED INDEX x ON dbo.floobat(n);
SELECT ID, n FROM dbo.floobat;
Run Code Online (Sandbox Code Playgroud)
哦哦!结果:
ID n
-- -------
2 Aaron
3 Norbert
1 Sparky -- < oops, this is no longer right
Run Code Online (Sandbox Code Playgroud)
您必须记住这一点:如果您不包含ORDER BY子句,那么您告诉 SQL Server您不关心订单.因此,它将找到返回数据的最有效方法,这可能会导致不同的观察顺序.添加上面的索引为SQL Server提供了更好的检索数据的访问路径.它仍然使用扫描,但该索引比聚集索引(它只能在页面上适合两行)更瘦.
即使没有索引,您也可能无法获得预期的结果,因为您的Cust_ID列未按升序插入是错误的.所以,如果你插入5比2,没有ORDER BY选择实际上导致2然后5(假设没有更好的指标存在).
除了创建(或删除,更改或重建)索引之外的其他事情可能会导致排序行为发生同样的变化.应用Service Pack,CU或修补程序; 刷新程序缓存; 使用各种RECOMPILE选项; 更新统计; 重启服务器; 添加或禁用跟踪标志; 更改服务器选项选项; 将数据库移动到其他服务器; 等等
因此,如果您想跟踪这些信息,您需要以某种方式自己添加它,因为其他几个答案已经解决了.