Sql server 使用存储过程作为列的默认值

Sql server 使用存储过程作为列的默认值,sql-server,Sql Server,我试图使用存储过程作为列的默认值。它叫“dbo.GetAdmin” 基本上,此存储过程查找用户id“admin”,如果它不存在,SP将插入它,然后将其作为用户记录返回 现在,我想将此SP用作以下列的默认值: ALTER TABLE [dbo].[Transaction] ADD CONSTRAINT [DF_Transaction_From] DEFAULT ([dbo].[GetAdmin]) FOR [From] 但我得到了这个错误: 在此上下文中不允许使用名称“dbo.GetAdmi

我试图使用存储过程作为列的默认值。它叫“dbo.GetAdmin”

基本上,此存储过程查找用户id“admin”,如果它不存在,SP将插入它,然后将其作为用户记录返回

现在,我想将此SP用作以下列的默认值:

ALTER TABLE [dbo].[Transaction] ADD  CONSTRAINT [DF_Transaction_From]  DEFAULT ([dbo].[GetAdmin]) FOR [From]
但我得到了这个错误:

在此上下文中不允许使用名称“dbo.GetAdmin”。有效表达式是常量、常量表达式和(在某些上下文中)变量。不允许使用列名

在这篇相关文章中,一位用户告诉我们必须使用函数而不是存储过程:

因为允许用户定义函数作为列的默认值

但根据函数的文档:

函数是计算值,不能对SQL Server执行永久性环境更改(即不允许使用
INSERT
UPDATE
语句)


因此,因为如果用户不存在,我必须插入它,所以我必须使用存储过程而不是函数。如何解决此问题?

如果必须这样做,插入触发器将允许此操作。我假设如果有人插入多条记录,则insert中每条记录的Admin值不会改变。否则,将需要一个循环来执行每个记录的过程。在做这件事之前,我会认真考虑其他选择。这可能是为了保持一致性。根据过程正在执行的操作,可以通过将过程代码拉入触发器,在触发器中执行基于集合的查询

例如,触发器代码可能类似于

SET NOCOUNT ON

IF NOT EXISTS(SELECT * FROM inserted) RETURN -- no inserted records (where clause)

DECLARE @AdminId int -- the same value for all records inserted by statement
EXECUTE @AdminId = [dbo].[GetAdmin]

IF @AdminId IS NULL RETURN -- don't bother updating NULL to NULL

UPDATE t
SET [From] = @AdminId
FROM [dbo].[Transaction] t
INNER JOIN inserted i.record_key = t.record_key -- match each inserted to itself uniquely
WHERE i.[From] IS NULL -- no value was provided upon insert

RETURN
此外,从触发器调用过程时,错误处理可能很棘手


如果您的DBA可以根据请求在SSMS中插入记录,而不提供ADMIN值,那么您可能不需要它。

您必须重新考虑您的设计……我实际上正在设计数据库,因此我可以重新考虑设计,但如何重新考虑?我将使用存储过程来将所有插入到该表中的内容,如果缺少新用户,SP可以创建新用户。将这种逻辑更贴近应用程序,而不是深入数据库。如果一个名为
Get(something)
的方法或存储过程突然开始产生改变状态的副作用,比如将行插入表中,我总是发现这是非常危险的。这与最小惊喜原则背道而驰——当我得到
get(something)
时,我的期望是它只得到值——永远不会改变任何值!(或插入新的)好的,我明白了。谢谢你的帮助!