2011-03-04 263 views
6

我有一個數據庫表我試圖做一個UPDATE/INSERT與存儲過程。讓我們來定義,像這樣的表:存儲過程NULL參數

CREATE TABLE Foo 
(
    Id   INT    IDENTITY(1, 1), 
    Name   VARCHAR(256) NOT NULL, 
    ShortName VARCHAR(32), 
    Sort   INT 
); 

我寫類似下面的存儲過程:

CREATE PROCEDURE Put_Foo 
(
    @Id   INT    = NULL OUTPUT, 
    @Name   VARCHAR(256), 
    @ShortName VARCHAR(32)  = NULL, 
    @Sort   INT    = NULL 
) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT 
     @Id = F.Id 
    FROM 
     Foo AS F 
    WHERE 
     F.Name = @Name; 

    IF (@Id IS NOT NULL) 
    BEGIN 
     UPDATE 
      Foo 
     SET 
      ShortName = @ShortName, 
      Sort   = @Sort 
     WHERE 
      Id = @Id; 
    END 
    ELSE 
    BEGIN 
     INSERT 
     INTO Foo 
     (
      Name, 
      ShortName, 
      Sort 
     ) 
     VALUES 
     (
      @Name, 
      @ShortName 
      @Sort 
     ); 

     SET @Id = SCOPE_IDENTITY(); 
    END 

    RETURN; 
END; 

我已經大大簡化了我處理的數據結構,但我希望這成爲我的點。我的問題是關於如何處理參數。有沒有一種方法可以在程序中確定@Sort是否作爲NULL傳入,或者通過參數列表中的默認聲明設置NULL?

編輯:

這樣做的目的是,我不想NULL參數來覆蓋所有列在UPDATE語句,除非它們被以這種方式明確傳遞。

+0

爲什麼不讓列沒有默認值? – 2011-03-07 21:22:06

回答

6

不,您無法檢測到@Sort如何變爲NULL。如果您的目標是在明確設置時捕獲,而不是默認設置,我會建議使用不同的默認值(可能是通常不會使用的值,如-1)。然後你可以假設如果@Sort是NULL,它顯式傳入,但是如果它是-1,你知道它是默認設置的。

+0

這可以工作,但我想能夠推廣到多個程序和參數。最終目標是我不希望NULL值以這種方式顯式傳遞,以便在更新達到時覆蓋列。 – rpf3 2011-03-04 20:14:05

+0

如果SQL支持重載過程,則可以創建2個版本的sproc,1與param,另一個不帶。唉,這是不可能的。 – 2011-03-04 20:19:27

+0

我知道......我試圖避免在每個表格中創建具體情況的多個過程 – rpf3 2011-03-04 20:27:02

0

取出默認值,然後將代碼調用PROC必須提供一個值(實值或NULL)

+0

雖然我不想總是要傳遞參數。例如,如果我從試圖僅基於名稱創建Foo的頁面調用Put_Foo,則它將覆蓋ShortName和Sort(如果已存在具有相同名稱的Foo)。 – rpf3 2011-03-04 20:34:10

+0

@rpf:如果它創建了* Foo,爲什麼會覆蓋它?我明白,創建=插入,不是嗎? – 2011-03-04 21:48:05

2

我覺得這是你在找什麼。如果其中一個參數爲空,它將使用數據庫中的值進行更新。另一種選擇是每次更新一列。

UPDATE Foo   
SET    
     ShortName = ISNULL(@ShortName, ShortName) 
    , Sort = ISNULL(@Sort, Sort) 
WHERE Id = @Id;