【问题标题】:Microsoft SQL Server - default value provided by stored procedureMicrosoft SQL Server - 存储过程提供的默认值
【发布时间】:2018-12-06 10:31:06
【问题描述】:

是否可以有一个非空列,通过调用存储过程在插入时生成值,该存储过程的参数是传递给插入行的值?

例如,我有表User

| username | name | surname | id |

插入看起来像这样:

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

id 列填充了一个(整数)值,该值是通过调用存储过程 mystoredproc 检索到的,参数为 myusernamemynamemysurname

另一个问题是,这个存储过程是在每一行上调用,还是以分组方式调用。例如,我希望我的存储过程采用 name 并向其附加一个随机整数,这样如果我插入 100 个名为“David”的用户,他们将获得相同的 id 和存储过程只会被调用一次。关于第二点的一个坏例子。

【问题讨论】:

  • 这种方式一次只能插入一行。
  • 如何定义列id?我不记得如何为主键定义自定义逻辑,而不是自动递增,调用存储过程。我需要谷歌做什么?虽然,id 列不一定是主键,在我的扩展中,当然不能是主键。
  • 你是什么意思“你会如何定义它”?你说它是一个整数。它还需要什么定义?
  • 如果使用函数而不是存储过程,可以在默认约束中调用函数:dba.stackexchange.com/questions/163714/…

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


【解决方案1】:

早安,

是否可以在插入时通过调用存储过程生成值的非空列

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

  1. 为列指定默认值并使用“NOT NULL”
  2. 在插入后的表上创建触发器
  3. 在触发器内部,您可以使用“inserted”虚拟表来获取插入的值。
  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

【讨论】:

  • 我同意其他 cmets 的观点,即这种情况听起来像是一个糟糕的设计。这个解决方案回答了这个问题,但我强烈建议您考虑重新设计系统,这样您就不需要有这个要求了
【解决方案2】:
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

【讨论】:

  • 我不知道这样的“插入.....在哪里”。这是伪代码吗?但更重要的是,我不确定这如何满足要求...... OP 想知道如何添加基于单个插入中的其他列更新一列的逻辑。
猜你喜欢
  • 2015-11-12
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 2013-05-09
相关资源
最近更新 更多