2012-03-06 34 views
5

Tôi có cấu trúc bảng sau đây cho một bảng cho thuê:Tôi làm cách nào để ngăn chặn chồng chéo ngày trong SQL?

hireId int primary key 
carId int not null foreign key 
onHireDate datetime not null 
offHireDate datetime not null 

Tôi đang cố gắng để chương trình một hệ thống đa người dùng không cho phép onhire và offhire kỳ cho xe ô tô để chồng lên nhau. Tôi cần để có thể thêm thuê theo thứ tự không tuần tự. Cũng cần cho phép chỉnh sửa tuyển dụng.

Bất kỳ cách nào để hạn chế các bảng hoặc sử dụng trình kích hoạt, vv để ngăn chặn chồng chéo? Tôi đang sử dụng khuôn khổ thực thể vì vậy tôi sẽ muốn chèn vào bảng như bình thường và sau đó nếu nó không thành công ném một số ngoại lệ catchable, vv

+3

giải pháp hướng cơ sở dữ liệu duy nhất mà tôi có thể nghĩ đến là thiết lập trình kích hoạt 'INSTEAD OF', một thủ tục thực hiện kiểm tra. nhưng tôi sẽ tránh nó và kiểm tra sự chồng chéo trong mã! – vulkanino

+0

Từ quan điểm khung thực thể, tôi không nghĩ rằng tôi có thể kiểm tra dễ dàng trong mã. Tôi có thể kiểm tra tại một thời điểm nhưng có khả năng hai người thêm/chỉnh sửa sự kiện cùng một lúc – GraemeMiller

+0

Tôi nghĩ rằng khuôn khổ thực thể sẽ giúp truy cập dữ liệu dễ dàng hơn, không khó hơn! Nó là một kiểm tra đơn giản sau khi tất cả. Đồng thời là một vấn đề, bạn có thể giải quyết bằng khóa, nếu kiến ​​trúc cho phép bạn (web/không quốc tịch?) – vulkanino

Trả lời

3

xem xét truy vấn này:

SELECT * 
FROM Hire AS H1, Hire AS H2 
WHERE H1.carId = H2.carId 
AND H1.hireId < H2.hireId 
AND 
    CASE 
    WHEN H1.onHireDate > H2.onHireDate THEN H1.onHireDate 
    ELSE H2.onHireDate END 
    < 
    CASE 
    WHEN H1.offHireDate > H2.offHireDate THEN H2.offHireDate 
    ELSE H1.offHireDate END 

Nếu tất cả các hàng gặp bạn quy tắc kinh doanh thì truy vấn này sẽ là bộ trống (giả sử closed-open representation of periods nghĩa là ngày kết thúc là hạt thời gian sớm nhất không được xem xét trong khoảng thời gian này).

SQL Server does not support subqueries within CHECK constraints, đặt cùng một logic trong một kích hoạt (nhưng không phải là một INSTEAD OF kích hoạt, trừ khi bạn có thể cung cấp logic để quyết trùng lặp).


truy vấn thay thế sử dụng Fowler:

SELECT * 
    FROM Hire AS H1, Hire AS H2 
WHERE H1.carId = H2.carId 
     AND H1.hireId < H2.hireId 
     AND H1.onHireDate < H2.offHireDate 
     AND H2.onHireDate < H1.offHireDate; 
+0

Vì vậy, tôi không nên sử dụng Thay vì kích hoạt để ném một ngoại lệ nếu chồng chéo xảy ra? Tôi có thể bắt ngoại lệ và yêu cầu người dùng khắc phục. – GraemeMiller

+0

@GraemeMiller: Sử dụng trình kích hoạt 'SAU '. – onedaywhen

+0

Vì vậy, tôi sẽ chèn mục và sau khi kích hoạt sẽ cuộn nó trở lại và đưa ra một lỗi trên chồng chéo? – GraemeMiller

3
CREATE TRIGGER tri_check_date_overlap ON your_table 
INSTEAD OF INSERT 
AS 
BEGIN 
    IF @@ROWCOUNT = 0 
     RETURN 

    -- check for overlaps in table 'INSERTED' 
    IF EXISTS(
     SELECT hireId FROM your_table WHERE 
      (INSERTED.onHireDate BETWEEN onHireDate AND offHireDate) OR 
      (INSERTED.offHireDate BETWEEN onHireDate AND offHireDate) 
    ) 
     BEGIN 
      -- exception? or do nothing? 
     END 
    ELSE 
     BEGIN 
     END 
END 
GO 
+0

không kiểm tra nó, tôi không biết nếu kiểm tra thực sự hoạt động. – vulkanino

+0

Nó không kiểm tra trùng lặp nếu hai hàng chồng chéo được chèn vào trong một câu lệnh chèn đơn (nơi không có hàng chồng lên hàng hiện có trong bảng) –

+0

@Damien_The_Unbeliever bạn có thể sửa SP không? – vulkanino

0

bây giờ tôi đang sử dụng kỹ thuật thiết kế miền driven. Điều này giúp tôi không lo lắng về việc kích hoạt cơ sở dữ liệu vv và giữ tất cả các logic trong mã .Net. Câu trả lời là ở đây để mọi người có thể thấy một giải pháp thay thế.

Tôi đối xử với phụ huynh của tập hợp các khoảng thời gian dưới dạng aggregate root và gốc có dấu thời gian. Tổng hợp gốc là một ranh giới nhất quán cho các giao dịch, phân phối và đồng thời (xem Evans - what I've learned since the blue book). Điều này được sử dụng để kiểm tra lần cuối cùng bất kỳ thay đổi nào được xác nhận cho cơ sở dữ liệu.

Sau đó tôi có phương pháp để thêm thời gian thuê cho phụ huynh. Tôi thử nghiệm trên chồng chéo khi thêm phong trào vào gốc tổng hợp. ví dụ. AddHire(start,end) - sẽ xác nhận rằng điều này tạo ra không có chồng lên nhau trong đối tượng miền bộ nhớ.

Vì không có chồng chéo tôi lưu các thay đổi (qua kho lưu trữ của tôi) và kiểm tra dấu thời gian của cơ sở dữ liệu vẫn giống như lúc bắt đầu quá trình. Giả sử dấu thời gian giống như khi tôi truy xuất thực thể, các thay đổi được duy trì và cơ sở dữ liệu cập nhật dấu thời gian.

Nếu ai đó cố gắng lưu các thay đổi khi gốc tổng hợp đang được thực hiện thì tôi sẽ cam kết trước tiên hoặc họ sẽ thực hiện. Nếu tôi cam kết trước, dấu thời gian sẽ không khớp và kiểm tra trùng lặp sẽ chạy lại để đảm bảo rằng chúng chưa tạo chồng chéo trong thời gian can thiệp.

Các vấn đề liên quan