VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
SQL với OracleĐọc dữ liệu
Bài 1/16
6 phút

Database, bảng và khoá

Nội dung bài · 7 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Cài Oracle trên máy
  4. 4.Tạo dữ liệu mẫu
  5. 5.Thử ngay
  6. 6.Lỗi hay gặp
  7. 7.Tóm tắt

Dữ liệu trong một List<Product> của chương trình C# mất khi chương trình tắt. Dữ liệu của cửa hàng phải còn nguyên, và nhiều người phải đọc và ghi cùng lúc mà không giẫm lên nhau. Việc đó do database đảm nhận. Khoá học này dùng Oracle, loại database phổ biến ở ngân hàng và doanh nghiệp lớn.

Khái niệm

🗄️ Database quan hệ (relational database): nơi lưu dữ liệu thành nhiều bảng, các bảng liên kết với nhau qua khoá.

📋 Bảng (table): tập hợp các dòng cùng cấu trúc, mỗi cột là một loại thông tin, mỗi dòng là một đối tượng.

🔑 Khoá chính (primary key): cột có giá trị không trùng và không được trống, dùng để chỉ đúng một dòng.

💬 SQL: ngôn ngữ dùng để đọc và thay đổi dữ liệu trong database quan hệ.

Bảng giống class, cột giống property, mỗi dòng giống một object.

Ví dụ

Một bảng sản phẩm đơn giản được tạo như sau:

CREATE TABLE product_samples (
  product_id NUMBER PRIMARY KEY,
  name       VARCHAR2(100) NOT NULL,
  price      NUMBER(12, 2) NOT NULL
);
  • Mỗi dòng trong ngoặc là một cột: tên cột, kiểu dữ liệu, rồi quy tắc.
  • PRIMARY KEY: product_id là khoá chính.
  • NOT NULL: cột này bắt buộc phải có giá trị.

Ba kiểu dữ liệu hay dùng nhất trong Oracle:

Kiểu Chứa gì Ví dụ
NUMBER số nguyên hoặc số thực 120, 5000.50
VARCHAR2(n) chuỗi tối đa n byte 'Bút bi'
DATE ngày giờ DATE '2025-01-05'

Chuỗi trong SQL đặt trong dấu nháy đơn: 'Bút bi'.

Cài Oracle trên máy

Khoá học này, chương EF Core của khoá ASP.NET Core và khoá WinForms dùng chung một Oracle chạy bằng Docker. Cài Docker Desktop, rồi chạy lệnh sau một lần:

docker run -d --name oracle -p 1521:1521 -e ORACLE_PASSWORD=oracle_pw -e APP_USER=shop -e APP_USER_PASSWORD=shop_pw gvenzl/oracle-free:slim-faststart
  • Lệnh tải Oracle Database Free và tạo sẵn user shop, mật khẩu shop_pw.
  • ORACLE_PASSWORD là mật khẩu của user quản trị system, khoá ASP.NET Core sẽ dùng đến.
  • Lần đầu mất vài phút. Chạy docker logs -f oracle, thấy dòng DATABASE IS READY TO USE! là dùng được.
  • Tắt máy xong, bật lại bằng docker start oracle.

Để gõ SQL, cài VS Code và extension Oracle SQL Developer. Tạo kết nối mới với user shop, mật khẩu shop_pw, host localhost, port 1521, service name FREEPDB1.

Tạo dữ liệu mẫu

Mọi bài trong khoá dùng chung một database cửa hàng với bốn bảng: khách hàng, sản phẩm, đơn hàng và dòng hàng (order_lines): một sản phẩm trong đơn kèm số lượng và đơn giá. Mở kết nối shop, dán toàn bộ script dưới đây rồi chạy cả script. Chỉ cần chạy một lần.

CREATE TABLE customers (
  customer_id NUMBER GENERATED BY DEFAULT AS IDENTITY
              PRIMARY KEY,
  name        VARCHAR2(100) NOT NULL,
  email       VARCHAR2(100),
  city        VARCHAR2(50)
);

CREATE TABLE products (
  product_id NUMBER GENERATED BY DEFAULT AS IDENTITY
             PRIMARY KEY,
  name       VARCHAR2(100) NOT NULL,
  price      NUMBER(12, 2) NOT NULL,
  stock      NUMBER NOT NULL
);

CREATE TABLE orders (
  order_id    NUMBER GENERATED BY DEFAULT AS IDENTITY
              PRIMARY KEY,
  customer_id NUMBER NOT NULL
              REFERENCES customers (customer_id),
  order_date  DATE NOT NULL,
  status      VARCHAR2(20) NOT NULL
);

CREATE TABLE order_lines (
  line_id    NUMBER GENERATED BY DEFAULT AS IDENTITY
             PRIMARY KEY,
  order_id   NUMBER NOT NULL
             REFERENCES orders (order_id),
  product_id NUMBER NOT NULL
             REFERENCES products (product_id),
  quantity   NUMBER NOT NULL,
  unit_price NUMBER(12, 2) NOT NULL
);

INSERT INTO customers (name, email, city)
  VALUES ('An', 'an@shop.vn', 'Hà Nội');
INSERT INTO customers (name, email, city)
  VALUES ('Bình', 'binh@shop.vn', 'Đà Nẵng');
INSERT INTO customers (name, email, city)
  VALUES ('Chi', NULL, 'Hà Nội');
INSERT INTO customers (name, email, city)
  VALUES ('Dũng', 'dung@shop.vn', 'TP.HCM');

INSERT INTO products (name, price, stock)
  VALUES ('Bút bi', 5000, 120);
INSERT INTO products (name, price, stock)
  VALUES ('Vở', 12000, 0);
INSERT INTO products (name, price, stock)
  VALUES ('Balo', 350000, 8);
INSERT INTO products (name, price, stock)
  VALUES ('Thước', 7000, 50);
INSERT INTO products (name, price, stock)
  VALUES ('Máy tính', 450000, 3);

INSERT INTO orders (customer_id, order_date, status)
  VALUES (1, DATE '2025-01-05', 'PAID');
INSERT INTO orders (customer_id, order_date, status)
  VALUES (1, DATE '2025-01-20', 'NEW');
INSERT INTO orders (customer_id, order_date, status)
  VALUES (2, DATE '2025-02-02', 'PAID');
INSERT INTO orders (customer_id, order_date, status)
  VALUES (3, DATE '2025-02-10', 'CANCELLED');

INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (1, 1, 10, 5000);
INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (1, 2, 5, 12000);
INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (2, 3, 1, 350000);
INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (3, 4, 2, 7000);
INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (3, 1, 3, 5000);
INSERT INTO order_lines
  (order_id, product_id, quantity, unit_price)
  VALUES (4, 5, 1, 450000);

COMMIT;

GENERATED BY DEFAULT AS IDENTITY cho Oracle tự cấp mã tăng dần 1, 2, 3… khi thêm dòng mới mà không ghi mã.

Một số bài sau sửa dữ liệu mẫu. Nếu kết quả của bạn khác trong bài, hãy chạy khối này rồi chạy lại script trên. Khối xoá mọi bảng của user shop, kể cả bảng tạo thử trong các bài:

BEGIN
  FOR t IN (SELECT table_name FROM user_tables) LOOP
    EXECUTE IMMEDIATE
      'DROP TABLE "' || t.table_name || '" CASCADE CONSTRAINTS';
  END LOOP;
END;

Thử ngay

Chạy câu lệnh sau bằng kết nối shop:

SELECT * FROM products ORDER BY product_id;

SELECT * lấy mọi cột. ORDER BY sắp kết quả theo mã, bài Sắp xếp sẽ nói kỹ hơn.

Đoán trước khi chạy: có bao nhiêu dòng, và sản phẩm số 2 là gì?

Xem kết quả
PRODUCT_ID NAME PRICE STOCK
1 Bút bi 5000 120
2 Vở 12000 0
3 Balo 350000 8
4 Thước 7000 50
5 Máy tính 450000 3

Năm dòng, sản phẩm số 2 là Vở. Mã do Oracle tự cấp theo thứ tự thêm vào. Tên cột hiện chữ hoa vì Oracle lưu những tên không đặt trong nháy kép ở dạng chữ hoa.

Lỗi hay gặp

Thêm dòng trùng khoá chính. INSERT thêm một dòng mới (học kỹ ở chương Thay đổi dữ liệu). Khoá chính không được trùng, nên Oracle báo lỗi ORA-00001: vi phạm ràng buộc không trùng.

-- SAI — lỗi: đã có sản phẩm mã 1
INSERT INTO products (product_id, name, price, stock)
  VALUES (1, 'Kéo', 15000, 10);
-- ĐÚNG — không ghi mã, để Oracle tự cấp
INSERT INTO products (name, price, stock)
  VALUES ('Kéo', 15000, 10);

Thử xong, chạy ROLLBACK; để bỏ dòng Kéo (bài Transaction sẽ giải thích).

Tóm tắt

  • Database quan hệ lưu dữ liệu thành nhiều bảng liên kết với nhau.
  • Mỗi bảng có cột (loại thông tin) và dòng (từng đối tượng).
  • Khoá chính không trùng, không trống, dùng để chỉ đúng một dòng.
  • Oracle hay dùng NUMBER, VARCHAR2, DATE. Chuỗi đặt trong nháy đơn.

Tự kiểm tra

0/3 câu
Câu 1

Bảng students có khoá chính student_id. Hai học sinh trùng tên. Có thêm được cả hai không?

Câu 2

Cột lưu số điện thoại như '0901234567' nên dùng kiểu nào trong Oracle?

Câu 3

Cột nào hợp làm khoá chính của bảng customers?

SELECT và WHERE

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Cài Oracle trên máy
  4. 4.Tạo dữ liệu mẫu
  5. 5.Thử ngay
  6. 6.Lỗi hay gặp
  7. 7.Tóm tắt