2010-02-26 90 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

你是對的。我沒有想到所有的事情都會說。 –