Sql server 必须声明标量变量"@“地位”&引用;“用户定义的表格类型”;

Sql server 必须声明标量变量"@“地位”&引用;“用户定义的表格类型”;,sql-server,stored-procedures,user-defined-types,Sql Server,Stored Procedures,User Defined Types,我使用的是用户定义的表类型,如下所示。请注意,我正在动态生成查询字符串,并在末尾执行该字符串。你可能会注意到一些引语 ALTER PROCEDURE MyPROC @phoneNo nvarchar(30) = null, @status dbo.StatusViewTableType READONLY AS BEGIN if(@option = 1) begin set @sql =

我使用的是用户定义的表类型,如下所示。请注意,我正在动态生成查询字符串,并在末尾执行该字符串。你可能会注意到一些引语

      ALTER PROCEDURE MyPROC
        @phoneNo nvarchar(30) = null,
        @status dbo.StatusViewTableType READONLY

        AS 
        BEGIN
     if(@option = 1)
    begin
      set @sql = 'SELECT   c.id,c.name,c.NewIc,c.OldIc,c.Title,c.nationality,c.CreatedDate,c.companyNo,c.NonIc,c.Email
                        FROM    customer c WITH (NOLOCK)
                        left outer join
                        dbo.Address with(nolock) on c.id =  dbo.Address.CustomerID 
                        left outer join dbo.ContactNo on c.id=dbo.ContactNo.CustomerID
                        WHERE     (c.id > 0) and ('


        if @oldIC <>'' and @phoneNo=''
            set @sql = @sql + ' (oldic ='''+ @oldIC + ''' )or'

        if @newIC <>'' and @phoneNo=''
            set @sql = @sql + ' (newIC ='''+ @newIC + ''' )or'

        if @companyno <>'' and @phoneNo=''
            set @sql = @sql + ' (companyno ='''+ @companyno + ''' )or'

        if @nonic <>'' and @phoneNo=''
            set @sql = @sql + ' (nonic ='''+ @nonic + ''' )or'

        If @phoneNo <>'' and @oldIC = '' and @newIC = '' and @companyno = '' and @nonic ='' 
        begin
            set @sql ='SELECT     c.id,c.name,c.NewIc,c.OldIc,c.Title,c.nationality,c.CreatedDate,c.companyNo,c.NonIc,c.Email
        FROM         dbo.Customer WITH (NOLOCK) c INNER JOIN
                              dbo.ContactNo WITH (NOLOCK)  ON c.id = dbo.ContactNo.CustomerID
        where   ContactNo = '''+ @phoneNo + ''' and  dbo.ContactNo.Contactability in (SELECT s.status   from  ' + [@status] + '  AS s ) '
        end
        if  @phoneNo='' 
        begin
        set @sql = Left(@sql,Len(@sql)-2)
        set @sql = @sql + ')'
        set @sql = @sql + '  and ( dbo.Address.Contactable in (SELECT  s.status   from ' + [@status] + '   AS s) or  dbo.ContactNo.Contactability in (SELECT  s.status from ' + [@status] + ' AS s) )'
        end 
print @sql

exec (@sql)
end
我对参数
@status
有问题。它在存储过程中无法识别

它抛出了一个异常:

必须声明标量变量“@status”

下面是我的
StatusViewTAbleType

CREATE TYPE [dbo].[StatusViewTableType] AS TABLE(
    [Status] [int] NOT NULL
)
GO

任何帮助都将不胜感激。

问题是您使用了不需要的单引号。试试这个

ALTER PROCEDURE Myproc @phoneNo NVARCHAR(30) = NULL,
                       @status  dbo.STATUSVIEWTABLETYPE READONLY
AS
  BEGIN
      SELECT *
      FROM   dbo.Customer WITH (NOLOCK)
             INNER JOIN dbo.ContactNo WITH (NOLOCK)
                     ON dbo.Customer.id = dbo.ContactNo.CustomerID
      WHERE  ContactNo = @phoneNo
             AND dbo.ContactNo.Contactability IN (SELECT status
                                                  FROM   @status)
  END 

问题是您使用了不需要的单引号。试试这个

ALTER PROCEDURE Myproc @phoneNo NVARCHAR(30) = NULL,
                       @status  dbo.STATUSVIEWTABLETYPE READONLY
AS
  BEGIN
      SELECT *
      FROM   dbo.Customer WITH (NOLOCK)
             INNER JOIN dbo.ContactNo WITH (NOLOCK)
                     ON dbo.Customer.id = dbo.ContactNo.CustomerID
      WHERE  ContactNo = @phoneNo
             AND dbo.ContactNo.Contactability IN (SELECT status
                                                  FROM   @status)
  END 

问题是您使用了不需要的单引号。试试这个

ALTER PROCEDURE Myproc @phoneNo NVARCHAR(30) = NULL,
                       @status  dbo.STATUSVIEWTABLETYPE READONLY
AS
  BEGIN
      SELECT *
      FROM   dbo.Customer WITH (NOLOCK)
             INNER JOIN dbo.ContactNo WITH (NOLOCK)
                     ON dbo.Customer.id = dbo.ContactNo.CustomerID
      WHERE  ContactNo = @phoneNo
             AND dbo.ContactNo.Contactability IN (SELECT status
                                                  FROM   @status)
  END 

问题是您使用了不需要的单引号。试试这个

ALTER PROCEDURE Myproc @phoneNo NVARCHAR(30) = NULL,
                       @status  dbo.STATUSVIEWTABLETYPE READONLY
AS
  BEGIN
      SELECT *
      FROM   dbo.Customer WITH (NOLOCK)
             INNER JOIN dbo.ContactNo WITH (NOLOCK)
                     ON dbo.Customer.id = dbo.ContactNo.CustomerID
      WHERE  ContactNo = @phoneNo
             AND dbo.ContactNo.Contactability IN (SELECT status
                                                  FROM   @status)
  END 

如果在完全限定对象名称中使用表值参数,则必须将其括在括号中,即,它应该是
[@Status]。Status
而不是
@Status]。Status
或使用别名

您可以非常简单地重新创建:

DECLARE @P TABLE (ID INT);
SELECT @P.ID FROM @P;
这会引发错误:

必须声明标量变量“@p”

我也不认为您正确使用了参数,我认为您的程序应该是:

ALTER PROCEDURE MyPROC
    @phoneNo nvarchar(30) = NULL,
    @status dbo.StatusViewTableType READONLY

AS 
BEGIN
    SELECT    * 
    FROM    dbo.Customer WITH (NOLOCK)  
            INNER JOIN dbo.ContactNo WITH (NOLOCK)  
                ON dbo.Customer.id = dbo.ContactNo.CustomerID
    WHERE   ContactNo = @phoneNo
    AND     dbo.ContactNo.Contactability IN (SELECT s.status FROM @status AS s);

END 
最后,我强烈建议不要这样做


编辑

关于您的动态SQL问题,请使用它,它将允许您使用参数,而不是类似于:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = ''' + @P + '''';
    
EXEC(@SQL);
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=''+@P+'';
EXEC(@SQL);
你会用

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = @P';
    
EXECUTE sp_executesql @SQL, N'@P NVARCHAR(10), @P;
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=@P';
执行sp_executesql@SQL,N'@P NVARCHAR(10),@P;

因此,您将@p作为参数传递给查询。这将解决所有单引号问题

如果在完全限定的对象名称中使用表值参数,则必须将其括在括号中,即,而不是
@Status。Status
应为
[@Status]。Status
或使用别名

您可以非常简单地重新创建:

DECLARE @P TABLE (ID INT);
SELECT @P.ID FROM @P;
这会引发错误:

必须声明标量变量“@p”

我也不认为您正确使用了参数,我认为您的程序应该是:

ALTER PROCEDURE MyPROC
    @phoneNo nvarchar(30) = NULL,
    @status dbo.StatusViewTableType READONLY

AS 
BEGIN
    SELECT    * 
    FROM    dbo.Customer WITH (NOLOCK)  
            INNER JOIN dbo.ContactNo WITH (NOLOCK)  
                ON dbo.Customer.id = dbo.ContactNo.CustomerID
    WHERE   ContactNo = @phoneNo
    AND     dbo.ContactNo.Contactability IN (SELECT s.status FROM @status AS s);

END 
最后,我强烈建议不要这样做


编辑

关于您的动态SQL问题,请使用它,它将允许您使用参数,而不是类似于:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = ''' + @P + '''';
    
EXEC(@SQL);
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=''+@P+'';
EXEC(@SQL);
你会用

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = @P';
    
EXECUTE sp_executesql @SQL, N'@P NVARCHAR(10), @P;
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=@P';
执行sp_executesql@SQL,N'@P NVARCHAR(10),@P;

因此,您将@p作为参数传递给查询。这将解决所有单引号问题

如果在完全限定的对象名称中使用表值参数,则必须将其括在括号中,即,而不是
@Status。Status
应为
[@Status]。Status
或使用别名

您可以非常简单地重新创建:

DECLARE @P TABLE (ID INT);
SELECT @P.ID FROM @P;
这会引发错误:

必须声明标量变量“@p”

我也不认为您正确使用了参数,我认为您的程序应该是:

ALTER PROCEDURE MyPROC
    @phoneNo nvarchar(30) = NULL,
    @status dbo.StatusViewTableType READONLY

AS 
BEGIN
    SELECT    * 
    FROM    dbo.Customer WITH (NOLOCK)  
            INNER JOIN dbo.ContactNo WITH (NOLOCK)  
                ON dbo.Customer.id = dbo.ContactNo.CustomerID
    WHERE   ContactNo = @phoneNo
    AND     dbo.ContactNo.Contactability IN (SELECT s.status FROM @status AS s);

END 
最后,我强烈建议不要这样做


编辑

关于您的动态SQL问题,请使用它,它将允许您使用参数,而不是类似于:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = ''' + @P + '''';
    
EXEC(@SQL);
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=''+@P+'';
EXEC(@SQL);
你会用

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = @P';
    
EXECUTE sp_executesql @SQL, N'@P NVARCHAR(10), @P;
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=@P';
执行sp_executesql@SQL,N'@P NVARCHAR(10),@P;

因此,您将@p作为参数传递给查询。这将解决所有单引号问题

如果在完全限定的对象名称中使用表值参数,则必须将其括在括号中,即,而不是
@Status。Status
应为
[@Status]。Status
或使用别名

您可以非常简单地重新创建:

DECLARE @P TABLE (ID INT);
SELECT @P.ID FROM @P;
这会引发错误:

必须声明标量变量“@p”

我也不认为您正确使用了参数,我认为您的程序应该是:

ALTER PROCEDURE MyPROC
    @phoneNo nvarchar(30) = NULL,
    @status dbo.StatusViewTableType READONLY

AS 
BEGIN
    SELECT    * 
    FROM    dbo.Customer WITH (NOLOCK)  
            INNER JOIN dbo.ContactNo WITH (NOLOCK)  
                ON dbo.Customer.id = dbo.ContactNo.CustomerID
    WHERE   ContactNo = @phoneNo
    AND     dbo.ContactNo.Contactability IN (SELECT s.status FROM @status AS s);

END 
最后,我强烈建议不要这样做


编辑

关于您的动态SQL问题,请使用它,它将允许您使用参数,而不是类似于:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = ''' + @P + '''';
    
EXEC(@SQL);
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=''+@P+'';
EXEC(@SQL);
你会用

DECLARE @SQL NVARCHAR(MAX) = 'SELECT A, B, C FROM T WHERE 1 = 1',
        @P NVARCHAR(10) = 'X';
IF @P <> '' 
    SET @SQL = @SQL + ' AND A = @P';
    
EXECUTE sp_executesql @SQL, N'@P NVARCHAR(10), @P;
DECLARE@SQL NVARCHAR(MAX)='从T中选择A、B、C,其中1=1',
@P NVARCHAR(10)='X';
如果@P''
设置@SQL=@SQL+'和A=@P';
执行sp_executesql@SQL,N'@P NVARCHAR(10),@P;

因此,您将@p作为参数传递给查询。这将解决所有单引号问题

动态SQL无法识别超出其范围的变量。这就是它出错的原因。

动态SQL无法识别超出其范围的变量。这就是它出错的原因。

动态SQL无法识别超出其范围的变量。这就是它出错的原因。

动态SQL无法识别其外部的变量