【发布时间】:2012-02-09 19:05:20
【问题描述】:
有没有办法让 SQL Server Management Studio 默认返回行降序? 每次我通过菜单打开一个表(例如通过选择返回所有行),我都会在顶部获得最旧的行。 我知道我可以在 sql 语句中添加 'order by desc',但是打字很烦人 :)
【问题讨论】:
标签: sql-server sql-order-by ssms
有没有办法让 SQL Server Management Studio 默认返回行降序? 每次我通过菜单打开一个表(例如通过选择返回所有行),我都会在顶部获得最旧的行。 我知道我可以在 sql 语句中添加 'order by desc',但是打字很烦人 :)
【问题讨论】:
标签: sql-server sql-order-by ssms
SQL 中没有默认的排序顺序
如果您在顶部看到“最旧”,那么这可能是引擎检索它的最快方式,因为它是存储在磁盘上的方式。
你不能保证按这个顺序得到它,除非你指定一个顺序,否则认为它是“无序的”!
ORDER BY 是按特定顺序获得结果的唯一方法。
根据指定的表和顺序,排序可能是一项昂贵的操作,因此无序是常态。
【讨论】:
TOP X 只是为了限制结果集。您当然可以添加ORDER BY。在正常情况下,如果没有连接,返回的结果很可能是聚集索引键顺序。
JNK 所说的 100% 正确。
但是,如果您只是希望它正常工作,并且仅在您打开表格而不是当你查询一个表时...
尝试添加聚集索引,第一个索引字段按降序索引。这可能实际上会导致您需要的结果。
(如果您在该字段上已有聚集索引,请编辑其属性并更改其顺序。)
如果这样的索引对表的实际使用友好,这只是一个明智的想法。仅仅为了您的方便,拥有一个以编程方式无用的索引将是自我挫败;)
【讨论】:
引自 Itzik Ben-Gan 的 Microsoft SQL Server 2012 T-SQL Fundamentals -> 第 1 章 -> 理论背景 -> 集合论:
...当您针对数据库中的表(例如员工表)编写 T-SQL 查询时,您应该将员工集视为一个整体,而不是单个员工。 ... 换句话说,对表的查询可以按任何顺序返回表行,除非您明确要求以特定方式对数据进行排序,可能是出于演示目的。
SSMS 不支持自定义的默认 SELECT 语句。如果确实支持,应该在 ORDER BY 子句之后放置哪一列,考虑表
即使 SQL SERVER 有一天也能列出最新的数据,这不是根据表考虑单个行(最新/最旧)的自然方式。尝试使用 UPDATE 语句结合 ORDER BY 子句来更新最新数据。
【讨论】:
您不能更改现有模板以从 SSMS 的上下文菜单中生成 SELECT。
谢天谢地,SSMS 是可扩展的。这意味着您可以编写自己的扩展来完全满足您的需求,或者您可以使用一些现有的解决方案。我会推荐 Mladen 的 SSMS 工具包:
直到最近它还是免费的,并且仍然适用于 2008r2 及更早的版本。
【讨论】:
查看 Profiler 的输出,查询似乎是动态生成的,所以我不会把希望寄托在可以在某处更改的模板上
/****** Script for SelectTopNRows command from SSMS ******/
SELECT TOP 1000 [field1]
,[field2]
,[field3]
,[last_modified]
FROM [test_database].[dbo].[t_test]
作为替代方案,您可以创建一个小型存储过程,该过程采用表名,然后从所述表中返回数据。假设您的表中有(重复出现的)逻辑可以指示记录的“年龄”,那么找出所述表的默认顺序应该不会太难。如果然后将此存储过程链接到热键,您可以轻松地按照您想要的顺序从所述表中获取前 n 条记录。我知道这与在对象资源管理器中获取信息并不完全相同,但我个人从不使用对象资源管理器,而是喜欢通过简单地在查询窗口中选择文本并按 CTRL-3 来获取表格的内容。
为了让你开始,它看起来像这样
IF OBJECT_ID('p_select_top_100_desc') IS NOT NULL DROP PROCEDURE p_select_top_100_desc
GO
CREATE PROCEDURE p_select_top_100_desc ( @table_name sysname)
AS
DECLARE @object_id int
DECLARE @order_by_col nvarchar(max)
DECLARE @sql nvarchar(max)
SELECT @object_id = Object_id(@table_name),
@order_by_col = ''
IF @object_id IS NULL
BEGIN
RaisError('Could not find table %s ?!', 16, 1, @table_name)
Return(-1)
END
-- find order by column
SELECT TOP 1 @order_by_col = c.name
FROM sys.columns c
WHERE c.object_id = @object_id
AND lower(c.name) in ('modified', 'last_modified', 'change_date', 'crdate', 'etc')
-- if none found, use the identity column
SELECT @order_by_col = c.name + ' DESC'
FROM sys.columns c
WHERE c.object_id = @object_id
AND c.is_identity = 1
AND @order_by_col = ''
-- if still none found, use the PK (reverse order)
SELECT @order_by_col = @order_by_col
+ (CASE WHEN ic.index_column_id = 1 THEN '' ELSE ',' END)
+ c.name
+ (CASE WHEN ic.is_descending_key = 0 THEN ' DESC' ELSE ' ASC' END)
FROM sys.indexes i
JOIN sys.index_columns ic
ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
JOIN sys.columns c
ON c.object_id = ic.object_id
AND c.column_id = ic.column_id
WHERE i.object_id = @object_id
AND i.is_primary_key = 1
AND @order_by_col = ''
ORDER BY ic.index_column_id
-- actual query
SELECT @sql = 'SELECT TOP 100 * FROM '
+ @table_name
+ (CASE WHEN @order_by_col = '' THEN '' ELSE ' ORDER BY ' + @order_by_col END)
PRINT @sql
EXEC (@sql)
Return 0
GO
EXEC p_select_top_100_desc 't_test'
要将其“链接”到热键,您需要转到Tools \ Customize 菜单,单击[Keyboard...] 按钮。展开树中的 Keyboard 分支并转到 Query Shortcuts 叶。然后,您会得到一个烦人的网格,它允许您将存储过程链接到 CTRL-nbr 组合。请注意,其中一些是固定的 + 在您配置它并按 OK 后,该设置仅适用于您新打开的查询窗口,现有的将适用于“旧”配置。
希望对你有所帮助……
PS:如果你将它命名为sp_select_top_n_desc 并在主数据库中编译它,你应该能够在整个服务器上使用它,而无需在每个数据库中部署它。但是,您可能需要切换到dynamic-sql,然后在所有sys.table 查询前加上DB_Name() 的输出,否则它可能会在master.sys.columns 表等中查找。这不是你的想要=)
【讨论】:
尝试像这样在该表上创建一个视图,并在您的选择子句或即席查询中使用它
CREATE VIEW dbo.yourTable_vw
AS
SELECT TOP 100 PERCENT *
FROM yourTable
ORDER BY yourcolumn DESC
GO
【讨论】:
实际上,您可以为 ssms 创建一个插件,将新项目添加到对象浏览器的上下文菜单中。
检查这个问题:Create custom menu item in Object Explorer
另一种方法是创建一个 SP,它在主数据库中(在所有服务器上)使用 ORDER BY 子句生成并执行 select 语句,并将键盘快捷键绑定到该 sp。
【讨论】:
虽然官方没有简单线性输入的默认排序顺序,但我使用 PK 或 IX 排序顺序获得了令人满意的 DESC 默认排序顺序。假设我对最后一个条目最感兴趣的日志表。
CREATE TABLE [dbo].[tableA]([DateTime] [datetime] NOT NULL,
CONSTRAINT [PK_tableA]
PRIMARY KEY CLUSTERED ([DateTime] DESC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
或者在 SSMS 中 ...
【讨论】:
对我来说 - 我首先使用 EF 代码,但每当我创建一个新表时都会这样做: 右键单击表,将表编写为 -> 删除和创建表,然后编辑 SQL 并将键更改为 DESC,然后运行脚本.. 完成(没有视图或任何混乱)
【讨论】:
create table MYTESTTABLE (
ID numeric(18, 0) identity(1, 1) not null
,COL1 numeric(18, 0) null
,COL2 numeric(18, 0) null
,COL3 numeric(18, 0) null
,COL4 numeric(18, 0) null
CONSTRAINT [PK_MYTESTTABLE] PRIMARY KEY CLUSTERED
(
[ID] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
【讨论】: