Tsql 存储过程中END之后的语句

Tsql 存储过程中END之后的语句,tsql,stored-procedures,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 statement

今天我遇到了一个有趣的问题。我正在修改一个存储过程,并在最后放了一个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
等将消失。我对从哪里开始有点困惑,所以我有几个问题:

  • SET ANSI_NULLS
    保存为SP的一部分。我已确认每个SP都有自己的值。SQL Server如何知道将其保存为SP的一部分,因为它以前未被引用?它是否对当前环境状态进行完整扫描,然后在运行
    ALTER PROCEDURE
    时保存状态(可能只有非默认值)
  • 显然,开始/结束是可选的,没有内在意义。那为什么还要包括它们呢?它们给出了一种不存在的范围的错误感觉。在我看来,没有开始/结束,在结束时进行一次尝试是最有意义的

  • BEGIN…END
    定义了一个代码块。它不定义脚本或过程的开始和结束。但是,我同意这可能令人困惑


    将保存SET QUOTED_标识符和SET ANSI_NULLS设置,但不保存其他设置。查看互操作性以了解更多信息。

    ANSI NULL和带引号的标识符存储为存储过程代码的元数据属性。您可以通过查看这些设置

    select * from sys.sql_modules 
    
    保存过程时,这些属性将设置为保存过程所通过的连接的任何属性。这会导致令人恼火的矛盾,所以要小心

    至于BEGIN/END,正如@bobs所说的——它们表示代码块,而不是表示存储过程代码的开始和结束。(函数,是的,过程,否)正如你所说,
    不开始/结束,在结束时进行操作最有意义
    是我多年来一直采用的方式

    从技术上讲,SQL将(尝试)将批处理中的所有内容保存为存储过程的一部分,也就是说,您提交的所有文本都将被GO语句(如果有的话)分解。如果在临时查询之前插入了RETURN语句,它们将包含在代码中,但永远不会运行

    包含一系列Transact-SQL 语句使一组 Transact-SQL语句可以是 执行<代码>开始和
    结束
    是 控制流语言关键字

    SET ANSI_NULLS
    ON
    时,使用
    WHERE
    column_name=
    NULL
    SELECT
    语句返回零行,即使column_name中存在空值。使用
    WHERE
    column\u name
    NULL
    SELECT
    语句返回零行,即使column\u name中存在非NULL值

    SET ANSI_NULLS
    处于禁用状态时,等于(=)和不等于()比较运算符不符合ISO标准。使用WHERE column\u name=NULL的
    SELECT
    语句返回列\u name中具有NULL值的行。使用
    WHERE
    column\u name
    NULL
    SELECT
    语句返回列中具有非NULL值的行。另外,使用
    WHERE
    column\u name XYZ\u value的SELECT语句将返回所有非XYZ\u值且非
    NULL的行

    SET ANSI_NULLS
    ON
    时,与空值的所有比较计算为未知。当
    SET ANSI_NULLS
    OFF
    时,如果数据值为空,则所有数据与空值的比较将计算为TRUE。如果未指定
    SET ANSI_NULLS
    ,则当前数据库的
    ANSI_NULLS
    选项的设置适用。有关
    ANSI_NULLS
    数据库选项的详细信息,请参阅
    ALTER database
    (Transact-SQL)和设置数据库选项

    SET ANSI_NULLS ON
    仅当比较的一个操作数是
    NULL
    变量或文本
    NULL
    时,才会影响比较。如果比较的两侧都是列或复合表达式,则该设置不会影响比较

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

    SET ANSI_NULLS
    应设置为ON以执行分布式查询


    在计算列或索引视图上创建或更改索引时,“设置ANSI_NULLS”也必须启用。如果
    SET ANSI_NULLS
    OFF
    ,则在计算列或索引视图上具有索引的表上的任何
    创建
    更新
    插入
    删除
    语句都将失败。SQL Server将返回一个错误,其中列出了所有违反所需值的设置选项。此外,当执行
    SELECT
    语句时,如果
    SET ANSI_NULLS
    OFF
    ,SQL Server将忽略计算列或视图上的索引值,并解析SELECT操作,就好像表或视图上没有此类索引一样。

    BEGIN/END用于作用域,就像在IF/WHILE/etc中包含多个语句一样。坦率地说,与PLSQL相比,TSQL的使用非常糟糕——PLSQL在使用BEGIN/END和使用分号终止行的方式上更加结构化/组织化。就像TSQL在WITH/CTE之前声明变量时要求在WITH/CTE之前使用分号一样…:/C语言经验的任何人都可以使用PLSQL并能够读取它。对于TSQL不能这么说…@OMG-那么在这种情况下它给出了什么“范围”?我唯一能想象的是如果你申报