Microsoft SQL Server-存储过程提供的默认值

时间:2018-06-27 13:39:01

标签: sql sql-server tsql sql-server-2014

是否可能有一个非null列,其中通过调用存储过程(其参数是传递给插入行的值)的存储过程在插入时生成值?

例如,我有表User

| username | name | surname | id |

插入看起来像这样:

INSERT INTO USER (username, name, surname) 
VALUES ('myusername', 'myname', 'mysurname');

id列中填充了一个(整数)值,该值是通过使用参数mystoredprocmyusernamemyname调用存储过程mysurname来检索的。

另一个问题是,该存储过程是在每一行上调用还是以分组的方式调用?例如,我希望存储过程采用name并在其中附加一个随机整数,这样,如果我插入100个名称为“ David”的用户,他们将得到相同的id并且存储过程将仅被调用一次。第二点有点不好的例子。

2 个答案:

答案 0 :(得分:2)

美好的一天,

  
    

是否可能有一个非null列,其中通过调用存储过程在插入时生成值

  

选项1:请检查是否适合您

  1. 为列指定默认值,并使用“ NOT NULL”
  2. 在插入后的表上创建触发器
  3. 在触发器内部,您可以使用“插入”虚拟表来获取插入的值。
  4. 使用这些值(使用插入的表),您可以一次使用所有行所需的逻辑来更新列

**可能不需要使用外部SP,但是如果需要,您可以从触发器执行SP

**触发器执行的所有操作与原始查询都在同一事务中。

  
    

是否将在每一行上调用此存储过程

  

不!对于您在同一条语句中插入的所有行,触发器将一次执行。插入的表包括所有已插入的行。在更新部分(第4步)中,您可以更新插入一次的所有行,而无需为每行执行某些操作

**如果您确实使用从触发器执行的外部SP,则可以将所有插入的表作为一个using Table-Valued Parameter

传递给它。

-------------------更新---------------

以下是使用此逻辑的完整示例:

drop table if exists T;
CREATE TABLE T (id int identity(2,2), c int NOT NULL default 1)
GO

CREATE TRIGGER tr ON T AFTER INSERT
AS BEGIN
    SET NOCOUNT ON;

    UPDATE T SET T.c = T2.C + 1
    FROM inserted T2
    INNER JOIN T T1 ON T1.id = T2.id

END

INSERT T(c) values (1) -- I insert the value 1 but the trigger will change it to 1+1=2
select * from T
GO

-- test multiple rows:
INSERT T(c) values (10),(20),(30),(40)
select * from T
GO

答案 1 :(得分:-1)

DECLARE @rc INT = 0,
  @UserID INT = ABS(CHECKSUM(NEWID())) % 1000000 + 1;

WHILE @rc = 0
BEGIN
  IF NOT EXISTS (SELECT 1 FROM dbo.Users WHERE UserId= @UserId)
  BEGIN
    INSERT dbo.Users(UserId) WHERE Username = @UserName SELECT @UserId;
    SET @rc = 1; 
  END
  ELSE
  BEGIN
    SELECT @UserId = ABS(CHECKSUM(NEWID())) % 1000000 + 1,
      @rc = 0;
  END
END