Sql server 在具有限制的表中插入记录

Sql server 在具有限制的表中插入记录,sql-server,constraints,Sql Server,Constraints,我使用sql server和如下表: MyTbale(ID int IDENTITY, Type Char(1), ParentId int) 我想限制我的用户插入第一条记录时使用的ParentId类型为'O',并且可以插入其他记录时使用的ParentId类型为每种类型。换句话说,如果用户想要插入ParentId=10的记录,必须将Type设置为'O',然后可以插入ParentId=10的每个类型 样本数据: Id Type ParentId 1 O 10 2

我使用sql server和如下表:

MyTbale(ID int IDENTITY, Type Char(1), ParentId int)
我想限制我的用户插入第一条记录时使用的ParentId类型为'O',并且可以插入其他记录时使用的ParentId类型为每种类型。换句话说,如果用户想要插入ParentId=10的记录,必须将Type设置为'O',然后可以插入ParentId=10的每个类型

样本数据:

Id     Type  ParentId
1      O     10
2      I     10
3      I     10
4      M     10
5      N     10
6      O     12
7      M     12
8      I     12
这个问题的最佳解决方案是什么?我认为可以将约束与UDF和触发器一起使用

编辑

通过以下格式,我可以添加检查约束:

Create FUNCTION [dbo].[f](@Id INT, @Date DATE) RETURNS BIT 
AS BEGIN
    DECLARE @R BIT = CASE WHEN EXISTS(SELECT Date FROM MyTable WHERE Date=@Date AND Id!=@Id) THEN 1 ELSE 0 END
    RETURN @R
END
GO

ALTER TABLE [dbo].[MyTable]  WITH CHECK ADD  CONSTRAINT [CK_test] CHECK  (([dbo].[F]([Id],[Date])=(0)))
通过以下查询,我可以为检查数据添加触发器:

CREATE TRIGGER dbo.tr_MyTable ON dbo.MyTable
INSTEAD OF INSERT
AS BEGIN
    IF EXISTS(SELECT * 
              FROM Inserted i
              LEFT JOIN MyTable t ON t.ParentId = i.ParentId AND t.Type = 'O'
              WHERE i.Type <> 'O'
                    AND t.Id IS NULL) BEGIN
        RAISERROR('Type must be equal to O in first row',16,1)
    END
    INSERT INTO dbo.MyTable(Type,ParentId)
    SELECT Type, ParentId
    FROM Inserted
END

而不是触发器将是一条出路。此外,如果您不需要返回错误信息,您可能会通过此稍加修改的建议获得一些性能:

CREATE TRIGGER dbo.tr_MyTable ON dbo.MyTable
INSTEAD OF INSERT
AS BEGIN

    INSERT INTO dbo.MyTable(Type,ParentId)
    SELECT Type, ParentId
    FROM Inserted
    LEFT JOIN MyTable t ON t.ParentId = i.ParentId AND t.Type = 'O'
              WHERE i.Type <> 'O'
                    AND t.Id IS NULL

您绝对不能对此使用检查约束。我认为扳机是最好的选择。我编辑我的问题。我可以使用约束和触发器,但正在寻找最佳解决方案。您的条件错误,您必须使用I.Type='O'或t。Id不为null。