Bảng. Khóa chính và bộ sinh giá trị
NOTICE: Tài liệu này là chương trích từ cuốn sách “The InterBase World” được viết bởi Alexey Kovyazin và Serg Vostrikov.
InterBase là một hệ quản trị cơ sở dữ liệu quan hệ. Ngoài ra, điều đó có nghĩa là tất cả dữ liệu trong InterBase được lưu trữ dưới dạng các bảng. Bảng như được hiểu từ quan điểm SQL rất giống với bảng thông thường, có thể được vẽ tay trên một tờ giấy hoặc tạo ra trong chương trình như Microsoft Excel. Các bảng trong InterBase có các cột và các dòng chứa dữ liệu. Bảng nhất thiết phải có tên, duy nhất trong một cơ sở dữ liệu. Các bảng là nơi lưu trữ chính thông tin trong cơ sở dữ liệu và do đó bạn nên hết sức cẩn thận khi tạo bảng.
Có các quy tắc mô tả cách tạo bảng trong cơ sở dữ liệu quan hệ, phản ánh dữ liệu của thế giới thực và đồng thời cho phép tổ chức lưu trữ thông tin hiệu quả trong cơ sở dữ liệu. Quá trình áp dụng các quy tắc này để thiết kế một cơ sở dữ liệu “đúng” được gọi là chuẩn hóa. Chúng tôi cố ý đặt từ “đúng” trong ngoặc kép, vì “cơ sở dữ liệu được chuẩn hóa” và “cơ sở dữ liệu được tối ưu hóa” không phải là từ đồng nghĩa. Bạn không nhất thiết phải tuân thủ các quy tắc chuẩn hóa một cách rập khuôn - luôn luôn điều chỉnh cho phù hợp với đặc thù của bài toán cụ thể.
Việc chuẩn hóa các bảng trong cơ sở dữ liệu được xem xét chi tiết trong sách [14. và do đó chúng tôi sẽ không cố gắng ôm đồm những điều không thể và sẽ quay trở lại chủ đề thảo luận của chúng ta - các bảng trong InterBase. Hãy xem xét cú pháp của câu lệnh DDL (DDL - Ngôn ngữ định nghĩa dữ liệu, xem thêm trong bảng thuật ngữ) cho phép tạo bảng:
CREATE TABLE table [EXTERNAL [FILE] “”] ( [, | …]);
Ở đây table là tên của bảng được tạo, - mô tả các cột (đôi khi chúng tôi sẽ nói - các trường) của bảng được tạo. Tùy chọn table [EXTERNAL [FILE] “”] có nghĩa là cái gọi là bảng ngoài sẽ được tạo, không được lưu trữ trong tệp cơ sở dữ liệu dùng chung, mà trong một tệp riêng biệt có tên . Như bạn có thể thấy, mọi thứ đều đơn giản - chúng ta xác định tên bảng và các cột mà nó chứa. Bây giờ chúng ta sẽ xem xét chi tiết cách xác định các cột. Cú pháp tạo một cột được mô tả bằng câu lệnh DDL sau:
= col { datatype | COMPUTED [BY] (< expr>) | domain}
[DEFAULT { literal | NULL | USER}]
[NOT NULL] [ ]
[COLLATE collation]
Đây là một định nghĩa khá lớn, tuy nhiên trong định nghĩa một cột chỉ có một phần nhỏ của các câu lệnh trên là bắt buộc. Mỗi cột trong bảng phải có tên, duy nhất trong bảng, cũng như một kiểu dữ liệu được xác định bởi câu lệnh datatype, hoặc một biểu thức để tính giá trị của cột (đối với các cột tính toán), hoặc một miền (xem bên dưới), được xác định bởi domain. Các kiểu dữ liệu đã được xem xét trong chương “Các kiểu dữ liệu”; do đó, bạn có thể dễ dàng hiểu cách biểu thức SQL để tạo một bảng được hình thành.
Hãy kết nối với cơ sở dữ liệu FIRSTBASE.gdb của chúng ta được tạo trước đó trong chương “Tạo cơ sở dữ liệu”, và chúng ta sẽ thử làm việc với các bảng trong thực tế. Khi nói đến việc tạo, xóa và cập nhật các bảng, bất kỳ công cụ quản trị InterBase nào - từ những công cụ được liệt kê trong ứng dụng “Các công cụ quản trị và phát triển InterBase”, cũng như tiện ích chuẩn isql.exe từ bộ cung cấp của bất kỳ bản sao InterBase nào đều phù hợp.
Dưới đây là một ví dụ về một bảng đơn giản có tên TABLE_EXAMPLE và chứa 3 trường với các kiểu khác nhau:
CREATE TABLE Table_example ( ID INTEGER, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION);
Bảng này minh họa trường hợp thường gặp nhất trong quá trình phát triển cơ sở dữ liệu. Tuy nhiên, cũng có các phương pháp khác để xác định trường. Ví dụ, chúng ta có thể đặt kiểu trường bằng cách sử dụng các miền. Miền là một kiểu được người dùng định nghĩa để thuận tiện cho việc áp dụng các tổ hợp tham số kiểu nhất định. Ví dụ, có thể định nghĩa miền D_ID để xác định các trường định danh. Sau khi định nghĩa miền, chúng ta có thể sử dụng nó để đặt kiểu cho một trường:
CREATE DOMAIN D_ID AS INTEGER; CREATE TABLE Тable_example ( ID D_ID, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION);
Trường ID sẽ có kiểu được xác định bởi miền D_ID. Do đó, sau khi xác định kiểu của trường trong miền, các kiểm tra và ràng buộc cần thiết, chúng ta có thể áp dụng miền này nhiều lần để tạo các trường có cùng chức năng. Ví dụ, các trường tiền tệ mà không cần sao chép tẻ nhạt và tiềm ẩn nguy cơ sai sót các định nghĩa kiểu biến. Cách thứ ba để đặt một cột trong bảng là định nghĩa nó như một cột tính toán (COMPUTED BY) và chỉ định một điều kiện theo đó giá trị của nó sẽ được tính. Ví dụ, chúng ta có thể muốn có một cột tính 10% từ giá trị của trường PRICE_1 trong bảng của mình. Trong trường hợp này, lệnh sau nên được viết:
CREATE TABLE Тable_example ( ID INTEGER, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION, PRICE_10 COMPUTED BY (PRICE_1.0.1));
Nhưng đừng nghĩ rằng ngay khi chúng ta chèn dữ liệu vào trường PRICE_1, trong trường PRICE_10 sẽ có một phần mười giá trị của trường này. Không, quá trình ở đây phức tạp hơn. Thực tế, chúng ta sẽ nhận được phần mười cần thiết chỉ khi tham chiếu đến trường PRICE_10, ví dụ khi thực hiện truy vấn SELECT đến bảng này. Nghĩa là không có dữ liệu nào được lưu trữ trong một cột tính toán, và việc tính toán biểu thức liên kết với trường được thực hiện khi truy xuất, và kết quả được tạo ra như câu trả lời cho truy vấn.
Vậy, chúng ta đã xem xét 3 cách chính để xác định các trường trong bảng. Bây giờ chúng ta hãy xem xét chi tiết các tùy chọn có thể được đặt khi tạo một cột. Tùy chọn [DEFAULT {literal | NULL | USER}] - cho phép đặt giá trị mặc định cho cột. Điều này rất thuận tiện cho việc tự động điền dữ liệu. Có 3 cách để đặt giá trị mặc định. Cách đầu tiên được chỉ định là literal và cho phép đặt giá trị mặc định dưới dạng hằng số văn bản, số hoặc ngày tháng. Ví dụ, chúng ta có thể tạo các biểu thức sau để tạo một cột với giá trị mặc định văn bản: NAME VARCHAR(80) DEFAULT ‘Василий Станиславович’
Do đó, tất cả các trường được chèn vào bảng sẽ nhận giá trị mặc định, tức là nếu giá trị khác chưa được xác định cho trường NAME, chuỗi ‘Vasily Stanislavovich’ sẽ xuất hiện. Cách thứ hai để đặt giá trị mặc định là chỉ định DEFAULT NULL trong định nghĩa cột. Và trong các bản ghi được tạo mới, giá trị của cột này sẽ là NULL, nếu giá trị khác, chắc chắn, chưa được đặt một cách rõ ràng. Một ví dụ:
PRICE_1 DOUBLE PRECISION DEFAULT NULL
Cách thứ ba để đặt giá trị mặc định là chỉ định DEFAULT USER trong định nghĩa cột. Do đó, trong các bản ghi được tạo mới, trường này sẽ chứa tên của người dùng hiện tại, tức là người dùng đã kết nối với InterBase và thực hiện việc chèn này (để biết thêm chi tiết về người dùng, xem chương “Bảo mật trong InterBase: người dùng, chức năng và quyền của họ” (phần 4)). Đối với một số trường, điều quan trọng là trường phải có giá trị không rỗng. Ví dụ, một trường không thể để trống theo đặc tả bài toán. Để đặt một ràng buộc ở cấp cơ sở dữ liệu rằng một trường phải có giá trị xác định, cần phải thêm phần bổ sung sau vào mô tả cột:
NAME VARCHAR(80) NOT NULL
Do đó, sẽ có một trường mà các giá trị null không thể được lưu trữ. Thông thường, ràng buộc NOT NULL được kết hợp với tùy chọn DEFAULT để chắc chắn gán một giá trị đúng cho trường này. Nhưng thường ràng buộc NOT NULL là không đủ. Ví dụ, trong trường hợp lưu trữ giá trong cơ sở dữ liệu, rõ ràng là chúng không thể nhận giá trị âm (mặc dù sẽ thật tuyệt nếu chúng ta được trả thêm tiền khi mua hàng). Để máy chủ kiểm tra các giá trị giá được chèn vào cơ sở dữ liệu theo điều kiện dương, cần phải xác định một cột theo cách sau:
PRICE_1 DOUBLE PRECISION CHECK (PRICE_1>0)
Các giá trị được chèn vào cột PRICE_1 sẽ được kiểm tra theo điều kiện dương. Cần lưu ý rằng các tùy chọn nhất quán khác nhau có thể được kết hợp, và ví dụ, chúng ta có thể đặt giá trị không rỗng và kiểm tra tính dương:
PRICE_1 DOUBLE PRECISION NOT NULL CHECK (PRICE_1>0)
Khi tạo các cột, một số tùy chọn không thể kết hợp, ví dụ không thể đặt NULL làm giá trị mặc định và đồng thời ràng buộc giá trị không rỗng. Cần lưu ý rằng các kiểm tra có thể thực hiện một loạt các chức năng hữu ích trong việc quản lý dữ liệu trong cơ sở dữ liệu. Chúng ta sẽ xem xét chi tiết việc sử dụng chúng trong chương “Các ràng buộc cơ sở dữ liệu”.
Vậy, chúng ta đã xem xét các cách tạo bảng và trường với các tùy chọn khác nhau. Tuy nhiên, có những trường hợp chúng ta phải thay đổi bảng đã tồn tại. Chắc chắn, chúng ta có thể tạo lại toàn bộ bảng. Đầu tiên, chúng ta nên thực hiện lệnh xóa bảng và sau đó tạo lại nó. Ví dụ:
DROP TABLE Table_example; CREATE TABLE Table_example(ID NUMERIC(15,2);
Nhưng cách thay đổi bảng như vậy có những nhược điểm đáng kể. Khi xóa một bảng bằng lệnh DROP, tất cả dữ liệu mà bảng chứa sẽ bị xóa và để không mất chúng, cần phải sao chép chúng vào các bảng tạm thời. Điều này khá rắc rối. Do đó, có lệnh ALTER TABLE để thay đổi cấu trúc bảng một cách dễ dàng, cho phép thêm các trường mới, xóa các trường hiện có, cũng như thêm / xóa các ràng buộc toàn vẹn tham chiếu.
Ví dụ, chúng ta muốn thêm một cột nữa vào bảng dùng để lưu trữ dữ liệu về tên đệm của một người:
ALTER TABLE Table_example ADD Patronimic VARCHAR(80);
Sau khi thực hiện lệnh này, bảng Table_example của chúng ta sẽ có một cột mới với tên Patronimic và kiểu VARCHAR (80). Nếu chúng ta muốn xóa một cột có tên NAME khỏi bảng, chúng ta nên thực hiện như sau:
ALTER TABLE Table_example DROP Name;
Bạn có thể xem cú pháp đầy đủ của câu lệnh ALTER TABLE trong [1.. Đây là một lệnh rất hữu ích, và chúng ta sẽ thường xuyên sử dụng nó.
Và phải làm gì, bạn sẽ hỏi, nếu cần sửa đổi một cột? Ví dụ, chúng ta đã quyết định rằng để lưu trữ tên, tốt hơn nên sử dụng trường HUMAN_NAME thay vì NAME. Trong trường hợp này, chúng ta có thể áp dụng ALTER TABLE
ALTER TABLE Table_example ALTER COLUMN NAME TO HUMAN_NAME;
Nếu chúng ta đã quyết định thay đổi kiểu của một trường, ví dụ để tăng số ký tự được lưu trữ trong một trường, chúng ta sẽ phải thay đổi miền của trường này bằng câu lệnh ALTER DOMAIN (xem chương “Các kiểu dữ liệu” ở trên).
Vậy, chúng ta đã xem xét việc tạo và sửa đổi các bảng trong InterBase. Bây giờ là lúc đi sâu hơn một chút vào lý thuyết cơ sở dữ liệu. InterBase như đã được nói là một cơ sở dữ liệu quan hệ. Ngoài ra, điều đó có nghĩa là mỗi bản ghi trong bảng nên có một đặc điểm để phân biệt bản ghi này với bản ghi khác. Cơ chế đặc biệt của các khóa duy nhất phục vụ mục đích này.
Khóa chính trong các bảng
Chắc chắn, chúng ta có thể tạo một bảng không chứa bất kỳ khóa nào. Không ai cấm chúng ta làm điều này. Nhưng, như đã nói trước đó, việc tạo một cơ sở dữ liệu hiệu quả là không thể nếu không tuân thủ các quy tắc chuẩn hóa. Sự hiện diện của các khóa là yếu tố quan trọng nhất của chuẩn hóa. Do đó, mặc dù chúng ta không nhằm mục đích xem xét lý thuyết và chuẩn hóa cơ sở dữ liệu, chúng ta nên giới thiệu định nghĩa về các khóa và xem xét chức năng của chúng trong InterBase. Chúng ta sẽ đi từng bước và bắt đầu với loại khóa phổ biến nhất - khóa chính.
Vậy, khóa chính là gì? Đó là một hoặc nhiều trường trong bảng, xác định duy nhất các bản ghi trong bảng này. Nghe có vẻ khó, tuy nhiên thực tế mọi thứ rất đơn giản. Hãy tưởng tượng một bảng thông thường, ví dụ bảng kế toán. Cột đầu tiên là gì? Đúng vậy, số thứ tự - 1, 2, 3 … Con số này biểu thị một dòng duy nhất trong bảng, và chỉ cần biết con số này là đủ để tìm một chuỗi trong bảng. Trong ví dụ này, nó sẽ là một khóa chính. Phần lớn các bảng trong cơ sở dữ liệu quan hệ nhất thiết phải có khóa chính (PK - viết tắt của Primary key). Nguyên tắc chung khi tạo bảng là tạo khóa chính. Khóa chính có thể được tạo khi tạo bảng hoặc sau đó. Giả sử rằng tại thời điểm tạo bảng, chúng ta đã quyết định rằng trường ID sẽ là khóa chính của chúng ta. Sau đó, chúng ta có thể thêm khóa chính theo cách sau:
CREATE TABLE Table_example ( ID INTEGER NOT NULL, NAME VARCHAR(80), PRICE_1 DOUBLE PRECISION, CONSTRAINT pkTable PRIMARY KEY (ID));
Cần làm gì để tạo khóa chính cho bảng table_example? Hãy xem điều gì đã thay đổi trong định nghĩa của bảng? Đầu tiên, cột ID đã có thêm định nghĩa NOT NULL. Điều này quan trọng, vì khóa chính phải là duy nhất và không được phép có giá trị không xác định. Và NULL như bạn biết là một giá trị không xác định. Do đó, tất cả các trường nằm trong khóa chính phải có ràng buộc NOT NULL. Để hoàn tất việc tạo khóa chính, cần viết ở cuối bảng: CONSTRAINT ()
Bạn có thể tìm thấy cú pháp đầy đủ của các ràng buộc trong chương “Database constraints” þ. 1, và với ví dụ về khóa chính của chúng ta, nó sẽ trông như sau:
CONSTRAINT pkTable PRIMARY KEY (ID)
Ở đây pkTable là tên của khóa chính, và ID là các cột mà nó chứa. Cách định nghĩa khóa chính cho các bảng như vậy rất tiện lợi khi tạo hàng loạt bảng (ví dụ, khi xây dựng nguyên mẫu của cơ sở dữ liệu dựa trên các script nhận được từ các nguồn CASE khác nhau). Nhưng phải làm gì nếu chúng ta cần thêm / xóa khóa chính cho bảng khi bảng đã tồn tại và đã có dữ liệu? Vì mục đích này, cần áp dụng một phần mở rộng khác của lệnh - ALTER TABLE. Ví dụ về việc thêm khóa chính vào bảng của chúng ta:
ALTER TABLE TABLE_EXAMPLE ADD CONSTRAINT FF PRIMARY KEY (ID);
Như vậy, bảng Table_example sẽ có chính xác khóa chính giống như trong ví dụ trước khi nó được tạo cùng với bảng. Để xóa khóa chính, cần nhập lệnh sau:
ALTER TABLE Table_example DROP CONSTRAINT pkTable;
Như vậy, khóa có tên pkTable sẽ bị xóa khỏi cơ sở dữ liệu.
Generators - người bạn tốt nhất của khóa chính
Chúng ta cần nói vài lời về việc triển khai khóa chính. Vì nó nhằm hỗ trợ tính duy nhất, không có hai bản ghi nào trong một bảng có thể có cùng giá trị của khóa này. Nghĩa là, để đáp ứng điều kiện, khi chèn một bản ghi mới vào bảng, InterBase phải kiểm tra tất cả các bản ghi trong bảng và xác định xem bảng có chứa các giá trị như vậy hay không. Để tìm kiếm nhanh, InterBase có cơ chế chỉ mục - các đối tượng InterBase đặc biệt, cho phép tìm bản ghi trong bảng rất nhanh. Do đó, khi tạo và xóa khóa chính, chỉ mục được tạo hoặc xóa cho trường (hoặc các trường) nằm trong khóa chính.
Như đã nói trước đó, khóa chính có thể chứa nhiều trường. Như vậy, chúng ta có thể nhận thấy tính duy nhất của một tổ hợp các giá trị của các trường này. Ví dụ, nếu chúng ta định nghĩa khóa cho các trường ID và NAME, máy chủ sẽ kiểm soát rằng không có tổ hợp giống nhau nào của các trường này trong bảng. Nghĩa là, các tổ hợp trường ID và 1 và “Ivanov”, 2 và “Ivanov” sẽ là hợp lệ vì chúng khác nhau ở giá trị của trường ID.
Như vậy, khóa chính có thể bao gồm nhiều trường thuộc bất kỳ kiểu nào. Tuy nhiên, trong thực tế, kiểu khóa phổ biến nhất là bộ đếm - một trường số nguyên, chứa các giá trị tăng dần. Tại sao lại như vậy? Đó là sự phản ánh của cuộc tranh luận lâu đời giữa khóa tự nhiên và khóa thay thế. Khái niệm khóa tự nhiên nói rằng chúng ta nên cố gắng sử dụng các giá trị thực sự tồn tại trong miền dữ liệu mà cơ sở dữ liệu phản ánh làm khóa. Ví dụ, nếu chúng ta phát triển một hệ thống đăng ký người dân cho văn phòng hộ chiếu, theo khái niệm này, tổ hợp số và loạt hộ chiếu nên được lấy làm khóa chính. Thực sự, mỗi người phải có một tổ hợp duy nhất của số và loạt hộ chiếu. Tuy nhiên, phải làm gì với thực tế rằng một người có thể đổi hộ chiếu trong suốt cuộc đời (liên quan đến việc đạt đến độ tuổi quy định, kết hôn, v.v.)? Trong trường hợp này, chúng ta sẽ phải thay đổi số và loạt hộ chiếu được gán tương ứng với người cụ thể, tức là thực sự, thay đổi khóa chính của chúng ta. Điều này không mong muốn từ quan điểm phát triển ứng dụng cơ sở dữ liệu: xét đến hệ thống liên kết phân nhánh giữa các bảng (chương tiếp theo dành cho vấn đề này), nhà phát triển sẽ phải tốn nhiều công sức để kiểm soát tình huống này.
Do đó, khóa thay thế được sử dụng trong hầu hết các trường hợp. Thay thế - có nghĩa là nhân tạo, tức là không tồn tại trong miền dữ liệu mà cơ sở dữ liệu của chúng ta mô tả, và được tạo ra một cách nhân tạo - để thuận tiện cho việc phát triển ứng dụng cơ sở dữ liệu. Như đã nói, thông thường bộ đếm là khóa chính. Một số DBMS, như Paradox và MS SQL, có một kiểu đặc biệt - bộ đếm (auto increment). Khi thêm một bản ghi mới vào bảng, giá trị trường tự động tăng với kiểu này theo giá trị tăng - thường là theo đơn vị. Trong InterBase không có trường kiểu bộ đếm, tuy nhiên hành vi như vậy có thể được thực hiện. Để tạo trường tự động được điền khi thêm bản ghi vào bảng, tập hợp các tài nguyên được sử dụng: đầu tiên trong số đó là generator.
Generator là gì? Nói một cách đơn giản, generator là một bộ đếm có tên. Trong một cơ sở dữ liệu, chúng ta có thể tạo một bộ đếm, đặt cho nó một tên duy nhất trong cơ sở này và kiểm soát các giá trị của bộ đếm này. Đó sẽ là một generator. Đây là một ví dụ về các câu lệnh DDL sẽ giải thích điều đó cho bạn:
CREATE GENERATOR g1; SET GENERATOR g1 TO 2445;
Trong dòng đầu tiên của ví dụ này, generator có tên g1 được tạo, và trong dòng thứ hai, giá trị 2445 được gán cho generator này. Bây giờ có một câu hỏi là làm thế nào để sử dụng generator thu được. Có một hàm tích hợp GEN_ID trong InterBase để lấy và thay đổi các giá trị của generator. Hàm này nhận các tham số là tên của generator và giá trị tăng, được áp dụng cho generator đã cho, và trả về giá trị số nguyên tương ứng với giá trị của generator, nhận được sau khi cộng giá trị tăng vào nó. Đây là một ví dụ về lệnh gọi hàm GEN_ID trong trigger hoặc stored procedure:
Current_value = GEN_ID (g1, 1)
Nếu chúng ta muốn nhận giá trị của generator, chúng ta có thể sử dụng truy vấn sau:
SELECT GEN_ID(g1, 1)FROM RDB$ DATABASE
Vì bảng RDB $ Database luôn chỉ chứa một bản ghi, chúng ta sẽ nhận được giá trị của generator g1 như kết quả của truy vấn đã cho.
Ở đây current_value là một biến (trong các chương sau bạn sẽ tìm thấy thông tin về cách sử dụng biến trong InterBase), g1 - một generator, 1 - giá trị tăng. Trong ví dụ này, giá trị của generator g1 sẽ được đưa vào biến current_value sau khi cộng giá trị tăng 1 vào nó, tức là giá trị tiếp theo của generator. Lưu ý rằng giá trị tăng có thể không bằng 1! Hơn nữa, nó thậm chí có thể là âm: Current_value = GEN_ID (g1, -23)
Kết quả của việc thực thi hàm này, giá trị hiện tại của generator g1 sẽ trừ đi 23. Như bạn có thể thấy, phạm vi ứng dụng có thể của generator khá rộng - nó có thể được sử dụng không chỉ để lấy giá trị khóa chính, mà còn để theo dõi các thay đổi toàn cục trong cơ sở dữ liệu.
Những người quen thuộc với cơ sở dữ liệu có thể đặt câu hỏi: “Điều gì sẽ xảy ra nếu đồng thời một số khách hàng cố gắng đưa dữ liệu vào cùng một bảng và đồng thời ‘kéo’ các generator? Họ sẽ nhận được các giá trị giống nhau hay khác nhau của generator?” Họ sẽ nhận được một cách rõ ràng các giá trị KHÁC NHAU của generator. Dù nỗ lực nhận giá trị của generator có ‘đồng thời’ đến đâu, mọi người yêu cầu sẽ nhận được giá trị duy nhất. Điều này được đảm bảo bởi ‘cấu trúc’ của các generator: chúng hoạt động ở mức thấp nhất của máy chủ và không có quá trình ghi và chèn nào ảnh hưởng đến chúng - người ta thường nói rằng các generator hoạt động ’ngoài ngữ cảnh của các giao dịch’. Nếu bạn muốn biết về các giao dịch, hãy đọc chương “Transactions. Parameters of transactions” (phần 1); cách các generator được tổ chức - “InterBase database structure” (phần 4). Vâng, thay mặt cho các generator, chúng ta có một cơ chế đáng tin cậy để tạo các khóa chính duy nhất. Tuy nhiên, chúng ta có thể sử dụng cơ chế này không? Làm thế nào để đưa giá trị nhận được từ generator vào trường khóa chính?
Vì mục đích này, có hai cách - chèn khóa chính thay mặt cho khách hàng và thay mặt cho máy chủ. Để nắm vững cách đầu tiên, chúng ta nên tham khảo chương “Usage of main components of FIBPlus " và để hiểu cách thứ hai - chương “Triggers” (phần 1). Ở đây chúng ta sẽ xem xét ngắn gọn điểm chính của cả hai cách.
Trong trường hợp tạo khóa chính thay mặt cho khách hàng, điều sau xảy ra. Khi bản ghi sẽ được chèn vào cơ sở dữ liệu được tạo, lệnh gọi hàm GEN_ID (, 1) được thực thi và giá trị nhận được được thay thế cho bản ghi này. Sau đó, việc chèn vào bảng diễn ra, và chúng ta được đảm bảo nhận được một khóa chính duy nhất.
Cách thứ hai - tạo khóa chính thay mặt cho máy chủ - nói chung loại bỏ mọi sự quan tâm từ phía khách hàng về việc giá trị khóa chính sẽ là gì. Trong trường hợp này, khi chèn bản ghi, trigger hoạt động - một đối tượng cơ sở dữ liệu đặc biệt, có thể thực hiện bất kỳ thao tác nào khi chèn / xóa / cập nhật các bản ghi trong bảng. Và trong trigger này, các thao tác sau được thực hiện: lệnh gọi hàm GEN_ID, nhận giá trị cần thiết của generator và chèn nó vào bảng. Ưu điểm của cách thứ hai là khi phát triển ứng dụng khách hàng, không cần phải lo lắng về việc tạo khóa chính, điều duy nhất bạn phải làm là viết một trigger cần thiết một lần. Nhưng nhược điểm là chúng ta không thể nhận giá trị của khóa được tạo trong ứng dụng ngay sau khi chèn! Nếu chúng ta sử dụng cách đầu tiên, chúng ta có thể nhận giá trị của khóa chính mặc dù chúng ta phải quan tâm đến việc tạo nó mỗi lần chèn. Rất khó để nói chắc chắn cách nào tốt hơn, tất cả phụ thuộc vào một vấn đề cụ thể. Trong cuốn sách này, chúng ta sẽ xem xét các biến thể có thể để giải quyết các câu hỏi về việc làm việc với khóa chính.
Kết luận
Vậy, trong chương này chúng ta đã xem xét cách tạo và cập nhật các bảng trong InterBase, cũng như xử lý các khóa chính. Như vậy, chúng ta đã xem xét các đối tượng chính trong InterBase có thể được gọi một cách có điều kiện là tĩnh, vì chúng chỉ lưu trữ thông tin và không thực hiện chuyển đổi thông tin. Tiếp theo, chúng ta sẽ nói về các cách kiểm soát thông tin và chuyển đổi thông tin trong cơ sở dữ liệu.