Sql 存储过程空参数

Sql 存储过程空参数,sql,stored-procedures,null,optional-parameters,Sql,Stored Procedures,Null,Optional Parameters,我有一个数据库表,我正试图使用存储过程对其进行更新/插入。让我们这样定义表: CREATE TABLE Foo ( Id INT IDENTITY(1, 1), Name VARCHAR(256) NOT NULL, ShortName VARCHAR(32), Sort INT ); 我编写了一个类似于以下内容的存储过程: CREATE PROCEDURE Put_Foo

我有一个数据库表,我正试图使用存储过程对其进行更新/插入。让我们这样定义表:

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语句中的任何列,除非它们以这种方式显式传递。

不,您无法检测@Sort是如何变为NULL的。如果您的目标是捕获显式设置的时间,而不是默认设置的时间,我建议使用不同的默认值(可能是通常不使用的值,如-1)。然后,您可以假设如果@Sort为NULL,则显式传入,但如果它为-1,则您知道它是默认设置的。

去掉默认值,然后调用proc的代码必须提供一个值(实值或NULL)

我想这就是您要寻找的。如果其中一个参数为null,它将使用数据库中的值进行updatedit。另一个选项是一次更新一列

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

这可能行得通,但我希望能够推广到多个过程和参数。最终目标是,如果达到更新,我不希望未以这种方式显式传递的空值覆盖列。如果SQL支持重载过程,则可以创建两个存储过程版本,一个带参数,另一个不带参数。唉,这是不可能的。我知道……我试图避免在每个表中创建多个特定于具体情况的过程。您能否提供更多关于您试图完成的内容的上下文?检测值是如何设置的并不是一个切实可行的选择。不过我不想总是传递参数。例如,如果我从一个试图仅基于名称创建Foo的页面调用Put\u Foo,它将覆盖ShortName,如果已经存在同名的Foo,它将进行排序。@rpf:如果它创建了Foo,为什么要覆盖它?我明白了,creating=inserting,不是吗?为什么不让列没有默认值呢?