Chuẩn SQL đề nghị một dạng khẳng định đơn giản cho phộp chỳng ta bắt buộc một điều kiện nào đú. Giống như cỏc phần tử lược đồ khỏc, chỳng ta mụ tả một khẳng định bằng lệnh CREATE. Dạng của một khẳng định là:
1. Cỏc từ khúa CREATE ASSERTION, 2. Tờn của khẳng định
3. Từ khúa CHECK, và
4. Một điều kiện được đặt trong dấu ngoặc. Như vậy, dạng của lệnh này là
CREATE ASSERTION < Tờn > CHECK < điềukiện >
Điều kiện trong assertion phải đỳng khi assertion được tạo ra và phải luụn luụn vẫn cũn đỳng; bất kỳ một sửa đổi cơ sở dữ liệu nào làm cho nú trở thành sai sẽ bị loại bỏ. Nhớ lại rằng cỏc kiểu ràng buộc CHECK khỏc mà chỳng ta đó xột cú thể bị vi phạm dưới một số điều kiện.
Cú một sự khỏc nhau giữa cỏch viết cỏc ràng buộc CHECK dựa trờn bộ và cỏch viết assertion. Cỏc kiểm tra dựa trờn bộ cú thể tham chiếu đến cỏc thuộc tớnh của quan hệ cú kiểm tra này xuất hiện trong mụ tả của nú. Vớ dụ, trong dũng 6) của vớ dụ 2.8 chỳng ta sử dụng cỏc thuộc tớnh Giới tớnh và Tờn mà khụng núi chỳng đi đến từ đõu. Chỳng tham chiếu đến cỏc thành phần của một bộ được chốn vào hoặc được cập nhật trong bảng GIÁOVIấN bởi vỡ bảng đú là một trong cỏc bảng được mụ tả trong lệnh CREATE TABLE. Điều kiện của một assertion khụng cú đặc quyền như vậy. Cỏc thuộc tớnh bất kỳ được tham chiếu đến trong điều kiện phải được giới thiệu trong assertion, thường là bằng việc chỉ ra quan hệ của chỳng trong một biểu thức select-from-where. Bởi vỡ điều kiện phải cú một giỏ trị lụgic, việc nhúm cỏc kết quả của điều kiện theo một cỏch nào đú để tạo ra một lựa chọn true/false đơn là việc bỡnh thường. Vớ dụ, chỳng ta cú thể viết điều kiện như là một
biểu thức sản xuất ra một quan hệ mà NOT EXISTS được ỏp dụng cho quan hệ đú; điều đú cú nghĩa là, ràng buộc là quan hệ này luụn luụn rỗng. Một cỏch khỏc, chỳng ta cú thể ỏp dụng một phộp toỏn nhúm như là SUM cho một cột của một quan hệ và so sỏnh nú với một hằng. Vớ dụ, chỳng ta cú thể đũi hỏi rằng tổng luụn luụn bộ hơn một giỏ trị cú giới hạn nào đú.
Vớ dụ 2.12: Giả sử chỳng ta muốn yờu cầu rằng muốn trở thành người quản lý của một đơn vị thỡ phải cú lương ớt nhất là 4000. Ta sẽ khai bỏo một assertion với với mục đớch rằng tập hợp cỏc đơn vị cú người quản lý với lương nhỏ hơn 4000 là rỗng. Assertion này cần cú hai quan hệ NHÂNVIấN và ĐƠNVỊ.
CREATE ASSERTION Quanly CHECK (NOT EXISTS
(SELECT *
FROM NHÂNVIấN NV, ĐƠNVỊ ĐV WHERE NV.MósốNV = ĐV.Mó sốNQL AND Lương <4000);
Nhõn tiện, cần chỳ ý rằng mặc dự ràng buộc này cú hai quan hệ, chỳng ta cú thể viết nú như cỏc ràng buộc CHECK dựa trờn bộ trờn hai quan hệ hơn là như một assertion đơn. Vớ dụ, chỳng ta cú thể viết như sau
CREATE TABLE ĐƠNVỊ
(TờnĐV VARCHAR(15) NOT NULL,
MósốĐV INT PRIMARY KEY,
Ngàybắtđầu DATE, MósốNQL CHAR(9) REFERENCES NHÂNVIấN(MósốNV), CHECK (MósốNQL NOT IN (SELECT MósốNV FROM NHÂNVIấN WHERE Lương < 4000)));
Tuy nhiờn, chỳ ý rằng ràng buộc này chỉ sẽ được kiểm tra khi cú một thay đổi xảy ra đối với quan hệ của nú, quan hệ ĐƠNVỊ. Cú thể nú khụng chặn được tỡnh trạng cú những người quản lý được ghi vào quan bệ NHÂNVIấN nhưng lại cú lương < 4000. Để nhận được hiệu quả đầy đủ của assertion, chỳng ta phải thờm một ràng buộc khỏc vào khai bỏo của bảng NHÂNVIấN, đũi hỏi rằng lương của một nhõn viờn phải >=4000 nếu anh ta là người quản lý một đơn vị.
Vớ dụ 2.13 Assertion sau đõy núi rằng tổng lương của mỗi đơn vị khụng được vượt quỏn 100000. Nú bao hàm quan hệ NHÂNVIấN.
CREATE ASSERTION Tổnglương CHECK (100000 >= ALL
(SELECT SUM(Lương) FROM NHÂNVIấN GROUP BY MósốĐV));
Vỡ ràng buộc này chỉ bao hàm cú một quan hệ NHÂNVIấN, nú cú thể được trỡnh bày như một ràng buộc CHECK dựa trờn biến bộ trong lược đồ đối với NHÂNVIấN hơn là như một assertion. Vỡ vậy, chỳng ta cú thể thờm vào định nghĩa của bảng NHÂNVIấN ràng buộc CHECK dựa trờn biến bộ như sau:
CHECK (100000>= ALL
(SELECT SUM(Lương) FROM NHÂNVIấN GROUP BY MósốĐV)); Để ý rằng, về nguyờn tắc, điều kiện này ỏp dụng cho mỗi bộ của bảng NHÂNVIấN. Tuy nhiờn, nú khụng kể ra cỏc thuộc tớnh của bộ một cỏch rừ ràng và mọi cụng việc được thực hiện trong truy vấn con. Cũng để ý thờm rằng nếu được cài đặt như một ràng buộc dựa trờn bộ thỡ việc kiểm tra khụng thể thực hiện trờn phộp xúa một bộ ra khỏi quan hệ NHÂNVIấN. Trong vớ dụ này, sự khỏc nhau đú khụng gõy ra tai hại bởi vỡ nếu ràng buộc được thỏa món trước khi xúa thỡ sau khi xúa nú cũng được thỏa món. Tuy nhiờn, nếu ràng buộc khụng phải là cận trờn mà là cận dưới của tổng lương theo từng
đơn vị thỡ chỳng ta cú thể tỡm thấy ràng buộc bị vi phạm ngay cả khi chỳng ta viết nú như là một kiểm tra dựa trờn bộ mà khụng phải là một assertion. Cuối cựng, ta cú thể bỏ một assertion. Lệnh làm việc đú cũng tuõn theo mẫu đối với mọi phần tử của lược đồ cơ sở dữ liệu.
DROP ASSERTION <Tờn của assertion>.
So sỏnh cỏc ràng buộc
Bảng sau đõy liệt kờ cỏc khỏc nhau cơ bản giữa cỏc kiểm tra dựa trờn thuộc tớnh, cỏc kiểm tra dựa trờn bộ và assertion
Kiểu ràng buộc Được mụ tả ở đõu
Khi nào được kớch hoạt Được đảm bảo đỳng ? CHECK dựa trờn thuộc tớnh Cựng với thuộc tớnh Trờn phộp chốn vào quan hệ hoặc cập nhật thuộc tớnh Khụng đảm bảo nếu cú truy vấn con CHECK dựa trờn bộ Phần tử của lược đồ quan hệ Trờn phộp chốn vào quan hệ hoặc cập nhật bộ Khụng đảm bảo nếu cú truy vấn con
Assertion Phần tử của lược
đồ cơ sở dữ liệu
Trờn một thay đổi đối với quan hệ được kể ra
Đảm bảo
2.4.2 Trigger
Cỏc trigger (hay cũn gọi là cỏc quy tắc ECA – event-condition-action rules) khỏc với cỏc loại ràng buộc thảo luận ở trờn ở ba điểm:
1. Cỏc trigger chỉ được đỏnh thức khi xảy ra một sự kiện do người lập trỡnh cơ sở dữ liệu chỉ ra. Cỏc loại sự kiện cho phộp thường là chốn, xúa
hoặc cập nhật đối với một quan hệ cụ thể. Một loại sự kiện khỏc được cho phộp trong nhiều hệ thống SQL là một kết thỳc giao tỏc.
2. Thay cho việc ngăn ngừa tức khắc sự kiện đó đỏnh thức nú, trigger kiểm tra một điều kiện. Nếu điều kiện khụng thỏa món thỡ chẳng cú cỏi gỡ liờn quan tới trigger xảy ra trong trả lời cho sự kiện này.
3. Nếu điều kiện của trigger được thỏa món thỡ hệ quản trị cơ sở dữ liệu sẽ thực hiện hành động liờn kết với trigger. Hành động đú cú thể là ngăn ngừa sự kiện xảy ra hoặc loại bỏ (undo) sự kiện (vớ dụ như xúa bộ được chốn vào). Núi túm lại, hành động cú thể là một hệ quả nào đú của cỏc phộp toỏn cơ sở dữ liệu, ngay cả cỏc phộp toỏn khụng kết nối theo một cỏch nào đú với sự kiện nổ ra
Trigger trong SQL
Một cõu lệnh trigger của SQL cho người sử dụng một số cỏc tựy chọn trong cỏc phần sự kiện, điều kiện và hành động. Sau đõy là một số đặc trưng chớnh:
1. Hành động cú thể được thực hiện hoặc trước hoặc sau khi sự kiện nổ ra 2. Hành động cú thể tham chiếu đến cả cỏc giỏ trị cũ và giỏ trị mới của cỏc
bộ được chốn, xúa hoặc cập nhật trong sự kiện làm bựng nổ hành động. 3. Cỏc sự kiện cập nhật cú thể được giới hạn đến một thuộc tớnh hoặc một
tập thuộc tớnh cụ thể.
4. Một điều kiện cú thể được chỉ ra bằng mệnh đề WHEN; hành động chỉ được thực hiện khi quy tắc được bựng nổ và điều kiện thỏa món khi xảy ra sự kiện bựng nổ
5. Người lập trỡnh cú tựy chọn chỉ ra rằng hành động được thực hiện hoặc: a) Một lần đối với mỗi bộ được cập nhật
b) Một lần đối với tất cả cỏc bộ được thay đổi trong một phộp toỏn cơ sở dữ liệu.
Trước khi đưa ra chi tiết về cỳ phỏp của trigger, chỳng ta hóy xột một vớ dụ minh họa cỏc điểm quan trọng về cỳ phỏp cũng như về ngữ nghĩa. Trong vớ dụ này, trigger thực hiện một lần đối với mỗi bộ được cập nhật
Vớ dụ 2.14: Viết một trigger của SQL ỏp dụng cho quan hệ NHÂNVIấN. Nú được kớch hoạt do cỏc cập nhật đối với thuộc tớnh Lương. Hiệu quả của trigger này là chặn ý định làm giảm lương của một nhõn viờn. Mụ tả của trigger như sau:
1) CREATE TRIGGER LươngTrigger
2) AFTER UPDATE OF Lương ON NHÂNVIấN 3) REFERENCING
4) OLD ROW AS OldTuple 5) NEW ROW AS NewTuple 6) FOR EACH ROW
7) WHEN (OldTuple.Lương > Newtuple.Lương) 8) UPDATE NHÂNVIấN
9) SET Lương = Oldtuple.Lương
10) WHERE MósốNV = Newtuple.MósốNV;
Dũng 1) đưa ra mụ tả với cỏc từ khúa CREATE TRIGGER và tờn của trigger. Dũng 2) cung cấp sự kiện bựng nổ, đú là cập nhật thuộc tớnh Lương của quan hệ NHÂNVIấN. Dũng 3) đến dũng 5) thiết lập một cỏch để cỏc phần hành động và điều kiện núi về bộ cũ (bộ trước khi cập nhật) và bộ mới (bộ sau khi cập nhật). Cỏc bộ này sẽ được tham chiếu đến như là Oldtuple và Newtuple theo mụ tả ở dũng 4) và dũng 5) tương ứng. Trong điều kiện và hành động, cỏc tờn này cú thể được sử dụng như là chỳng là cỏc biến bộ được mụ tả trong mệnh đề FROM của mụt truy vấn SQL thụng thường. Dũng 6), cõu FOR EACH ROW, biểu thị đũi hỏi rằng trigger này được thực hiện một lần đối với mỗi một bộ được cập nhật. Nếu khụng cú cõu này hoặc nú được thay bằng ngầm định FOR EACH STATEMENT, thỡ trigger sẽ xuất hiện một lần đối với một lệnh SQL, khụng quan tõm đến sự kiện bựng nổ đó thay đổi cỏc bộ bao nhiờu lần. Chỳng ta khụng thể khai bỏo bớ danh cho cỏc hàng mới và cỏc hàng cũ nhưng chỳng ta cú thể sử dụng OLD TABLE và NEW TABLE sẽ đưa ra sau đõy. Dũng 7) là phần điều kiện của trigger. Nú núi rằng chỳng ta chỉ thực hiện hành động khi lương mới thấp hơn lương cũ,
nghĩa là lương của một nhõn viờn bị cắt giảm. Cỏc dũng 8) đến 10) tạo nờn phần hành động. Hành động này là một lệnh cập nhật của SQL thụng thường, nú cú tỏc động khụi phục lương của nhõn viờn thành lương trước khi cập nhật. Để ý rằng về nguyờn tắc, mỗi một bộ của NHÂNVIấN được xem xột để cập nhật, nhưng mệnh đề WHERE của dũng 10) đảm bảo rằng chỉ cú bộ được cập nhật là sẽ bị ảnh hưởng.
Sau đõy chỳng ta sẽ đưa ra cỏc tựy chọn do trigger cung cấp và biểu diễn cỏc tựy chọn đú như thế nào.
- Dũng 2) của vớ dụ trờn núi rằng hành động của quy tắc được thực hiện sau sự kiện xảy ra như được chỉ ra bằng từ khúa AFTER. Chỳng ta cú thể thay thế AFTER bằng BEFORE, trong trường hợp này điều kiện WHEN được kiểm tra trước khi sự kiện xảy ra, nghĩa là trước khi sự cập nhật làm đỏnh thức trigger được thực hiện đối với cơ sở dữ liệu. Nếu điều kiện là đỳng thỡ hành động của trigger được thực hiện. Sau đú, sự kiện đỏnh thức trigger được thực hiện mà khụng cần quan tõm đến điều kiện cú đỳng hay khụng.
- Ngoài UPDATE, cỏc sự kiện bựng nổ khỏc là INSERT, DELETE. Mệnh đề OF Lương trong dũng 2) là tựy chọn đối với sự kiện UPDATE và nếu cú mặt thỡ nú xỏc định sự kiện chỉ là cập nhật của cỏc thuộc tớnh được liệt kờ sau từ khúa OF. Một mệnh đề OF khụng được cho phộp đối với cỏc sự kiện INSERT hoặc DELETE; cỏc sự kiện này chỉ cú nghĩa đối với cỏc bộ toàn vẹn.
- Mệnh đề WHEN là tựy chọn. Nếu khụng cú nú thỡ hành động được thực hiện mỗi khi trigger được đỏnh thức.
- Trong khi chỳng ta chỉ ra một cõu lệnh SQL đơn như là một hành động, Hành động cú thể gồm nhiều cỏc cõu lệnh như vậy. Cỏc cõu lệnh cỏch nhau bằng dấu hai chấm và được đặt trong cặp BEGIN … END.
- Khi một sự kiện bựng nổ là một cập nhật thỡ sẽ cú cỏc bộ cũ và cỏc bộ mới, đú là cỏc bộ trước và sau cập nhật tương ứng. Chỳng ta cho cỏc bộ này cỏc tờn OLD ROW AS VÀ NEW ROW AS như đó thấy trong cỏc dũng 4) và 5). Nếu sự kiện bựng nổ là một phộp chốn thỡ chỳng ta cú thể sử dụng
mệnh đề NEW ROW AS để đặt tờn cho bộ được chốn vào và khụng cho phộp cú OLD ROW AS. Ngược lại, trong phộp xúa OLD ROW AS được sử dụng để đặt tờn cho bộ bị xúa và khụng cho phộp cú NEW ROW AS.
- Nếu chỳng ta bỏ qua FOR EACH ROW ở dũng 6) thỡ trigger mức dũng như ở vớ dụ trờn sẽ trở thành trigger mức lệnh. Một trigger mức lệnh được thực hiện một lần khi một lệnh của một kiểu thớch hợp được thực hiện, khụng quan tõm đến bao nhiờu hàng – khụng, một, nhiều - cú ảnh hưởng. Vớ dụ, nếu chỳng ta cập nhật toàn bộ bảng với một lệnh cập nhật SQL, một trigger cập nhật mức lệnh sẽ chỉ thực hiện một lần, trong khi đú một trigger mức bộ sẽ thực hiện một lần đối với mỗi bộ được cập nhật. Trong một trigger mức lệnh, chỳng ta khụng thể tham chiếu đến cỏc bộ cũ và cỏc bộ mới một cỏch trực tiếp giống như chỳng ta đó núi trong cỏc dũng 4) và 5). Tuy nhiờn, một trigger bất kỳ - mức dũng hoặc mức bộ - cú thể tham chiếu đến quan hệ của cỏc bộ cũ (cỏc bộ bị xúa hoặc phiờn bản cũ của cỏc bộ được cập nhật) và quan hệ của cỏc bộ mới (cỏc bộ được chốn vào hoặc phiờn bản mới của cỏc bộ được cập nhật) bằng việc sử dụng cỏc mụ tả giống như OLD TABLE AS OldStuff hoặc NEW TABLE AS NewStuff.
Vớ dụ 2.15: Giả sử chỳng ta muốn ngăn ngừa trung bỡnh lương của cỏc nhõn viờn xuống dưới 3000. Ràng buộc này cú thể bị vi phạm bằng một phộp chốn, một phộp xúa hoặc bằng một phộp cập nhật đối với Lương trong bảng NHÂNVIấN. Điểm tế nhị là ở chỗ, trong một lệnh INSERT hoặc UPDATE chỳng ta cú thể chốn vào hoặc sửa đổi nhiều bộ của NHÂNVIấN và trong quỏ trỡnh cập nhật, trung bỡnh lương cú thể tạm thấp xuống dưới 3000 và sau đú lại vượt lờn trờn 3000 tại thời điểm sự cập nhật hoàn thành. Chỳng ta chỉ muốn loại bỏ toàn bộ tập hợp cỏc cập nhật nếu trung bỡnh lương xuống dưới 3000 ở cuối mỗi lệnh.
Việc viết một trigger cho mỗi sự kiện chốn, xúa, cập nhật của quan hệ NHÂNVIấN là cần thiết. Sau đõy là trigger cho sự kiện cập nhật. Cỏc trigger cho chốn và xúa cũng tương tự.
1) CREATE TRIGGER TBlươngTrigger
3) REFERENCING
4) OLD TABLE AS OldStuff
5) NEW TABLE AS NewStuff
6) FOR EACH STATEMENT
7) WHEN (3000 > (SELECT AVG(Lương) FROM NHÂNVIấN)
8) BEGIN
9) DELETE FROM NHÂNVIấN
10) WHERE (Họđệm,Tờn, MósốNV, Ngàysinh, Địachỉ, Giớitớnh,Lương, MósụNGS, MósốĐV) IN NewStuff ;
11) INSERT INTO NHÂNVIấN
12) (SELECT * FROM OldStuff)
13) END;
Cỏc dũng từ 3) đến 5) khai bỏo rằng NewStuff và OldStuff là tờn của cỏc quan hệ chứa cỏc bộ mới và cỏc bộ cũ dớnh dỏng đến phộp toỏn quan hệ làm đỏnh thức trigger của chỳng ta. Chỳ ý rằng một phộp toỏn quan hệ cú thể sửa đổi nhiều bộ của một quan hệ và nếu một lệnh như vậy được thực hiện thỡ sẽ cú nhiều bộ trong Newstuff và OldStuff.
Nếu một phộp toỏn là một UPDATE thỡ NewStuff và OldStuff tương ứng là phiờn bản mới và cũ của cỏc bộ được cập nhật. Nếu trigger tương tự được viết cho phộp xúa thỡ cỏc bộ bị xúa sẽ ở trong OldStuff và sẽ khụng cú mụ tả tờn quan hệ NewStuff cho NEW TABLE như trong trigger này. Cũng như vậy, trong trigger tương tự cho phộp chốn, cỏc bộ mới sẽ ở trong NewStuff và khụng cú khai bỏo cho OldStuff.
Dũng 6) núi với ta rằng trigger này được thực hiện một lần cho một lệnh, khụng cần quan tõm đến bao nhiờu bộ đó được cập nhật Dũng 7) là một điều