qh_thúy... · web viewxét ví dụ minh họa, “tìm tất cả khách hàng có cả tài...

53
PHẦN II CƠ SỞ DỮ LIỆU QUAN HỆ Cơ sở dữ liệu là một kho chứa dữ liệu và dùng để chia sẻ. Để biến dữ liệu ở dạng cơ sở dữ liệu quan hệ có thể dùng được cho người sử dụng, chúng ta phải phân tích một số vấn đề chính. Thứ nhất, làm thế nào mà người sử dụng có thể chỉ định rõ các yêu cầu của mình trên dữ liệu: Một trong những ngôn ngữ truy vấn nào mà họ có thể dùng? Chương 4 sẽ bao hàm ngôn ngữ SQL, vốn là ngôn ngữ truy vấn được sử dụng nhiều nhất hiện nay. Chương 5 sẽ trình bày hai ngôn ngữ truy vấn khác QBE và Datalog, vốn là ngôn ngữ truy vấn thay thế SQL dùng để trích xuất dữ liệu quan hệ. Một vấn đề quan trọng khác là sự an toàn và toàn vẹn của dữ liệu; Cơ sở dữ liệu cần phải bảo vệ dữ liệu khỏi các hiểm nguy từ các hoạt động cố ý hoặc vô ý của người sử dụng. Bộ phận đảm bảo tính toàn vẹn của một cơ sở dữ liệu phải đảm bảo rằng các cập nhật dữ liệu không gây ra vi phạm ràng buộc toàn vẹn. Bộ phận đảm bảo sự an toàn của cơ sở dữ liệu bao gồm việc xác thực người sử dụng và điều khiển việc truy cập, nhằm giới hạn các hoạt động của mỗi người sử dụng. Chương 6 sẽ trình bày các vấn đề về an toàn và toàn vẹn dữ liệu. 1

Upload: others

Post on 03-Jan-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

PHẦN II

CƠ SỞ DỮ LIỆU QUAN HỆ

Cơ sở dữ liệu là một kho chứa dữ liệu và dùng để chia sẻ. Để biến dữ liệu ở dạng cơ sở dữ liệu quan hệ có thể dùng được cho người sử dụng, chúng ta phải phân tích một số vấn đề chính. Thứ nhất, làm thế nào mà người sử dụng có thể chỉ định rõ các yêu cầu của mình trên dữ liệu: Một trong những ngôn ngữ truy vấn nào mà họ có thể dùng? Chương 4 sẽ bao hàm ngôn ngữ SQL, vốn là ngôn ngữ truy vấn được sử dụng nhiều nhất hiện nay. Chương 5 sẽ trình bày hai ngôn ngữ truy vấn khác QBE và Datalog, vốn là ngôn ngữ truy vấn thay thế SQL dùng để trích xuất dữ liệu quan hệ.

Một vấn đề quan trọng khác là sự an toàn và toàn vẹn của dữ liệu; Cơ sở dữ liệu cần phải bảo vệ dữ liệu khỏi các hiểm nguy từ các hoạt động cố ý hoặc vô ý của người sử dụng. Bộ phận đảm bảo tính toàn vẹn của một cơ sở dữ liệu phải đảm bảo rằng các cập nhật dữ liệu không gây ra vi phạm ràng buộc toàn vẹn. Bộ phận đảm bảo sự an toàn của cơ sở dữ liệu bao gồm việc xác thực người sử dụng và điều khiển việc truy cập, nhằm giới hạn các hoạt động của mỗi người sử dụng. Chương 6 sẽ trình bày các vấn đề về an toàn và toàn vẹn dữ liệu.

1

Page 2: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

CHƯƠNG 4SQL

4.1 Nền tảng

IBM phát triển phiên bản đầu tiên của SQL tại phòng nghiên cứu ở San Jose (hiện nay là Trung tâm nghiên cứu Almaden). Thực tế, ngôn ngữ SQL có nguồn gốc từ ngôn ngữ Sequel, là một phần của dự án “System R” ở những năm đầu thập niên 1970. Sau đó ngôn ngữ Sequel được cải tiến và đổi tên thành SQL (Structured Query Language - Ngôn ngữ truy vấn có cấu trúc). Hiện này có nhiều ứng dụng hỗ trợ ngôn ngữ SQL. SQL đã dần dần trở thành ngôn ngữ cơ sở dữ liệu quan hệ chuẩn.

Năm 1986, Viện tiêu chuẩn quốc gia Mỹ (American National Standards Institute - ANSI) và Tổ chức chuẩn hóa quốc tế (ISO) đã đề xuất ra chuẩn SQL, đặt tên là SQL-86. Năm 1987, IBM đã tự đề xuất ra chuẩn SQL riêng của họ, đặt tên là SAA-SQL. Năm 1989, ANSI mở rộng chuẩn SQL thành SQL-89. Chuẩn SQL tiếp theo sau đó là SQL-92 và phiên bản gần đây nhất là SQL:99.

Trong chương này, chúng tôi trình bày khái quát về SQL, chủ yếu về chuẩn SQL-92. Chúng tôi cũng trình bày một vài đặc điểm của chuẩn SQL:1999 – là chuẩn cao hơn của chuẩn SQL-92.

Các thành phần của ngôn ngữ SQL bao gồm:

Ngôn ngữ định nghĩa dữ liệu: (Data-Definition Language, DDL). DDL cung cấp các lệnh dùng để định nghĩa các lược đồ quan hệ, xóa các quan hệ và sửa các lược đồ quan hệ.

Ngôn ngữ thao tác dữ liệu: (Interactive data-manipulation language, DML). DML bao gồm ngôn ngữ truy vấn dựa trên cả hai đại số quan hệ và các phép toán trên các bộ của quan hệ. DML bao gồm các lệnh dùng để chèn, xóa và sửa các bộ dữ liệu trên cơ sở dữ liệu.

Định nghĩa khung nhìn: (View definition). DDL chứa các lệnh để định nghĩa các khung nhìn.

Điều khiển giao tác: SQL chứa các lệnh dùng để chỉ rõ phần bắt đầu và kết thúc của các giao tác.

SQL nhúng và SQL động: SQL nhúng và SQL động định nghĩa cách thức các lệnh SQL có thể được nhúng trong các ngôn ngữ lập trình phổ biến như C, C++, Java, PL/I, Cobol, Pascal và Fortran.

Sự toàn vẹn. DDL bao gồm các lệnh để chỉ rõ các ràng buộc toàn vẹn mà dữ liệu được lưu trên cơ sở dữ liệu buộc phải thỏa mãn. Các cập nhật gây ra vi phạm ràng buộc toàn vẹn sẽ không được cho phép.

Sự xác thực. DDL bao gồm các lệnh để chỉ rõ các quyền truy cập đến các quan hệ và các khung nhìn.

2

Page 3: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Trong chương này, chúng tôi trình bày tổng quan về DML và các đặc điểm cơ bản của DDL. Chúng tôi cũng trình bày sơ lược về SQL nhúng và SQL động, bao gồm các chuẩn ODBC và JDBC cho việc tương tác với cơ sở dữ liệu bằng các ngôn ngữ lập trình C và Java.

Trong chương này và các chương về sau, chúng tôi sử dụng lược đồ quan hệ mẫu về việc kinh doanh của ngân hàng như sau:

Branch-schema = (branch-name, branch-city, assets)

Customer-schema = (customer-name, customer-street, customer-city)

Loan-schema = (loan-number, branch-name, amount)

Borrower-schema = (customer-name, loan-number)

Account-schema = (account-number, branch-name, balance)

Depositor-schema = (customer-name, account-number)Lưu ý, trong chương này và một số nơi khác của sách, chúng tôi sử dụng dấu gạch nối trong lược đồ, các quan hệ và các thuộc tính để dễ đọc. Thực tế trong hệ thống SQL, dấu gạch nối là không hợp lệ (vì nó được xem là phép toán trừ). Các đơn giản để dịch các tên này là dùng dấu gạch dưới (“_”). Ví dụ, chúng tôi dùng branch_name thay cho branch-name.

4.2 Cấu trúc cơ bản

Một cơ sở dữ liệu quan hệ bao gồm một tập hợp các quan hệ, mỗi quan hệ được gán một tên duy nhất và có một cấu trúc nhất định. SQL cho phép sử dụng giá trị rỗng để gán cho các giá trị không biết hoặc không tồn tại. SQL cho phép người sử dụng chỉ rõ các thuộc tính nào không thể gán giá trị rỗng (chúng ta sẽ thảo luận vấn đề này ở mục 4.11).

Cấu trúc cơ bản của một biểu thức SQL bao gồm ba mệnh đề: Select, From và Where.

Mệnh đề Select tương ứng với phép chiếu của đại số quan hệ. Nó được sử dụng để liệt kê các thuộc tính được yêu cầu xuất hiện trong kết quả của truy vấn.

Mệnh đề From tương ứng với phép toán tích Đề-các của đại số quan hệ. Nó liệt kê các quan hệ sẽ được quét qua trong quá trình thực hiện truy vấn.

Mệnh đề Where tương ứng với điều kiện lọc của đại số quan hệ. Nó đề cập đến các thuộc tính của quan hệ xuất hiện trong mệnh đề From.

Cấu trúc thông thường của một truy vấn SQL có dạng:select A1, A2, . . .,An

from r1, r2, . . . , rm

where PMỗi Ai đại diện cho một thuộc tính và một ri đại diện cho một quan hệ. P là điều kiện lọc. Truy vấn trên tươgn đương với biểu thức đại số quan hệ như sau:

ΠA1, A2,...,An(σP (r1 × r2 × · · · × rm))3

Page 4: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Nếu không có mệnh đề Where thì nghĩa là truy vấn không có điều kiện. Tuy nhiên, không giống như kết quả của một biểu thức đại số quan hệ, kết quả của truy vấn SQL có thể chứa nhiều bộ giống nhau, chúng tôi sẽ bàn vấn đề này ở phần 4.2.8.

SQL hình thành nên phép tích Đề-các của các quan hệ có tên trong mệnh đề From, sau đó thực hiện phép chọn đại số quan hệ dựa trên các điều kiện ở mệnh đề Where và sau đó lọc lấy các kết quả của các thuộc tính ở mệnh đề Select. Trong thực tế, SQL có thể chuyển đổi biểu thức sang dạng tương đương để có thể thực hiện hiệu quả hơn.

4.2.1 Mệnh đề select

Dĩ nhiên, kết quả của một truy vấn SQL là một quan hệ. Chúng ta hãy xét một ví dụ đơn giản bằng cách sử dụng lược đồ quan hệ ngân hàng ở trên, yêu cầu “Hãy tìm tên của tất cả các chi nhánh trong quan hệ loan”.

select branch-namefrom loan

Kết quả của một quan hệ bao gồm một thuộc tính với tiêu đề branch-name. Các ngôn ngữ truy vấn thông dụng thường dựa trên các ghi chú toán học rằng một quan hệ là một tập hợp. Do đó, các bộ có giá trị giống nhau không bao giờ xuất hiện trong các quan hệ. Trong thực tế, việc loại bỏ các giá trị giống nhau thường mất rất nhiều thời gian. Do đó, SQL (và các ngôn ngừ truy vấn khác) cho phép xuất hiện các bộ giống nhau trong quan hệ cũng như trong kết quả truy vấn.

Trong trường hợp chúng ta muốn loại bỏ các giá trị trùng nhau trong truy vấn, chúng ta phải chèn thêm từ khóa distinct sau mệnh đề select. Chúng ta có thể viết lại truy vấn ở trên như sau:

select distinct branch-namefrom loan

nếu chúng ta muốn loại bỏ các giá trị trùng nhau.

SQL cho phép chúng ta sử dựng từ khóa all để chỉ định rõ ràng là muốn hiển thị tất cả giá trị trùng nhau:

select all branch-namefrom loan

Do việc hiển thị các giá trị trùng nhau là việc mặc định trong SQL, chúng ta không cần phải sử dụng từ khóa all trong các ví dụ về sau. Trong trường hợp muốn loại bỏ các giá trị trùng nhau trong kết quả truy vấn, chúng ta sử dụng từ khóa distinct. Trong hầu hết các truy vấn, distinct rất ít được sử dụng, lý do là số lượng bộ trùng nhau trong kết quả truy vấn là không quan trọng. Tuy nhiên, trong một số trường hợp, số lượng bộ trùng nhau là quan trọng, chúng ta sẽ bàn lại vấn đề nay ftrong phần 4.2.8.

Ký hiệu “*” được dùng để đại diện cho “tất cả các thuộc tính”. Do đó, việc sử dụng loan.* trong ngay sau mệnh đề select sẽ chỉ ra rằng tất cả các thuộc tính của quan hệ

4

Page 5: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

loan sẽ được lựa chọn. Mệnh đề select với dạng select * sẽ chỉ ra rằng tất cả các thuộc tính của tất cả các quan hệ xuất hiện trong mệnh đề from sẽ được lựa chọn.

Mệnh đề select cũng có thể chứa các biểu thức số học liên quan các toán tử +, -, * và / trên các hằng số hoặc các thuộc tính của các bộ. Ví dụ, truy vấn:

select loan-number, branch-name, amount * 100from loan

sẽ trả về một quan hệ tương đương quan hệ loan, ngoại trừ thuộc tính amount sẽ được nhân cho 100.

SQL cũng cung cấp các kiểu dữ liệu đặc biệt và cho phép các hàm số học thực hiện trên các kiểu dữ liệu này.

4.2.2 Mệnh đề where

Chúng ta sẽ mô tả việc sử dụng mệnh đề where trong SQL. Xét truy vấn “Hãy tìm tất cả các số tài khoản có gửi tiền ở ngân hàng trong quan hệ loan tại chi nhánh Perryridge với số tiền vay mượn lớn hơn $1200”. Truy vấn này được viết dưới dạng SQL như sau:

select loan-numberfrom loanwhere branch-name = ’Perryridge’ and amount > 1200

SQL sử dụng các toán tử logic and, or và not để thực hiện phép nối mà không dùng các ký tự toán học như ∧, ∨, và ¬ trong mệnh đề where. Các toán tử của các phép nối có thể được thay thế bằng các toán tử so sánh như <, <=, >, >=, = và <>.

SQL cho phép chúng ta sử dụng các toán tử so sánh để so sánh chuỗi và các biểu thức số học, cũng như đối với các kiểu dữ liệu đặc biệt, ví dụ kiểu ngày tháng.

SQL chứa toán tử between để làm đơn giản hóa mệnh đề where khi muốn chỉ ra giá trị nằm trong khoảng nhỏ hơn hoặc bằng, lớn hơn hoặc bằng. Ví dụ , nếu chúng ta muốn biết số tài khoản vay mượn của quan hệ loan với số tiền vay mượn trong khoảng từ $90,000 đến $100,000, chúng ta có thể sử dụng từ khóa between để viết lệnh:

select loan-numberfrom loanwhere amount between 90000 and 100000

thay thế cho lệnh: select loan-numberfrom loanwhere amount <= 100000 and amount >= 90000

Tương tự, chúng ta sử dụng toán tử so sánh not between để định nghĩa giá trị nằm ngoài khoảng giá trị được đưa ra.

4.2.3 Mệnh đề from

5

Page 6: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Cuối cùng, chúng ta hãy thảo luận việc sử dụng mệnh đề from. Mệnh đề from định nghĩa phép tích Đề-các của các quan hệ trong mệnh đề. Bởi vì phép kết nối tự nhiên được định nghĩa dưới dạng phép tích Đề-các, cho nên phép chọn và phép chiếu dễ dàng được mô tả dưới dạng câu lệnh SQL. Ví dụ, biểu thức đại số quan hệ dưới đây:

Πcustomer-name, loan-number, amount (borrower x loan)

dùng để truy xuất thông tin “Tìm tất cả khách hàng có tiền gửi và vay ở ngân hàng, liệt kê tên khách hàng, số tài khoản vay ngân hàng và số tiền mượn.” Trong SQL, truy vấn này có thể viết như sau:

select customer-name, borrower.loan-number, amountfrom borrower, loanwhere borrower.loan-number = loan.loan-number

Lưu ý rằng giống như đại số quan hệ, SQL sử dụng cú pháp relation-name.attribute-name để tránh sự nhập nhằng trong trường hợp tên thuộc tính xuất hiện trong nhiều quan hệ. Chúng ta có thể viết borrower.customer-name thay vì customername trong mệnh đề select. Tuy nhiên, bởi vì thuộc tính customer-name chỉ xuất hiện trong một quan hệ trong mệnh đề from, nên không xảy ra việc nhập nhằng dữ liệu khi chúng ta chỉ viết customer-name.

Chúng ta có thể mở rộng truy vấn trước đó và xét thêm một trường hợp phức tạp. Ví dụ, chúng ta yêu cầu người vay tiền ở chi nhánh Perryridge: “Tìm tên khách hàng, tên tài khoản vay mượn và số tiền mượn của tất cả sự vay mượn ở chi nhánh Perryridge”. Để viết truy vấn này, chúng ta cần có hai ràng buộc ở mệnh đề where và chúng được liên kết nhau qua toán tử logic and:

select customer-name, borrower.loan-number, amountfrom borrower, loanwhere borrower.loan-number = loan.loan-number andbranch-name = ’Perryridge’

Ngoài ra, SQL còn chứa một số phần mở rộng để thực hiện các phép kết nối tự nhiên và kết nối ngoài trong mệnh đề from. Chúng ta sẽ thảo luận về phần mở rộng này ở phần 4.10.4.2.4 Phép toán đổi tênSQL cung cấp cơ chế cho phép đổi tên quan hệ và tên thuộc tính. Việc đổi tên được sử dụng như một mệnh đề, có dạng:

old-name as new-name

Mệnh đề as có thể xuất hiện ở mệnh đề select hoặc mệnh đề from.

Xét lại ví dụ trước đó:select customer-name, borrower.loan-number, amountfrom borrower, loanwhere borrower.loan-number = loan.loan-number

6

Page 7: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Kết quả của truy vấn này là một quan hệ với các thuộc tính như sau: customer-name, loan-number, amount.

Tên của các thuộc tính trong bảng kết quả được rút trích từ tên của các thuộc tính trong quan hệ ở mệnh đề from.

Tuy nhiên, chúng ta không thể lúc nào cũng có thể rút trích tên theo cách này, vì một số lý do như sau: Thứ nhất, hai quan hệ ở mệnh đề from có thể có các thuộc tính có cùng tên với nhau, dẫn đến trường hợp bảng kết quả có cột bị trùng tên. Thứ 2, nếu chúng ta sử dụng các biểu thức số học trong mệnh đề select, kết quả của thuộc tính đó không có tên. Thứ 3, cho dù tên thuộc tính có thể rút trích từ quan hệ như ở ví dụ trước, nhưng chúng ta muốn thay đổi tên thuộc tính ở bảng kết quả. Do đó, SQL cung cấp một cách đổi tên các thuộc tính trong quan hệ kết quả.

Ví dụ, nếu chúng ta muốn tên thuộc tính loan-number sẽ được thay thể bằng loan-id, chúng ta có thể viết lại truy vấn như sau:

select customer-name, borrower.loan-number as loan-id, amountfrom borrower, loanwhere borrower.loan-number = loan.loan-number

4.2.5 Các biến của bộ

Mệnh đề as cũng đặc biệt được sử dụng để định nghĩa các biến của bộ. Trong SQL, một biến của bộ phải gắn với một quan hệ cụ thể. Hai biến của bộ được định nghĩa ở mệnh đề from bằng mệnh đề as. Để mô tả cho ý này, chúng tôi viết lại truy vấn “Đối với các khách hàng có tiền gửi ở ngân hàng, liệt kê tên, số tài khoản gửi và số tiền gửi” như sau:

select customer-name, T.loan-number, S.amountfrom borrower as T, loan as Swhere T.loan-number = S.loan-number

Lưu ý rằng chúng ta định nghĩa biến của bộ ở mệnh đề from bằng cách đặt tên biến sau tên của quan hệ mà nó thay thế với từ khoa as đặt ở giữa (từ khóa as là tùy chọn, có thể có hoặc không). Khi chúng ta viết biểu thức ở dạng relation-name.attribute-name thì relation-name có thể được thay thế bằng biến của bộ.

Các biến của bộ được sử dụng nhiều nhất khi muốn so sánh hai bộ của cùng một quan hệ. Nhắc lại rằng, trong một vài trường hợp, chúng ta có thể sử dụng phép toán đổi tên trong đại số quan hệ. Giả sử chúng ta muốn thực hiện truy vấn “Tìm tên của tất cả chi nhánh có tài sản lớn hơn tài sản của chi nhánh ở Brooklyn”. Chúng ta có thể viết biểu thức SQL như sau:

select distinct T.branch-namefrom branch as T, branch as Swhere T.assets > S.assets and S.branch-city = ’Brooklyn’

Quan sát ví dụ ở trên, chúng ta thấy rằng không thể sử dụng cú pháp branch.asset, bởi vì nó không thể chỉ định rõ branch ở chi nhánh nào.

7

Page 8: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

SQL cho phép chúng ta sử dụng cú pháp (v1, v2, …, vn) để định nghĩa một bộ của của n giá trị v1, v2, …, vn. Các toán tử so sánh có thể dược sử dụng trên các bộ và việc sắp xếp được định nghĩa theo từ điển. Ví dụ, (a1, a2) <= (b1, b2) là đúng nếu a1 < b1 hoặc (a1 = b1) ∧ (a2 <= b2); tương tự, hai bộ bằng nhau nếu tất cả các thuộc tính của nó tương ứng bằng nhau.

4.2.6 Các toán tử chuỗi

SQL chỉ rõ các chuỗi bằng cách đặt chúng trong cặp nháy đơn, ví dụ, ‘Perryridge’ mà chúng ta thấy ở ví dụ trước. Ký tự nháy đơn là một phần của chuỗi và dùng để thay thế cặp dấu ngoặc kép; ví dụ, chuỗi “It’s right” được thay bằng ‘It’s right’.

Phép toán trên chuỗi được sử dụng nhiều nhất là việc so sánh sử dụng toán tử like. Toán tử like thường đi kèm với một trong hai ký tự đặc biệt sau:

Phần trăm (%): Ký tự % đại diện cho một chuỗi ký tự. Dấu gạch chân (_): Ký tự _ đại diện cho một ký tự bất kỳ.

Việc so sánh chuỗi phân biệt chữ hoa và chữ thường, nghĩa là ký tự in hoa khác với ký tự thường và ngược lại. Để minh hoặc việc so sánh chuỗi, chúng ta hãy xét các ví dụ sau:

‘Perry%’ sẽ trả về kết quả là các chuỗi bắt đầu bằng “Perry”. ‘%idge%’ sẽ trả về các chuỗi có chứa chuỗi con “idge”, ví dụ như ‘Perryridge’,

‘Rock Ridge’, ‘Mianus Bridge’ và ‘Ridgeway’. ‘_ _ _’ sẽ trả về bất kỳ chuỗi nào có chứa đúng 3 ký tự. ‘_ _ _%’ sẽ trả về bất kỳ chuỗi nào có chứa ít nhất 3 ký tự.

SQL sử dụng toán tử like để so sánh chuỗi. Xét truy vấn Tìm tên các khách hàng có địa chỉ đường chứa chuỗi ‘Main’”. Truy vấn này có thể được viết như sau:

select customer-namefrom customerwhere customer-street like ’%Main%’

Đối với các chuỗi có chứa ký tự đặc biệt (như %, và _ ), SQL cho phép dùng ký tự thoát. Ký tự thoát được sử dụng ngay trước ký tự đặc biệt để chỉ ra rằng ký tự đặc biệt phải được coi như ký tự thông thường. Chúng ta định nghĩa ký tự thoát cho phép so sánh like bằng cách sử dụng ký tự thoát. Để minh họa, xét các ví dụ sau có sử dụng dấu vạch chéo ngược (\) như ký tự thoát:

Like ‘ab\%cd%’ escape ‘\’ sẽ trả về các chuỗi bắt đầu với “ab%cd”. Like ‘ab\\cd%’ escape ‘\’ sẽ trả về các chuỗi bắt đầu với “ab\cd”.

SQL cho phép chúng ta tìm các chuỗi không giống thay vì tìm các chuỗi giống nhau bằng cách sử dụng toán tử so sánh not like.

SQL cũng cho phép một số hàm xử lý chuỗi như nối chuỗi (sử dụng “||”), rút trích chuỗi con, tìm chiều dài của chuỗi, chuyển đổi giữa ký tự hoa và thường. SQL:1999 có

8

Page 9: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

hỗ trợ toán tử similar to dùng để so sánh chuỗi tố thơn toán tử like; cú pháp của các toán tử này tương tự như cú pháp sử dụng trong các biểu thức thông thường trên Linux.

4.2.7 Sắp xếp sự hiển thị của các bộ

SQL hỗ trợ người sử dụng một số điều khiển để sắp xếp việc hiển thị của các bộ trong một quan hệ. Mệnh đề order by sẽ làm cho các bộ trong kết quả truy vấn xuất hiện theo thứ tự được sắp xếp. Để liệt kê theo thứ tự chữ cái cho tất cả các khách hàng có tiền gửi ở ngân hàng và có vay mượn tiền tại chi nhánh Perryridge, chúng ta viết như sau:

select distinct customer-namefrom borrower, loanwhere borrower.loan-number = loan.loan-number and branch-name = ’Perryridge’order by customer-name

Theo mặc định, mệnh đề order by liệt kê các mục dữ liệu theo thứ tự tăng dần. Để chỉ rõ thứ tự sắp xếp, chúng ta có thể dùng desc cho sắp xếp giảm dần và asc cho sắp xếp tăng dầu. Hơn nữa, việc sắp xếp có thể được thực hiện trên nhiều thuộc tính. Giả sử chúng ta muốn liệt kê toàn bộ quan hệ loan theo thứ tự giảm dần của số lượng vay. Nếu vài tài khoản có cùng số lươgj vay, chúng ta sắp xếp theo thứ tự tăng dầu của số tài khoản vay. Chúng ta diễn đạt truy vấn này ở dạng SQL như sau:

select *from loanorder by amount desc, loan-number asc

Để thực hiện yêu cầu order by, SQLphải thực hiện phép sắp xếp. Bởi vì việc thực hiện sắp xếp trên một lượng lớn các bộ sẽ rất tốn kém, do đó chỉ nên sắp xếp khi thấy cần thiết.

4.2.8 Giá trị lặp lạiSử dụng các quan hệ có giá trị lặp lại mang lại một số thuận lợi. SQL không chỉ định nghĩa những bộ nào xuất hiện trong kết quả truy vấn mà còn chỉ ra có bao nhiêu bản sao của các bộ xuất hiện trong kết quả truy vấn. Chúng ta có thể định nghĩa ngữ nghĩa của các giá trị lặp lại bằng cách sử dụng phiên bản đa giá trị của các toán tử quan hệ. Ở đây chúng tôi định nghĩa phiên bản đa giá trị của một vài toán tử đại số quan hệ. Cho các quan hệ đa giá trị r1 và r2,

1. Nếu có c1 bản sao của bộ t1 trên r1 và t1 thỏa mãn phép chọn σθ thì có có c1 bản sao của t1 trên σθ (r1)

2. Đối với mỗi bản sao của bộ t1 trên r1, có một bản sao của bộ ΠA(t1) trên ΠA(r1), trong đó ΠA(t1) là ký hiệu của phép chiếu một bộ t1.

9

Page 10: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

3. Nếu có c1 bản sao của bộ t1 trên r1 và c2 bản sao của bộ t2 trên r2 thì sẽ có c1*c2

bản sao của bộ t1.t2 trên r1 x r2.

Ví dụ, giả sử quan hệ r1 với lược đồ (A, B) và r2 với lược đồ (C) là các bộ đa giá trị như sau:

r1 = {(1, a), (2, a)} r2 = {(2), (3), (3)}Thì phép ΠB(r1) sẽ cho kết quả là {(a), (a)}, trong khi đó ΠB(r1) × r2 sẽ là:

{(a, 2), (a, 2), (a, 3), (a, 3), (a, 3), (a, 3)}

Bây giờ chúng ta có thể định nghĩa số lượng bản sao của mỗi bộ trong kết quả của một truy vấn SQL. Một truy vấn SQL có dạng:

select A1, A2, . . .,An

from r1, r2, . . . , rm

where P

sẽ tương đương với biểu thức đại số quan hệ sau:ΠA1, A2,...,An(σP (r1 × r2 × · · · × rm))

Bằng cách sử dụng phiên bản đa giá trị của toán tử quan hệ σ, Π, và ×.

4.3 Các phép toán trên tập hợp

Các phép toán union, intersect và except thực hiện trên các quan hệ và các phép toán đại số quan hệ ∪, ∩ và − tương ứng. Giống như phép hợp, phép giao và phép trừ trên đại số quan hệ, các quan hệ tham gia vào phép toán phải tương thích, nghĩa là phải có cùng tập các thuộc tính.

Xét một số truy vấn mẫu liên quan đến phép union, intersect và except của hai tập hợp: Tập tất cả các khách hàng có tài khoản gửi ở ngân hàng được thực hiện vởi query:

select customer-namefrom depositor

và tập các khách hàng có vay nợ của ngân hàng được thực hiện bởi query:select customer-namefrom borrower

Chúng ta sẽ gọi các quan hệ thu được từ kết quả của hai truy vấn trên tương ứng là d và b.

4.3.1 Phép hợpĐể tìm tất cả khách hàng vừa có tài khoản và có vay nợ của ngân hàng, chúng ta viết:

(select customer-namefrom depositor)union(select customer-namefrom borrower)

10

Page 11: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Khác với mệnh đề select, phép union tự động loại bỏ các giá trị trùng nhau.

Do đó, ở truy vấn trước, nếu một khách hàng - giả sử tên Jones – có một vài tài khoản và/hoặc có vay mượn của ngân hàng thì Jones sẽ chỉ xuất hiện một lần trong bảng kết quả.

Nếu chúng ta muốn giữ lại tất cả các giá trị lặp lại, chúng ta phải viết union all thay cho union như sau:

(select customer-namefrom depositor)union all(select customer-name from borrower)

Số lượng các bộ trùng nhau trong kết quả bằng với tổng số lượng các giá trị trùng nhau xuất hiện trong cả hai d và b. Do đó, nếu Jones có ba tài khoản ở ngân hàng và hai tài khoản vay mượn thì sẽ có năm bộ kết quả với tên Jones trong bảng kết quả.

4.3.2 Phép giao

Để tìm tất cả các khách hàng có cả tài khoản gửi và tài khoản vay mượn ở ngân hàng, chúng ta viết:

(select distinct customer-namefrom depositor)intersect(select distinct customer-namefrom borrower)

Phép giao intersect tự động loại bỏ các giá trị trùng nhau. Do đó, trong truy vấn trước, nếu một khách hàng tên Jones có một vài tài khoản và tài khoản vay mượn tại ngân hàng, thì Jones sẽ xuất hiện chỉ một lần trong kết quả.

Nếu chúng ta muốn giữa lại tất cả các giá trị trùng nhau, chúng ta phải viết intersect all thay cho intersect:

(select customer-namefrom depositor)intersect all(select customer-namefrom borrower)

Số lượng các bộ trùng nhau xuất hiện trong các kết quả tương đương với số lượng tối thiểu các bộ trùng nhau trong cả hai d và b. Do đó, nếu Jones có ba tài khoản ở ngân hàng và hai tài khoản vay mượn thì sẽ có hai bộ tên Jones xuất hiện ở bảng kết quả.

4.3.3 Phép loại trừ

11

Page 12: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Để tìm tất cả khách hàng có tài khoản ở ngân hàng nhưng không có tài khoản vay mượn tại ngân hàng, ta viết:

(select distinct customer-namefrom depositor)except(select customer-namefrom borrower)

Phép loại trừ except tự động loại bỏ các giá trị trùng nhau. Do đó, ở truy vấn trước, một bộ với tên Jones sẽ xuất hiện (chỉ một lần) trong bảng kết quả chỉ khi Jones có một tài khoản gửi tiền tại ngân hàng nhưng Jones không có tài khoản vay mượn. Nếu chúng ta muốn giữ lại tất cả các giá trị trùng nhau, chúng ta viết except all thay cho except:

(select customer-namefrom depositor)except all(select customer-namefrom borrower)

Số lượng các bản sao trùng nhau của một bộ trong bảng kết quả tương đương với số lượng các bộ trùng nhau của d trừ đi số lượng bản sao của bộ trong b. Do đó, nếu Jones có ba tài khoản và một tài khoản vay mượn thì sẽ có hai bộ kết quả tên Jones trong bảng kết quả. Ngược lại, nếu Jones có hai tài khoản và ba tài khoản vay mượn thì không có bộ kết quả nào tên Jones.

4.4 Các hàm gộpCác hàm gộp là các hàm thực hiện việc thu thập các giá trị làm đầu vào và trả về một giá trị đơn. SQL hỗ trợ năm hàm tập hợp:

• Hàm tính trung bình: avg • Hàm tìm giá trị nhỏ nhất: min• Hàm tìm giá trị lớn nhất: max• Hàm tính tổng: sum• Hàm đếm: count

Đầu vào của hàm sum và hàm avg phải là một tập hợp các con số, đối với các hàm khác thì đầu vào ngoài con số có thể là kiểu dữ liệu không phải kiểu số, ví dụ kiểu chuỗi. Để minh họa, xét truy vấn “Tìm trung bình số tiền hiện có của các tài khoản tại chi nhánh Perryridge”. Chúng ta viết truy vấn này như sau:

select avg (balance)from accountwhere branch-name = ’Perryridge’

Kết quả của truy vấn này là một quan hệ với một thuộc tính duy nhất, chứa một bộ duy nhất với giá trị số tương ứng với giá trị trung bình của số tiền hiện có tại chi nhánh

12

Page 13: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Perryridge. Một cách tùy chọn, chúng ta có thể đặt tên cho thuộc tính của quan hệ kết quả bằng cách sử dụng mệnh đề as.

Có một số tình huống xảy ra khi chúng ta muốn thực hiện hàm gộp không chỉ trên một tập của bộ duy nhất mà còn trên một nhóm của tập các bộ, chúng ta phải chỉ rõ yêu cầu đó trong SQL bằng cách sử dụng mệnh đề group by. Thuộc tính hoặc tập các thuộc tính được cho trong mệnh đề group by được sử dụng để thành lập các nhóm. Các bộ với cùng giá trị trên tất cả các thuộc tính trong mệnh đề group by được dặt trong một nhóm.

Để minh họa, xét truy vấn “Tìm trung bình số tiền hiện có tại mỗi chi nhánh”. Chúng ta viết truy vấn này như sau:

select branch-name, avg (balance)from accountgroup by branch-name

Việc giữ lại các giá trị trùng nhau là việc quan trọng trong việc tính toán giá trị trung bình. Giả sử số tiền hiện có trong các tài khoản tại chi nhánh nhỏ Brighton là $1000, $3000, $2000 và $1000. Giá trị trung bình của các tài khoản là $7000/4=$1750.00. Nếu loại bỏ giá trị trùng nhau, chúng ta sẽ có câu trả lời sai ($6000/3=$2000).

Có một số trường hợp khi chúng ta phải loại bỏ giá trị trùng nhau trước khi tính toán hàm gộp Nếu chúng ta muốn loại bỏ giá trị tùng nhau, chúng ta sử dụng từ khóa distinct trong biểu thức gộp. Ví dụ xét truy vấn “Tìm số người có gửi tiền tại mỗi chi nhánh”. Trong trường hợp này, chỉ đếm mỗi người có tài khoản gửi ở ngân hàng một lần, cho dù người đó có nhiều tài khoản gửi tiền ở ngân hàng. Chúng ta viết truy vấn này như sau:

select branch-name, count (distinct customer-name)from depositor, accountwhere depositor.account-number = account.account-numbergroup by branch-name

Đôi khi thật hữu ích khi thực hiện trên một nhóm hơn là trên các bộ. Ví dụ, chúng ta có thể chỉ quan tâm đến số tiền trung bình tại các chi nhánh có giá trị lớn hơn $1200. Điều kiện này không chỉ áp dụng trên một bộ đơn mà còn áp dụng trên mội nhóm được thành lập bởi mệnh đề group by. Để diễn giải truy vấn này, chúng ta sử dụng mệnh đề having của SQL. SQL ứng dụng mệnh đề having sau khi nhóm đã được thành lập, do đó hàm gộp có thể được sử dụng. Chúng ta diễn giải truy vấn này bằng SQL như sau:

select branch-name, avg (balance)from accountgroup by branch-namehaving avg (balance) > 1200

13

Page 14: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Đôi khi chúng ta muốn đối xử toàn bộ quan hệ như một nhóm đơn. Trong các trường hợp đó, chúng ta không sử dụng mệnh đề group by. Xét truy vấn “Tìm số tiền trung bình của mỗi tài khoản”. Chúng ta viết truy vấn này như sau:

select avg (balance)from account

Chúng ta sử dụng hàm gộp count thường xuyên để đếm số lượng các bộ trong một quan hệ. Cú pháp của hàm này trong SQL là count(*). Do đó, để tìm số các bộ trong quan hệ customer, chúng ta viết:

select count (*)from customer

SQL không cho phép sử dụng distinct với count(*). Sẽ là hợp lệ khi sử dụng distinct với hàm max và min, cho dù kết quả không thay đổi. Chúng ta có thể sử dụng từ khóa all thay cho distinct để chĩ rõ là muốn giữ lại các giá trị trùng nhau, nhưng all là ngầm định, do đó không cần làm thế.

Nếu mệnh đề where và mệnh đề having xuất hiện trong cùng một truy vấn, SQL thực hiện mệnh đề where trước. Các bộ thỏa mãn biểu thức ở mệnh đề where sau đó sẽ được lập thành nhóm bởi mệnh đề group by. Tiếp theo đó SQL thực hiện mệnh đề having, tại mỗi nhóm, SQL sẽ loại bỏ ra khỏi nhóm những bộ không thỏa mãn mệnh đề having. Cuối cùng mệnh đề select sử dụng những nhóm còn lại để sinh ra các bộ trong bảng kết quả.

Để minh họa cho việc sử dụng cả hai mệnh đề having và where trong cùng một truy vấn, chúng ta xét truy vấn “Tìm số tiền trung bình của mỗi khách hàng sống ở Harrison và có tối thiểu ba tài khoản.”

select depositor.customer-name, avg (balance)from depositor, account, customerwhere depositor.account-number = account.account-number anddepositor.customer-name = customer.customer-name andcustomer-city = ’Harrison’group by depositor.customer-namehaving count (distinct depositor.account-number) >= 3

4.5 Giá trị rỗng

SQL cho phép sử dụng các giá trị rỗng để chỉ sự thiếu thông tin về giá trị của một thuộc tính. Chúng ta có thể sử dụng từ khóa đặc biệt trong các yêu cầu để kiểm tra giá trị null. Do đó, để tìm số tài khoản có sổ tiết kiệm ở ngân hàng nhưng với số tiền là rỗng, chúng ta viết:

select loan-numberfrom loanwhere amount is null

14

Page 15: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Từ khóa is not null sẽ kiểm tra sự không xuất hiện của giá trị rỗng. Việc sử dụng giá trị null trong các phép toán so sánh và số học sẽ gây ra một số rắc rối. (Đã thảo luận ở mục 3.3.4).

Bây giờ chúng ta chỉ ra cách thức SQL thao tác với các giá trị rỗng. Kết quả của biểu thức số học (ví dụ +, -, * hoặc /) là rỗng nếu bất kỳ các giá trị đầu vào là rỗng. SQL coi như unknown đối với kết quả của phép so sánh các giá trị rỗng (hoặc so sánh giá trị rỗng với khác rỗng).

Bởi vì câu lệnh ở mệnh đề where có thể liên quan đến các toán tử boolean như and, or và not nên việc định nghĩa các toán tử boolean được đề cập thêm để giải quyết giá trị unknown.

and: Kết quả của true và unknown là unknown, của false và unknown là false, trong khi của unknown và unknown là unknown.

or: Kết quả của true hoặc unknown là true, của false hoặc unknown là unknown, trong khi của unknown hoặc unknown là unknown.

not: Kết quả của not unknown là unknown.

SQL định nghĩa kết quả của câu lệnh SQL:select . . . from R1, · · ·,Rn where P

chứa (phép chiếu) các bộ trong R1x R2 x … Rn trong đó thỏa mãn yêu cầu P (là true với P). Nếu yêu cầu P định giá trị của các bộ trong R1x R2 x … Rn là false hoặc unknown thì các bộ đó không được đưa vào bảng kết quả.

SQL cũng cho phép chúng ta kiểm tra kết quả của phép so sánh có phải là unknown hay không, ngoài giá trị true và false, bằng cách dùng các mệnh đề is unknown và is not unknown. Các giá tị rỗng cũng gấy ra rắc rối trong việc xử lý đối với các toán tử gộp. Ví dụ, giả sử một vài bộ trong quan hệ loan có giá trị rỗng với thuộc tính amount. Xét truy vấn sau về tổng tất cả số tiền (amount) của tất cả các tài khoản trong loan:

select sum (amount)from loan

Các giá trị sẽ được tính tổng lại bao gồm các giá trị rỗng bởi vì có một vài bộ là giá trị rỗng. Chuẩn SQL cho rằng toán tử sum sẽ bỏ qua giá trị rỗng. Nói chung, các hàm gộp sẽ đối xử với các giá trị rỗng theo luật sau: Tất cả các hàm gộp, ngoại trừ hàm count(*) sẽ bỏ qua giá trị rỗng trong các giá trị đầu vào. Phép count của một giá trị rỗng cho kết quả là 0 và tất cả các phép toán gộp sẽ trả về giá trị rỗng khi ứng dụng trên tập rỗng.

Dữ liệu kiển boolean có thể có các giá trị như true, false và unknown như đã được giới thiệu trong SQL:1999.

4.6 Truy vấn con lồng vào nhauSQL cung cấp một cơ chế cho các truy vấn con lồng. Một truy vấn con với select-from where được lồng trong một truy vấn khác. Các truy vấn con thường được sử

15

Page 16: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

dụng để thực hiện các phép kiểm tra tập thành viên, thực hiện các so sánh trên tập hợp và xác định số các yếu tố trong một tập hợp. Chúng ta sẽ nghiên cứu chúng trong các phần nhỏ tiếp theo dưới đây.

4.6.1 Thành viên của tập hợp

SQL cung cấp từ khóa in để kiểm tra thành viên của tập hợp, trong đó tập hợp là tập các giá trị được sinh ra từ mệnh đề select. Từ khóa not in kiểm tra tính không phải là thành viên của tập hợp. Xét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng ta viết truy vấn này bằng cách giao của hai tập hợp: tập các khách hàng là người gửi tiền và tập các khách hàng và người vay tiền của ngân hàng. Chúng ta có thể thực hiện cách khác bằng cách tìm tất cả chủ tài khoản tại ngân hàng là thành viên của tập hợp khách vay tiền. Rõ ràng cách tính này cho ra cùng kết quả với cách trước đó nhưng cách này bắt chúg ta phải dùng toán tử in của SQL. Chúng ta bắt đầu tìm tất cả chủ tài khoản và viết truy vấn con như sau:. (select customer-name

from depositor)

Sau đó chúng ta cần tìm các khách hàng là người vay tiền tại ngân hàng và là người xuất hiện trong danh sách chủ tài khoản trong truy vấn con. Để thực hiện việc này, chúng ta lồng truy vấn con. Truy vấn như sau:

select distinct customer-namefrom borrowerwhere customer-name in (select customer-namefrom depositor)

Ví dụ này chỉ ra rằng có thể viết một truy vấn bằng nhiều cách. Đặc điểm này rất có ích cho người dùng vì nó cho phép người dùng sử dụng cách nào thuận tiện với họ nhất. Chúng ta sẽ thấy rằng có một số dư thừa trong SQL.

Trong ví dụ trước, chúng ta kiểm tra tính thành viên trên một quan hệ có một thuộc tính. Phép kiểm tra này cho phép kiểm tra tính thành viên của bất kỳ quan hệ nào trong SQL. Do đó chúng ta có thể viết lại truy vấn “Tìm tất cả các khách hàng có tài khoản vay và tài khoản gửi lại chi nhánh Perryridge” bằng một cách khác:

select distinct customer-namefrom borrower, loanwhere borrower.loan-number = loan.loan-number andbranch-name = ’Perryridge’ and(branch-name, customer-name) in(select branch-name, customer-namefrom depositor, accountwhere depositor.account-number = account.account-number)

16

Page 17: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Chúng ta sử dụng toán tử not in một cách tương tự như in. Ví dụ, tìm tất cả khách hàng có vay mượn ngân hàng nhưng không có tài khoản gửi ở ngân hàng, chúng ta viết:

select distinct customer-namefrom borrowerwhere customer-name not in (select customer-namefrom depositor)

Các toán tử in và not in cũng có thể được sử dụng trong tập liệt kê. Truy vấn tiếp theo sẽ chọn ra tên các khách hàng có vay mượn ngân hàng và tên khách hàng không phải là Smith hay Jones.

select distinct customer-namefrom borrowerwhere customer-name not in (’Smith’, ’Jones’)

4.6.2 Phép so sánh trên tập hợp

Để minh họa cho khả năng của truy vấn lồng đối với các tập so sánh, xét truy vấn “Tìm tên tất cả các chi nhánh có tài sản lớn hơn ít nhât một chi nhánh tại Brooklyn”. Trong phần 4.2.5, chúng ta viết truy vấn này như sau:

select distinct T.branch-namefrom branch as T, branch as Swhere T.assets > S.assets and S.branch-city = ’Brooklyn’

Tuy nhiên, SQL cung cấp thêm một cách viết khác. Yêu cầu “lớn hơn ít nhật một” được thay thế bằng > some. Cấu trúc này cho phép chúng ta viết lại truy vấn như sau:

select branch-namefrom branchwhere assets > some (select assetsfrom branchwhere branch-city = ’Brooklyn’)

Truy vấn con(select assetsfrom branchwhere branch-city = ’Brooklyn’)

sẽ sinh ra tập tất cả tài sản của tất cả chi nhánh ở Brooklyn. SQL cũng cho phép các so sánh <some, <=some, >=some, =some và <>some.

Coi như bài tập, hãy chứng tỏ rằng =some thì tương đương với in, trong khi đó <>some thì không giống not in. Từ khóa any tương đương với some tỏng SQL. Các phiên bản trươcs đos cuar SQL chỉ cho phép any. Các phiên bản sau thêm vào từ khóa thay thế some để tránh nhập nhằng về ngữ nghĩa của từ khóa any trong tiếng Anh.

17

Page 18: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Bây giờ chúng ta sửa một chút ở câu truy vấn: Tìm tên của tất cả chi nhánh có tài sản lớn hơn tài sản của mỗi chi nhánh ở Brooklyn. Cấu trúc >all tương ứng với yêu cầu “lớn hơn tất cả”. Sử dụng cấu trúc này, chúng ta viết truy vấn như sau:

select branch-namefrom branchwhere assets > all (select assetsfrom branchwhere branch-city = ’Brooklyn’)

Tương tự với some, SQL cũng cho phép các so sánh <all, <=all, >=all, =all và <>all. Như một bài tập, hãy chứng tỏ rằng <>all tương đương với not in.

Một ví dụ khác về so sánh tập hợp, xét truy vấn “Tìm chi nhánh có trung bình số tiền lớn nhất”. Trong SQL, các hàm gộp không thể lồng vào nhau. Do đó, chúng ta không thể sử dụng max(avg(…)). Thay vào đó, chúng ta có thể dùng cách: Trong khi chúng ta viết truy vấn tìm tất cả trung bình số tiền nhiều nhất, chúng ta lồng truy vấn con của một truy vấn lớn hơn về tìm các chi nhánh có trung bình số tiền lớn hơn hoặc bằng với tất cả các giá trị trung bình khác:

select branch-namefrom accountgroup by branch-namehaving avg (balance) >= all (select avg (balance)from accountgroup by branch-name)

4.6.3 Kiểm tra các quan hệ rỗng

SQL chứa các đặc tính cho việc kiểm tra một truy vấn con có bất kỳ bộ nào trong bảng kết quả hay không. Mệnh đề exists trả về giá trị true nếu tham số truy vấn con là khác rỗng. Sử dụng lệnh exists chúng ta có thể viết truy vấn “Tìm tất cả khách hàng có tài khoản gửi và tài khoản vay mượn tại ngân hàng” theo một cách khác:

select customer-namefrom borrowerwhere exists (select *from depositorwhere depositor.customer-name = borrower.customer-name)

Chúng ta có thể kiểm tra sự không tồn tại của các bộ trong truy vấn con bằng cách sử dụng lệnh not exists. Chúng ta có thể sử dụng lệnh not exists để mô phỏng phép toán trên tập hợp. Chúng ta có thể viết “quan hệ A chứa quan hệ B” bằng “not exists (B except A).” Để mô phỏng toasn tử not exists, xét lại truy vấn “Tìm tất cả khách hàng có có một tài khoản tại tất cả chi nhanhs ở Brooklyn.” Đối với khách hàng, chúng ta cần xem có phải tập của tất cả các chi nhánh mà khách hàng đó có tài khoản chưa tập tất cả chi nhánh ở Brooklyn. Sử dụng lệnh except, chúng ta có thể viết lại truy vấn như sau:

18

Page 19: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

select distinct S.customer-namefrom depositor as Swhere not exists ((select branch-namefrom branchwhere branch-city = ’Brooklyn’)except(select R.branch-namefrom depositor as T, account as Rwhere T.account-number = R.account-number andS.customer-name = T.customer-name))

Ở đây, truy vấn con:(select branch-namefrom branchwhere branch-city = ’Brooklyn’)finds all the branches in Brooklyn. The subquery(select R.branch-namefrom depositor as T, account as Rwhere T.account-number = R.account-number andS.customer-name = T.customer-name)

tìm tất cả các chi nhánh mà khách hàng S.customer-name có một tài khoản. Do đó, mệnh đề select bên ngoài mang mỗi khách hàng và kiểm tra xem tập các chi nhánh mà khách hàng đó có tài khoản có chứa tập tất cả các chi nhánh tại Brooklyn hay không.

4.6.4 Kiểm tra sự không hiện diện của các bộ trùng nhau

SQL chứa một đặc tính cho việc kiểm tra một truy vấn con có bất kỳ các bộ trùng nhau trong kết quả. Lệnh unique trả về giá trị true nếu tham số truy vấn con chứa các bộ không rỗng. Sử dụng lệnh construct, chúng ta có thể viết truy vấn “Tìm tất cả khách hàng có nhiều nhất một tài khoản tại chi nhánh Perryridge” như sau:

select T.customer-namefrom depositor as Twhere unique (select R.customer-namefrom account, depositor as Rwhere T.customer-name = R.customer-name andR.account-number = account.account-number andaccount.branch-name = ’Perryridge’)

Chúng ta có thể kiểm tra sự tồn tại của các bộ trùng nhau bằng cách sử dụng lệnh not unique. Để minh họa cho lệnh này, xé truy vấn “Tìm tất cả khách hàng có ít nhất hai tài khoản tiết kiệm tại chi nhánh Perryridge,” chúng ta viết lại như sau:

select distinct T.customer-namefrom depositor Twhere not unique (select R.customer-name

19

Page 20: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

from account, depositor as Rwhere T.customer-name = R.customer-name andR.account-number = account.account-number andaccount.branch-name = ’Perryridge’)

Một cách hình thức, từ khóa unique kiểm tra trên một quan hệ được định nghĩa là bất thành nếu và chỉ nếu quan hệ chứa hai bộ t1 và t2 sau cho t1=t2. Bởi vì việc kiểm tra t1=t2 là bất thành nếu bất kỳ thuộc tính của t1 và t2 là rỗng cho nên kết quả của unique là true cho dù có nhiều bản sao của một bộ.

4.7 Khung nhìn

Chúng ta định nghĩa khung nhìn trong SQL bằng cáh sử dụng lệnh create view. Để định nghĩa một khung nhìn, chúng ta phải cho mỗi khung nhìn một tên. Dạng của lệnh create view như sau:

create view v as <query expression>

trong đó <query expression> là bất kỳ biểu thức truy vấn hợp lệ. Tên của khung nhìn được đặt là v. Quan sát thấy rằng cú pháp chúng ta sử dụng để định nghĩa khung nhìn trên đại số quan hệ là dựa trên SQL.

Ví dụ, xét khung nhìn chứa tên chi nhánh và tên các khách hàng hoặc có một tài khoản gửi hoặc một tài khoản vay tại chi nhánh đó. Giả sử chúng ta muốn đặt tên khung nhìn là all-customer. Chúng ta định nghĩa khung nhìn đó như sau:

create view all-customer as(select branch-name, customer-namefrom depositor, accountwhere depositor.account-number = account.account-number)union(select branch-name, customer-namefrom borrower, loanwhere borrower.loan-number = loan.loan-number)

Tên các thuộc tính trong khung nhìn có thể chĩ rõ như sau:create view branch-total-loan(branch-name, total-loan) asselect branch-name, sum(amount)from loangroup by branch-name

Khung nhìn ở trên cho mỗi chi nhánh một tổng số tiền vay nợ của khách hàng tại chi nhánh. Bởi vì biểu thức sum(amount) không có tên, thuộc tính tên nên được chỉ rõ trong định nghĩa khung nhìn. Các tên khung nhìn có thể xuất hiện bất kỳ nơi nào mà tên quan hệ có thể xuất hiện. Sử dụng khung nhìn all-customer, chúng ta có thể tìm tất cả các khacsh hàng của chi nhánh Perryridge bằng cách viết như sau:

select customer-namefrom all-customer

20

Page 21: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

where branch-name = ’Perryridge’

4.8 Các truy vấn phức tạpCác truy vấn phức tạp thường khó hoặc không thể viết như một khối SQL đơn hoặc khối hợp/giao/trừ của SQL. (một SQL bao gồm một cau lệnh đơn select from wher, có thể có mệnh đề group by và having.) Ở đây chúng ta nghiên cứu hai cách tạo đa khối SQL để diễn đạt truy vấn phức tạp: quan hệ được sinh ra và mệnh đề with.

4.8.1 Các quan hệ được sinh ra

SQL cho phép một biểu thức truy vấn còn dược dùng trong mệnh đề from. Nếu chúng ta sử dụng biểu thức này thì chúng ta phải đặt tên cho qua hệ kết quả và chúng ta có thể đặt lại tên cho các thuộc tính. Chúng ta thực hiện việc đặt lại tên bằng cách sử dụng mệnh đề as. Ví dụ, xét truy vấn con:

(select branch-name, avg (balance)from accountgroup by branch-name)as result (branch-name, avg-balance)

Truy vấn này sinh ra một quan hệ chứa tên của các chi nhánh và trung bình số tiền hiện có tương ứng của mỗi chi nhánh. Kết quả của truy vấn con được đặt tên là result, với các thuộc tính branch-name và avg-balance.Để minh họa cho việc sử dụng biểu thức truy vấn con trong mệnh đề from, xét truy vấn “Tìm số tiền trung bình của các chi nhánh có số tiền trung bình lớn hơn $1200.” Chúng ta đã viết truy vấn này ở phần 4.4 bằng cách sử dụng mệnh đề having. Bây giờ chúng ta có thể viết lại truy vấn đề having như sau:

select branch-name, avg-balancefrom (select branch-name, avg (balance)from accountgroup by branch-name)as branch-avg (branch-name, avg-balance)where avg-balance > 1200

Lưu ý rằng chúng ta không cần sử dụng mệnh đề having, bởi vì truy vấn con trong mệnh đề from tính trung bình số tiền và kết quả đó được đặt tên là branch-avg; chúng ta có thể sử dụng trực tiếp các thuộc tính của branch-avg trong mệnh đề where.Một ví dụ khác, giả sử chúng ta muốn tìm giá trị cao nhất về số tiền của các chi nhánh. Mệnh đề having không thể giúp chúng ta tỏng việc này, nhưng chúng ta có thể viết truy vấn này một cách dễ dàng bằng cách sử dụng truy vấn con trong mệnh đề from, như sau:

select max(tot-balance)from (select branch-name, sum(balance)from accountgroup by branch-name) as branch-total (branch-name, tot-balance)

21

Page 22: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

4.8.2 Mệnh đề with

Các truy vấn phức tạp sẽ dễ viết và dễ hiểu hơn nếu chúng ta ngắt chúng thành những khung nhìn nhỏ, sau đó kết hợp lại như một chương trình có cấu trúc với các thủ tục là các công việc nhỏ. Tuy nhiên, không giống như một định nghĩa thủ tục, mệnh đề create view tạo ra một khung nhìn trong cơ sở dữ liệu và khung nhìn sẽ tồn tại đến khi có lệnh drop view view-name được thực thi.Mệnh đề with cung cấp một cách định nghĩa khung nhìn tạm thời trong đó khung nhìn chỉ có giá trị ở truy vấn có mệnh đề with. Xét truy vấn sau dùng để liệt kê các tài khoản có số tiền cao nhất; Nếu co nhiều tài khoản có cùng số tiền cao nhât, tất cả chúng được lựa chọn.. with max-balance (value) as

select max(balance)from accountselect account-numberfrom account, max-balancewhere account.balance = max-balance.value

Mệnh đề with được giới thiệu trong SQL:1999, hiện tại chỉ được hỗ trợ bởi một vài cơ sở dữ liệu. Chúng ta có thể viết truy vấn trên bằng cách sử dụng truy vấn con lồng trong mệnh đề from hoặc mệnh đề where. Tuy nhiên, sử dụng các truy vấn con lồng có thể làm truy vấn khó đọc và khó hiểu hơn. Mệnh đề with làm truy vấn rõ hơn, nó cho phép một định nghĩa khung nhìn được sử dụng nhiều chỗ trong môtj truy vấn.Ví dụ, giả sử chúng ta muốn tìm tất cả các chi nhánh mà tổng số tiền hiện có nhỏ hơn trung bình số tiền của tất cả các chi nhánh khác. Chúng ta viết truy vấn bằng cách sử dụng mệnh đề with như sau:

with branch-total (branch-name, value) asselect branch-name, sum(balance)from accountgroup by branch-namewith branch-total-avg(value) asselect avg(value)from branch-totalselect branch-namefrom branch-total, branch-total-avgwhere branch-total.value >= branch-total-avg.value

Dĩ nhiên chúng ta có thể tạo một truy vấn tương đương bằng cách không sử dụng mệnh đề with, nhưng sẽ khó hiểu và phức tạp hơn. Cách viết lại truy vấn tương đương coi như bài tập.

4.9 Sửa đổi cơ sở dữ liệu22

Page 23: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Chúng ta giới hạn sự chú ý đến bây giờ về việc rút trích thông tin về cơ sở dữ liệu. Bây giờ chúng ta chỉ ra làm cách nào thêm, gỡ bỏ hoặc thay đổi thông tin với SQL.

4.9.1 Xóa

Yêu cầu xóa được diễn đạt cùng kiểu với truy vấn. Chúng ta có thể chỉ xóa A delete request is expressed in much the same way as a query. SQL diễn đạt phép xóa bởi:

delete from rwhere P

trong đó P đại diện cho điều kiện và r là tên quan hệ. Trước tiên lệnh xóa delete sẽ tìm tất cả các bộ t trong r mà trong đó P(t) là đúng và sau đó xóa chúng khỏi r. Mệnh đề where có thể lược bỏ, khi đó tất cả các bộ của r sẽ bị xóa.Lưu ý rằng lệnh delete chỉ thực hiện trên một quan hệ. Nếu chúng ta muốn xóa các bộ từ nhiều quan hệ khác, chúng ta phải sử dụng một lệnh delete cho mỗi quan hệ.

Điều kiện trong mệnh đề where có thể phức tạp và được thể hiện bằng câu lệnh select đặt trong mênhj đề where. Mệnh đề where có thể rỗng. Ví dụ, yêu cấu:

delete from loansẽ xóa tất cả các bộ trong quan hệ loan. Sau đây là một số ví dụ về câu lệnh xóa trong SQL:

Xóa tất cả các bộ của quan hệ account tại chi nhánh Perryridge.delete from accountwhere branch-name = ’Perryridge’

Xóa tất cả các bộ trong quan hệ loan với số tiền vay mượn trong khoảng $1300 và $1500.delete from loanwhere amount between 1300 and 1500

Xóa tất cả các bộ trong quan hệ account của mỗi chi nhánh tại Needham.delete from accountwhere branch-name in (select branch-namefrom branchwhere branch-city = ’Needham’)

Trước tiên, yêu cầu delete sẽ tìm tất cả các chi nhánh ở Needham, sua đó xóa tất cả các bộ trong quan hệ account đạt được ở chi nhánh đó.Lưu ý rằng, mặc dù mỗi một lần chúng ta chỉ có thể xóa các bộ trong một quan hệ, nhưng chúng ta có thể tham chiếu nhiều quan hệ khác trong mệnh đề select-from-where được lồng trong mệnh đề wherecủa câu lệnh delete. Yêu cầu delete có thể chứa một select lồng trong đó tham chiếu đến quan hệ có các bộ sẽ bị xóa. Ví dụ, giải sử chúng ta muốn xóa các bản ghi của quan hệ account có số tiền nhỏ hơn số tiền trung bình. Chúng ta có thể viết:

delete from account23

Page 24: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

where balance < (select avg (balance)from account)

Trước tiên, lệnh delete kiểm tra mỗi yêu cầu trong quan hệ account để kiểm tra account đó có số tiền có nhỏ hơn số tiền trung bình tại ngân hàng hay không. Sau đó,tất cả các bộ thỏa mãn điều kiện sẽ bị xóa. Việc thực hiện tất cả các kiểm tra trước khi thực hiện việc xóa là rất quan trọng – nếu một số bộ bị xóa trước khi kiểm tra, giá trị trung bình có thể thay đổi và kết quả cuối cùng của phép delete sẽ phụt huộc vào thứ tự các bộ được xử lý!

4.9.2 Chèn

Để chèn dữ liệu vào trong một quan hệ, chúng ta hoặc phải chỉ rõ bộ nào được chèn hoặc viết một truy vấn đưa ra tập các bộ sẽ được chèn. Rõ ràng, các giá trị thuộc tính của các booj được chèn phải nằm trong tập thuộc tính của quan hệ được chèn. Tương tự, các bộ được chèn phải có giá trị nằm trong miền cho phép.

Câu lệnh đơn giản nhất là yêu cầu chèn một bộ. Giả sử chúng ta muốn chèn một tài khoản có số tài khoản là A-9732 tại chi nhánh Perryridge và có số dư là $1200. Chúng ta viết:

insert into accountvalues (’A-9732’, ’Perryridge’, 1200)

Trong ví dụ này, các giá trị được chỉ rõ theo thứ tự tương ứng với tên các thuộc tính được liệt kê trong lược đồ quan hệ. Để thuận tiện cho người sử dụng không nhớ thứ tự của các thuộc tinhs, SQL cho phép liệt kê tên các thuộc tính trong câu lệnh insert. Ví dụ, câu lệnh SQL insert sau đây sẽ diễn đạt tương tự yêu cầu của câu lệnh bên trên:

insert into account (account-number, branch-name, balance)values (’A-9732’, ’Perryridge’, 1200)insert into account (branch-name, account-number, balance)values (’Perryridge’, ’A-9732’, 1200)

Tổng quát hơn, chúng ta có thể muốn chèn các bộ vào kết quả của một truy vấn. Giả sử chúng ta muốn chèn vào quan hệ account với số tiền $200 như một món quà cho tất cả các khách hàng vay nợ tại chi nhánh Perryridge. Xem số tài khoản vay mượn như số tài khoản gửi tiền tại ngân hàng. Chúng ta viết:

insert into accountselect loan-number, branch-name, 200from loanwhere branch-name = ’Perryridge’

Trong phần này, thay vì chỉ rõ một bộ, chúng ta dùng câu lệnh select để chỉ ra tập các bộ. Trước tiên, SQL sẽ duyệt qua mệnh đề select, cho một tập các bộ và sau đó chèn vào quan hệ account. Mỗi bộ có một loan-number (giống như số tài khoản của một khách hàng mới), một branch-name (Perryridge), và một tài khoản khởi tạo ban đầu ($200).

24

Page 25: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Chúng ta cũng cần thêm các bộ vào quan hệ depositor; chúng ta làm việc này bằng cách viết:

insert into depositorselect customer-name, loan-numberfrom borrower, loanwhere borrower.loan-number = loan.loan-number andbranch-name = ’Perryridge’

Truy vấn này chèn một bộ (customer-name, loan-number) vào quan hệ depositor cho mỗi tên khách hàng customer-name có một tài khoản vay nợ tại chi nhánh Perryridge với số tài khoản vay mượn là loan-number.Việc quét qua cầu lệnh select trước khi thực hiện chèn là rất quan trọng. Nếu chúng ta thực hiện một vài phép chèn trước khi quét qua câu lệnh select, ví dụ có một yêu cầu:

insert into accountselect *from account

thì có thể chúng ta sẽ chèn một số lượng không xác định của các bộ! Yêu cầu sẽ chèn bộ đầu tiên vào account lần nữa, rồi tạo ra một bản sao thứ hai của bộ. Bởi vì bản sao thứ 2 là một phần của account hiện tại, nên câu lệnh select có thể tìm thấy nó và bản sao thứ ba sẽ được chèn vào account. Câu lệnh select sau đó có thể tìm thấy bản sao thứ ba và chèn bản sao thứ tư, cứ thế tiếp diễn mãi. Việc duyệt qua câu lệnh select trước khi thực hiện phép chèn sẽ tránh được rắc rối trên.Các thảo luận của chúng ta trong câu lệnh insert chỉ xét các ví dụ có giá trị được cho đối với mội thuộc tính được chèn giá trị. Các thuộc tính còn lại được gán giá trị rỗng và ký hiệu là null. Xét yêu cầu:

insert into accountvalues (’A-401’, null, 1200)

Chúng ta biết rằng số tài khoản A-401 có $1200, nhưng tên chi nhánh chưa biết. Xét truy vấn:

select account-numberfrom accountwhere branch-name = ’Perryridge’

Bởi vì ta chưa biết chi nhánh nào có chứa mã tài khoản A-401, chúng ta không thể xác định có phải là thuộc chi nhánh “Perryridge” hay không.Chúng ta có thể cấm việc chèn các giá trị rỗng vào trong các thuộc tính được chỉ định bằng cách sử dụng SQL DLL, sẽ bàn ở phần 4.11.

4.9.3 Cập nhật

Trong một số trường hợp nào đó, chúng ta muốn thay đổi giá trị trong một bộ mà không cần thay đổi tất cả các giá trị trong bộ đó. Yêu cầu này có thể được thực hiện nhờ lệnh update. Giống như lệnh insert và delete, chúng ta có thể chọn các bộ để cập nhật bằng cách sử dụng truy vấn.

25

Page 26: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Giả sử rằng muốn thực hiện việc chi trả lợi nhuận hàng năm cho tất cả các tài khoản lên 5%. Chúng ta viết:

update accountset balance = balance * 1.05

Câu lệnh cập nhập trên được thực hiện một lần cho các bộ trong quan hệ account. Nếu lợi nhuận chỉ trả cho các tài khoản có số tiền lớn hơn hoặc bằng $1000 or more, chúng ta có thể viết:

update accountset balance = balance * 1.05where balance >= 1000

Một cách tổng quát, mệnh đề where của lệnh update có thể chứa bất kỳ câu lệnh select hợp lệ bất kỳ (bao gồm các câu lệnh select lồng). Giống như lệnh insert và delete, câu lệnh select lồng trong lệnh update có thể đề cập đến quan hệ sẽ được cập nhật. Cũng giống như trước đó, đầu tiên SQL kiểm tra tất cả các bộ trong quan hệ để xác định bộ nào sẽ được cập nhật, sau đó thực hiện lệnh cập nhật lên các bộ đó.Ví dụ, chúng ta có thể thực hiện yêu cẩu “Trả 5% lợi luận cho các tài khoản có số tiền lớn hơn trung bình số tiền” như sau:

update accountset balance = balance * 1.05where balance > select avg (balance)from account

Bây giờ chúng ta giả sử rằng tất cả các tài khoản có số dư trên $10,000 sẽ được nhận 6% lợi nhuận, các trường hợp khác nhận 5%. Chúng ta có thể viết hai lệnh update như sau:

update accountset balance = balance * 1.06where balance > 10000update accountset balance = balance * 1.05where balance <= 10000

Lưu ý rằng, như trong chương 3, thứ tự của hai lệnh update là rất quan trọng. Nếu chúng ta thay đổi thứ tự của hai lệnh, một tài khoản với số dư dưới $10,000 sẽ nhận tổng cộng 11.3% lợi nhuận. SQL cung cập cấu trúc case, cho phép chúng ta sử dụng để thực hiện cả hai lệnh cập nhật với một câu update, tránh được rắc rối với thứ tự của các phép cập nhật.

update accountset balance = casewhen balance <= 10000 then balance * 1.05else balance * 1.06end

Dạng chung của câu lệnh case như sau:casewhen pred1 then result1

26

Page 27: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

when pred2 then result2. . .when predn then resultnelse result0end

Phép toán sẽ trả về kết quả resulti, trong đó i là vế trước của pred1, pred2, . . . , predn mà nó thỏa mãn; Nếu không có điều kiện nào thỏa mãn thì phép toán sẽ trả về kết quả là result0. Câu lệnh case có thể được sử dụng bấy kỳ nơi nào mà giá trị mong muốn được chỉ định.

4.9.4 Cập nhật khung nhìnĐể minh họa, xét định nghĩa khung nhìn sau:

create view loan-branch asselect branch-name, loan-number from loan

Bởi vì SQL cho phép tên khung nhìn xuất hiện ở bất cứ nơi nào mà tên quan hệ được phép, chúng ta có thể viết:

insert into loan-branchvalues (’Perryridge’, ’L-307’)

SQL trình bày phép chèn này bằng cách chèn vào trong quan hệ loan, bởi vì loan là quan hệ thực sự mà khung nhìn loan-branch được tạo ra từ đó. Do đó, chúng ta phải có một vài giá trị cho amount. Giá trị này là giá trị rỗng. Do đó, kết quả của phép insert trước đó cho bộ (’L-307’, ’Perryridge’, null) vào quan hệ loan.Như đã trình bày ở Chương 3, việc cập nhật khung nhìn rất khó thực hiện khi khung nhìn được tạo ra từ nhiều quan hệ. Chính vì lý do đó, nhiều hệ thống cơ sở dữ liệu dựa trên SQL đề ra các ràng buộc sau đây để cho phép cập nhật khung nhìn:

Một thao tác sửa đổi được cho phép qua khung nhìn chỉ nếu khi khung nhìn được tạo ra từ một quan hệ của cơ sở dữ liệu quan hệ thực tế - nghĩa là, cơ sở dữ liệu mức logic.

Với ràng buộc này, các phép update, insert, và delete sẽ bị ngăn cấm như ví dụ khung nhìn all-customer được định nghĩa trước đó.

4.9.5 Các giao tác

Một giao tác, transaction, bao gồm tuần tự các truy vấn và/hoặc cập nhật. Các chuẩn SQL chỉ rõ rằng một giao tác bắt đầu với việc khi một câu lệnh SQL được thực hiện.Một trong nhứng câu lệnh SQL dưới đây sẽ kết thúc giao tác:

Commit work: Chuyển giao giao tác hiện tại, nghĩa là lệnh này làm cho các cập nhật được thực hiện bởi giao tác trở nên vĩnh diễn trong cơ sở dữ liệu. Sau khi giao tác được chuyển giao, một giao tác mới tự động bắt đầu.

Rollback work: Sẽ gây ra việc giao tác hiện tại sẽ bị thu hồi lại; nghĩa là lệnh này sẽ xóa bỏ tất cả các cập nhật được thực hiện bằng câu lệnh SQL trong giao tác. Do đó, trạng thái của cơ sở dữ liệu sẽ được phục hồi như trước khi thực hiện câu lệnh đầu tiên của giao tác.

27

Page 28: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Từ khóa work là tùy chọn trong cả hai câu lệnh. Giao tác rollback rất hữu ích trong trường hợp một số lỗi được phát hiện trong quá trình thực hiện giao tác. Lệnh commit lưu tất cả các thay đổi cho tài liệu mà nó được thao tác, trong khi lệnh rollback thì tương đương với việc thoát khỏi việc soạn thảo mà không lưu lại các thay đổi. Khi một giao tác thực hiện lệnh commit work, các tác động của nó không thể xóa bỏ lại bằng lệnh rollback work. Hệ thống cơ sở dữ liệu phải đảm bảo rằng trong một số hư hỏng, ví dụ như một lỗi xuất hiện trong một câu lệnh SQL, hoặc tắt nguồn điện, hoặc xung đột hệ thống, thì các tác động của giảo tác sẽ bị thu hồi lại khi nó chưa thực hiện lệnh commit work. Trong trường hợp tắt nguồn điện hoặc xung đột hệ thống, lệnh rollback sẽ thực hiện khi hệ thống khởi động lại.Ví dụ, để chuyển tiền từ một tài khoản vào một tài khoản khác, chúng ta cần cập nhật số dư của cả hai tài khoản. Hai câu lệnh cập nhật sẽ hình thành một giao tác. Nếu một lỗi xảy ra trong khi thực hiện giao tác này, thì một trong các lệnh của nó phải khôi phục lại trạng thác ban đầu, để cho cơ sở dữ liệu được nhất quán. Trong nhiều SQL, mặc định mỗi câu lệnh SQL được coi như mà một giao tác và nó sẽ bị thu hồi lại ngay sau khi nó được thực hiện. Việc tự động chuyển giao các câu lệnh SQL phải được tắt nếu giao tác đó chứa nhiều câu lệnh SQL. Các gỡ bỏ việc tự động chuyển giao phụ thuộc vào mỗi chuẩn SQL cụ thể.

4.10 Các quan hệ được kết nối ∗∗SQL không chỉ cung cấp cơ chế phép tích Đề-các để liên kết các bộ của quan hệ mà còn cung cấp các cơ chế khác cho việc kết nối các quan hệ, bao gồm kết nối có điều kiện và kết nối tự nhiên, cũng như các dạng kết nối bên ngoài. Các phép toán thêm vào thường được sử dụng trong các biểu thức truy vấn con trong mệnh đề from.

Hình 4.1. Quan hệ cho vay, loan, và quan hệ mượn, borrower

4.10.1 Các ví dụ

Chúng ta minh họa các phép kết nối bằng cách sử dụng quan hệ loan và borrower trong Hình 4.1. Chúng ta bắt đầu với ví dụ đơn giản của phép kết nối trong. Hình 4.2 hiển thị kết quả của biểu thức:

loan inner join borrower on loan.loan-number = borrower .loan-numberBiểu thức tính toán phép kết nối theta của hai quan hệ loan và borrower, với điều kiện kết nối là loan.loan-number = borrower.loan-number. Các thuộc tính của kết quả bao gồm các thuộc tính của quan hệ bên trái tiếp theo là các thuộc tính của quan hệ bên phải.

28

Page 29: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Lưu ý rằng thuộc tính loan-number xuất hiện hai lần trong hình – lần thứ nhất từ quan hệ loan, và lần thứ hai từ quan hệ borrower. Chuẩn SQL không yêu cầu tên các thuộc tính là duy nhất. Mệnh đề as dùng để gán tên cho các thuộc tính trong kết quả của truy vấn con.Chúng ta đổi tên các thuộc tính của quan hệ kết quả của phép kết nối bằng cách sử dụng mệnh đề as, như minh họa dưới đây:

loan inner join borrower on loan.loan-number = borrower.loan-numberas lb(loan-number, branch, amount, cust, cust-loan-num)

Chúng ta đổi tên sự xuất hiện thứ hai của loan-number thành cust-loan-num. Thứ tự của các thuộc tính trong kết quả của phép kết nối là quan trọng cho việc đổi tên. Tiếp theo, chúng ta xét một ví dụ của phép left outer join:

loan left outer join borrower on loan.loan-number = borrower.loan-numberloan-number branch-name amount customer-name loan-number

Hình 4.2 Kết quả của phép kết nối trong, loan inner join borrower onloan.loan-number = borrower .loan-number .

Figure 4.3 Kết quả của phép kết nối bên trái, loan left outer join borrower onloan.loan-number = borrower .loan-number.

Chúng ta có thể tính toán phép toán kết nối bên trái như sau. Đầu tiên, tính kết quả của phép kết nối trong như trước đó. Sau đó, đối với mỗi bộ t trong quan hệ phía bên trái là quan hệ loan không kết hợp với bất cứ bộ nào trong quan hệ borrower phía bên phải trong phép kết nối trong, thêm một bộ r vào quan hệ kết quả: Các thuộc tính của bộ r được dẫn xuất từ quan hệ bên trái được làm đầy với các giá trị của bộ t, và các thuộc tính còn lại của r được làm đầy với giá trị rỗng. Hình 4.3 chỉ ra quan hệ kết quả. Bộ (L-170, Downtown, 3000) và (L-230, Redwood, 4000) kết hợp với các bộ quả quan hệ borrower và xuất hiện trong kết quả của phép kết nối trong, và do đó cũng xuất hiện trong kết quả của kết nối bên trái. Mặt khác, bộ (L-260, Perryridge, 1700) không kết hợp với bất kỳ bộ nào của quan hệ borrower trong phép kết nối trong, và do đó bộ (L-260, Perryridge,1700, null, null) được trình bày trong kết quả của phép kết nối bên trái.

29

Page 30: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Cuối cùng, chúng ta xét một ví dụ về phép kết nối tự nhiên, natural join:loan natural inner join borrower

Biểu thức tính toán phép kết nối tự nhiên của hai quan hệ. Kết quả chỉ hiển thị các thuộc tính chung của hai quan hệ loan và borrower là loan-number. Hình 4.4 trình bày kết quả của biểu thức. Kết quả này tương tự như kết quả của phép kết nối trong với điều kiện on như trong hình 4.2, bởi vì chúng có cùng điều kiện kết nối. Tuy nhiên, thuộc tính loan-number chỉ xuất hiện một lần trong kết quả của phép kết nối tự nhiên, trong khi đó nó xuất hiện hai lần trong kết quả của phép kết nối với điều kiện on.

Hình 4.4 Kết quả của kết nối trong, loan natural inner join borrower.

4.10.2 Điều kiện và các kiểu kết nối

Trong phần 4.10.1, chúng ta đã xét ví dụ về các phép kết nối được cho phép trogn SQL. Các phép kết nối sẽ thực hiện trên hai quan hệ và trả về một quan hệ kết quả. Mặc dù biểu thức kết nối ngoài thường được sử dụng ở mệnh đề from, nhưng chúng cũng có thể được sử dụng ở bất cứ nơi nào mà một quan hệ có ể sử dụng.Mỗi biến của phép kết nối trong SQL bao gồm một kiểu kết nối và một điều kiện kết nối. Điều kiện kết nối chỉ ra các bộ nào trong hai quan hệ sẽ kết hợp với nhau và thuộc tính nào sẽ hiện diện trong kết quả kết nối. Kiểu kết nối định nghĩa các bộ nào trong mỗi quan hệ sẽ không kết nối với bộ nào trong quan hệ còn lại (dựa vào điều kiện kết nối). Hình 4.5 chỉ ra một số kiểu kết nối và điều kiện kết nối được phép.

Hình 4.5 Các kiểu kết nối và điều kiện kết nối.

Kiểu kết nối đầu tiên là kết nối trong, inner join, và ba kiển kết nối ngoài. Trong ba điều kiện kết nối, chúng ta đã thấy phép kết nối tự nhiên, natural join, và điều kiện on trước đó, và chúng ta sẽ thảo luận điều kiện using ở phần cuối của mục này.Việc sử dụng điều kiện kết nối là bắt buộc đối với các kết nối ngoài, nhưng là tùy chọn đối với kết nối trong (nếu không có điều kiện thì kết quả của kết nối trong giống như tích Đề-các). Về mặt cú pháp, từ khóa natural xuất hiện trước kiểu kết nối, như trình bày trước đó, trong khi đó các điều kiện on và using xuất hiện cuối của biểu thức kết nối. Từ khóa inner và outer là tùy chọn, bởi vì phần cuối của kiểu kết nối cho phép chúng ta suy ra kiểu kết nối là kết nối trong hay ngoài.

30

Page 31: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Ý nghĩa của điều kiện natural, theo thuật ngữ là các bộ từ hai quan hệ kết hợp với nhau theo cách đơn giản. Thứ tự của các thuộc tính trong quan hệ kết quả của phép kết nối tự nhiên như sau. Các thuộc tính kết nối (nghĩa là các thuộc tính chúng của hai quan hệ) sẽ xuất hiện trước, theo thứ tự chúng xuất hiện trong quan hệ phía bên trái. Tiếp đến là tất cả các thuộc tính không tham gia kết nối của quan hệ bên trái và cuối cùng là các thuộc tính không tham gia kết nối của quan hệ bên phải.Kết nối ngoài bên phải, right outer join thì tương tự như kết nối ngoài bên trái, left outer join. Các bộ từ quan hệ bên phải không khớp với bất kỳ bộ nào trong quan hệ bên trái được thay bằng giá trị rỗng và được thêm vào quan hệ kết quả của kết nối ngoài bên phải.Sau đây là một ví dụ của việc kết hợp điều kiện kết nối tự nhiên với kiểu kết nối ngoài bên phải:

loan natural right outer join borrowerHình 4.6 chỉ ra kết quả của biểu thức này. Các thuộc tính của kết quả được định nghĩa bởi kiểu kết nối, là kiểu kết nối tự nhiên; do đó, loan-number chỉ xuất hiện một lần. Hai bộ đầu tiên trong kết quả là từ kết nối tự nhiên của loan và borrower. Bộ (Hayes, L-155) từ quan hệ bên phải không khớp với bộ nào với quan hệ bên trái loan trong kết nối tự nhiên. Do đó, bộ (L-155, null, null, Hayes) xuất hiện trong bảng kết quả.

Figure 4.6 The result of loan natural right outer join borrower. Điều kiện kết nối using(A1,A2, . . . , An) thì tương tự như điều kiện kết nối tự nhiên, ngoại trừ rằng các thuộc tính kết nối là A1,A2, . . . , An, chứ không phải là tất cả các thuộc tính chung của cả hai quan hệ. Các thuộc tính A1,A2, . . .,An phải chỉ chứa các thuộc tính chung của cả hai quan hệ và chúng chỉ xuất hiện một lần trong kết quả của phép kết nối.Kiểu kết nối full outer join là sự kết hợp của kiểu kết nối bên trái và kết nối bên phải. Sau khi tính toán kết quả của kết nối trong, nó mở rộng với các bộ rỗng từ quan hệ bên trái mà không khớp với bộ nàocủa quan hệ bên phải, và thêm chúng vào bảng kết quả. Tương tự, nó mở rộng các bộ rỗng của quan hệ bên phải mà không khớp với bộ nào của quan hệ bên trái và thêm chúng vào bảng kết quả.

Ví dụ, Hình 4.7 trình bày kết quả của biểu thức:loan full outer join borrower using (loan-number)

31

Page 32: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Hình 4.7 Kết quả của kết nối ngoài đầy đủ của: loan full outer join borrower using(loan-number).

Một ví dụ khác của việc sử dụng phép toán kết nối ngoài, chúng ta có thể viết truy vấn “Tìm tất cả các khách hàng có một tài khoản nhưng không có tài khoản vay mượn tại ngân hàng” như sau:

select d-CNfrom (depositor left outer join borroweron depositor.customer-name = borrower.customer-name)as db1 (d-CN, account-number, b-CN, loan-number)where b-CN is null

Tươgn tự, chúng ta có thể viết truy vấn “Tìm tất cả khách hàng hoặc có tài khoản ở ngân hàng hoặc có tài khoản vay mượn (hoặc không có cả hai loại) tại ngân hàng” với phép kết nối tự nhiên ngoài đầy đủ như sau:

select customer-namefrom (depositor natural full outer join borrower)where account-number is null or loan-number is null

SQL-92 cũng hỗ trợ hai kiểu kết nối khác, gọi là kết nối chéo cross join và kết nối hợp, union join. Phép đầu tiên tương tự như kết nối trong không có điều kiện kết nối; phép thứ hai tương tự như kết nối ngoài đầy đủ trên điều kiện sai “false”—nghĩa là, ở đó kết nối trong là rỗng.

4.11 Ngôn ngữ định nghĩa dữ liệu

Trong hầu hết các thảo luận của chúng ta về SQL và cơ sở dữ liệu quan hệ, chúng ta đã chấp nhận tập các quan hệ được cho. Dĩ nhiên, tập các quan hệ trong cơ sở dữ liệu phải được chỉ rõ trong hệ thống bằng ngôn ngữ định nghĩa dữ liệu, data definition language (DDL).Ngôn ngữ DDL không chỉ định nghĩa một tập các quan hệ mà còn chỉ ra thông tin về mỗi quan hệ, bao gồm:

Lược đồ của mỗi quan hệ Miền giá trị tương ứng cho mỗi thuộc tính Các ràng buộc toàn vẹn Tập các chỉ mục được giữ lại trong mỗi quan hệ

32

Page 33: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Thông tin về phân quyền và bảo mật của mỗi quan hẹ Cấu trúc lưu trữ vật lý của mỗi quan hệ trên đĩa

Ở đây chúng ta sẽ thảo luận định nghĩa lược đồ quan hệ và các miền giá trị, chúng ta chuyển các đặc điểm khác của SQL DDL sang Chương 6.

4.11.1 Các kiểu dữ liệu trong SQL

Chuẩn SQL hỗ trợ một loạt cac kiểu dữ liệu sau:

char(n): Kiểu ký tự chuỗi với độ dài cố định n. Dạng đầy đủ, character, có thể được sử dụng.

varchar(n): Kiểu ký tự chuỗi với độ dài thay đổi với sự chỉ ra độ dài tối đa n. Dạng đầy đủ character varying, có thể được sử dụng.

int: Kiểu số nguyên (một tập xác định các số nguyên). Có thể viết đây đủ là integer.

smallint: Kiểu số nguyên nhỏ numeric(p, d): Kiểu số thập phân với độ chính xác được người dùng chỉ ra.

Con số bảo gồm p chữ số (gồm cả dấu) và d của p chữ số là số thập phân. Vì vậy, numeric(3,1) cho phép 44.5 được lưu trữ, nhưng không cho phép 444.5 hoặc 0.32

real, double precision: Kiểu số thực động. float(n): Số thực động với độ chính xác n chữ số. date: Ngày theo lịch chứa năm (bốn số), tháng và ngày của tháng. time: Giờ trong ngày, trả về giờ, phút và giây. Biến time(p) có thể chỉ ra số

thập phân của giây (ngầm định là 0). Nó cũng có thể lưu trữ thông tin về múi giờ cùng với thông tin về thời gian.

timestamp: Sự kết hợp giữa date và time. Biến timestamp(p) có thể dùng để chỉ số các số thập phân cho giây (mặc định là 6).

Các giá trị ngày và thời gian có thể như sau:date ’2001-04-25’time ’09:30:00’timestamp ’2001-04-25 10:29:01.45’

Ngày phải chỉ rõ định dạng năm, tiếp theo là tháng và ngày. Thuộc tính time hoặc timestamp có thể có phần thập phân như timestamp ở trên. Chúng ta có thể sử dụng biểu thức dạng cast e as t để chuyển đổi một ký tự chuỗi e sang kiểu t, trong đó t là một trong date, time, hoặc timestamp. Chuỗi phải là dạng phù hợp được trình bài tại phần đầu của đoạn này.Để rút trích các giá trị cụ thể của date hoặc time d, chúng ta có thể sử dụng extract (field from d), trong đó field có thể là một trong year, month, day, hour, minute, hoặc second.

33

Page 34: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

SQL cho phép các toán tử so sánh trên tất cả các kiểu dữ liệu được liệt kê bên trên, và nó cho phép cả hai phép so sánh và số học. SQL cũng cung cấp một kiểu dữ liệu gọi là interval, dùng để tính khoảng cách về ngày tháng và thời gian. Ví dụ, nếu x và y là kiểu date, thì x − y là khoảng thời gian về số ngày từ ngày x đến ngày y. Tương tự, phép cộng hoặc trừ một khoảng thời gian trên kiểu date trả về kiểu date. Thông thường chúng ta hay so sánh các giá trị từ các miền tương xứng với nhau compatible. Ví dụ, bởi vì mỗi small integer là một integer, nên phép so sánh x < y, trong đó x là small integer coi và y là integer (hoặc ngược lại), được cho phép. Chúng ta thực hiện phép so sánh này bằng cách coi small integer x như là một integer. Phép chuyển đổi kiểu này gọi là type coercion.

Thông thường Type coercion được sử dụng trong các ngôn ngữ lập trình thông thường cũng như trong hệ cơ sở dữ liệu.Để minh họa, giả sử rằng miền giá trị của customer-name là kiểu chuỗi với chiều dài 20, và miền của branch-name là kiểu chuỗi với chiều dài 15. Mặc dù chiều dài chuỗi có thể khác nhau, chuẩn SQL coi hai miền giá trị này là như nhau.

SQL cho phép khai báo một thuộc tính bào gồm chỉ định not null và cấm chèn giá trị rỗng cho thuộc tính này. Bất kỳ sửa đổi trên cơ sở dữ liệu mà gây ra việc chèn giá trị rỗng cho thuộc tính với giá trị not null sẽ gây ra lỗi. Có một số trường hợp chúng ta muốn tránh giá trị rỗng. Cụ thể, cấm chèn giá trị rỗng cho thuộc tính là khóa chính của lược đồ quan hêk. Do đó, trong ví dụ về ngân hàng của chúng ta, quan hệ customer phải cấm giá trị rỗng cho thuộc tính customer-name, vì đó là thuộc tính khóa của quan hệ customer.

4.11.2 Định nghĩa lược đồ trong SQL

Chúng ta định nghĩa một quan hệ SQL bằng cách sử dụng câu lệnh create table:create table r(A1D1,A2D2, . . . , AnDn,[ integrity-constraint1],…,[ integrity-constraintk])

Trong đó r là tên của quan hệ, mỗi Ai là tên một thuộc tính của lược đồ quan hệ r, và Di là kiểu dữ liệu của thuộc tính Ai. Các ràng buộc được phép bao gồm:

• primary key (Aj1,Aj2, . . .,Ajm): Khóa chính primary key chỉ ra thuộc tính Aj1,Aj2, . . .,Ajm trở thành khóa chính của quan hệ. Các thuộc tính khóa chính được yêu cầu là duy nhất và khác rỗng. Nghĩa là, không có bộ nào có giá trị rỗng cho thuộc tính khóa chính và không có hai bộ nào trong quan hệ có giá trị ở thuộc tính khóa chính là giống nhau. Mặc dù việc chỉ ra khóa chính là rùy chọn nhưng thông thường tốt nhất phải chỉ định khóa chính cho mỗi quan hệ.

• check(P): Mệnh đề check chỉ ra điều kiện P phải thỏa mãn các bộ trong quan hệ.

34

Page 35: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Lệnh create table cũng bao gồm các ràng buộc khác, sẽ được đề cập ở Chương 6.

Hình 4.8 trình bày một phần các định nghĩa của SQL DDL cho một cơ sở dữ liệ trống. Lưu ý rằng, như ở các chương trước đó, chúng ta không cố gắng mô hình hóa chính xác thế giới thực trong cơ sở dữ liệu ví dụ về ngân hàng. Trong thế giới thực, nhiều người có thể có cùng tên, do đó, customer-name không thể là khóa chính của customer; một customer-id cần được sử dụng làm khóa chính. Chúng ta sử dụng customer-name như là khóa chính để làm cho lược đồ cơ sở dữ liệu đơn giản và ngắn gọn.

Nếu một bộ mới được chèn hoặc một bộ được sửa có giá trị rỗng cho thuộc tính khóa chính, hoặc nếu bộ có cùng giá trị trên thuộc tính khóa chính với bộ đã có trong quan hệ đó thi SQL báo lỗi và ngăn cản việc cập nhật. Tương tự,SQL báo lỗi ngăn cản việc cập nhật nếu điều kiện check không thỏa mãn.Mặc định, null là giá trị hợp hệ của mỗi thuộc tính trong SQL, ngoại trừ thuộc tính đó được chỉ định là not null. Một thuộc tính có thể được khai báo là khác rỗng, not null, theo cách sau đây:

account-number char(10) not nullcreate table customer(customer-name char(20),customer-street char(30),customer-city char(30),primary key (customer-name))

create table branch(branch-name char(15),branch-city char(30),assets integer,primary key (branch-name),check (assets >= 0))

create table account(account-number char(10),branch-name char(15),balance integer,primary key (account-number),check (balance >= 0))

create table depositor(customer-name char(20),account-number char(10),primary key (customer-name, account-number))

35

Page 36: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Hình 4.8 Một phần định nghĩa SQL cho cơ sở dữ liệu ngân hàng

SQL cũng hỗ trợ ràng buộc toàn vẹn:unique (Aj1,Aj2, . . . , Ajm)

Câu lệnh unique chỉ ra rằng các thuộc tính Aj1,Aj2, . . .,Ajm là khóa dự tuyển; nghĩa là không có hai bộ nào trong quan hệ có giá trị giống nhau ở các thuộc tính khóa chính. Tuy nhiên, các thuộc tính khóa dự tuyển được phép có giá trị rỗng trừ khi chúng được định nghĩa với not null. Nhắc lại rằng giá trị rỗng không tương đương với bất kỳ giá trị nào khác.

Việc đối xử với các giá trị rỗng ở đây giống như cấu trúc unique được định nghĩa trong phần 4.6.4. Việc sử dụng của mệnh đề check để đảm bảo rằng các giá trị thuộc tính thỏa mãn điều kiện được chỉ định, tác động đến việc tạo một hệ thống các kiểu dữ liệu hùng mạnh. Ví dụ, mệnh đề check trong lệnh create table cho quan hệ branch sẽ kiểm tra giá trị của assets phải là không âm. Ví dụ khác, xét câu lệnh sau:

create table student(name char(15) not null,student-id char(10),degree-level char(15),primary key (student-id),check (degree-level in (’Bachelors’, ’Masters’, ’Doctorate’)))

Ở đây chúng ta sử dụng mệnh đề check để mô phỏng kiểu giá trị số bằng cách chỉ ra rằng degree-level phải là một trong các giá trị ’Bachelors’, ’Masters’, hoặc ’Doctorate’. Chúng ta xét thêm các dạng khác của điều kiện check, cũng như một lớn ràng buộc được gọi là ràng buộc toàn vẹn tham chiếu trong Chương 6.

Một quan hệ mới được tạo ban đầu là rỗng. Chúng ta có thể dùng lệnh insert để chèn dữ liệu vào quan hệ. Nhiều sản phẩm của cơ sở dữ liệu quan hệ có các tiện ích chèn dữ liệu với khối lượng lớn dùng để một lần chèn nhiều bộ vào trong một quan hệ.

Để loại bỏ một quan hệ ra khỏi cơ sở dữ liệu SQL, chúng tôi sử dụng lệnh drop table. Lệnh drop table xóa tất cả các thông tin về quan hệ bị xóa bỏ từ cơ sở dữ liệu. Lệnh:

drop table rthì mạnh mẽ hơn lệnh:

delete from r

Lệnh thứ hai này giữ lại quan hệ r, nhưng xóa toàn bộ các bộ của r. Lệnh đầu tiên không chỉ xóa các bộ của r, mà còn xóa lược đồ của r. Sau khi r bị loại bỏ, không có bộ nào có thể được chèn vào r trừ khi gọi lại lệnh create table.

36

Page 37: QH_Thúy... · Web viewXét ví dụ minh họa, “Tìm tất cả khách hàng có cả tài khoản vay và tài khoản tiết kiệm tại ngân hàng”. Trước đó, chúng

Chúng ta sử dụng lệnh alter table để thêm các thuộc tính vào một quan hệ đã có. Tất cả các bộ trong quan hệ được gán giá trị rỗng cho các thuộc tính mới. Hình thức của câu lệnh alter table như sau:

alter table r addADtrong đó r là tên một quan hệ đã tồn tại, A là tên của thuộc tính được thêm vào và D là miền của giá trị thuộc tính được thêm vào. Chúng ta có thể bỏ thuộc tính ra khỏi quan hệ bằng lệnh:

alter table r drop A

trong đó r là tên của một quan hệ đã có, A là tên của tả quan hệ. Nhiều hệ thống cơ sở dữ liệu không hỗ trợ việc loại bỏ các thuộc tính, mặc dù chúng cho ppép xóa toàn bộ các bảng.

37