Chuyển đến nội dung chính

SQL ON DELETE RESTRICT: Ngăn ngừa mất dữ liệu ngoài ý muốn

Tìm hiểu cách SQL ON DELETE RESTRICT bảo vệ tính toàn vẹn dữ liệu. Học cách nó chặn các thao tác xóa không an toàn và khi nào chọn nó thay cho quy tắc CASCADE hoặc SET NULL.
· 10 phút đọc

Khám phá cùng AI

Xóa dữ liệu trong SQL thường không đơn giản chỉ là loại bỏ một hàng. Trong cơ sở dữ liệu quan hệ, các bảng thường liên kết với nhau, và việc xóa một bản ghi ở bảng này có thể tác động đến bảng khác. 

SQL cung cấp mệnh đề ON DELETE, định nghĩa điều gì sẽ xảy ra khi một hàng được tham chiếu bị xóa. Sau mệnh đề ON DELETE, bạn có thể chỉ định hành vi, như chặn thao tác xóa, tự động loại bỏ hàng phụ thuộc, hoặc cập nhật dữ liệu tham chiếu.

Trong hướng dẫn này, tôi sẽ giới thiệu ràng buộc ON DELETE RESTRICT, ràng buộc này ngăn xóa một hàng cha nếu vẫn còn các hàng con phụ thuộc. Tôi cũng sẽ trình bày chi tiết cách ràng buộc hoạt động, vì sao cơ sở dữ liệu thực thi nó, và khi nào đó là lựa chọn đúng so với các quy tắc xóa khác. Cuối cùng, nếu bạn đang tìm hành vi ngược lại — nơi việc xóa hàng cha sẽ tự động loại bỏ các bản ghi liên quan — hãy xem hướng dẫn về SQL ON DELETE CASCADE của chúng tôi.

ON DELETE RESTRICT trong SQL là gì?

Ràng buộc ON DELETE RESTRICT trong SQL là một tính năng an toàn của cơ sở dữ liệu. Nó đảm bảo bạn không thể xóa một bản ghi "cha" nếu vẫn còn các bản ghi "con" đang trỏ đến nó.

Lưu ý: Trong khi các cơ sở dữ liệu như PostgreSQL và MySQL hỗ trợ trực tiếp từ khóa RESTRICT, SQL Server thực thi hành vi hạn chế tương tự bằng ON DELETE NO ACTION.

Tính toàn vẹn tham chiếu và khóa ngoại

Tính toàn vẹn tham chiếu là nguyên tắc rằng các mối quan hệ giữa các bảng phải luôn hợp lệ. Khóa ngoại thực thi điều này bằng cách yêu cầu các giá trị trong bảng con phải tương ứng với các hàng tồn tại trong bảng cha. Ví dụ, một DepartmentID trong bảng Employees có thể tham chiếu đến một ID cụ thể trong bảng Departments.

Do đó, các quy tắc DELETE trong SQL tồn tại vì việc xóa một hàng cha có thể phá vỡ mối quan hệ này. Cơ sở dữ liệu cần hướng dẫn rõ ràng về việc nên chặn thao tác xóa, lan truyền (cascade) nó, hay áp dụng hành động khác với các hàng phụ thuộc.

RESTRICT thực sự có nghĩa là gì

Khi bạn định nghĩa một khóa ngoại với ON DELETE RESTRICT, cơ sở dữ liệu sẽ kiểm tra các hàng con liên quan trước khi thực hiện xóa. Nếu tồn tại bản ghi con, thao tác xóa sẽ bị tự động từ chối.  Trong trường hợp này, RESTRICT dừng việc xóa thay vì sửa đổi dữ liệu, như chúng ta sẽ thấy ở phần sau của hướng dẫn.

Cách ON DELETE RESTRICT hoạt động trong SQL

Để hiểu cách ràng buộc ON DELETE RESTRICT hoạt động, bạn cần xem cơ sở dữ liệu đánh giá thao tác xóa từng bước trong một giao dịch như thế nào.

Quan hệ giữa bảng cha và bảng con

Trong SQL, bảng cha lưu trữ các bản ghi chính, còn bảng con lưu trữ các bản ghi phụ thuộc. Ví dụ, cơ sở dữ liệu của bạn có thể có bảng cha Categories với category_id là “Electronics.” Bảng con Products sẽ có một bản ghi “Smartphone”, được liên kết với bảng cha bằng category_id.

Khi bạn chạy lệnh DELETE trên bảng cha, bộ máy cơ sở dữ liệu sẽ lập tức quét tất cả các bảng con liên quan để xem có hàng nào đang trỏ đến ID cha cụ thể đó hay không.

Điều gì xảy ra khi bạn cố xóa các hàng bị hạn chế?

Nếu bạn cố xóa một hàng cha vẫn đang được tham chiếu, cơ sở dữ liệu sẽ dừng thao tác và đưa ra lỗi. Thông báo lỗi này cho biết có vi phạm ràng buộc khóa ngoại.

Hành vi này là chủ ý, buộc bạn phải đưa ra quyết định có ý thức là xóa hoặc cập nhật các hàng con phụ thuộc trước, hoặc cân nhắc lại xem có nên xóa hàng cha hay không.

SQL ON DELETE RESTRICT so với các quy tắc xóa khác

Trong một hệ quản trị CSDL, có các quy tắc cụ thể chi phối cách dữ liệu có thể bị xóa khỏi các bảng liên quan. Phần này sẽ so sánh ràng buộc ON DELETE RESTRICT với các quy tắc xóa phổ biến trong SQL, để bạn thấy rõ mỗi quy tắc ảnh hưởng đến dữ liệu liên quan như thế nào.

RESTRICT vs. CASCADE trong SQL

Ràng buộc RESTRICT trong SQL chặn việc xóa hàng cha nếu có hàng con tham chiếu đến nó, đảm bảo không xảy ra mất dữ liệu ngoài ý muốn. Truy vấn sau cho thấy cách triển khai RESTRICT khi định nghĩa lược đồ bảng. Nó ngăn việc xóa một khách hàng nếu có đơn hàng nào đó tham chiếu đến khách hàng đó.

-- Parent table
CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    name VARCHAR(100)
);

-- Child table with ON DELETE RESTRICT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE RESTRICT
);

Tuy nhiên, ràng buộc CASCADE trong SQL đảm bảo rằng một thao tác xóa sẽ tự động xóa tất cả các hàng con phụ thuộc. Trong ví dụ dưới đây, CASCADE cho phép tự động xóa mọi đơn hàng liên quan đến một khách hàng khi bản ghi khách hàng bị xóa.

-- Child table with ON DELETE CASCADE
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE CASCADE
);

RESTRICT so với SET NULL và SET DEFAULT

Các ràng buộc SET NULL và SET DEFAULT trong SQL giữ lại các hàng con nhưng thay đổi cách chúng tham chiếu đến hàng cha.

Ví dụ, trong truy vấn dưới đây, khi một khách hàng bị xóa, customer_id trong các đơn hàng liên quan được đặt thành NULL, giữ lại các bản ghi đơn hàng nhưng loại bỏ liên kết tới khách hàng.

-- Child table using SET NULL
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT NULL,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE SET NULL
);

Nếu bạn dùng ràng buộc SET DEFAULT, khi một khách hàng bị xóa, customer_id trong các đơn hàng liên quan sẽ được đặt về giá trị mặc định, vừa giữ lại bản ghi đơn hàng vừa gán cho chúng một giá trị giữ chỗ được xác định trước.

-- Child table using SET DEFAULT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT DEFAULT 0,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE SET DEFAULT
);

Tạo khóa ngoại với ON DELETE RESTRICT trong SQL

Để triển khai ràng buộc ON DELETE RESTRICT trong SQL, bạn cần định nghĩa nó khi tạo mối quan hệ giữa hai bảng.

Định nghĩa RESTRICT trong lược đồ bảng

Bạn có thể chỉ định hành vi xóa trong SQL khi tạo bảng hoặc thêm sau nếu bảng của bạn đã tồn tại.

Ví dụ dưới đây cho thấy cách sử dụng ràng buộc khóa ngoại ON DELETE RESTRICT trong câu lệnh CREATE TABLE khi định nghĩa một bảng mới trong SQL.

-- Stores department details
CREATE TABLE departments (
    department_id INT PRIMARY KEY, 
    department_name VARCHAR(100)
);

-- -- Prevents deleting a department with employees
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,      -- Unique employee identifier
    department_id INT, 
    CONSTRAINT fk_employees_departments
        FOREIGN KEY (department_id)
        REFERENCES departments(department_id)
        ON DELETE RESTRICT 
);

Truy vấn dưới đây thêm cùng một quy tắc khóa ngoại vào bảng employees hiện có bằng câu lệnh ALTER TABLE trong SQL, để ngăn việc xóa các phòng ban vẫn đang được nhân viên tham chiếu.

-- Adds a foreign key constraint after the table already exists
ALTER TABLE employees
ADD CONSTRAINT fk_employees_departments
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
ON DELETE RESTRICT;    -- Blocks deletion of departments that have employees

Hành vi xóa mặc định trong SQL

Trong nhiều hệ quản trị cơ sở dữ liệu phổ biến như SQL Server, PostgreSQL và MySQL, RESTRICT là hành vi mặc định. Nếu bạn định nghĩa một khóa ngoại mà không chỉ định mệnh đề ON DELETE nào, cơ sở dữ liệu thường sẽ hành xử như thể bạn đã viết ON DELETE NO ACTION hoặc ON DELETE RESTRICT. Thiết kế này đảm bảo bạn nhận được lỗi thay vì vô tình xóa một lượng lớn dữ liệu liên quan.

Các trường hợp sử dụng phổ biến cho ON DELETE RESTRICT trong SQL

Trong các kịch bản thực tế, ràng buộc ON DELETE RESTRICT trong SQL được áp dụng ở nơi tính toàn vẹn dữ liệu đòi hỏi phải giám sát rõ ràng trước khi xóa.

Bảo vệ dữ liệu tham chiếu quan trọng

Ràng buộc RESTRICT trong SQL thường được dùng cho các bảng biểu diễn dữ liệu tham chiếu cốt lõi như người dùng, tài khoản, sản phẩm hoặc các giá trị tra cứu. Những bản ghi này thường được chia sẻ trên nhiều phần của hệ thống, và việc tự động xóa chúng có thể dẫn đến mất dữ liệu diện rộng hoặc không nhất quán.

Ví dụ, xóa một người dùng vẫn sở hữu đơn hàng, nhật ký kiểm toán hoặc quyền hạn thường là không an toàn. Với ràng buộc ON DELETE RESTRICT trong SQL, cơ sở dữ liệu sẽ chặn thao tác xóa và buộc bạn phải xử lý các phụ thuộc đó trước, qua đó giữ gìn tính toàn vẹn của dữ liệu lịch sử và giao dịch.

Thực thi quy trình dọn dẹp rõ ràng

Ràng buộc RESTRICT trong SQL cũng hữu ích khi bạn muốn việc dọn dẹp phải có chủ đích và có thể truy vết. Nó buộc các nhà phát triển và quản trị viên phải thận trọng trong cách họ xử lý dữ liệu. Thay vì để cơ sở dữ liệu tự động xóa bản ghi, ràng buộc RESTRICT buộc bạn rà soát dữ liệu phụ thuộc để quyết định có xóa các bản ghi con, gán lại chúng cho một bản ghi cha mới, hay hủy thao tác.

Khắc phục lỗi DELETE do RESTRICT gây ra trong SQL

Khi ràng buộc ON DELETE RESTRICT chặn thao tác xóa, lỗi phát sinh có thể gây bối rối nếu bạn không lường trước. Hiểu các lỗi này giúp bạn xử lý an toàn.

Hiểu lỗi vi phạm ràng buộc

Khi bạn cố xóa một hàng cha vẫn đang được tham chiếu, cơ sở dữ liệu sẽ đưa ra lỗi vi phạm ràng buộc khóa ngoại. Dưới đây là cách thông báo xuất hiện trên các hệ cơ sở dữ liệu khác nhau:

  • PostgreSQL: ERROR: update or delete on table "parent_table" violates foreign key constraint "fk_name" on table "child_table"

  • MySQL: Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails…

  • SQL Server: The DELETE statement conflicted with the REFERENCE constraint "FK_Name". The conflict occurred in database "DBName", table "dbo.ChildTable", column 'ParentID'.

Trong tất cả các cơ sở dữ liệu, thông báo lỗi sẽ chỉ ra những điểm sau:

  • Ràng buộc khóa ngoại nào bị vi phạm
  • Bảng nào đang là bảng con
  • Giá trị khóa nào vẫn đang được tham chiếu

Xử lý an toàn các thao tác xóa bị chặn

Nếu bạn nhận lỗi xóa bị chặn nhưng vẫn muốn xóa hàng cha, tôi khuyến nghị dùng một trong các lựa chọn sau:

Xóa bản ghi con trước: Nếu dữ liệu phụ thuộc không còn cần thiết, hãy chạy câu lệnh DELETE trên các hàng con trước, rồi xóa bản ghi cha.

-- Step 1: Remove dependencies
DELETE FROM Orders WHERE CustomerID = 501; 
-- Step 2: Now the parent delete will work
DELETE FROM Customers WHERE CustomerID = 501;

Cập nhật tham chiếu của hàng con: Nếu bạn muốn giữ lại các hàng con nhưng loại bỏ hàng cha, hãy cập nhật các hàng con để tham chiếu đến một ID cha khác.

-- Reassign orders to a "General" customer account (ID 999)
UPDATE Orders SET CustomerID = 999 WHERE CustomerID = 501;

Thay đổi ràng buộc: Trong các tình huống quản trị hiếm gặp, bạn có thể tạm thời vô hiệu kiểm tra khóa ngoại. Đây là thao tác rủi ro, có thể dẫn đến hỏng dữ liệu nếu không được xử lý cực kỳ cẩn thận.

Ghi chú và hành vi theo từng hệ cơ sở dữ liệu

Mặc dù khái niệm ràng buộc ON DELETE RESTRICT trong SQL là tiêu chuẩn trên các cơ sở dữ liệu SQL, các bộ máy khác nhau xử lý thời điểm và logic nội bộ hơi khác nhau.

Hành vi của PostgreSQL, MySQL và SQL Server

Trong PostgreSQL, MySQL và SQL Server, ràng buộc ON DELETE RESTRICT ngăn xóa một hàng cha khi tồn tại các hàng con liên quan. Tuy nhiên, các bộ máy này có một vài khác biệt cú pháp nhỏ sau:

MySQL: Tuân thủ chặt chẽ ràng buộc RESTRICT của SQL. Nếu bạn không chỉ định quy tắc, mặc định sẽ là RESTRICT.

-- MySQL: RESTRICT is the default if no rule is specified
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
);

PostgreSQL: Hỗ trợ cả RESTRICT và NO ACTION. Dù chúng gần như giống nhau, RESTRICT được kiểm tra ngay lập tức, trong khi NO ACTION cho phép hoãn kiểm tra.

-- PostgreSQL: NO ACTION (can be deferred)
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE NO ACTION
);

SQL Server: Dùng ràng buộc NO ACTION như tương đương với hành vi RESTRICT tiêu chuẩn. Nó không dùng từ khóa RESTRICT trong cú pháp T-SQL, nhưng đạt cùng kết quả bằng cách ngăn thao tác xóa.

-- SQL Server: Uses NO ACTION instead of RESTRICT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE NO ACTION
);

Tôi khuyến nghị nghiên cứu các khóa học Introduction to SQL Server và Creating PostgreSQL Databases để tìm hiểu thêm về sự khác nhau giữa các biến thể SQL khi tạo cơ sở dữ liệu.

Ràng buộc hoãn kiểm và hành vi giao dịch

Trong các cấu hình nâng cao như PostgreSQL hoặc Oracle, bạn có thể gặp ràng buộc hoãn kiểm (deferred). Điều này có nghĩa ràng buộc được kiểm tra tại thời điểm cam kết giao dịch, thay vì ngay khi câu lệnh DELETE được thực thi.

Trong các hệ thống như vậy, một thao tác xóa vốn dĩ sẽ bị RESTRICT chặn có thể tạm thời xem như thành công trong phạm vi giao dịch, nhưng sẽ thất bại khi bạn cố gắng cam kết. Điều này cho phép các thao tác phức tạp nhiều bước, như xóa và chèn lại dữ liệu liên quan trong cùng một giao dịch, trong khi vẫn đảm bảo tính toàn vẹn ở cuối cùng.

Khóa học Introduction to Oracle SQL của chúng tôi sẽ giúp bạn hiểu sâu hơn cách Oracle xử lý truy vấn.

Chọn chiến lược ON DELETE phù hợp

Chọn đúng ràng buộc giúp bạn cân bằng giữa tính toàn vẹn dữ liệu và tính tiện dụng của ứng dụng. Hãy cân nhắc các kịch bản sau để chọn phương pháp phù hợp với mệnh đề ON DELETE.

Khi nào RESTRICT là lựa chọn an toàn nhất

Dùng ràng buộc ON DELETE RESTRICT trong SQL khi:

  • Dữ liệu có giá trị cao: Các bản ghi cha quan trọng và được tham chiếu rộng rãi trong cơ sở dữ liệu.

  • Cần rà soát thủ công: Bạn muốn buộc con người hoặc một luồng logic nghiệp vụ cụ thể quyết định điều gì xảy ra với dữ liệu phụ thuộc.

  • Ngăn chặn việc xóa “âm thầm”: Bạn muốn đảm bảo một nhà phát triển không vô tình xóa hàng nghìn hàng chỉ với một thao tác CASCADE.

Tôi gợi ý bạn thử lộ trình kỹ năng SQL Server for Database Administrators nếu bạn thường xuyên thiết kế hoặc vận hành cơ sở dữ liệu trong công việc. 

Khi nào nên cân nhắc lựa chọn khác

Khi ràng buộc RESTRICT có thể quá cứng nhắc với hệ thống của bạn, hãy cân nhắc các lựa chọn sau:

  • Dùng ràng buộc CASCADE khi bản ghi con không còn ý nghĩa nếu thiếu bản ghi cha.

  • Dùng ràng buộc SET NULL khi mối quan hệ là tùy chọn.

  • Dùng ràng buộc SET DEFAULT khi bạn có một “giá trị giữ chỗ” sẽ nhận mọi bản ghi mồ côi để hệ thống vận hành trơn tru.

Kết luận

Ràng buộc ON DELETE RESTRICT trong SQL là một quy tắc khóa ngoại bảo vệ, ưu tiên tính toàn vẹn dữ liệu hơn sự tiện lợi bằng cách chặn xóa các hàng cha khi vẫn còn bản ghi con phụ thuộc. Bằng cách khuyến khích chiến lược dọn dẹp có chủ đích và xác định rõ trách nhiệm thao tác xóa, ràng buộc RESTRICT đóng vai trò như một lớp an toàn trong thiết kế quan hệ. Theo thực hành tốt, hãy luôn chọn quy tắc xóa của SQL dựa trên logic nghiệp vụ và ngữ nghĩa dữ liệu, thay vì mặc định theo sự tiện lợi hay nhu cầu ngắn hạn.

Tôi khuyến nghị tham gia khóa học Database Design, nơi bạn sẽ học cách tạo và quản lý cơ sở dữ liệu cũng như chọn hệ quản trị phù hợp với nhu cầu của mình. Tôi cũng đề xuất thử lộ trình nghề nghiệp Associate Data Engineer in SQL để nắm các nền tảng về kỹ thuật dữ liệu và kho dữ liệu.  

Allan Ouko

Tác giả

Allan Ouko

Biên tập viên kỹ thuật về Khoa học dữ liệu với kinh nghiệm thực tế trong phân tích dữ liệu, trí tuệ doanh nghiệp và khoa học dữ liệu. Tôi viết nội dung thực tiễn, tập trung vào ngành về SQL, Python, Power BI, Databricks và kỹ thuật dữ liệu, dựa trên công việc phân tích trong thế giới thực. Bài viết của tôi kết nối chiều sâu kỹ thuật với tác động kinh doanh, giúp các chuyên gia chuyển đổi dữ liệu thành những quyết định vững chắc.

SQL ON DELETE RESTRICT - Câu hỏi thường gặp

Sự khác nhau giữa RESTRICT và NO ACTION là gì?

Trong hầu hết cơ sở dữ liệu, chúng hoạt động giống nhau. RESTRICT kiểm tra ngay lập tức, trong khi NO ACTION có thể được kiểm tra khi kết thúc câu lệnh hoặc giao dịch.

Điều gì xảy ra khi tôi cố xóa một hàng cha bị hạn chế?

Thao tác DELETE sẽ thất bại, và cơ sở dữ liệu đưa ra lỗi vi phạm ràng buộc khóa ngoại.

ON DELETE RESTRICT khác ON DELETE CASCADE như thế nào?

RESTRICT chặn hoàn toàn thao tác xóa, còn CASCADE tự động xóa tất cả các hàng con phụ thuộc.

Làm thế nào để xử lý một thao tác DELETE bị ON DELETE RESTRICT chặn?

Làm thế nào để xử lý một thao tác DELETE bị ON DELETE RESTRICT chặn?

Tôi có thể đổi một khóa ngoại hiện có để dùng ON DELETE RESTRICT không?

Có. Bạn có thể gỡ và tạo lại ràng buộc khóa ngoại với ON DELETE RESTRICT bằng ALTER TABLE.

Chủ đề

Liên quan