禁止插入具有默认约束的行

时间:2016-11-11 08:32:40

标签: sql sql-server triggers sql-server-2016

有没有办法阻止在表中的指定列中插入数据并仅使用默认(约束)值?

E.g。我有专栏:

LogInsert (DF GETDATE())
LogUser   (DF ORIGINAL_LOGIN())

都使用DEFAULT约束定义。我不想允许用户插入这些列,但在插入新行时使用默认值。

这会引起错误。

INSERT  INTO T1
        ( C1
        ,C2
        ,LogInsert
        ,LogUser
        )
VALUES  ( 'A'
        ,'B'
        ,'20160101 10:53'
        ,'domain\user'
        );

用户应该能够毫无错误地执行以下脚本。

INSERT  INTO T1
        ( C1, C2 )
VALUES  ( 'A', 'B' );

2 个答案:

答案 0 :(得分:2)

您始终可以为用户提供工作视图而不是表格。然后,您可以选择完全隐藏列,或者(如此处)使它们计算,以便它们不能通过视图将值插入到列中:

create table dbo._T1 (
    ID int IDENTITY(1,1) not null,
    Inserted datetime2 constraint DF__T1_Inserted DEFAULT (SYSDATETIME()) not null,
    ABC varchar(10) not null,
    constraint PK__T1 PRIMARY KEY (ID)
)
go
create view dbo.T1
with schemabinding
as
    select
        ID,
        COALESCE(Inserted,SYSDATETIME()) as Inserted,
        ABC
    from dbo._T1
go
insert into dbo.T1 (ABC) values ('abc')
go
insert into dbo.T1 (ABC,Inserted) values ('def',SYSDATETIME())

结果:

(1 row(s) affected)

Msg 4406, Level 16, State 1, Line 19
Update or insert of view or function 'dbo.T1' failed because it contains a derived or constant field.

所有用户查询都继续使用T1。它恰好是一个观点,而不是一张桌子。

在上面,视图使用COALESCE(Inserted,SYSDATETIME())。这里使用的内容并不重要,并且它不需要匹配,例如默认定义。所有重要的是某些计算在Inserted列上执行,以便它成为视图中的只读列。

答案 1 :(得分:0)

您可以在表格上创建一个Check Constraint,例如下面的

CREATE TABLE [dbo].[T1]
(
     [C1] VARCHAR(50)
    ,[LogInsert] DATETIME DEFAULT GETDATE()
    ,[LogUser] VARCHAR(500) DEFAULT ORIGINAL_LOGIN()
)

ALTER TABLE [T1]  WITH CHECK ADD  CONSTRAINT [CK_T1_LogInsert] CHECK ([LogInsert] = GETDATE())
ALTER TABLE [T1]  WITH CHECK ADD  CONSTRAINT [CK_T1_LogUser] CHECK ([LogUser] = ORIGINAL_LOGIN())


INSERT INTO [dbo].[T1] ([C1]) VALUES ('A')
INSERT INTO [dbo].[T1] ([C1]) VALUES ('B')
INSERT INTO [dbo].[T1] ([C1]) VALUES ('C')

SELECT * FROM [dbo].[T1]

--Will Fail
INSERT INTO [dbo].[T1] ([C1],[LogInsert]) VALUES ('D','2016-11-11 00:00')
INSERT INTO [dbo].[T1] ([C1],[LogUser]) VALUES ('D','Not Your UserName')

OR

您可以强制用户仅使用存储过程进行插入,而不允许将其作为参数进行插入,对于批量插入,也可以使用表变量。

相关问题