存储过程中END之后的语句

时间:2010-11-15 20:34:15

标签: tsql stored-procedures

我今天遇到了一个有趣的问题。我正在改变存储过程并在最后放置一个select语句。它本来是临时的,只是用于处理数据。我很惊讶后来发现声明已经保存并且在SP运行时正在执行。

SET ANSI_NULLS ON
GO

-- Comments usually go here and are saved as part of the SP
ALTER PROCEDURE [dbo].[MySP]
    @param INT
AS
BEGIN
    --Your normal SQL statements here
END

--You can also add SQL statements here
select * from LargeTable

--You have access to the params
select @param

有意义的是保存所有内容,而不仅仅是BEGIN / END内的内容,否则评论和SET ANSI_NULLS等将会消失。我对从哪里开始有点困惑,所以我有几个问题:

  1. SET ANSI_NULLS会被保存为SP的一部分。我已经确认每个SP都有自己的价值。 SQL Server如何知道将其保存为SP的一部分,因为之前没有引用它?它是否对当前环境状态进行全面扫描,然后在ALTER PROCEDURE运行时保存状态(可能只是非默认值)?
  2. 显然BEGIN / END是可选的,没有内在含义。为什么他们甚至包括在内?它们给出了一种不存在的错误范围。在我看来,没有BEGIN / END和最后的GO会最有意义。

3 个答案:

答案 0 :(得分:5)

BEGIN...END定义了一段代码。它没有定义脚本或过程的开始和结束。但是,我同意这可能令人困惑。

保存SET QUOTED_IDENTIFIER和SET ANSI_NULLS设置,但不保存其他设置。有关详细信息,请查看互操作性here

答案 1 :(得分:5)

ANSI NULLS和QUOTED IDENTIFIERS存储为存储过程代码的元数据属性。您可以通过

查看这些设置
select * from sys.sql_modules 

保存过程时,这些属性将设置为保存过程的连接所属的属性。这可能导致恼人的不一致,所以要小心。

至于BEGIN / END,它与@bobs一样 - 它们表示代码块,它们不表示存储过程代码的开始和结束。 (功能,是的,程序,没有。)正如你所说,no BEGIN/END and a GO at the end would make the most sense是我多年来一直这样做的方式。

从技术上讲,SQL将(尝试)将批处理中的所有内容保存为存储过程的一部分 - 即,您提交的所有文本,由GO语句(如果有)分解。如果您在即席查询之前粘贴了RETURN语句,它们将包含在代码中但从不运行。

答案 2 :(得分:1)

  

附上一系列Transact-SQL   陈述使一组   Transact-SQL语句可以   执行。 BEGINEND是。{   控制流语言关键字。

SET ANSI_NULLSON时,即使column_name中存在空值,使用SELECT column_name = WHERE的{​​{1}}语句也会返回零行。使用NULL column_name<>的SELECT语句即使column_name中存在非空值,WHERE也会返回零行。

NULL为OFF时,Equals(=)和Not Equal To(<>)比较运算符不遵循ISO标准。使用WHERE column_name = NULL的SET ANSI_NULLS语句将返回column_name中具有空值的行。使用SELECT column_name<>的SELECT语句WHERE返回列中包含非空值的行。此外,使用NULL column_name<>的SELECT语句XYZ_value返回非XYZ_value且不是WHERE的所有行。

NULLSET ANSI_NULLS时,所有与空值的比较都会计算为UNKNOWN。当ONSET ANSI_NULLS时,如果数据值为NULL,则将所有数据与空值的比较计算为TRUE。如果未指定OFF,则应用当前数据库的SET ANSI_NULLS选项的设置。有关ANSI_NULLS数据库选项的更多信息,请参阅ANSI_NULLS(Transact-SQL)和设置数据库选项。

仅当比较的一个操作数是ALTER DATABASE的变量或文字SET ANSI_NULLS ON时,

NULL才会影响比较。如果比较的两侧都是列或复合表达式,则该设置不会影响比较。

要使脚本按预期工作,无论NULL数据库选项或ANSI_NULLS的设置如何,请在可能包含null的比较中使用IS SET ANSI_NULLSNULL值。

IS NOT NULL应设置为ON以执行分布式查询。

在计算列或索引视图上创建或更改索引时,SET ANSI_NULLS也必须为ON。如果SET ANSI_NULLSSET ANSI_NULLS,则计算列或索引视图上包含索引的表上的任何OFFCREATEUPDATEINSERT语句都将失败。 SQL Server将返回一个错误,列出违反所需值的所有SET选项。此外,当您执行DELETE语句时,如果SELECTSET ANSI_NULLS,SQL Server将忽略计算列或视图上的索引值并解析选择操作,就好像没有这样的索引一样在表格或视图上。