Skip to content

Chained CRUD - Examples & Best Practices

This document contains practical examples, comparison with traditional SQL, FAQ, and best practices. For method details, see the sub-pages:


Comprehensive Examples

Example 1: User Management System

vb
' Query active user list (sort + pagination)
If db.Table("users") _
    .Where("status=?", "active") _
    .WhereNotNull("email") _
    .OrderByDesc("last_login") _
    .Page(1, 20) _
    .RowRead Then
    
    Do Until db.Rs.EOF
        Debug.Print db.Rs!name & " | " & db.Rs!email
        db.Rs.MoveNext
    Loop
End If

' Search users (fuzzy match + OR condition)
db.Table("users") _
    .WhereLike("name", "%" & keyword & "%") _
    .OrWhereLike("email", "%" & keyword & "%") _
    .OrderBy("name") _
    .RowRead

' Create new user
With db.Table("users")
    .Field "name", txtName.Text
    .Field "age", CLng(txtAge.Text)
    .Field "email", txtEmail.Text
    .Field "status", "active"
    .RowCreate
    newId = db.LastInsertId
End With

' Update user info
With db.Table("users").Where("id=?", userId)
    .Field "name", txtName.Text
    .Field "email", txtEmail.Text
    .RowUpdate
End With

' Delete expired users
db.Table("users").Where("status=?", "expired").WhereNull("email").RowDelete

Example 2: Report Statistics

vb
' Department count statistics
db.Table("users") _
    .Columns("dept,COUNT(*) AS cnt") _
    .GroupBy("dept") _
    .Having("cnt>5") _
    .OrderByDesc("cnt") _
    .RowRead

' Monthly sales summary
db.Table("orders") _
    .Columns("YEAR(created_at) AS y,MONTH(created_at) AS m,SUM(amount) AS total") _
    .GroupBy("YEAR(created_at)") _
    .GroupBy("MONTH(created_at)") _
    .WhereBetween("created_at", "2026-01-01", "2026-12-31") _
    .OrderBy("y") _
    .OrderBy("m") _
    .RowRead

' Quick statistics
Dim totalUsers As Long
totalUsers = db.Table("users").RowCount

Dim avgSalary As Variant
avgSalary = db.Table("users").Where("dept=?", "IT").RowAvg("salary")

Dim maxOrder As Variant
maxOrder = db.Table("orders").RowMax("amount")

' Get all department names list
Dim depts As Collection
Set depts = db.Table("users").Distinct.Columns("dept").RowPluck("dept")

Example 3: Multi-Table Join Query

vb
' Order details (orders + users + products)
db.Table("orders") _
    .Columns("orders.id,users.name AS user_name,products.title AS product,orders.amount") _
    .Join("users", "orders.user_id=users.id") _
    .LeftJoin("products", "orders.product_id=products.id") _
    .Where("orders.amount>?", 100) _
    .WhereBetween("orders.created_at", "2026-01-01", "2026-06-30") _
    .OrderByDesc("orders.amount") _
    .Limit(50) _
    .RowRead

Example 4: Check Existence and Extract List

vb
' Check if email exists before registration
If db.Table("users").Where("email=?", newEmail).RowExists Then
    MsgBox "This email is already registered"
    Exit Sub
End If

' Get admin ID list
Dim adminIds As Collection
Set adminIds = db.Table("users").WhereIn("role", "admin,superadmin").RowPluck("id")

' Batch operation: mark all admins as online
With db.Table("users").WhereIn("id", "1,2,3,5")
    .Field "online_status", True
    .RowUpdate
End With

Comparison with Traditional SQL

Query Comparison

vb
' ── Traditional SQL Approach ──
db.Sql("SELECT id,name FROM users WHERE age > 18 AND dept IN ('IT','HR') ORDER BY age DESC LIMIT 10").Fetch

' ── Chained Builder Approach ──
db.Table("users") _
    .Columns("id,name") _
    .Where("age>?", 18) _
    .WhereIn("dept", "IT,HR") _
    .OrderByDesc("age") _
    .Limit(10) _
    .RowRead

Insert Comparison

vb
' ── Traditional SQL Approach ──
db.Sql("INSERT INTO users (name,age) VALUES ('Zhang San',25)").Exec

' ── Chained Builder Approach ──
db.Table("users").Field("name", "Zhang San").Field("age", 25).RowCreate

Update Comparison

vb
' ── Traditional SQL Approach ──
db.Sql("UPDATE users SET name='Li Si' WHERE id=1").Exec

' ── Chained Builder Approach ──
db.Table("users").Where("id=?", 1).Field("name", "Li Si").RowUpdate

Delete Comparison

vb
' ── Traditional SQL Approach ──
db.Sql("DELETE FROM users WHERE status='expired'").Exec

' ── Chained Builder Approach ──
db.Table("users").Where("status=?", "expired").RowDelete

Chained Advantages

DimensionTraditional SQLChained Builder
ReadabilityLong string concatenation, hard to readMethod chain with clear semantics
SQL Injection RiskManual value concatenation, easy to miss escapingAutomatic parameter escaping
Cross-DatabaseNeed to write different pagination/limit syntaxAuto-adapts MySQL/MSSQL/Access
MaintainabilityChanging conditions requires rewriting entire SQLAdd/remove chained methods
DebuggingNeed to print complete SQLEach step corresponds to a SQL clause

FAQ

Q1: Can the chained builder and Sql() method be mixed?

Not recommended. The chained builder (Table + Where + ...) and the traditional approach (Sql) use different internal states. If Sql() has been called, chained conditions won't apply; and vice versa. Choose one approach:

vb
' Approach 1: Chained builder (recommended for standard CRUD)
db.Table("users").Where("id=?", 1).RowRead

' Approach 2: Traditional SQL (suitable for complex queries, subqueries, etc.)
db.Sql("SELECT * FROM users WHERE id = 1").Fetch

Q2: What if complex queries don't fit the chained approach?

For advanced SQL like subqueries, UNION, window functions that the chained builder cannot cover, use the traditional Sql() approach:

vb
' Subquery - use Sql() approach
db.Sql("SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 1000)").Fetch

' UNION query - use Sql() approach
db.Sql("SELECT name FROM users UNION SELECT name FROM admins").Fetch

Q3: Can Where and WhereLike be used together?

Yes, they are both AND conditions and will be automatically merged:

vb
db.Table("users") _
    .Where("dept=?", "IT") _
    .WhereLike("name", "%Zhang%") _
    .RowRead
' Generated: WHERE dept='IT' AND name LIKE '%Zhang%'

Q4: How does OrWhere priority work?

OrWhere is wrapped in parentheses to ensure correct combination with AND conditions:

vb
db.Table("users").Where("age>?", 18).OrWhere("role='VIP'").RowRead
' Generated: WHERE age > 18 OR (role='VIP')

Q5: Can Rs editing continue after RowCreate?

Yes. RowCreate does not automatically reset the builder, allowing you to continue operating on Rs:

vb
With db.Table("users").RowCreate
    .Rs!name = "Zhang San"
    If someCondition Then
        .Rs!email = "zhang@test.com"
    End If
    .Rs.Update
End With

Q6: What's the difference between Page and Limit/Offset?

MethodUse CaseImplementation
Page(N,M)Standard paginationADO PageSize/AbsolutePage, universal for all databases
Limit(M)Simple truncationSQL LIMIT M, MySQL/MSSQL syntax adaptation
Offset(N)Offset with LimitSQL OFFSET N, MySQL/MSSQL syntax adaptation

Do not use Page and Limit/Offset simultaneously - choose one.

Q7: Is builder state preserved after chained method execution?

No. Terminal methods (RowRead, RowCreate, RowUpdate, RowDelete, RowCount, etc.) automatically call ResetBuilder to clear all internal state after execution. Next chained call must start again from Table().


Best Practices

1. Use With to Simplify Chained Calls

vb
' Recommended: Clear With structure
With db.Table("users").Where("id=?", userId)
    .Field "name", newName
    .Field "age", newAge
    .RowUpdate
End With

' Not recommended: Scattered writing
db.Table "users"
db.Where "id=?", userId
db.Field "name", newName
db.Field "age", newAge
db.RowUpdate

2. Prefer Chained Parameter Escaping

vb
' Recommended: Where placeholder auto-escaping
db.Table("users").Where("name=?", userName).RowRead

' Not recommended: Manual value concatenation
db.Table("users").Where("name='" & userName & "'").RowRead

3. Always Set Conditions for Update/Delete

vb
' Safe: Must have Where condition
db.Table("users").Where("id=?", 1).RowUpdate
db.Table("users").Where("status=?", "expired").RowDelete

' Dangerous: No condition will error (builder protection)
db.Table("users").RowUpdate  ' Error: no condition set

4. Use Sql() for Complex Queries

vb
' Chained: Standard CRUD, simple conditions, sorting, pagination
db.Table("users").Where("age>?", 18).OrderByDesc("id").Page(1, 10).RowRead

' Sql(): Subqueries, UNION, window functions, complex expressions
db.Sql("SELECT * FROM (SELECT id,name FROM users UNION SELECT id,name FROM admins) t").Fetch

Last Updated: 2026-06-26

VB6 and LOGO copyright of Microsoft Corporation