Some backend libraries let you write SQL queries as they are and deliver them to the database. They still handle making the connection, pooling, etc.
ORMs introduce a different API for making SQL queries, with the aim to make it easier. But I find them always subpar to SQL, and often times they miss advanced features (and sometimes not even those advanced).
It also means every time I use a ORM, I have to learn this ORM’s API.
SQL is already a high level language abstracting inner workings of the database. So I find the promise of ease of use not to beat SQL. And I don’t like abstracting an already high level abstraction.
Alright, I admit, there are a few advantages:
- if I don’t know SQL and don’t plan on learning it, it is easier to learn a ORM
- if I want better out of the box syntax highlighting (as SQL queries may be interpreted as pure strings)
- if I want to use structures similar to my programming language (classes, functions, etc).
But ultimately I find these benefits far outweighed by the benefits of pure sql.
TL;DR you can’t be an expert at every aspect of coding, so I let the big boys handle SQL and don’t torture the world with my abysmal SQL code.
I’ve seen enough bad SQL to claim you’re wrong (I write bad SQL myself, so if you write SQL like I do, you’re bad at it).
Seriously, the large majority of devs write terrible SQL and don’t know how to optimise queries in any way. They just mash together a query with whichever JOIN
they learned first. NATURAL JOIN
? Sure, don’t mind if I do! Might end up being a LEFT JOIN
, RIGHT JOIN
, or INNER JOIN
, but at least I got my data back right?
Off the top of your head, do you know all the joins that exist, when to use which one, and which ones are aliases for another? Do you know how to write optimal JOIN
s when querying data with multiple relations?
When writing similar queries, do you think most are going to copy-paste something that worked and adapt it? What if you find out that it could be optimised? Then you’ll have to search for all queries that look somewhat similar and fix those.
When you create an index for a table, are you going to tell me you are going to read up on the different types each time to make sure you’re using the one that makes sense? Postgres has 6, MySQL only has 2 tbf depending on storage engine, but what about other DBs? If you write something for one DB and a client or user wants to host it with another, what will your code look like afterwards?
Others have brought up models in code, so that’s already discussed, but what about migrations? Do you think it’s time well-spent writing every single migration yourself? I had the distinct pleasure of having to deal with hand-written migrations that were copy-pasted and modified columns that had nothing to do with the changed models, weren’t in a transaction, failed half-way through, and tracking down which migration had actually failed. These were seasoned developers who completely forgot to put any migration in transactions. They had to learn the hard way.
ORMs introduce a different API for making SQL queries, with the aim to make it easier.
I wouldn’t say that, but instead, that they strive to keep everything contained in one language/stack/deployment workflow, with the benefit of code reusability (for instance, it’s completely idiotic, if you ask me, that your models’ definition and validation code get duplicated in 3 different application layers (front/API/DB) in as many different languages.
ORMs are not a 100% solution, but do wonders for the first 98% while providing escape hatches for whatever weird case you might encounter, and are overall a net positive in my book. Moreover, while I totally agree that having DB/storage-layer knowledge is super valuable, SQL isn’t exactly a flawless language and there’s been about 50 years of programming language research since it was invented.
You, my friend, should try EdgeDB. A database and an ORM in one.
When you change the data model, you can get to 100%, which you say is impossible for ORMs
This is a project I am already keeping a close eye on, but I would rather qualify it as a “better SQL” than as an alternative to your typical (framework’s) ORM. For instance, it won’t morph CRUD operations and data migrations into a language/stack that’s native to the rest of the project (and by extension, imply learning another language/stack/set of tools…)
Dapper.net is the right balance imo… you get the shape the query and get object field mapping.
Completely agree. Most ORMs focus on hiding SQL away (for good reasons, such as portability and type safety), but I wish there were more approaching it in the reverse. That is, have the user write schemas, queries and migrations in SQL, and generate models with typesafe APIs in return. I’m only aware of SQLDelight in this space, but it’s such a great idea to have the source of truth be actual SQL, and a build time generator and validator working alongside you.
Check out Elixir’s Ecto. You basically do write SQL for querying, it’s just lightly wrapped in a functional approach.