NOCOUNT
这是关于语句的用法和语义的一个小问题。我已经看到它使用了几种不同的方式,我想知道实际需要什么。
我在 MSDN 上看到它带有尾随分号和 GO 语句,如下所示:
SET NOCOUNT ON;
GO
我已经看到没有尾随分号:
SET NOCOUNT ON
GO
我已经看到它没有 GO 语句
SET NOCOUNT ON
我意识到这GO
只是一个批次结束的信号,但是应该调用它以NOCOUNT
使其生效吗?
分号的意义何在?
NOCOUNT
这是关于语句的用法和语义的一个小问题。我已经看到它使用了几种不同的方式,我想知道实际需要什么。
我在 MSDN 上看到它带有尾随分号和 GO 语句,如下所示:
SET NOCOUNT ON;
GO
我已经看到没有尾随分号:
SET NOCOUNT ON
GO
我已经看到它没有 GO 语句
SET NOCOUNT ON
我意识到这GO
只是一个批次结束的信号,但是应该调用它以NOCOUNT
使其生效吗?
分号的意义何在?
一个 ';' 是一个内存终止符,我一直认为 GO 语句是一个批处理终止符。
因此,如果您创建 DDL,例如创建 proc、视图、函数或其他对象,您可以执行以下操作:
创建 proc blah 为 .... GO
创建 proc blah2 为 .... GO
然后你可以有一个很好的创建脚本。如果您没有 GO,它会中断,因为它会说:“Create (thing) must be the first statement in a creation ....” 这意味着 SQL 认为您正在为两者执行单个操作。'GO' 说:“新范围,新对象”。所以它解决了这个问题。如果您查看 pubs 和 Northwind(旧的 MS 测试数据库)的创建脚本,我相信他们都在为单个“*.sql”文件使用批处理终止符。它使在单个文件中进行大量创建成为可能。
一个 ; 只会将内存终止到一个语句。大多数时候省略它们是可以的,但是你们中的一些 SQL 专家会知道你无法摆脱它的一个很大的地方是...... CTE!
是的,CTE 会立即对您大喊大叫,因为它以“with”开头,但您也可以使用带有“with”的 (nolock) 提示,因此它需要区分两个事务,因此您应该使用“;”。
例如:
Select * from table -- standard SQL no biggie
或者
Select * from table
Select * from table2 -- these are fine stacked and will run
但...
Select * from table
with a as (select * from table2) select * from a
将立即中断,因为它不知道 'with' 的上下文已更改为新语句。如果您一丝不苟,正确的 SQL 应该是这样的:
Set NoCount ON; -- No thank you engine I don't need to see counts
Set Transaction Level Isolation Level Read Uncommitted; -- Set me to dirty reads as default
Select
*
from table
;
Select
*
from table2
;
SQL 引擎将其视为:
Set NoRead ON;-- 不,谢谢引擎,我不需要查看计数\nSet Transaction Level Isolation Level Read Uncommitted;\n-- 将我设置为默认脏读\n\nSelect\n*\nfrom table\n ;\n\n从表2中选择\n*\n\n;
所以它需要告诉它空白在哪里终止的人的一点帮助。否则它不是人类,不知道一个语句在哪里停止,另一个语句从哪里开始。
不管你做什么,如果你是为别人写的,并且根据明确的指导方针,我总是被告知要做';' 终结者使其成为正式的结束序列。
GO 是一个批处理终止器,但您可以使用它更改上下文,这对于切换数据库非常有用,例如:
使用数据库1 GO
从 TableOnDatabase1 中选择 *;
使用 Database2 GO
从 TableOnDatabase2 中选择 *;
另外为了节省空间,我做了一行,但实际上你应该在单独的行上执行主要的 sql 语法以及子语法,例如:
Select
ColumnA
, ColumnB
, count(ColumnC) as cnt
From table
Where thing happens
Group by
ColumnA
, ColumnB
Having Count(ColumnC) > 1
Order by ColumnA
编辑常见的现实世界示例:
set nocount on;
declare @Table table ( ints int);
declare @CursorInt int = 1;
while @CursorInt <= 100
begin
insert into @Table values (@CursorInt)
set @CursorInt += 1
End
-- wait a second engine you did not tell me what happened in the 'Messages' section?!
-- aw come on I want to see each transaction!
Set nocount off;
while @CursorInt <= 200
begin
insert into @Table values (@CursorInt)
set @CursorInt += 1
End
-- okay that is annoying I did not have to see 100: "(1 row(s) affected)"
您可以在过程范围内根据需要打开和关闭带有内存终止符的“nocount”。当我想在我的过程中看到一些插入并忽略其他插入时,我总是这样做。在某些情况下,如果我想将它们传递出去,我会设置一个输出变量或一个简单的最终行数选择以返回。
分号结束当前的 SQL 语句。
据我所知,在 SET NOCOUNT ON 之后不需要它。
你不应该需要'GO'来让 NOCOUNT 生效,尽管我不太确定。