aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL AND và OR: giữ điều kiện tenant bằng dấu ngoặc đúng chỗ

Suong Nguyen by Suong Nguyen
05/11/2026
in Backend
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn muốn lấy đơn đang mở hoặc đang chờ của tenant hiện tại. Câu WHERE có đủ ba điều kiện, parameter cũng được bind, nhưng kết quả vẫn xuất hiện đơn của tenant khác. Nguyên nhân có thể nằm ở cách AND và OR được nhóm, không nằm ở giá trị truyền vào.

Bài đọc tài liệu PostgreSQL 17 và SQLite ngày 05/11/2026. Ví dụ được chạy với Python 3.9.6, SQLite 3.54.0 trong database bộ nhớ; chưa chạy PostgreSQL server, ORM hoặc đo hiệu năng. Các tenant và đơn đều là dữ liệu tự tạo phục vụ kiểm tra.

Đọc biểu thức theo thứ tự ưu tiên

Trong hai hệ quản trị được đối chiếu, AND có độ ưu tiên cao hơn OR. Vì thế A AND B OR C được nhóm thành (A AND B) OR C. Nó không có nghĩa là A AND (B OR C).

Gọi A là đúng tenant, B là trạng thái open và C là trạng thái pending. Ở biểu thức đầu tiên, chỉ cần C đúng thì hàng có thể được chọn dù A sai. Xuống dòng hoặc thụt lề không thay thế dấu ngoặc trong việc xác định nhóm biểu thức.

1. Tạo dữ liệu khiến lỗi lộ ra

Chạy đoạn Python sau trong file mới. Database chỉ tồn tại trong bộ nhớ của tiến trình:

import sqlite3

db = sqlite3.connect(":memory:")
db.executescript("""
CREATE TABLE demo_orders (
    id INTEGER PRIMARY KEY,
    tenant_id INTEGER NOT NULL,
    status TEXT NOT NULL
);
INSERT INTO demo_orders VALUES
    (1, 7, 'open'),
    (2, 7, 'pending'),
    (3, 8, 'pending'),
    (4, 7, 'closed'),
    (5, 8, 'open');
""")

wrong = db.execute("""
    SELECT id FROM demo_orders
    WHERE tenant_id = ? AND status = ? OR status = ?
    ORDER BY id
""", (7, "open", "pending")).fetchall()

correct = db.execute("""
    SELECT id FROM demo_orders
    WHERE tenant_id = ? AND (status = ? OR status = ?)
    ORDER BY id
""", (7, "open", "pending")).fetchall()

assert wrong == [(1,), (2,), (3,)]
assert correct == [(1,), (2,)]
print("wrong:", wrong)
print("correct:", correct)

Hàng 3 thuộc tenant 8 nhưng có trạng thái pending. Nó là ca đối chứng quyết định: nếu bộ test chỉ chứa dữ liệu tenant 7, hai truy vấn có thể trả kết quả giống nhau và lỗi không lộ.

Binding giữ giá trị tách khỏi cú pháp SQL; nó không tự sửa cấu trúc logic của câu lệnh. Ví dụ dùng placeholder ? theo sqlite3 của Python. Khi chuyển sang driver PostgreSQL, dùng cú pháp parameter của driver, không thay bằng nối chuỗi.

2. Dùng IN khi hai trạng thái áp lên cùng một cột

Trong trường hợp này có thể diễn đạt gọn bằng IN. Nối tiếp file vừa chạy:

with_in = db.execute("""
    SELECT id FROM demo_orders
    WHERE tenant_id = ? AND status IN (?, ?)
    ORDER BY id
""", (7, "open", "pending")).fetchall()
assert with_in == correct

other_tenant = db.execute("""
    SELECT id FROM demo_orders
    WHERE tenant_id = ? AND status IN (?, ?)
    ORDER BY id
""", (8, "open", "pending")).fetchall()
assert other_tenant == [(3,), (5,)]
db.close()

IN ở đây giúp người đọc nhìn thấy một nhóm trạng thái. Đừng dùng nó để thay cơ học mọi OR: hai nhánh có thể liên quan các cột hoặc quy tắc hoàn toàn khác nhau. Với danh sách động, tạo đúng số placeholder và bind từng giá trị; xác định riêng hành vi khi danh sách rỗng.

Kiểm tra query builder và các điều kiện bổ sung

Khi dùng ORM, đọc SQL sinh ra thay vì chỉ nhìn chuỗi method trong code. Nhóm OR thường cần một callback hoặc biểu thức con của thư viện. Kiểm tra cả tenant hiện tại, tenant khác có cùng trạng thái, trạng thái bị loại và tenant không có hàng.

Nếu thêm điều kiện chưa xóa hoặc quyền xem, đặt nó ở cấp nhóm đúng với yêu cầu. Viết câu nghiệp vụ bằng lời trước: tất cả hàng phải thuộc tenant hiện tại, và trạng thái phải nằm trong danh sách được chọn. Sau đó đối chiếu từng nhóm ngoặc với câu ấy.

Giới hạn cần giữ rõ

Schema demo đặt tenant và status NOT NULL nên không đi vào logic ba giá trị của NULL. Thêm cột nullable cần thêm ca kiểm tra riêng. Bài cũng không khẳng định thứ tự thực thi vật lý của điều kiện; ưu tiên toán tử quyết định cách hiểu biểu thức, không buộc optimizer đánh giá từng vế theo thứ tự viết.

Một WHERE đúng là phần cần kiểm tra, chưa thay thế toàn bộ thiết kế phân quyền. Giá trị tenant phải đến từ ngữ cảnh đã được xác thực của ứng dụng. Kết quả kiểm thử nhỏ chứng minh lỗi và cách nhóm trong fixture này; hãy đưa ca tenant chéo vào bộ regression test của endpoint thực tế.

Nguồn tham khảo

  • PostgreSQL 17: operator precedence
  • SQLite: thứ tự ưu tiên biểu thức
  • Python: sqlite3 và parameter binding

Tags: Kiểm thửSQLSQLite
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQLite REPLACE: cột bị bỏ qua có thể mất giá trị cũ

by Suong Nguyen
06/11/2026
0

So sánh INSERT OR REPLACE với ON CONFLICT DO UPDATE để thấy một cột không truyền vào có được giữ lại hay không.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL LIKE: tìm dấu % và _ như ký tự thật bằng ESCAPE

by Suong Nguyen
04/11/2026
0

Kết hợp bind parameter và ESCAPE để ô tìm kiếm chứa % hoặc _ không vô tình trở thành một mẫu wildcard khác ý định người dùng.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL AVG gặp NULL: dữ liệu chưa có không tự trở thành số 0

by Suong Nguyen
03/11/2026
0

So sánh AVG(value), AVG(COALESCE(value, 0)) và COALESCE(AVG(value), 0) để thấy vị trí xử lý NULL có thể đổi ý nghĩa trung bình.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL EXISTS: lọc khách có đơn mà không nhân dòng khách hàng

by Suong Nguyen
02/11/2026
0

So sánh JOIN với EXISTS trên fixture có nhiều đơn cho một khách để giữ đúng đơn vị một dòng trong danh sách trả về.

Next Post
Minh họa các khái niệm AI, mạng nơ-ron và lập trình trên máy tính

Top-k accuracy: nhãn đúng nằm trong danh sách chưa có nghĩa dự đoán đầu tiên đúng

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native ActivityIndicator: dừng spinner có cần bỏ cả vùng giữ chỗ?
  • Array.reduce thiếu initialValue: mảng rỗng lỗi, một phần tử không gọi callback
  • Android SharedPreferences.apply: đọc lại được chưa chứng minh đã ghi xong xuống đĩa

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply