SQL Server的隐藏功能


215

SQL Server的一些隐藏功能是什么?

例如,未记录的系统存储过程,做一些有用的技巧却没有足够记录的技巧?


答案

感谢大家提供的所有出色答案!

存储过程

  • sp_msforeachtable:使用“?”运行命令 替换为每个表名(v6.5及更高版本)
  • sp_msforeachdb:使用“?”运行命令 替换为每个数据库名称(v7及更高版本)
  • sp_who2:与sp_who一样,但包含更多有关故障排除块的信息(v7及更高版本)
  • sp_helptext:如果需要存储过程的代码,请查看&UDF
  • sp_tables:返回范围内数据库的所有表和视图的列表。
  • sp_stored_procedures:返回所有存储过程的列表
  • xp_sscanf:将数据从字符串读取到每个格式参数指定的参数位置。
  • xp_fixeddrives::查找具有最大可用空间的固定驱动器
  • sp_help:如果要了解表的结构,表的索引和约束。以及视图和UDF。快捷键是Alt + F1

片段

  • 以随机顺序返回行
  • 上次修改日期的所有数据库用户对象
  • 仅返回日期
  • 查找哪个日期属于当前星期内的记录。
  • 查找上周发生日期的记录。
  • 返回当前星期开始的日期。
  • 返回上周开始的日期。
  • 查看已部署到服务器的过程的文本
  • 删除所有与数据库的连接
  • 表校验和
  • 行校验和
  • 将所有过程拖放到数据库中
  • 还原后正确重新映射登录ID
  • 从INSERT语句调用存储过程
  • 按关键字查找程序
  • 将所有过程拖放到数据库中
  • 以编程方式查询事务日志中的数据库。

功能

  • HashBytes()
  • 加密密钥
  • PIVOT命令

杂项

  • 连接字符串附加
  • TableDiff.exe
  • 登录事件的触发器(Service Pack 2中的新增功能)
  • 通过持久计算列(pcc)提高性能。
  • sys.database_principles中的DEFAULT_SCHEMA设置
  • 强制参数化
  • 十进制存储格式
  • 在几秒钟内找出最受欢迎的查询
  • 可扩展的共享数据库
  • SQL Management Studio中的表/存储过程筛选器功能
  • 跟踪标志
  • GO重复批处理后的编号
  • 使用架构的安全性
  • 使用内置的加密功能,视图和带有触发器的基表进行加密

4
如果知道,最好在每个答案中包含适用的版本。(2000年及以后,仅2005年,2000年等)
bw

这个问题有很多好处。请不要删除它!:-)
Sklivvz 2012年

Answers:


91

在Management Studio中,您可以在GO批处理结束标记后放置一个数字,以使该批处理重复该次数:

PRINT 'X'
GO 10

将打印“ X”十次。在进行重复性操作时,这可以避免繁琐的复制/粘贴操作。


70

许多SQL Server开发人员似乎仍然不了解DELETE,INSERT和UPDATE语句上的OUTPUT子句(SQL Server 2005及更高版本)。

知道哪些行已被INSERT,UPDATE或DELETEd使用非常有用,并且OUTPUT子句可以很容易地做到这一点-它允许访问称为inserted和的“虚拟”表deleted(如触发器):

DELETE FROM (table)
OUTPUT deleted.ID, deleted.Description
WHERE (condition)

如果要将值插入具有INT IDENTITY主键字段的表中,并带有OUTPUT子句,则可以立即获取插入的新ID:

INSERT INTO MyTable(Field1, Field2)
OUTPUT inserted.ID
VALUES (Value1, Value2)

而且,如果您要进行更新,则知道发生了什么更改将非常有用-在这种情况下,inserted表示新值(在UPDATE之后),而deleted在UPDATE之前引用旧值:

UPDATE (table)
SET field1 = value1, field2 = value2
OUTPUT inserted.ID, deleted.field1, inserted.field1
WHERE (condition)

如果将返回很多信息,则OUTPUT的输出也可以重定向到临时表或表变量(OUTPUT INTO @myInfoTable)。

非常有用-鲜为人知!

马克


52

sp_msforeachtable:使用'?'运行命令 用每个表名替换。例如

exec sp_msforeachtable "dbcc dbreindex('?')"

每个表最多可以发出3条命令

exec sp_msforeachtable
    @Command1 = 'print ''reindexing table ?''',
    @Command2 = 'dbcc dbreindex(''?'')',
    @Command3 = 'select count (*) [?] from ?'

也, sp_MSforeachdb


2
您可以通过在问号周围使用单引号来获取查询中的表名。sp_msforeachtable“选择计数(*),'?' 作为禁忌?”
乔迪

51

连接字符串附加功能:

MultipleActiveResultSets = true;

这使ADO.Net 2.0及更高版本可以在单个数据库连接上读取多个,仅转发和只读的结果集,如果您需要进行大量读取,则可以提高性能。即使您混合使用查询类型,也可以将其打开。

应用程序名称= MyProgramName

现在,当您想通过查询sysprocesses表查看活动连接的列表时,程序的名称将显示在program_name列中,而不是“ .Net SqlClient数据提供程序”


7
我对公司提出了“应用名称”的要求。每个新应用都必须具有唯一的名称。使追踪哪个应用程序锁定/中断变得容易得多。
尼尔N

2
应用程序名称也可以用作探查器中的过滤器。如果您只想查看自己的查询而不是同事的查询,则对您有很大帮助。
Mathias F

33

TableDiff.exe

  • 表差异工具允许您发现和协调源表和目标表或视图之间的差异。Tablediff Utility可以报告架构和数据的差异。tablediff最受欢迎的功能是它可以生成一个可以在目标上运行的脚本,该脚本可以协调表之间的差异。

链接


31

一种鲜为人知的TSQL技术,用于以随机顺序返回行:

-- Return rows in a random order
SELECT 
    SomeColumn 
FROM 
    SomeTable
ORDER BY 
    CHECKSUM(NEWID())

6
非常适合小结果集。除非您有足够的时间,否则我不会在具有超过10000行的表上使用它
John Sheehan

我已经在比它大得多的桌子上使用它,并且它并不太慢。
米奇·

CHECKSUM()的目的是什么?您可以仅通过NEWID()进行订购。
乔纳斯·林肯

6
我什至在不使用CHECKSUM()的情况下,即使在1亿(1亿)行上也看到了不错的结果。另外,我也要问,为什么不只是ORDER BY NEWID?
Troy DeMonbreun

5
@GateKiller:我已经回滚了您的编辑,因为Checksum()没错;它减小了排序列的大小。
米奇·麦特

30

在Management Studio中,您可以通过以下方式快速获取表的列的逗号分隔列表:

  1. 在对象资源管理器中,展开给定表下的节点(这样您将看到列,键,约束,触发器等的文件夹)
  2. 指向“列”文件夹,然后拖入查询。

当您不想使用通过右键单击表并选择“脚本表为...”,然后选择“插入到...”而返回的令人讨厌的格式时,此方法非常方便,因为它可以与其他文件夹一起使用文件夹中包含的逗号分隔名称列表。


23

行构造器

您可以使用单个插入语句插入多行数据。

INSERT INTO Colors (id, Color)
VALUES (1, 'Red'),
       (2, 'Blue'),
       (3, 'Green'),
       (4, 'Yellow')

我投了赞成票,但随后在MSSQL 2005中尝试了它,但它不起作用。仅2008年?
richardtallent

11
是的,这是2008
。– Rob Boek 09年

2
当我从DB2转到SQL Server时,我错过了这一功能。在DB2中,使用此语句而不是单独的插入语句时,速度有了显着提高
Nathan Koop,2010年



20

找出最受欢迎的查询

  • 使用sys.dm_exec_query_stats,您可以通过单个查询找出查询分析的许多组合。

与命令链接

select * from sys.dm_exec_query_stats 
order by execution_count desc


16

例外与相交

这两个关键字不是编写复杂的联接和子查询,而是比较两个查询结果时表达查询意图的一种更简洁,更易读的方式。作为SQL Server 2005的新功能,它们对UNION进行了强有力的补充,而UNION在TSQL语言中已经存在多年了。

EXCEPT,INTERSECT和UNION的概念是集合论的基础,是所有现代RDBMS使用的关系建模的基础和基础。现在,使用TSQL可以更直观,更轻松地生成维恩图类型结果。


16

我知道它不是完全隐藏的,但是没有太多人知道PIVOT命令。我能够更改使用游标的存储过程,并花了2分钟时间来运行快速的6秒代码,这是行数的十分之一!


16

在出于测试目的或其他目的还原数据库时很有用。重新正确映射登录ID:

EXEC sp_change_users_login 'Auto_Fix', 'Mary', NULL, 'B3r12-36'

我以前没有使用过此过程,因此必须将对象所有权更改为临时用户,删除原始用户,重新添加原始用户,然后再分配所有权。嗯...
StingyJack

15

删除所有与数据库的连接:

Use Master
Go

Declare @dbname sysname

Set @dbname = 'name of database you want to drop connections from'

Declare @spid int
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id(@dbname)
While @spid Is Not Null
Begin
        Execute ('Kill ' + @spid)
        Select @spid = min(spid) from master.dbo.sysprocesses
        where dbid = db_id(@dbname) and spid > @spid
End

是否有一个单行代码或一个drop数据库参数可以为我执行此操作?我注意到,如果您尝试通过ui“删除数据库”,则有一个“关闭现有连接”复选框,这意味着它是一个布尔参数。
DevinB

1
实际上,我只是找到了两行解决方案。ALTER DATABASE [@ DATABASE_NAME @] SET READ_ONLY并具有立即回滚-这将断开所有用户的连接ALTER DATABASE [@ DATABASE_NAME @] SET READ_WRITE并具有ROLLBACK
IMAGETE

1
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE也会阻止任何新的连接发生。
ErikE

15

表校验和

Select CheckSum_Agg(Binary_CheckSum(*)) From Table With (NOLOCK)

行校验和

Select CheckSum_Agg(Binary_CheckSum(*)) From Table With (NOLOCK) Where Column = Value

2
这些使您可以为表中的所有数据生成校验和。这是检查两行或两个表是否相同的简单快捷方法。
GateKiller

15

我不确定这是否是隐藏功能,但我偶然发现了这一点,并发现它在许多情况下都很有用。您可以在单个select语句中合并一组字段,而不是使用游标并遍历select语句。

例:

DECLARE @nvcConcatonated nvarchar(max)
SET @nvcConcatonated = ''

SELECT @nvcConcatonated = @nvcConcatonated + C.CompanyName + ', '
FROM tblCompany C
WHERE C.CompanyID IN (1,2,3)

SELECT @nvcConcatonated

结果:

Acme, Microsoft, Apple,

2
您还可以使用COALESCE()进行相同的操作,而无需初始化变量。SELECT @nvcConcatonated = COALESCE(@nvcConcatonated +',','')+ CAST(C.CompanyName as VARCHAR(255))FROM ...
Christopher Klein

这也适用于更新语句。有时对执行诸如串联已更新的ID列表之类的操作很有用。
EBarr 2011年

14

如果您想要存储过程的代码,则可以:

sp_helptext 'ProcedureName'

(不确定它是否为隐藏功能,但我一直都在使用它)


不知道为什么,但是sp_helptext输出在原始文件中任何过长的行上都有些愚蠢。在编写Sproc脚本时,不会发生这种情况,所以也许存在另一种更健壮的导出机制?sp_helptext'MyView'也很有用。
克里斯汀2009年

我不确定你是什么意思。对我来说,SP的代码以与原始文件中脚本化的格式相同的格式输出(包括所有CR,等等)
Eduardo Molteni

我不记得确切的细节,但它与文本的存储方式有关,我认为这与页面大小有关。输出基本上是正确的,但是每隔一段时间,您就会得到一个额外的换行符。
RolandTumble

13

存储过程的诀窍是可以从INSERT语句调用它们。当我在处理SQL Server数据库时,我发现这非常有用。

CREATE TABLE #toto (v1 int, v2 int, v3 char(4), status char(6))
INSERT #toto (v1, v2, v3, status) EXEC dbo.sp_fulubulu(sp_param1)
SELECT * FROM #toto
DROP TABLE #toto

1
可悲的是不能与@TableVariable一起使用
Kristen

这项非常有用的技术的痛苦在于,与大多数#tables不同,您必须完全定义所有列。懒惰的方法是在要调用的proc内部创建#table,然后在tempdb中使用sp_help,复制并粘贴,从proc中删除代码。完成
阿道夫·大蒜

12

在SQL Server 2005/2008中,以在SELECT查询结果中显示行号:

SELECT ( ROW_NUMBER() OVER (ORDER BY OrderId) ) AS RowNumber,
        GrandTotal, CustomerId, PurchaseDate
FROM Orders

ORDER BY是强制性条款。OVER()子句告诉SQL Engine对指定列(在本例中为OrderId)中的数据进行排序,并根据排序结果分配数字。


不会,如果他们使用的语法SUGER在SQL引擎解析它的语法词为“RowNumberInTable”简单
没有

1
+1用于窗口功能。您可以使用OVER(PARTITION BY ...)来对记录的子集进行处理。msdn.microsoft.com/zh
Matt Stephenson

10

对于解析存储过程参数很有用:xp_sscanf

从字符串中读取数据到每个format参数指定的参数位置。

以下示例使用xp_sscanf基于源字符串格式中的位置从源字符串中提取两个值。

DECLARE @filename varchar (20), @message varchar (20)
EXEC xp_sscanf 'sync -b -fproducts10.tmp -rrandom', 'sync -b -f%s -r%s', 
  @filename OUTPUT, @message OUTPUT
SELECT @filename, @message

这是结果集。

-------------------- -------------------- 
products10.tmp        random

4
我一定有一个愚蠢的时刻(不,真的)。你能告诉我我们可以在哪里使用吗?
拉吉(Raj More)2009年

9

仅返回日期

Select Cast(Floor(Cast(Getdate() As Float))As Datetime)

要么

Select DateAdd(Day, 0, DateDiff(Day, 0, Getdate()))

简短版-SELECT CAST(FLOOR(CAST(@DateTime AS FLOAT))AS DATETIME)
Meff,

当然好。CASTFLOORCAST规则。
StingyJack

找不到对它的引用,但我似乎记得测试建议SELECT DateAdd(Day,0,DateDiff(Day,0,@DateTime))更快的测试。无论哪种方式,都很高兴能得到启发!
克里斯汀2009年

找到了此sqlteam.com/forums/topic.asp?TOPIC_ID=35296#107617,但其中不包含CAST / FLOOR方法。对中型记录集的非正式测试表明,DATEADD可能比CAST / FLOOR快大约7%-对于大多数情况而言,这还不足以使他们担心
Kristen 2009年

但是,我添加了另一种方法。我的快速测试表明,浇铸地板方法要快800纳秒。所以里面什么也没有。
GateKiller

9

dm_db_index_usage_stats

这样,即使表中没有DateUpdated列,您也可以知道表中的数据是否最近已更新。

SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update,*
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID( 'MyDatabase')
AND OBJECT_ID=OBJECT_ID('MyTable')

来自以下代码的代码:http//blog.sqlauthority.com/2009/05/09/sql-server-find-last-date-time-updated-for-any-table/

引用自以下信息的信息: SQL Server-表的最后插入行的日期/时间是什么?

在SQL 2005及更高版本中可用


7

以下是一些我认为有用的功能,但很多人似乎并不了解:

sp_tables

返回可以在当前环境中查询的对象列表。这意味着除同义词对象外,任何可以出现在FROM子句中的对象。

链接

sp_stored_procedures

返回当前环境中的存储过程列表。

链接


7

查找哪个日期属于当前星期内的记录。

where dateadd( week, datediff( week, 0, TransDate ), 0 ) =
dateadd( week, datediff( week, 0, getdate() ), 0 )

查找上周发生日期的记录。

where dateadd( week, datediff( week, 0, TransDate ), 0 ) =
dateadd( week, datediff( week, 0, getdate() ) - 1, 0 )

返回当前星期开始的日期。

select dateadd( week, datediff( week, 0, getdate() ), 0 )

返回上周开始的日期。

select dateadd( week, datediff( week, 0, getdate() ) - 1, 0 )

很好,但不会使用TransDate上的索引。我宁愿写
vaso 2010年

其中TransDate> = convert(datetime,floor(convert(float,dateadd(day,-datepart(weekday,@date)+1,@date)))))和TransDate> = convert(datetime,floor(convert(float,dateadd (day,7-datepart(weekday,@date)+1,@date))))
vaso 2010年

更正:TransDate> = convert(datetime,floor(convert(float,dateadd(day,-datepart(weekday,@date)+1,@date)))))和TransDate <convert(datetime,floor(convert(float, dateadd(day,7-datepart(weekday,@date)+1,@date))))
vaso 2010年

7

与其说是隐藏功能,不如说是在Management Studio中的Tools \ Options \ Keyboard下设置键映射:Alt + F1默认为sp_help“选定的文本”,但是我不能不为sp_helptext“ selected text”添加Ctrl + F1


我还配置了USE命令,以便沿着数据库移动
Jhonny D. Cano -Leftware- 09年

7

持久计算列

  • 计算列可以帮助您将运行时计算成本转移到数据修改阶段。计算列与行的其余部分一起存储,并且当计算列上的表达式与查询匹配时将透明地使用计算列。您还可以在PCC上建立索引,以加快对表达式的筛选和范围扫描。

链接


7

有时候,没有合适的列可以作为排序依据,或者您只希望表中的默认排序顺序,而您想枚举每一行。为此,您可以在“ order by”子句中添加“(select 1)”,您将获得所需的内容。整洁吧?

select row_number() over (order by (select 1)), * from dbo.Table as t

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.