SQL vs NoSQL: What I Learned Building Real Applications

A practical guide from someone who learned both the hard way
Learning Curve
You hear so much about SQL before you actually understand what it is.
You just know it's important because it deals with technology.
Turns out, it's the pivotal factor of why the internet exists at all.
Data.
Data is the most important piece of what makes the internet work. Every transaction, download, delete, cookie, link.
Everything that helps maintain information for a business, company, or regular person like you and me. And to shuffle through all that stored data in a huge database?
You need the right tool.
SQL: The Structured Approach
SQL | `Structured Query Language` | is used to maintain and structure relationships through tables using key/value pairs. According to GeeksforGeeks (2018), SQL databases use a fixed schema where data is organized into tables with predefined relationships.
I learned through our hands-on training through my CST-345 coursework, building applications for pet stores, bookstores, and criminal databases.
The Basics That Clicked Fast!
-- Simple query from my Pet Store application
SELECT ID, NAME, PRICE, DESCRIPTION, PET_CATEGORIES_ID
FROM pets
WHERE NAME LIKE '%fluffy%';
The fundamentals came easy:
SELECT,FROM,WHEREto pull data from fieldsMathematical expressions like
SUM(),MAX(),MIN()JOINto connect related tablesGROUP BYandORDER BYfor organization
Where It Got Tricky: JOINs
JOINs only made sense when I understood the relationships. Here's a real example from my Bookstore database:
-- Getting customer names with their reviews
SELECT
customers.first_name,
customers.last_name,
reviews.rating,
reviews.comments
FROM customers
JOIN reviews ON customers.customer_id = reviews.customer_id
WHERE reviews.rating >= 4;
This works because there's a foreign key relationship: reviews.customer_id references customers.customer_id.
Each review "belongs to" one customer (Smallcombe, 2024).
The hard part?
When JOINs got complex:
-- From my Bookstore: Books, Authors, Works, and Sales
SELECT
authors.first_name,
authors.last_name,
works.title,
books.isbn,
sales.sale_date,
customers.first_name AS buyer_first_name
FROM authors
JOIN works ON authors.author_id = works.author_id
JOIN books ON works.work_id = books.work_id
JOIN books_has_sales ON books.isbn = books_has_sales.books_isbn
JOIN sales ON books_has_sales.sale_id = sales.sale_id
JOIN customers ON sales.customer_id = customers.customer_id
WHERE authors.last_name = 'Orwell';
That's six tables joined together to answer: "Who bought George Orwell's books and when?"
This is where SQL shines { complex relational queries } (MongoDB, 2024).
MongoDB: The Document Approach
Then Activity 6 hit: converting my C# Music Player from MySQL to MongoDB.
MongoDB doesn't use tables.
It uses documents (like JSON).
According to MongoDB's documentation (2024), NoSQL databases like MongoDB store data in flexible schema that allows horizontal scaling which is show to say, a bunch of data can be distributed to multiple servers at once time to manage large traffics of data.
The Paradigm Shift
MySQL approach (what I had before):
albums table: id | title | artist | year | imageURL | description
tracks table: id | title | videoURL | album_id (foreign key)
MongoDB approach (what I converted to):
{
"_id": "6331e64e8027c38f9faabccb",
"Title": "Abbey Road",
"Artist": "The Beatles",
"Year": 1969,
"ImageURL": "https://upload.wikimedia.org/...",
"Description": "Abbey Road is the eleventh studio album...",
"Tracks": [
{
"_id": "63372d434b5b453b067266cf",
"TrackTitle": "Come Together",
"VideoURL": "https://www.youtube.com/..."
},
{
"_id": "63374429177f0ab0572893b3",
"TrackTitle": "Something",
"VideoURL": "https://www.youtube.com/..."
}
]
}
No separate Tracks table. No foreign keys. Tracks live inside the Album document.
This is what MongoDB calls embedded documents (MongoDB, n.d.).
Data that's frequently accessed together, gets stored together.
Setting Up: The Real Installation Journey
C# with MySQL: Smoothest Path
Install NuGet package:
MySQL.DataCreate connection string:
string connectionString = "datasource=localhost;port=4406;username=root;password=root;database=my_pet_store;";
- Write queries:
MySqlConnection conn = new MySqlConnection(connectionString);
conn.Open();
MySqlCommand command = new MySqlCommand("SELECT * FROM pets", conn);
That's it. Took maybe 10 minutes.
Java with MySQL: More Configuration
Same database, different language. More environmental setup:
static final String DB_URL = "jdbc:mysql://localhost:4406/my_pet_store";
static final String USERNAME = "root";
static final String PASSWORD = "root";
Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
Had to configure:
JDBC drivers
Classpath settings
IDE-specific configurations (Eclipse vs VS Code made a difference)
Time investment: 30-45 minutes of setup, then smooth sailing.
MongoDB with C# Atlas: Most Setup, Best Payoff
This was intense. Following the Activity 6 guide:
Step 1: Create MongoDB Atlas account
Step 2: Create cluster
Step 3: Set up database user
Step 4: Configure IP whitelist
this trips people up, your IP changes on different networks
Step 5: Get connection string:
private const string CONNECTION = "mongodb+srv://myAtlasDBUser:myatlas-001@myatlasclusteredu.7try9i7.mongodb.net/?retryWrites=true&w=majority";
Step 6: Install NuGet: MongoDB.Driver
Step 7: Update models with BSON attributes:
using MongoDB.Bson.Serialization.Attributes;
internal class Album
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public int Year { get; set; }
public string ImageURL { get; set; }
public string Description { get; set; }
public List<Track> Tracks { get; set; }
}
Time investment: 2-3 hours first time.
But here's the kicker
it flagged my GitHub commit immediately when I tried to push with the password in the connection string. That taught me about environment variables faster than any tutorial.
What Were My Takeaways
The Code Tells the Story
Let me show you side-by-side comparisons from my actual applications.
Example 1: Getting All Records
MySQL (Pet Store):
public List<Products> GetAllProducts()
{
List<Products> allProducts = new List<Products>();
MySqlConnection conn = new MySqlConnection(connectionString);
conn.Open();
MySqlCommand command = new MySqlCommand(
"SELECT PRODUCT_ID, PRODUCT_NAME, PRODUCT_DESCRIPTION, PRODUCT_PRICE, PRODUCT_AMOUNT, PRODUCT_CATEGORY_ID FROM products",
conn
);
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Products product = new Products
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Description = reader.GetString(2),
WholesalePrice = reader.GetDouble(3),
RetailPrice = reader.GetDouble(4),
CategoryID = reader.GetInt32(5),
};
allProducts.Add(product);
}
}
conn.Close();
return allProducts;
}
MongoDB (Music Player):
public List<Album> GetAllAlbums()
{
var result = _albumCollection.Find(m => true).ToList();
return result;
}
Two lines vs 30. That's not an exaggeration.
MongoDB's driver with LINQ made queries incredibly specific and easy to implement. (Smallcombe, 2024).
Example 2: Searching with Wildcards
MySQL (Pet Store):
public ArrayList<Pet> searchForMany(String searchTerm)
{
ArrayList<Pet> myPets = new ArrayList<>();
Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
String queryString = "SELECT ID, NAME, PRICE, DESCRIPTION, PET_CATEGORIES_ID FROM pets WHERE NAME LIKE ?";
PreparedStatement pstmt = conn.prepareStatement(queryString);
pstmt.setString(1, "%" + searchTerm + "%");
ResultSet rs = pstmt.executeQuery();
while(rs.next())
{
Pet pet = new Pet();
pet.setId(rs.getInt("ID"));
pet.setName(rs.getString("NAME"));
pet.setPrice(rs.getDouble("PRICE"));
pet.setDescription(rs.getString("DESCRIPTION"));
pet.setCategoryId(rs.getInt("PET_CATEGORIES_ID"));
myPets.add(pet);
}
return myPets;
}
MongoDB (Music Player):
internal List<Album> SearchAlbum(string searchTerms)
{
var results = _albumCollection.Find(m => m.Title.ToLower().Contains(searchTerms.ToLower())).ToList();
return results;
}
One line. The LINQ expression m => m.Title.ToLower().Contains(searchTerms.ToLower()) replaced the entire PreparedStatement setup.
Example 3: Adding Nested Data
This is where MongoDB really shined for my music app.
The Problem: Adding a track to an album
MySQL approach (what I would have had to do):
-- First, get the album_id
SELECT id FROM albums WHERE title = 'Abbey Road';
-- Then insert into tracks table with foreign key
INSERT INTO tracks (title, videoURL, album_id)
VALUES ('Come Together', 'https://youtube.com/...', 5);
MongoDB approach (what I actually did):
internal Album AddTrackToAlbum(Album albumGetsNewTrack, Track newTrack)
{
// Handle null case (important!)
if (albumGetsNewTrack.Tracks == null)
{
albumGetsNewTrack.Tracks = new List<Track>();
}
// Add track to the list
albumGetsNewTrack.Tracks.Add(newTrack);
// Update the entire document
_albumCollection.FindOneAndReplace(
m => m._id == albumGetsNewTrack._id,
albumGetsNewTrack
);
return albumGetsNewTrack;
}
No separate table. No foreign key. Just modify the document and save.
The Struggles Were Real
Struggle #1: MongoDB _id Confusion
My first error:
System.InvalidOperationException: Element '_id' does not match any field or property of class Album
The problem: I was using int Id (MySQL habit). MongoDB uses string _id with ObjectId format.
The fix:
// WRONG (MySQL thinking)
public int Id { get; set; }
// RIGHT (MongoDB)
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
Struggle #2: Null Reference on Tracks
When I tried to add a track to an album that had no tracks yet:
System.NullReferenceException: Object reference not set to an instance of an object
The problem: Some albums in my database didn't have a Tracks array initialized.
The fix: Always check for null before adding:
if (albumGetsNewTrack.Tracks == null)
{
albumGetsNewTrack.Tracks = new List<Track>();
}
This taught me about MongoDB's schema flexibility.
Not every document needs the same fields (MongoDB, 2024).
Struggle #3: JOIN vs Embedded Documents
In MySQL, I was used to this pattern:
-- Get album with its tracks (requires JOIN)
SELECT albums.*, tracks.title, tracks.videoURL
FROM albums
LEFT JOIN tracks ON albums.id = tracks.album_id
WHERE albums.title = 'Abbey Road';
In MongoDB, I kept trying to think in JOINs when I should have been thinking in embedded documents:
// Just get the album - tracks are already inside!
Album album = _albumCollection.Find(m => m.Title == "Abbey Road").FirstOrDefault();
// Tracks are right here:
foreach (Track track in album.Tracks)
{
Console.WriteLine(track.TrackTitle);
}
No JOIN needed. The mental shift took time.
What Surprised Me
Surprise #1: MongoDB's Security First Approach
The moment I tried to commit my connection string to GitHub:
private const string CONNECTION = "mongodb+srv://myAtlasDBUser:myatlas-001@myatlasclusteredu...";
MongoDB Atlas flagged it. I got an email warning that my credentials were exposed. That forced me to learn about:
Environment variables
Configuration files (
.gitignore)Secrets management
MySQL never warned me about this.
MongoDB's cloud-first design meant security was built-in from day one.
Surprise #2: LINQ Made MongoDB Feel Native in C#
Coming from SQL strings:
string queryString = "SELECT * FROM albums WHERE title LIKE '%Abbey%'";
To LINQ expressions:
var results = _albumCollection.Find(m => m.Title.Contains("Abbey")).ToList();
It felt more like writing C# code than database queries.
MongoDB's C# driver is incredibly well-designed.
Surprise #3: No Migrations Needed
With MySQL, changing the schema meant migration scripts:
ALTER TABLE albums ADD COLUMN genre VARCHAR(50);
With MongoDB, I just... added the field to my C# class:
public string Genre { get; set; }
Next time I saved an album, it had the field.
Old documents without it? Still worked fine.
Schema flexibility means faster iteration (GeeksforGeeks, 2018).
How Can I Use It In Real World Time
Real Scenarios
Let me walk through actual use cases from my work and coursework.
Scenario 1: Active Directory Ticket System
The Need: To be able to track users issues, departments, categories, employees, and resolutions.
The Data Model:
Users belong to Departments
Tickets reference Users
Tickets have Categories
Tickets are assigned to employees
Tickets have multiple Updates (status changes, notes)
MySQL wins here because:
-- Complex query I'd need to run:
SELECT
users.name AS user_name,
departments.dept_name,
tickets.subject,
categories.category_name,
technicians.name AS assigned_to,
COUNT(updates.id) AS update_count
FROM tickets
INNER JOIN users ON tickets.user_id = users.id
INNER JOIN departments ON users.dept_id = departments.id
INNER JOIN categories ON tickets.category_id = categories.id
LEFT JOIN technicians ON tickets.assigned_to = technicians.id
LEFT JOIN updates ON tickets.id = updates.ticket_id
WHERE departments.dept_name = 'IT'
GROUP BY tickets.id
ORDER BY tickets.created_date DESC;
This is relationship hell.
Multiple entities with many-to-many connections.
SQL was built for this (Oracle, 2024).
Scenario 2: Documentation Wiki (DVOUtion Blog)
The Need: Store blog posts with metadata, tags, and content.
The Data Model:
{
"_id": "507f1f77bcf86cd799439011",
"title": "SQL vs NoSQL: What I Learned",
"author": "Don Bowman",
"date": "2026-02-01",
"tags": ["databases", "SQL", "MongoDB", "education"],
"content": "You hear so much about SQL...",
"viewCount": 142,
"comments": [
{
"author": "Reader1",
"text": "Great explanation!",
"date": "2026-02-02"
}
]
}
MongoDB wins here because:
Each blog post is self-contained
Comments are always accessed with the post
Tags are flexible (can add/remove without schema changes)
No relationships to other entities
I don't need to JOIN anything. Just grab the document.
Scenario 3: E-Commerce Product Catalog
The Need: Products with categories, multiple images, variants, reviews.
This is the gray area. Let me show you both approaches:
MySQL approach:
products: id | name | description | base_price
categories: id | name
product_categories: product_id | category_id (many-to-many)
variants: id | product_id | size | color | sku | price
images: id | product_id | url | order
reviews: id | product_id | user_id | rating | comment
MongoDB approach:
{
"_id": "...",
"name": "Running Shoes",
"description": "...",
"categories": ["Athletic", "Shoes", "Running"],
"variants": [
{"size": "10", "color": "Red", "sku": "RS-10-RED", "price": 89.99}
],
"images": [
{"url": "...", "order": 1},
{"url": "...", "order": 2}
],
"reviews": [
{"user": "john_doe", "rating": 5, "comment": "Great shoes!"}
]
}
My choice? Depends on scale.
Small shop (< 10,000 products): MongoDB for flexibility
Large shop with complex inventory: MySQL for better queries across products
Why? Because at scale, you'll need queries like:
-- Find all products in category 'Running'
-- with ratings > 4
-- that have variants in size 10
-- under $100
That's easier in SQL when data is normalized (Smallcombe, 2024).
Tools I Actually Used
MySQL Tools
MySQL Workbench (MySQL Workbench)
Visual schema design
EER diagrams (saved my life for understanding relationships)
Query builder
Best for: Initial schema design
phpMyAdmin (phpMyAdmin)
Quick browsing and editing
Integrated with MAMP
Best for: Development and testing
MongoDB Tools
MongoDB Compass (MongoDB Compass)
Visual document explorer
JSON import/export
Aggregation pipeline builder
Best for: Understanding your data structure
MongoDB Atlas Dashboard
Cloud cluster management
Performance monitoring
IP whitelisting
Best for: Production deployments
Final Thoughts: The Right Tool for the Job
After building applications with both, here's my framework:
When to Choose Choose SQL:
✅ Complex relationships across many tables
✅ A need for strict data consistency
✅ Stable And Maintainable Schemas
✅ Complex reporting requirements
✅ Team familiarity with SQL
My examples: Ticket systems, inventory management, accounting systems
When to Choose MongoDB:
✅ Hierarchical data (JSON-like structures)
✅ Rapid iteration and changing requirements
✅ Data accessed as complete units
✅ Horizontal scaling needs
✅ Modern development stack (Node.js, Python, C#)
My examples: Content management, user profiles, logging systems, my DVOUtion blog
Personal Thoughts
As someone learning and developing the understanding of how these languages and tools work hand and hand. I see databases like tools in a workshop. You wouldn't use a hammer for everything, even if you're really good with hammers.
Its about finding best case scenario, what feels right for your business.
I am interested about this topic and look forwarded to seeing what you think about either
MongoDB or MySQL «
What’s Your Thoughts?
Until we meet again, be smooth like water my friends.
- Keep Walking, Friends. -
Resources & Documentation
GeeksforGeeks. (2018, October 26). Difference between SQL and NoSQL.
Smallcombe, M. (2024, February 15). SQL vs NoSQL: 5 Critical Differences. Integrate.io.
Erickson, J. (2024, August 29). What is MySQL? Oracle.
MongoDB. (2024). NoSQL Vs SQL Databases.
MongoDB.(n.d.) https://www.mongodb.com/resources/products/fundamentals/embedded-mongodb
Smallcombe, M. (n.d.). MongoDB vs. MySQL: Compare Database Performance & Speed. Integrate.io.
MongoDB. (2024). Relational Vs. Non-Relational Databases.
MySQL Workbench: https://www.mysql.com/products/workbench/
phpMyAdmin: https://www.phpmyadmin.net/
MongoDB Compass: https://www.mongodb.com/products/tools/compass



