Learn SQL, dammit
gun.io
gun.io
So of course, learn SQL as fully as possible. But I recommend using an ORM that allows you to make full use of your SQL knowledge at all times.
Nobody can agree on the point of ORMs, which is a large part of the reason why there's so much debate over whether to use them and how. I must say, if their point is to eliminate maintenance and debugging, then they are failing miserably at it.
But that's kind of the point- with a decent ORM library there isn't really much work to do.
model = MyModel.load(id)
Add a new field to your model? It'll handle it. It might even modify the table for you. With raw SQL you'd have to go and edit your UPDATE and INSERT statements each time. Seems like a lot more maintenance/potential debugging to me.SQL is about a lot more than CRUD and tables.
ORMs exist to simplify CRUD operations. If you are trying to do something that is a not a CRUD operation then you'd be mad to try and use an ORM to do it.
Also if you want to support more than one type database, I would use an ORM.
An example - in the game industry we often have technical artists - pretty cool bunch of folks with awesome talents - art (maya, motionbuilder, etc.) and coding (python, mel, C/C++) - these folks are never afraid to step into the dark woods, and would take SQL and learn it as if it was nothing dangerous, but they surely won't mind a good ORM. From what I've learned, they see most of these things as tools.
There are plenty of people who already know SQL and are comfortable using it, but still prefer to use an ORM though. It's not like ORMs are only used or liked by people who don't know SQL.
Personally, I agree with OP that nobody should ever use an ORM as an excuse to not know SQL. You need to know SQL anyway.
So, once we agree on that, your question "Is there any reason to use an ORM if I know SQL" (that's basically what you mean when you phrase it in the inverse "Is there any reason it would be suboptimal to NOT use an ORM", right?) -- basically just boils down to "Is there ever any reason to use an ORM?".
A topic which is basically the equivalent editor/OS war of db-based web development on HN or reddit. Meaning it's an argument that can and does go on forever, and you can find in-depth treatments of in many other threads.
anyway it is usually never the case. Why would you build a complex app only to tear it appart with going back to raw SQL ?
i'm not talking about SQLAlchemy but often the main problem with ORM is performance. Especially when a orm has its own query language on top of the SQL language ( Like Hibernate or Doctrine ).
A good ORM imho is what you described , something very light but still usefull enough so one doesnt have to do data transformation from rows to objects. How does SQLAchemy fetch related objects ? is it is lazy ? or does it fetch everything when doing a join query for instance.
Anyway thank you for your great work with SQLAlchemy.
OT but thanks for SQLAlchemy. It's the model ORM in my opinion. It's the only one I've ever used that feels like it respects SQL. When I started working with Python fulltime I spent days reading through the SQLAlchemy source - I learnt a lot from that.
select order_number,sum(line_value) as order_value from order_line
group by order_number
having order_value > 100;
And: select order_number,order_value from
( select order_number,sum(line_value) as order_value from order_line
group by order_number )
where order_value > 100;
I'd expect them to have the same explain plan and runtime characteristics. Isn't HAVING just syntactic sugar for the fact queries can be arbitrarily nested? Syntactic sugar isn't fundamental IMHO.I'm actually not sure what I said is true (you can possibly do more with nested queries than you could do with just joins and group by/having?), but I DO think group by/having came before nested queries in rdbms implementations.
While you could think of nested subqueries as syntactic sugar, you might also want to think of them as a view you specify on the fly, or a "derived table" of information.
Each RDBMS optimizes a bit differently, but depending on your system subqueries may have query plan implications as well. Sometimes they'll make your query faster, other times slower. It all depends on the RDBMS, table indexes, and the operations you are doing inside the nested query.
Personally, I'd recommend using HAVING instead of using WHERE with a nested SUM. The query optimizer may create the same execution plan in the end, but the HAVING is a bit more explicit in what you are doing.
For those familiar with SQL, HAVING indicates you are filtering your query on an aggregate value, where as a WHERE indicates you are filtering records out of consideration before they are aggregated (as someone else as pointed out in another comment).
...
having sum(line_value) > 100;
Would the performance be the same? That's up to the individual DB. To say, "Yes, they would" implies that all DBMS vendors implement query plans the same way. I think that, fundamentally, they should perform the same way but again: it's not up to you or I; it's up to the people who wrote the query execution engine.
Funny thing is, I've used HAVING a lot in the past, but couldn't have explained the difference succinctly without cheating and looking it up.
The other big piece of advice is the tried and true incremental approach. The more complicated something is, the more likely I am to use the SQL client the way one uses a REPL and incrementally write the query:
1. Write basic SELECT
2. Add another clause (WHERE filter, GROUP BY, etc...)
3. Execute (syntax/sanity test)
4. Finish or Goto step 2
Just like everything else in programming it's amazing how much simpler things are when you just piece them together one step at a time.[1]: https://en.wikipedia.org/wiki/Set_theory
[2]: http://seanmehan.globat.com/blog/2011/12/20/set-theory-and-s...
Celko calls this "thinking in sets."
SELECT *
FROM employees e
WHERE EXISTS (SELECT 1
FROM assignments a
WHERE a.employee_id = e.id)
For a while in Oracle this was a lot faster than IN/NOT IN. I'm not sure if that's still the case, or if it's true for other systems. I believe I read that in Postgres the query planner does the same thing whether you use EXISTS/NOT EXISTS or IN/NOT IN.EDIT: This kind of query is great with Rails scopes, because you can write something like this:
class Employee
scope :with_assignments, where(<<-EOQ)
EXISTS (SELECT 1
FROM assignments a
WHERE a.employee_id = employees.id)
EOQ
end
and that is easily composeable with other scopes/conditions/etc since it doesn't force you to use any joins. Yay for mixing SQL with your ORM!select whatever from wherever where user_id in (select id from users where somethingorother like '%lol%');
Got an index on user_id? Too bad. Ignored.
If you precompute the values, though?
select whatever from wherever where user_id in (1, 2, 3);
Sweet, I love indexes! I'll definitely use them.
If you use a nested loop join, where you hit the index once for each inner query result, that's O(n*log m). If on the other hand you do a hash join, skipping the index but doing a full table scan of wherever, the complexity is O(m+n). So which is the faster choice depends on how many rows the inner query returns.
If you want to plan up front, before you know what m is, how would you decide which join to use?
I don't think this is true, unless it's a very recent change. Here's a post from 2009 comparing NOT IN/NOT EXISTS/LEFT JOIN WHERE IS NULL for Postgres:
http://explainextended.com/2009/09/16/not-in-vs-not-exists-v...
scope :with_assignments, joins(:assignments)
(or :assignment, depending on how your association is defined)
In tsql, you are not allowed to have order by in a subquery (if memory serves me right)
Edit: Oh crap, I forgot this isn't SO, and the formatting went out the window.
SELECT
user_name,
(SELECT TOP 1 last_action FROM actions WHERE actions.user_id=users.user_id ORDER BY action_timestamp)
FROM
users
(TOP is T-SQLs version of LIMIT)Also, thanks for making me aware of CROSS APPLY, haven't seen that before!
In Postgres, it appears that this does the same thing as IN.
[0] http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QU...
[1] http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUEST...
Don't believe me?
1. Do you have objects? 2. Do you have relational data?
There's the O and the R. How do you get them together? That's where the M comes in. You use a library that knows how to do the M, or you do your own M with a bunch of getters and setters, for loops and case statements.
Eventually, any little change to the database becomes a regression nightmare.
Once you find yourself saying "I know, I'll build a code generator to create these DAOs", that's when you should finally realize you should have used a real ORM. Sadly, many people still won't get it at this point and will go ahead with the code generator.
Bullshit. You are making absurd generalizations based on your personal view of how the rest of the world operates.
>1. Do you have objects?
No, I do not. That makes it pretty obvious that I do not use an ORM doesn't it? "Everyone" includes more than just people using OO languages.
Then you are doing XRM, where X = Objects, structs, vars...
The user clicks save. Now what? You've got to get that change to the data in the dictionary inserted into the correct place in the relational database.
You're going to write code to do by hand what an ORM wants to do for you.
Absolutely crazy.
It all depends on the coverage of your server-side web engineers...some will go deeper into the JavaScript/UI, some go deeper into the data-model.
Joel Spolsky covered this well in his article "The Law of Leaky Abstractions": http://www.joelonsoftware.com/articles/LeakyAbstractions.htm...
If you were a developer that did interact with databases (but not a DBA or specifically a "database developer"), you could probably get by with the four that correspond to CRUD operations directly (SELECT, INSERT, UPDATE, DELETE), so knowing "about 3" isn't all that bad.
So I'm surprised he didn't know SQL after developing .NET for years, but not that surprised he had a Masters but didn't know SQL.
I had to work with SQL through PHP for a while and I found myself "composing" SQL queries in a myriad of ways. I tried to not repeat myself, but it felt like the Django ORM would have gone a lot further in cleaning up the query-building.
In conjunction with Django forms and Django Admin, maybe even the template language, the ORM makes query construction reusable.
One of the kickers is the ability to unify object construction from table columns. It's easy to convert a string or number to some Python field. It's more elaborate with Decimal, Json, or whatever you want to cook up.
Where things get complex is when your framework starts introducing other concepts such as query generators, unit-of-work, caching, lazy-loading, etc.
One of the most critical features is query generation, which I think is the point of this article. Simple queries are pretty easy to abstract, such as loading rows by primary key or querying based off a simple index. Other queries, especially aggregate queries, get tricky fast. I argue that often it is much harder and more work to construct an appropriate query via your frameworks query generator.
Fortunately many good frameworks allow you to essentially write the exact SQL to be executed and the rest of the framework (mapping, caching, unit-of-work) "just works" with the results.
Google cache: http://webcache.googleusercontent.com/search?q=cache%3Agun.i...
I looked at the code, nothing looked THAT bad, so I did an EXPLAIN, noticed a missing index, added it. I ran the report in 4 minutes.
Clearly, whoever wrote that report didn't know nearly enough about SQL.
'Think about it, though: it’s absurd that you would even need to learn any SQL at all! The very nature of an ORM is to bypass SQL.'
I think the nature of ORM is to map object oriented code to relation data. So not to bypass, but to pass between the two conveniently. Conveniences that ORMs do automatically that otherwise you do manually are type checking, sql sanitization, and merging logic (methods) with the data in the same class. Knowing SQL does not make the above tasks any easier, so does not, in any way, prompt dropping ORMs.
Also, there is the wrong use of 'begs the question' in the same paragraph :)
That was a bad translation from day one, and people are now using the phrase in a way that makes more sense.
You can't make this stuff up.
But the point that one needs to know SQL even if one is using an ORM is just obvious to me. It boggles and scares me that anyone thinks they can be a competent web developer without knowing SQL.
I was going to say "...if they use an rdbms, maybe they just use some NoSQL and can get away without it." But you know what, nope, not even that caveat -- if you don't know SQL and rdbms, you aren't going to be competent to know if some nosql is right the choice, or which one, either.
1. Joe Celko's Trees and Hierarchies in SQL for Smarties 2. Joe Celko's Thinking in Sets: Auxiliary, Temporal, and Virtual Tables in SQL
[Edit: However, in the spirit of the OP it's perfectly reasonable to expect your devs to know or be able to learn SQL.]
Because knowing SQL doesn't make you a better Python programmer. It might make you a better application developer, but SQL knowledge is not a subset of Python knowledge.