views:

419

answers:

10

It seems like a no brainer to me. I've heard countless stories about people forgetting the WHERE clause in an UPDATE or DELETE and trashing an entire table. I know that careless people shouldn't be issuing queries directly and all that... and that there are legitimate cases where you want to affect all rows, but wouldn't it make sense to have an option on by default that requires such queries to be written like:

UPDATE MyTable SET MyColumn = 0 WHERE *

Or without changing the language,

UPDATE MyTable SET MyColumn = 0 WHERE 1 = 1 -- tacky, I know
+9  A: 

Because the spec doesn't require it, and you shouldn't be running ad hoc sql directly against production data anyway.

Joel Coehoorn
"shouldn't be running ad hoc sql directly against production data anyway". lol. People also shouldn't exceed the speed limit on the highway - but they do, and people are now forced to wear seatbelts to prevent injury. The OP is wondering why seatbelts aren't required in SQL land.
TheSoftwareJedi
Seatbelts should at least be an option
rpetrich
While seatbelts should be an option, IMHO, there doesn't need to be any. We are programmers, and have been given great power, power to cause the rise and fall of databases; we must use great responsibility and care in our day-to-day work. The admin can enable a seatbelt if one is available, but I don't think we should expect one to be there.
sheepsimulator
So you require a WHERE clause, so Mr Dumb learns to type WHERE 1=1 instead. People who don't want to think will go to extraordinary lengths to continue to be able to not think. Thinkers meanwhile, will, if MS implemented this nonsense, ditch it and move to something less lunatic. Fortunately, it ain't gonna happen.
Mike Woodhouse
@sheepsimulator lol- Is that some kind of whack line from spiderman? :)
dotjoe
+3  A: 

Making this mistake is a long engrained rite-of-passage for programmers. We've all made it - and royally screwed up production data - learning a lot in the process of fixing it. You only make this mistake once, so it's kind of fun watching a developer join the ranks when it happens.

Preventing it from happening would ruin all the fun!

:)

TheSoftwareJedi
In all seriousness, my first job in high school working in tech support for a .com they literally would have us lowly techs running commands like "update users set lockedout = 0 where ..." while an app was perpetually "in development". then they'd scream when someone forgot the where clause. :) But I've always wondered why they would even allow that syntax and I still don't really see a valid reason.
Josh Einstein
+2  A: 

Joel, I think the point of Josh's question is why doesn't the spec require it, or at lease have an Option Setting that will make the specific database require it?

Since the spec does not require it as you say, there is an opportunity for an errant query (either ad hoc or simply a programatic bug) to change rows in the database you didn't intend to change.

An implicit "ALL ROWS" seems way more dangerous than an implicit "NO ROWS".

Anthony
I would have to agree that it would probably be in the best interest of all if it was an implicit NO ROWS.
Josh Curren
+1  A: 

I know from experience that you only make this one once... after it happens once you always make sure to never let it happen again!!!

Josh Curren
+3  A: 

Just to play it safe we can always run in a transaction:

BEGIN TRAN

UPDATE MyTable SET MyColumn = 0

Then if the row count looks good:

COMMIT TRAN
Robin
That's a great suggestion. I pretty much always do that if for no other reason than to make sure my criteria is good.
Josh Einstein
+4  A: 

from my point of view this is a rethoric question, I mean it's kind of a suggestion...

In deed, I find it is a really good one, there could be some setting like "SAFE_UPDATE" or something like that...

what I usually do, besides robin's tip (ALLWAYS open a transaction), is to run the query with select, just to have a look at the records that will be updated, something like this

update mytable set column = xx
-- select * from mytable
where mycondition = mycondition

before updating I just select the from the select and see what it returns...

anyway, you should allways have a backup (I heard sql 2005 snapshots are pretty cool too) and work inside a transaction...

opensas
+3  A: 

Isn't it possible to set auto commit to false in your client session as a default? You have to issue a "commit" to see your changes that way, in an almost "are you sure you want to do this?" fashion.

I believe that was the default for all Oracle TOAD clients at a former employer.

duffymo
Nice! I hadn't known about it but it's called SET IMPLICIT_TRANSACTIONS { ON | OFF } and as you noted, it causes commands to require explicit commit. While I will most certainly run with that option on from now on, it still feels wrong to me that SQL defaults to affecting all rows.
Josh Einstein
If it's "nice", why not vote up and accept the answer? You'll have to alert the SQL standards body to let them know that you don't approve of their decision.
duffymo
I did vote it up but someone came along and voted all the agreeing answers down. I didn't mark it as the answer because I was waiting to see if someone would come along with some explanation as to why it can't or shouldn't be done. But it looks like the "we're programmers so we shouldn't make mistakes" answer is the most popular. I'll mark yours.
Josh Einstein
A: 

Don't try to make your system idiot-proof - idiots are extremely ingenious! :-)

What would stop them to just simply add WHERE 1=1 to every query - possibly even from a template? I don't think this would accomplish anything at all....

Marc

marc_s
I think you missed the point Marc. My point is that by mistakenly omitting a selective filter, SQL assumes you want to delete/update everything which I feel is a completely ridiculous default assumption. I am assuming (quite reasonably I think) that it's very unusual for one to want an update/delete to affect all rows and so there would be no reason to add WHERE 1=1 to a default template.
Josh Einstein
A: 

Josh it actually is not all that unusual to want to delete or update all rows in a table.

HLGEM
A: 

MySQL DOES provide that option for ad hoc queries. It's called --safe-updates (or --i-am-a-dummy). As others have pointed out, we've all made that mistake once. Those of us who run ad hoc queries all the time, sometimes at 1AM, have made the mistake more than once.

Although I normally hate "idiot proof" systems and "are you sure" dialogs, I like this option. You should always be careful, but even being careful you'll make perhaps one error per thousand hours. If you spend 50 hours a week logged in as root on production systems, one error per thousand hours is 2 1/2 major screw ups per year. For that reason, and one other, we find --safe-updates to be very useful.

There are two reasons that it's more useful than most MS confirmation messages. First it catches something that is most likely to be an error, unlike "are you sure you want to delete that file?". Most file deletes really are desired, so the confirmation is an annoyance. Most "delete from users" , if missing a where clause, really is an error. Secondly, it points out exactly what the likely problem is - the missing where clause. It's as if the file delete confirmation was smart enough to say "that's the brand new updated copy, not the old copy you think you're deleting. Do you really want to delete the new copy, or did you intend to delete the old one instead?"

Anyway, generally I hate "idiot proof", but I like --safe-updates, and if it's an option those who don't want it need not use it. My one concern is that if you constantly work on a system that DOES have the feature, someone might get sloppy and be in trouble when they switch to a system without it, such as switching from MySQL to MSSQL.

Scratch the last caveat - no one in their right mind would switch to MS after becoming familiar with open source. :)

Ray