AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 142296
Accepted
ola
ola
Asked: 2016-06-27 14:40:52 +0800 CST2016-06-27 14:40:52 +0800 CST 2016-06-27 14:40:52 +0800 CST

书中与存储过程中的变量范围相关的矛盾

  • 772

我正在阅读 70-461 TSQL 培训书,关于存储过程的部分是这样说的:

Proc1 中声明的变量和 Proc1 的参数对于 Proc1 调用的任何过程都是不可见的

但是在同一本书中是这个示例代码:

CREATE PROCEDURE Sales.ListCustomerByAddress
(@address AS NVARCHAR(60))
AS
DECLARE @SQLString AS NVARCHAR(4000);
SET @SQLString = '
SELECT companyname, contactname
FROM Sales.Customers WHERE address = @address';

EXECUTE sp_executesql
         @statement = @SQLString,
         @params = N'@address NVARCHAR(60)',
         @address = @address;
RETURN;  
GO  

我对引用语句的理解是@SQLString变量和@address参数不能被sp_executesql过程可见和引用?变量是一个包含值的对象,因此如果它不存在或看不到(例如在中@statement =),如何使用或传递该值

有人可以帮助调和这个矛盾吗?

t-sql sql-server-2012
  • 1 1 个回答
  • 123 Views

1 个回答

  • Voted
  1. Best Answer
    Solomon Rutzky
    2016-06-27T17:54:19+08:002016-06-27T17:54:19+08:00

    该文档中没有矛盾。这里的混淆似乎是关于读者对变量范围如何工作的期望的隐含假设。在许多其他语言中,在外部作用域中声明的变量对子例程/函数是可见的。例如(这不是它在 T-SQL 中的工作方式;我只是在说明变量范围通常是如何工作的):

    int OuterVariable = 5;
    
    function int Sub1 (int Param1)
    {
      int InnerVariable = 10;
    
      return InnerVariable + OuterVariable + Param1;
    }
    
    int Result = Sub1(3);
    

    由于在外部作用域中声明的变量通常对内部作用域(即全局)可见,因此上面的代码在调用未声明的声明时不会Sub1出错OuterVariable。相反,子例程可以访问的值OuterVariable(在某些语言中,它甚至可以覆盖该值)。Result因此,末尾的值为18。

    所以,当书中说:

    “Proc1 中声明的变量和 Proc1 的参数对 Proc1 调用的任何过程都不可见”

    他们说 T-SQL 不是那样工作的。他们并不是说 Proc1 中的变量不能传递到子 Proc 调用中;他们说如果你想在 sub-Proc 调用中使用这些值,那么你必须通过输入参数显式地传递它们。从本质上讲,“可见”意味着“无需通过输入参数显式传入即可使用”。

    也许这将有助于说明:

    CREATE PROCEDURE dbo.InnerProc(@InnerInputParam INT, @InnerName NVARCHAR(30))
    AS
    SELECT @InnerInputParam AS [InnerParam], @InnerName AS [InnerName];
    
    -- SELECT @OuterName; -- commented out as this is a parse error
    GO
    
    CREATE PROCEDURE dbo.OuterProc(@OuterInputParam INT)
    AS
    DECLARE @OuterName NVARCHAR(30) = N'Mr. Outer Scope';
    
    EXEC dbo.InnerProc
            @InnerInputParam = @OuterInputParam,
            @InnerName = @OuterName;
    GO
    

    执行EXEC dbo.OuterProc 5;或EXEC dbo.OuterProc @OuterInputParam = 5;(同样的事情)将返回:

    InnerParam     InnerName
    5              Mr. Outer Scope
    

    这些值被 dbo.InnerProc“知道”,因为它们是传入的。并且它们被传入是因为它们对 dbo.InnerProc 不“可见”,即使它们在执行期间存在于 dbo.OuterProc 的外部/父范围内。但是在 dbo.InnerProc 中都不能引用@OuterInputParamnor @OuterName,因为内部/子范围不知道外部/父范围,至少对于变量(包括表变量)和参数是这样。

    最后,将所有这些与本书中的初始示例联系起来,这就是为什么我在使用sp_executesql: 时尽力更改变量名称以使代码更具可读性。更改一个变量名可能会使它更清楚一点:

    SET @SQLString = '
    SELECT companyname, contactname
    FROM Sales.Customers WHERE address = @InnerAddress';
    
    EXECUTE sp_executesql
             @statement = @SQLString,
             @params = N'@address NVARCHAR(60)',
             @InnerAddress = @address;
    
    • 3

相关问题

  • 如何判断 SQL Server 数据库是否仍在使用?

  • 为什么 Denali 序列应该比标识列表现更好?

  • 实施 PIVOT 查询

  • SQL Server 不应该支持范围吗?

  • 什么是 SQL Server“德纳利”?什么是新的?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve