2017-09-25 87 views
0

我需要關於SQL Server 2012中用於檢查輸入值的函數的幫助。如果函數檢測到數字,則返回0,如果檢測字符返回1。在函數中傳遞值而不引用T-SQL/SQL Server 2012?

但是,對於通過引號和沒有引號的相同數字,我得到2個不同的結果。

select dbo.IS_ALIEN('56789') 

返回0

select dbo.IS_ALIEN(56789) 

返回1(我需要返回0)

這是我的函數:

ALTER FUNCTION [dbo].[IS_ALIEN] 
    (@alienNAIC CHAR(1)) 
RETURNS NUMERIC(10,0) 
AS 
BEGIN 
    DECLARE @nNum NUMERIC(1,0); 

    BEGIN 
     SET @NnUM = ISNUMERIC(@alienNAIC) 
    END 
    BEGIN 
     IF @nNum = 1 
      RETURN 0; 
     END 

     RETURN 1; 
    END 

相同的概念爲:

select dbo.IS_ALIEN('AA-11990043') 

返回1

select dbo.IS_ALIEN(NULL) 

返回1(我需要它返回0)

我使用Oracle函數的引用(下面的代碼是剛剛從舊數據庫引用):

create or replace FUNCTION "IS_ALIEN" 
    ( alienNAIC IN char) 
    RETURN NUMBER IS 
    nNum number; 
BEGIN 
    SELECT MOD(alienNAIC, 2) into nNum FROM dual; 
    return 0; 
EXCEPTION 
WHEN INVALID_NUMBER THEN 
    return 1; 
END; 

但T-SQL函數不允許發生異常的異常。所以我儘量轉換得更接近。

+1

提示:在管理工作室運行'SELECT CAST(56789 As CHAR(1))'並檢查結果。這是Sql Server甚至在任何代碼運行之前轉換爲參數類型的問題。這聽起來像你需要使用'sql_variant'類型來解決問題,這不是一件容易的事情。 –

+0

ahh我得到一個星號(*) –

+1

總是使用標籤指定服務器的版本。如果您使用的是2008及更高版本,則可以使用ISNUMERIC功能。順便說一句,當你將@alienNAIC char(1)定義爲參數時,它只需要輸入的第一個字符。 – FLICKER

回答

2

我建議你使用這樣的事情(我修剪下來有點):

ALTER FUNCTION [dbo].[IS_ALIEN](@alienNAIC NVARCHAR(10)) 
RETURNS INT -- NOTE: You could also return tinyint or bit 
AS 
BEGIN 
    IF ISNUMERIC(@alienNAIC) = 1 
     RETURN 0; 

    RETURN 1; 
END 

與您試圖什麼麻煩的是,有一個隱式轉換爲CHAR(1),其結果肯定是不像@Joel指出的那樣:

SELECT CAST(0 As CHAR(1)) -- returns character '0', ISNUMERIC(0) = 1 
SELECT CAST(9 As CHAR(1)) -- returns character '9', ISNUMERIC(0) = 1 
SELECT CAST(12345 As CHAR(1)) -- any number over 9 returns character '*', ISNUMERIC(12345) = 0 

這是一個奇怪的隱式鑄造案例,我以前沒有見過。通過使參數爲NVARCHAR(假設未來可能會有雙字節輸入),將正確檢查字符串,並且傳入的整數將被隱式轉換爲NVARCHAR,並且ISNUMERIC檢查將成功。

編輯 重讀的問題和意見,它看起來像你想找出一個特定的字符串語法來確定,如果事情是一個「異類」與否。如果你是舒服不斷變化的業務邏輯來解決什麼顯然是一個貧窮的遺產執行,你可以考慮這樣的事情,而不是:

ALTER FUNCTION [dbo].[temp](@alienNAIC NVARCHAR(10)) 
RETURNS INT -- NOTE: You could also return tinyint or bit 
AS 
BEGIN 
    IF @alienNAIC like 'AA-%' AND ISNUMERIC(RIGHT(@alienNAIC, LEN(@alienNAIC) - 3)) = 1 
     RETURN 1; -- notice this is now 1 instead of 0, we're doing a specific check for 'AA-nnnnn...' 

    RETURN 0; 
END 

注意,這對傳統的數據進行徹底的測試,如果這是有史以來互動與它 - 你永遠不知道遺留系統遺留下來的垃圾數據。解決這個問題很可能會破壞其他事情。如果你確實做了這個改變,記錄一下。

+0

感謝您對此修復的更改。這是我正在尋找的。 –

1

如果您需要檢查只是第一個字符,那麼你可以做這樣的:

CREATE FUNCTION [dbo].[IS_ALIEN] 
    (@alienNAIC VARCHAR(200)) 
RETURNS TINYINT 
AS 
BEGIN 
    IF LEFT(@alienNAIC,1) BETWEEN '0' AND '9' RETURN 1; 
    RETURN 0 
END 
GO 
0

好像你正在嘗試檢查一個字符串是否以非數字字符開頭。這種模式匹配可以使用LIKE進行,例如

declare @var nvarchar(10)='A56789' 

select 
    case when @var LIKE '[0-9]%' 
     then 0 else 1 
    end AS IsAlien 

返回

1 

兩個declare @var nvarchar(10)=56789declare @var int=56789返回0,因爲數目隱式轉換爲字符串。

該表達式非常短,您可能不需要將其轉換爲函數。如果你這樣做,它可能是簡單的:

create FUNCTION [dbo].[IS_ALIEN] (@alienNAIC varchar(200)) 
RETURNS INT 
begin 
    return case when @alienNAIC LIKE '[0-9]%' 
          then 0 else 1 
         end 

end 

如果你想在WHERE子句中執行檢查,只需用LIKE,沒有任何功能,例如:

WHERE alienNAIC NOT LIKE '[0-9]%' 

這種特殊的模式只是範圍搜索,涵蓋09......之間的所有值。服務器可以使用覆蓋文本列的索引來快速識別匹配。當它必須檢查函數的結果時,它不能這樣做。它必須在過濾之前計算每一行的值。

相關問題