【问题标题】:An expression of non-boolean type specified in a context where a condition is expected, near '@where'在预期条件的上下文中指定的非布尔类型的表达式,靠近“@where”
【发布时间】:2018-06-01 14:02:51
【问题描述】:
DECLARE @str VARCHAR(MAX)=''

SET @str='
DECLARE @where VARCHAR(max)=''''

IF 1>2 
BEGIN
SET @where='' Test_Group_Id=1''
END
ELSE
BEGIN
SET @where='' Party_Master_Id=1''
END

SELECT * FROM dbo.Party_Details WHERE 1=1 and @where';

EXECUTE(@str)

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。跨度>
  • 在尝试执行之前 PRINT @str 会看到什么?
  • WHERE 1=1?重点是什么?这完全浪费了优化器的时间,应该被删除。除非你能想到1=1 为假的时候?
  • 实际上,我认为您确实需要更好地解释这一点。你在IF 中的测试是IF 1 > 2,它总是错误的。因此,当您的查询总是 SELECT * FROM dbo.Party_Details WHERE Party_Master_Id=1; 时,为什么需要动态 SQL?
  • 我无法访问您在下面的 cmets 中引用的第三方 Oasis 站点 - 请在此处提供完整的复制。请参阅minimal reproducible exampleHow to Ask 了解更多详情

标签: sql-server stored-procedures dynamic-sql


【解决方案1】:

您也可以在没有动态 sql 的情况下执行此操作。像这样的东西。 where 1 = 1 很傻,所以我删除了它。当然 1 > 2 会被替换为某种真实情况。

select *
from dbo.Party_Details
where 1 = case when 1 > 2 then Test_Group_Id else Party_Master end

【讨论】:

    【解决方案2】:

    试试这个

    DECLARE @str VARCHAR(MAX)=''
    
    DECLARE @where VARCHAR(max)=''''
    
    IF 1>2 
    BEGIN
    SET @where= 'Test_Group_Id=1'
    END
    ELSE
    BEGIN
    SET @where='Party_Master_Id=1'
    END
    
    SET @str = 'SELECT * FROM dbo.Party_Details WHERE 1=1 and ' + @where
    
    EXECUTE(@str)
    

    【讨论】:

    • 请不要删除我查询的分隔部分。 all in query in dynamic part 查看我的查询并找到这个变量'@strCrDr'oasis.sandstorm.io/grain/HLhEkpxMmdfTw6ABh9LiDD
    • @AshishMaurya 没有人会删除任何东西——这里的人正在向您展示如何正确地构建您想要的动态 SQL。此外,我无法访问该第三方 Oasis 网站 - 请在此处放置完整的复制品。请参阅minimal reproducible exampleHow to Ask 了解更多详情
    【解决方案3】:

    尽管其他人提供了实现明显期望的最终结果的变通方法,但如果这就是您要问的问题,以下是您收到错误的实际原因:

    您正在尝试在动态 sql 查询中执行动态 sql 查询,但您只是做了一半。

    如果你打印了@str 而不是执行它,你会看到:

    DECLARE @where VARCHAR(max)=''''
    
    IF 1>2 
    BEGIN
    SET @where='' Test_Group_Id=1''
    END
    ELSE
    BEGIN
    SET @where='' Party_Master_Id=1''
    END
    
    SELECT * FROM dbo.Party_Details WHERE 1=1 and @where
    

    @str INSIDE 内的代码并未尝试在其最终选择中将 @where 替换为 @where 的值。

    要在动态查询中完全执行动态查询,您必须执行整个 string-concat 加上 EXEC。所以这会起作用:

    DECLARE @str VARCHAR(MAX)=''
    
    SET @str='
    DECLARE @where VARCHAR(max)=''''
    DECLARE @str2 varchar(max)
    
    IF 1>2 
    BEGIN
    SET @where='' Test_Group_Id=1''
    END
    ELSE
    BEGIN
    SET @where='' Party_Master_Id=1''
    END
    
    SET @str2 = ''SELECT * FROM dbo.Party_Details WHERE 1=1 and '' + @where
    EXECUTE(@str2)
    ';
    
    EXECUTE(@str)
    

    【讨论】:

      【解决方案4】:

      你缺少基础知识...

      编辑:对 OP 和 Peter 的解释

      语法被破坏,因为实际运行的SELECT 语句是

      SELECT * FROM dbo.Party_Details WHERE 1=1 and 'Party_Master_Id=1'
      

      这对 sql server 没有意义,因为在 AND 运算符之后没有条件检查。

      这应该可以工作

      DECLARE @str VARCHAR(MAX)=''
      DECLARE @where VARCHAR(max)=''
      
      IF 1>2 
      BEGIN
      SET @where='Test_Group_Id=1'
      END
      ELSE
      BEGIN
      SET @where='Party_Master_Id=1'
      END
      
      
      SET @str='SELECT * FROM dbo.Party_Details WHERE 1=1 and '+@where
      
      EXECUTE(@str)
      

      【讨论】:

      • 请不要删除我查询的分隔部分。 all in query in dynamic part 查看我的查询并找到这个变量'@strCrDr'oasis.sandstorm.io/grain/HLhEkpxMmdfTw6ABh9LiDD
      • 我的朋友很抱歉,但您应该尝试更好地解释。我真的很想念你想说的话
      • @AshishMaurya @strCrDr 在您的问题中不在您的 SQL 中。如果您的 SQL 比您的问题中的更多,edit 您的问题,不要在没有任何上下文的情况下发布所有答案的 cmets,并期望人们点击一个没有详细信息的链接。
      • @AshishMaurya 没有人会删除任何东西——这里的人正在向您展示如何正确地构建您想要的动态 SQL。此外,我无法访问该第三方 Oasis 网站 - 请在此处放置完整的复制品。请参阅minimal reproducible exampleHow to Ask 了解更多详情
      • 我想在游标中使用,所以 SET @str='SELECT * FROM dbo.Party_Details WHERE 1=1 and '+@where we not set
      【解决方案5】:

      这行得通

          DECLARE @str VARCHAR(MAX);
      
      set @str= '
      DECLARE @str VARCHAR(MAX);
      DECLARE @where VARCHAR(max);
      IF 1>2 
      BEGIN
       SET @where='' Test_Group_Id=1''
      END
      ELSE
      BEGIN
       SET @where='' Party_Master_Id=1''
      END
      set @str=''SELECT * FROM dbo.Party_Details WHERE 1=1 AND '' + @where
      exec(@str)
      '
      exec(@str)
      

      这是有效的,因为没有类型转换,您传递给执行函数的字符串值将起作用。最好在动态 SQL 部分之外定义变量。

      【讨论】:

      • 是的,在您回复其他人并更清楚地说明这一点后,我意识到了。
      • 请不要删除我查询的分隔部分。 all in query in dynamic part 查看我的查询并找到这个变量'@strCrDr'oasis.sandstorm.io/grain/HLhEkpxMmdfTw6ABh9LiDD
      • @AshishMaurya 没有人会删除任何东西 - 这里的人正在向您展示如何正确构建您想要的动态 SQL。此外,我无法访问该第三方 Oasis 网站 - 请在此处放置完整的复制品。请参阅minimal reproducible exampleHow to Ask 了解更多详情
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 2011-09-22
      • 2013-02-11
      • 1970-01-01
      相关资源
      最近更新 更多