0

最初に、この非常によく似た質問を確認してください: SQL Server 2008 の一意の日付範囲フィールド

上記の質問に対する答え ( David Hallによる) は、1 つの小さな省略で必要なものの 90% です。次の例を見てください。

--#### Create example table
CREATE TABLE [dbo].[tbl_Example](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [StockCode] [varchar](20) NOT NULL,
    [ValidFrom] [datetime] NOT NULL,
    [ValidUntil] [datetime] NOT NULL,
    [Type] [char](1) NOT NULL,
 CONSTRAINT [PK_tbl_Example] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

--#### Add the trigger (based on David Halls answer - I allow duplicate date ranges as long as the StockCode or Type differ)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[DateRangeTrigger] ON [dbo].[tbl_Example]
    FOR INSERT, UPDATE
AS
    BEGIN
        IF EXISTS ( SELECT  t.ValidFrom ,
                            t.ValidUntil
                    FROM    tbl_Example t
                            JOIN inserted i ON ( i.StockCode = t.StockCode
                                                 AND i.Type = t.Type
                                                 AND i.ValidFrom > t.ValidFrom
                                                 AND i.ValidFrom < t.ValidUntil
                                                 AND i.id <> t.id
                                               )
                                               OR ( i.StockCode = t.StockCode
                                                    AND i.Type = t.Type
                                                    AND i.ValidUntil < t.ValidUntil
                                                    AND i.ValidUntil > t.ValidFrom
                                                    AND i.id <> t.id
                                                  )
                                               OR ( i.StockCode = t.StockCode
                                                    AND i.Type = t.Type
                                                    AND i.ValidFrom < t.ValidFrom
                                                    AND i.ValidUntil > t.ValidUntil
                                                    AND i.id <> t.id
                                                  ) ) 
            BEGIN
                RAISERROR ('Date range cant overlap existing date ranges for given StockCode and Type', 16, 1)
                IF ( @@TRANCOUNT > 0 ) 
                    ROLLBACK
            END
    END
GO

--#### Problem: its allowing duplicate date ranges where Start and End Dates are 100% equal
INSERT [dbo].[tbl_Example] ([StockCode], [ValidFrom], [ValidUntil], [Type]) VALUES (N'Test', CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'O')
INSERT [dbo].[tbl_Example] ([StockCode], [ValidFrom], [ValidUntil], [Type]) VALUES (N'Test', CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'O')

[ValidFrom]Dave のトリガーを使用すると、または[ValidUntil]等しい場合、重複する日付を挿入できることに注意してください。

OR一致する開始または一致する終了または両方を考慮して、トリガーにさらに多くの句を追加する以外に、この最後の句を防ぐためにトリガーを微調整する最も簡単な方法は何ですか?

明確にするために、私が防止しようとしている重複は次のとおりです。

赤の 2 つの色合いが異なる行であると仮定します。

4

1 に答える 1

4

この条件の方が適切だと思います。

IF EXISTS ( SELECT  * --No need to choose columns in an EXISTS
        FROM    tbl_Example t1
         inner join
                tbl_Example t2
                  on
                     t1.StockCode = t2.StockCode and
                     t1.Type = t2.Type and
                     t1.ValidFrom < t2.ValidTo and
                     t2.ValidFrom < t1.ValidTo and
                     t1.ID <> t2.ID
        where
            t1.ID in (select ID from inserted))
BEGIN
     RAISERROR ('Date range cant overlap existing date ranges for given StockCode and Type', 16, 1)
     ROLLBACK --We're in a trigger, we *must* be in a transaction
END

オーバーラップを検出するためのより単純な条件を使用します。つまり、両方の行がもう一方の行が終了する前に開始する場合にオーバーラップが存在します。

于 2013-05-15T14:42:06.823 に答える