2010-02-26 57 views
0

我在运行此查询时遇到错误,因为数据类型money无法隐式转换为varchar。但是,在尝试转换之前,我正在使用if语句来确保数据类型不是金钱。显然,转换正在执行。有人知道为什么sql服务器条件

表: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
从数据类型的钱为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 '''[email protected]+'''= ''money'' 
begin 
    if (select max(['[email protected]+']) from ['[email protected]+']) = 0 
     and (select min(['[email protected]+']) from ['[email protected]+']) = 0 
    print '' '[email protected]+' money'' 
end 

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

何时字面上的字符串'钱'不会自己平等? – dnord

+0

此代码是动态生成的。它通常不是'钱'!='钱',它使用当前列数据类型。即如果'varchar'!='钱'。 我用这个例子是因为它试图告诉我,因为它正在执行下一行,实际上'钱'!='钱' – Colin

+0

所以*提供的*代码实际上是生成并产生了错误?我在SSMS 2008中运行它,它运行时没有缺陷。 –

回答

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(['[email protected]+']) from ['[email protected]+']) = 0 
     and (select min(['[email protected]+']) from ['[email protected]+']) = 0 
    print '' '[email protected]+' 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 ['[email protected]+'] 
    HAVING MAX(['[email protected]+']) = 0 
    AND MIN(['[email protected]+']) = 0)) 
BEGIN 
    PRINT '' '[email protected]+' '' 
END'; 
ELSE 
    SELECT @hold = 'IF(NOT EXISTS(
    SELECT * 
    FROM ['[email protected]+'] 
    WHERE ['[email protected]+'] IS NOT NULL 
    AND LEN(['[email protected]+']) > 0)) 
BEGIN 
    PRINT '' '[email protected]+' '' 
END'; 
+0

谢谢,我没有意识到错误来自于编译vs在运行时 – Colin

0

一些提示,以优化发电机

重写

SELECT @hold = 
'if '''[email protected]+'''= ''money'' 
begin 
... 
end 

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

其次,我想不出的情况下,当

[rebate2] IS NOT NULL 

并不意味着

len(CONVERT(VARCHAR(8000), [rebate2])) > 0 
换句话说

,只要rebate2不为空,它的字符串长度大于0

+0

“换句话说,只要rebate2不是NULL,它的字符串长度就会更大0”不,SQL Server会在空字符串'和空值。 –

+0

@ Shannon Severance MONEY NOT NULL值作为表示空字符串。 – devio

+0

你是对的。我没有想到所有的事情都会说。 –