简体   繁体   English

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

[英]Microsoft SQL Server - default value provided by stored procedure

Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure the parameters of which are values passed to insert into the row? 是否可以有一个非null列,其中通过调用存储过程(其参数是传递值以插入到行中)的存储过程在插入时生成值?

For example, I have table User : 例如,我有表User

| username | name | surname | id |

Insert looks like this: 插入看起来像这样:

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

The id column is populated with an (integer) value retrieved by calling stored procedure mystoredproc with parameters myusername , myname , mysurname . 通过使用参数myusernamemynamemysurname调用存储过程mystoredproc检索到的(整数)值来填充id列。

A further question is, would this stored procedure be called on each row, or can it be called in a grouped fashion. 另一个问题是,将在每一行上调用此存储过程,还是以分组的方式调用它? For example, I'd like my stored procedure to take the name and append a random integer to it so that that if I insert 100 users with the name 'David', they will get the same id and the stored procedure will be called only once. 例如,我希望存储过程采用name并在其中附加一个随机整数,这样,如果我插入100个用户名“ David”,则他们将获得相同的id ,并且存储过程将仅被调用一旦。 A bit of a bad example on the second point. 第二点有点不好的例子。

Good day, 美好的一天,

Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure 是否可以有一个非空列,其中通过调用存储过程在插入时生成值

Option 1: please check if this work for you 选项1:请检查是否适合您

  1. Specify Default Value for the Column and use "NOT NULL" 为列指定默认值,并使用“ NOT NULL”
  2. create trigger on the table AFTER INSERT 在表AFTER INSERT上创建触发器
  3. Inside the trigger, you can use the virtual table "inserted" in order to get the inserted values. 在触发器内部,可以使用“插入”虚拟表来获取插入的值。
  4. Using these values (using the inserted table) you can update the column using the logic you need for all the rows at once 使用这些值(使用插入的表),您可以一次使用所有行所需的逻辑来更新列

** there is no need to use external SP probably, but you can execute SP from trigger if needed **可能不需要使用外部SP,但是如果需要,您可以从触发器执行SP

** All executed by a trigger is in the same transaction as the original query. **触发器执行的所有操作与原始查询在同一事务中。

would this stored procedure be called on each row 将在每一行上调用此存储过程吗

NO! 没有! The trigger will be executed once for all rows you insert in the same statement. 对于在同一条语句中插入的所有行,触发器将执行一次 The inserted table includes all the rows which were inserted. 插入的表包括所有已插入的行。 In your update section (step 4) you can update all the rows which were inserted in once and no need to execute something for each row 在更新部分(第4步)中,您可以更新插入一次的所有行,而无需为每行执行任何操作

** If you do use external SP which is executed from the trigger then you can pass it all the inserted table as one using Table-Valued Parameter **如果您确实使用从触发器执行的外部SP,则可以使用表值参数将所有插入的表作为一个传递给它。

------------------- update --------------- -------------------更新---------------

Here is a full example of using this logic: 这是使用此逻辑的完整示例:

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
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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM