SQL服务器条件

时间:2010-02-26 19:30:21

标签: sql sql-server sql-server-2008

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

表:BBH_NEW col: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

错误:
Msg 257,Level 16,State 3,Line 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'

2 个答案:

答案 0 :(得分:2)

据我所知,当您收到错误时,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';

答案 1 :(得分:0)

优化发电机的一些提示

重写

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

as

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

其次,我不能想到

时的情况
[rebate2] IS NOT NULL

并不意味着

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

换句话说,只要rebate2不为NULL,其字符串长度就会大于0