เป็นวิธีที่ถูกต้องเพื่อให้แน่ใจว่ารายการที่ไม่ซ้ำกันในการออกแบบฐานข้อมูลชั่วคราวคืออะไร?


10

ฉันมีปัญหากับการออกแบบฐานข้อมูลชั่วคราว ฉันจำเป็นต้องรู้วิธีการตรวจสอบให้แน่ใจว่าฉันมีบันทึกการใช้งานเพียงหนึ่งเดียวสำหรับระยะเวลาที่กำหนดสำหรับร้านค้า ฉันได้อ่านคำตอบนี้แล้ว แต่ฉันเกรงว่าฉันไม่สามารถคาดหัวได้ว่าไกทำงานอย่างไร โดยเฉพาะอย่างยิ่งฉันจะทำงานที่กระตุ้นให้มีอยู่ของฉันที่ป้องกันการปรับปรุงเพื่อบันทึกและแทรกบันทึกใหม่แทน ปัญหาที่แท้จริงของฉันคือฉันไม่รู้วิธีป้องกัน Store จากวันที่มีผลมากกว่าหนึ่งวันเมื่อวันที่เสร็จสิ้นเป็นโมฆะ (เช่นป้องกันการบันทึก 2 รายการสำหรับร้านค้า)

นี่คือสิ่งที่ฉันมี แต่มันช่วยให้ฉันสามารถแทรกบันทึกใหม่สำหรับร้านค้าที่มีวันที่มีประสิทธิภาพที่แตกต่างกัน

นิยามของตาราง:

/****** Object:  Table [PCR].[Z_STORE_TEAM]    Script Date: 05/09/2014 13:05:57 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Z_STORE_TEAM]') AND type in (N'U'))
DROP TABLE [Z_STORE_TEAM]
GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Z_STORE_TEAM]') AND type in (N'U'))
BEGIN
CREATE TABLE [Z_STORE_TEAM](
    [STORENUM] [int] NOT NULL,
    [TEAM] [varchar](10) NULL,
    [EFFECTIVE] [date] NOT NULL,
    [FINISHED] [date] NULL,
PRIMARY KEY CLUSTERED 
(
    [STORENUM] ASC,
    [EFFECTIVE] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

ข้อมูลตัวอย่าง:

INSERT [Z_STORE_TEAM] ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) VALUES (1, N'1', CAST(0x01380B00 AS Date), CAST(0x81380B00 AS Date))
INSERT [Z_STORE_TEAM] ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) VALUES (1, N'2', CAST(0x81380B00 AS Date), NULL)
INSERT [Z_STORE_TEAM] ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) VALUES (2, N'1', CAST(0x01380B00 AS Date), NULL)
INSERT [Z_STORE_TEAM] ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) VALUES (2, N'2', CAST(0x20380B00 AS Date), NULL)

แทนที่จะอัพเดททริกเกอร์:

CREATE TRIGGER [tr_ZStoreTeam_update] 
   ON  [Z_STORE_TEAM]
   INSTEAD OF UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here
    INSERT INTO PCR.Z_STORE_TEAM(STORENUM,TEAM,EFFECTIVE)
    SELECT I.STORENUM,I.TEAM,GETDATE() AS EFFECTIVE
    FROM inserted I
    INNER JOIN PCR.Z_STORE_TEAM ST
        ON I.STORENUM = ST.STORENUM

    UPDATE ST
    SET FINISHED = GETDATE()
    FROM PCR.Z_STORE_TEAM ST
    INNER JOIN inserted I
        ON ST.STORENUM = I.STORENUM
        AND ST.EFFECTIVE = I.EFFECTIVE
END

GO

คำตอบ:


13

วิธีที่ปลอดภัยที่สุดที่จะทำคือการบังคับใช้กฎเกณฑ์ทางธุรกิจของคุณโดยใช้ built-in จำกัด มี Referential Integrity เป็นอเล็กซานเดคัซอธิบายในบทความของเขา, "การจัดเก็บช่วงเวลาที่ไม่มีการทับซ้อน"

การใช้เทคนิคที่ระบุไว้ที่นั่นกับผลลัพธ์ของตารางตัวอย่างในสคริปต์ต่อไปนี้:

CREATE TABLE [Z_STORE_TEAM](
    [STORENUM] [int] NOT NULL,
    [TEAM] [varchar](10) NULL,
    [EFFECTIVE] [date] NOT NULL,
    [FINISHED] [date] NULL,
    PRIMARY KEY CLUSTERED 
    (
        [STORENUM] ASC,
        [EFFECTIVE] ASC
    )
) ON [PRIMARY];

INSERT [Z_STORE_TEAM] 
    ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) 
VALUES 
    (1, N'1', CAST(0x01380B00 AS Date), CAST(0x81380B00 AS Date)),
    (1, N'2', CAST(0x81380B00 AS Date), NULL),
    (2, N'1', CAST(0x01380B00 AS Date), NULL);

แก้ไข:

-- New column to hold the previous finish date
ALTER TABLE dbo.Z_STORE_TEAM 
ADD PreviousFinished date NULL;
GO
-- Populate the previous finish date
UPDATE This
SET PreviousFinished = Previous.FINISHED
FROM dbo.Z_STORE_TEAM AS This
CROSS APPLY
(
    SELECT TOP (1) 
        Previous.FINISHED
    FROM dbo.Z_STORE_TEAM AS Previous
    WHERE 
        Previous.STORENUM = This.STORENUM
        AND Previous.FINISHED <= This.EFFECTIVE
    ORDER BY 
        Previous.FINISHED DESC
) AS Previous;
GO
ALTER TABLE dbo.Z_STORE_TEAM 
ADD CONSTRAINT UQ_STORENUM_PreviousFinished
UNIQUE (STORENUM, PreviousFinished);
GO
ALTER TABLE dbo.Z_STORE_TEAM
ADD CONSTRAINT CK_PreviousFinished_NotAfter_Effective
CHECK (PreviousFinished = EFFECTIVE);
GO
ALTER TABLE dbo.Z_STORE_TEAM
ADD CONSTRAINT UQ_STORENUM_FINISHED
UNIQUE (STORENUM, FINISHED);
GO
ALTER TABLE dbo.Z_STORE_TEAM
ADD CONSTRAINT FK_STORENUM_PreviousFinished
FOREIGN KEY (STORENUM, PreviousFinished)
REFERENCES dbo.Z_STORE_TEAM (STORENUM, FINISHED);
GO
ALTER TABLE dbo.Z_STORE_TEAM
ADD CONSTRAINT CK_EFFECTIVE_Before_FINISHED
CHECK (EFFECTIVE < FINISHED);

ความพยายามที่จะแทรกแถวที่สี่ของข้อมูลตัวอย่างล้มเหลวในขณะนี้ด้วยข้อความแสดงข้อผิดพลาด:

INSERT [Z_STORE_TEAM] 
    ([STORENUM], [TEAM], [EFFECTIVE], [FINISHED]) 
VALUES 
    (2, N'2', '20140201', NULL);

ข้อความผิดพลาด

โปรดอ่านบทความของ Alex เพื่อทำความเข้าใจว่าข้อ จำกัด เหล่านี้ช่วยให้มั่นใจว่าข้อมูลตารางของคุณจะถูกต้องได้ตลอดเวลา การมีข้อ จำกัด บังคับใช้ความถูกต้องของข้อมูลหมายความว่าไม่จำเป็นต้องใช้รหัสทริกเกอร์

บทความที่เกี่ยวข้องโดยผู้เขียนคนเดียวกัน:

การแก้ไขช่วงเวลาต่อเนื่องในตารางประวัติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.