sql server 条件

Posted

技术标签:

【中文标题】sql server 条件【英文标题】:sql server conditionals 【发布时间】:2010-02-26 19:30:20 【问题描述】:

运行此查询时出现错误,因为数据类型 money 无法隐式转换为 varchar。但是,在尝试转换之前,我使用 if 语句来确保数据类型不是金钱。显然,无论如何都在执行转换。有人知道为什么吗?

表:BBH_NEW 列:rebate2 数据类型:钱

if 'money'= 'money'
begin
   if (select max([rebate2]) from [BBH_NEW]) = 0 
   and (select min([rebate2]) from [BBH_NEW]) = 0
     print ' rebate2 '
     print ' 1 '
end   

if 'money'!= 'money'
begin
   IF NOT EXISTS (SELECT top 1 * FROM [BBH_NEW] WHERE [rebate2] IS NOT NULL and
   len([rebate2]) > 0 ) 
   BEGIN 
      print ' rebate2 ' 
   end
end

错误: 消息 257,第 16 级,状态 3,第 11 行 不允许从数据类型 money 到 varchar 的隐式转换。使用 CONVERT 函数运行此查询。


是的,此代码已生成。如果有帮助,这是用于生成它的代码:

select @temp = 
    data_type FROM information_schema.columns
WHERE table_schema = 'dbo'
AND table_name = @tblname 
AND column_name = @col

SELECT @hold = 
    'if '''+@temp+'''= ''money'' 
begin
   if (select max(['+@col+']) from ['+@tblname+']) = 0 
       and (select min(['+@col+']) from ['+@tblname+']) = 0
   print '' '+@col+' money''
end 

    if '''+@temp+'''!= ''money'' 
begin
   IF NOT EXISTS (SELECT max([' + @col + ']) FROM ['+ @tblname + '] 
       WHERE len( [' + @col + ']) > 0 ) 
       BEGIN 
          print '' ' + @col + ' '' 
       end 
end'

【问题讨论】:

什么时候字符串'money'不等于自己? 此代码是动态生成的。它通常不是 'money' != 'money' ,它使用当前列数据类型。即如果'varchar'!='钱'。我使用这个例子是因为它试图告诉我事实上 'money' != 'money' 因为它正在执行下一行 那么提供的代码实际上是生成并产生了错误?我在 SSMS 2008 中运行它,它运行时没有任何缺陷。 我在 SSMS 2008 中运行它并得到错误。源代码见上面的编辑 if '''+@temp+'''!= ''money'': 不应该是 ''money'' 吗? 【参考方案1】:

据我了解,当您收到错误时,列 BBH_NEW.rebate2 的类型为 money。在 T-SQL 中,您不能有一个无法编译的查询,这就是您所遇到的。即使 always-false if 块中的查询不会运行,它也不会编译,因为数据类型不匹配。

首先,为您提供一个快速解决方案 - 使用 CONVERT 或 CAST 显式更改数据类型。

if 'money'!= 'money'
begin
   IF NOT EXISTS (SELECT top 1 * FROM [BBH_NEW] WHERE [rebate2] IS NOT NULL and
   len(CONVERT(VARCHAR(8000), [rebate2])) > 0 ) 
   BEGIN 
      print ' rebate2 ' 
   end
end

但是,必须有更好的方法来完成您正在做的任何事情......该 SQL 何时生成?如果是在运行时,你可以不生成不会运行的部分吗?也许是这样的?

SELECT @hold = CASE WHEN @temp = 'money' THEN 
    'if (select max(['+@col+']) from ['+@tblname+']) = 0 
       and (select min(['+@col+']) from ['+@tblname+']) = 0
   print '' '+@col+' money'''
ELSE
    'IF NOT EXISTS (SELECT max([' + @col + ']) FROM ['+ @tblname + '] 
       WHERE len( [' + @col + ']) > 0 ) 
       BEGIN 
          print '' ' + @col + ' '' 
       end'
END

或者也许将世代改为这个......

SELECT @temp = DATA_TYPE 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = @tblname 
AND COLUMN_NAME = @col

IF(@temp = 'money')
    SELECT @hold = 'IF(EXISTS(
    SELECT 1 
    FROM ['+@tblname+'] 
    HAVING MAX(['+@col+']) = 0 
    AND MIN(['+@col+']) = 0))
BEGIN
    PRINT '' '+@col+' ''
END';
ELSE
    SELECT @hold = 'IF(NOT EXISTS(
    SELECT * 
    FROM ['+@tblname+'] 
    WHERE ['+@col+'] IS NOT NULL
    AND LEN(['+@col+']) > 0))
BEGIN
    PRINT '' '+@col+' ''
END';

【讨论】:

谢谢,我没有意识到错误来自编译 vs 在运行时【参考方案2】:

一些优化生成器的提示

重写

SELECT @hold = 
'if '''+@temp+'''= ''money'' 
begin
...
end 

作为

if @temp = 'money'
begin
...
end

第二,我想不出什么时候

[rebate2] IS NOT NULL

不暗示

len(CONVERT(VARCHAR(8000), [rebate2])) > 0

也就是说,只要rebate2不为NULL,它的字符串长度就大于0

【讨论】:

"也就是说,只要rebate2不为NULL,它的字符串长度就大于0" 不,SQL Server区分空字符串''和null。 @Shannon Severance 其中 MONEY NOT NULL 值表示空字符串。 你是对的。我说话没有考虑清楚。

以上是关于sql server 条件的主要内容,如果未能解决你的问题,请参考以下文章

将 Crystal Reports 条件转换为 SQL Server 条件

SQL Server:条件聚合;

SQL Server 条件流

SQL Server - 条件语句的查询执行计划

SQL Server中如果查询条件为空,则查询全部,如何实现?

SQL server如何查询满足条件的前3数据