使用SYSNAME数据类型输入/输出TSQL过程

时间:2015-08-06 07:00:50

标签: sql sql-server tsql stored-procedures types

我正在尝试弄清楚数据类型sysname的使用以及解析器如何隐式转换和/或识别 none-quoted-literals 。使用着名的函数object_id来测试存在,请考虑这一点。

--Sanity test
begin
    if object_id('NotExistingProcedure','P') is not null print N'Exists.';
    else print N'Not exists.';
end
go

--This works.
begin
    declare @ObjectName sysname = 'NotExistingProcedure',
            @ObjectType sysname = 'P';
    if object_id(@ObjectName,@ObjectType) is not null print N'Exists.';
    else print N'Not exists.';
end
go

--This does not.
begin
    declare @ObjectName sysname = NotExistingProcedure,
            @ObjectType sysname = P;
    if object_id(@ObjectName,@ObjectType) is not null print N'Exists.';
    else print N'Not exists.';
end
go

--But this works.
create procedure TestExists
    @ObjectName sysname,
    @ObjectType sysname
as
    if object_id(@Objectname,@ObjectType) is not null print N'Exists.';
    else print N'Not exists.';
go

exec TestExists NotExistingProcedure,P;

任何人都可以解释为什么使用非引用文字来分配类型SYSNAME的变量在将参数传递给过程但不在外部时有效。

1 个答案:

答案 0 :(得分:0)

SYSNAME

  

sysname数据类型用于表列,变量和存储   存储对象名称的过程参数。。的确切定义   sysname与标识符规则相关。因此,它可以   因SQL Server实例而异。 sysname在功能上是相同的   as nvarchar(128),但默认情况下,sysname为NOT NULL。在   在早期版本的SQL Server中,sysname被定义为varchar(30)。

现在在您的示例中不起作用:

begin
    declare @ObjectName sysname = NotExistingProcedure,
            @ObjectType sysname = P;
    if object_id(@ObjectName,@ObjectType) is not null print N'Exists.';
    else print N'Not exists.';
end
go

错误:

  

无效的列名称' NotExistingProcedure'。

     

列名无效' P'。

基于DECLARE文档

DECLARE 
{ 
    { @local_variable [AS] data_type  | [ = value ] }
  | { @cursor_variable_name CURSOR }
} [,...n] 

enter image description here

所以你可以将value分配到:

  

=值

     

为变量分配一个值。值可以是常量表达式,但它必须与变量匹配   声明类型或可隐式转换为该类型。

然后Expressions

enter image description here

因此解析器需要列名,但没有列名(因为它不是SELECT语句)。

这就是你收到错误的原因:

  

列名称无效' NotExistingProcedure'。

现在让我们继续讨论最后一个有效的例子:

create procedure TestExists
    @ObjectName sysname,
    @ObjectType sysname
as
    if object_id(@Objectname,@ObjectType) is not null print N'Exists.';
    else print N'Not exists.';
go

exec TestExists NotExistingProcedure,P;
go

基于EXECUTE

enter image description here

所以当你看到你可以通过value

  

     

是要传递给模块或传递命令的参数值。如果未指定参数名称,则参数   必须按照模块中定义的顺序提供值。

     

如果参数的值是对象名,字符串或由数据库名称或模式名称限定,则必须将整个名称括在单引号中。如果值为a parameter是关键字,关键字必须用双引号括起来。

这表示应该使用'关闭。

如果您尝试传递架构:

exec TestExists dbo.NotExistingProcedure, P;
go
-- Incorrect syntax near '.'.

你需要用

括起来
exec TestExists 'dbo.NotExistingProcedure', P;
go

当它是关键字时,您可以使用[]引用它:

exec TestExists [from], P;
go

总结一下:

  1. 在声明SYSNAME类型的变量时,您无法传递不带引号的名称。
  2. EXEC为关键字或包含架构名称
  3. 时,您无法将不带引号的名称传递给int
  4. 找不到为什么传递不带引号的文字作品的文件