I have a couple of points, unrelated.<p>(1) Tabular data comes to people naturally. It's not an obscure, impractical theory foisted on us by E. F. Codd. Peer over the shoulder of your non-programmer coworkers: the front-office secretary, the project manager, the company president. You will find that each of them love Excel. They're using it for address books, project statuses, meeting minutes, and a million other things. Some might say they're abusing it, because Excel is meant for math, and they're using it just because it makes it easy to set things into tables.<p>(2) Organizing a complex application into tabular data is hard. Look again at your secretary's Excel spreadsheet of contacts, and you will see that it fails the first level of normalization: contact names and company addresses are repeated across rows. Changes are delicate, and the spreadsheet likely has bad data.<p>An application of even medium complexity, if properly normalized, will need several tables, including one-to-many and many-to-many tables. For each column, you must choose among a cornucopia of data types: boolean, integer, real, numeric, date, time, timestamp, enum, text, array, json, and several others. Furthermore, have you chosen the right constraints: primary key, foreign key, unique, check constraint, rules, trigger functions? Most pages of the app will involve joining several tables, and often there is a way to arrange it that makes it run 100 times faster. But then again, such is the case in any programming language.<p>So I do not blame programmers who want to reach for the NoSQL database. It is a thousand times easier to just:<p><pre><code> save(json_encode($_POST));
</code></pre>
or whatever. I've been programming with SQL all day long for over 10 years, and it's still hard. I'm still finding better ways to write the SQL or use features of my database (PostgreSQL) that I wasn't using, at least not as much as I could.<p>The biggest encouragement I can give to someone who doesn't know anything beyond<p><pre><code> select * from table
</code></pre>
is that writing it in SQL is almost always shorter than in your procedural language of choice. How would you enforce all these rules in procedural:<p><pre><code> create table sales (
id serial primary key,
sold timestamp,
emp int references employees,
cust int not null references customers on update cascade,
item int not null references items on update cascade,
qty int not null check (qty > 0),
price numeric (12, 2) not null check (price > 0)
)
</code></pre>
or formulate this report:<p><pre><code> select emp
from sales
where age(sold) < '3 years'
group by emp
having sum(price) > 1000000
order by 1
</code></pre>
(DISCLAIMER: The code in this post is not guaranteed to compile.)