2011-03-04 268 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;