如何在动态sql查询中引用字段?

如何在动态sql查询中引用字段?,sql,sql-server,sql-server-2008,stored-procedures,Sql,Sql Server,Sql Server 2008,Stored Procedures,我在sql Server中有一个动态sql查询。所以我构建它,将它设置为一个变量,然后尝试根据日期设置where子句的格式。但是,当我尝试这样做时,我得到的“多部分标识符的字段名”无法绑定。我认为这是因为实际的表是从克劳斯动态生成的,所以在编译之前无法看到它们。有办法吗 这里我想说的是,给我指定年份+月份之间DOB的所有人员,例如,201001和201012将是2010年的整个年份。下面是代码的一部分 ALTER PROCEDURE get_persons_by_search_crite

我在sql Server中有一个动态sql查询。所以我构建它,将它设置为一个变量,然后尝试根据日期设置where子句的格式。但是,当我尝试这样做时,我得到的“多部分标识符的字段名”无法绑定。我认为这是因为实际的表是从克劳斯动态生成的,所以在编译之前无法看到它们。有办法吗

这里我想说的是,给我指定年份+月份之间DOB的所有人员,例如,201001和201012将是2010年的整个年份。下面是代码的一部分

    ALTER PROCEDURE get_persons_by_search_criteria

@month_from as nvarchar(2) = null,
@year_from as nvarchar(4) = null,
@month_to as nvarchar(2) = null,
@year_to as nvarchar(4) = null


AS

declare @from_date varchar(10)
declare @to_date varchar(10)
declare @sqlstr varchar(5000)

set @sqlstr = ' SELECT     
    Person.PersonID, 
    Person.FirstName, 
    Person.LastName, 
FROM    Person '

--Attemtping to create a value like 201108 (year + month)
set @from_date = Convert(VarChar(10), @year_from) + Replace(Str(@month_from, 2), ' ', '0')  
set @to_date = Convert(VarChar(10), @year_to) + Replace(Str(@month_to, 2), ' ', '0') 

set @sqlstr = @sqlstr +  ' WHERE '
set @sqlstr = @sqlstr + Convert(VarChar(10), Person.DOBYear) + Replace(Str(Person.DOBMonth, 2), ' ', '0') 
set @sqlstr = @sqlstr + ' BETWEEN '   + @from_date + ' and ' + @to_date


exec(@sqlstr)

此行给出了错误,因为在构建动态字符串时PERSON表未打开

set @sqlstr = @sqlstr + Convert(VarChar(10), Person.DOBYear) + Replace(Str(Person.DOBMonth, 2), ' ', '0')
试试这个

set @sqlstr = @sqlstr + ' Convert(VarChar(10), Person.DOBYear) + Replace(Str(Person.DOBMonth, 2), '' '', ''0'') '

我知道你已经解决了你的问题并接受了答案,但我想我还应该指出一些其他潜在的改进(对你和这个问题的未来读者都是如此)

这不是更容易看上眼睛,更容易遵循,更容易维护吗

总结:

  • 创建、更改或引用对象时

  • 当您不需要支持Unicode数据时,不要使用Unicode(
    NCHAR
    /
    NVARCHAR
    )(例如,数字永远不需要包含UMLAUT)。在这种情况下可能没有那么重要,但在其他情况下可能至关重要

  • 开始
    /
    结束
    中包装您的过程主体-这将防止您无意中从查询窗口提取其他不需要的代码。并始终在程序开始时使用
    SET NOCOUNT ON
    。我在“我的”中解决了这些和其他问题

  • 为避免行为发生变化,应始终包含一个
    orderby
    子句。如果今天它按名字下单,明天开始按姓氏下单,就会有人抱怨。见第二节

  • 尽可能学习在没有动态SQL的情况下编写SQL。如果要继续使用动态SQL,至少请尝试使用而不是。我在最近的另一个问题中解释了原因:

更好的做法是,首先将他们的出生日期存储为一个日期。为什么要将年和月存储为单独的字符串?你这样做一定有原因,但我无法想象这是什么。它所做的只是使这种字符串匹配的效率低于实际使用日期时的效率,降低了对值执行任何类型的日期操作的能力,并且使验证传入的值变得非常困难。现在,如果有人打电话给你,你的东西会比它应该有的时候窒息:

EXEC get_persons_by_search_criteria 
    @month_from = '97',
    @year_from  = 'Audi',
    @month_to   = 'TT',
    @year_to    = 'Oy!!';

他们可以这样做,因为你不执行任何验证。对于日期变量,至少返回的错误消息是有意义的。现在,对于我们的任何一个版本,它们只会得到一个空的结果集。

这看起来不需要是动态SQL。为什么不能使用上一个问题中的?提问时请指出SQL Server的版本@Martin的内存显然比我的好,但我们并不都知道上次有人问你“SQL Server的版本是什么?”
EXEC get_persons_by_search_criteria 
    @month_from = '97',
    @year_from  = 'Audi',
    @month_to   = 'TT',
    @year_to    = 'Oy!!';