- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Admin
Holy crap! This actually generates a different query plan than just delete or truncate. It has two table scans for the price of one. As long as we are deleting the whole table, let's do it in an extra expensive way.
Admin
Hey - You can never be too careful with those tricky hash indexes...
I wonder if he did some traces and determined that was... well... no...
You know, this one is just a scary look into an oddly formed mind...
8-)
Admin
Perhaps he was trying (ineffectively) to deal with concurrency issues?
Admin
Fourth! Or fifth...I'm not sure, maybe neither of those...nevermind.
Databases are stupid. Back in my day, you had to write the one's and zero's out with a stick in a small box of sand sitting on your desk. Kids got it so easy these days.
Admin
ah, this isn't too bad to be honest. he/she is an obviously a relative newb to SQL and thought that "delete from
" had a mandatory "where" clause.Admin
I'd try something like
DELETE FROM HashIndex WHERE ItemHash IN (SELECT ItemHash FROM HashIndex)
Not sure if the syntax works but in principle it'd be even more wasteful.
Admin
Admin
If you have access to the table schema and the right permissions, it might be faster to do a
DROP TABLE IF EXISTS ItemHash;
CREATE TABLE ItemHash (table def);
if you're emptying the table completely.
Admin
So the items with a null ItemHash value would be left in the table? Which would make it different from deleting everything? Assuming ItemHash isn't a required field? Or am I totally off? Its been a while since I've done much with SQL queries...
Admin
At least you had fingers and toes. Back in my day, I lived at the bottom of a lake, and giant monsters would come out and nibble on me fingers and toes till all I had left were stumps. I had to write my data schemas with me nose in the mud, and as soon as a carp stirred I lost everything and had to start all over again.
Plus the mud was hosted by 1and1.
Admin
Yes, keeping all the null values is most imporant
Admin
Apparently I've been one-upped, and then the one-upper was one-upped. Which means, according to my math, I've been two-upped. Now I have enough lives to find the princess, who is apparently in another castle.
Admin
And then the one-upper shall become.. the one-uppee!!!111!!!!!!1
Admin
You're spot on. Null is not >= anything, nor is it < anything. The code therefore deletes all records that do not have a null ItemHash value.
Admin
Don't you know DELETE is faster when you delete rows by the INDEX?
Idiots.
Admin
Admin
I always wondered what those stupid zen gardens were for. After hearing this, I rank them up there with the abacus.
Admin
FIRST!
Admin
Duh. Everyone knows a plain old TRUNCATE operates WAY TOO QUICKLY. This coder is obviously paid by the CPU cycle.
Admin
Especially if the table looks like:
Admin
Admin
god this forum software sucks...
You guys must be regular posters on Slashdot. http://en.wikipedia.org/wiki/Slashdot_subculture
Admin
Quite obviously, the WTFery is that he used a subselect. He should have used a self join and having clause:
DELETE FROM HashIndex hi1, HashIndex hi2
WHERE hi1.ItemHash = hi2.ItemHash
GROUP BY ItemHash
HAVING hi2.ItemHash >= min(hi2.ItemHash)
* wonder if that would even work. Probably not. I was just amused by the idea.
Admin
It's pretty poor language design to make it much easier to do bad things than what you probably wanted to do. SQL is full of cases like this.
We've seen how it's much easier to delete everything than it is to delete one particular row. It's also much easier to select everything -- which is usually quite an expensive operation -- than it is to select a particular row by its primary key or to retrieve a limited number of rows, or to retrieve only a subset of the columns. It's much easier to clobber an entire column of data than to change a field in a particular row.
Crazy.
Admin
You must be a youngster.
http://www.phespirit.info/montypython/four_yorkshiremen.htm
Admin
Items with a null ItemHash would be left in the table anyways. That's the great thing about null, is that it doesn't evaluate to anything. Try:
select 1 where 1 <= null or 1 >=null
Should return nothing.
Admin
This remembers me another SQL code I saw once:
drop MyTable;
create MyTable .....
:#
Admin
This is actually true in MySQL (insert MySQL flames here) if you use the --I-am-a-dummy flag.
Admin
SQL is like Unix in this regard - YAFI, YGI. It's easier to delete everything because it's easier to say "delete everything", etc.
Admin
OMG it's real...
Admin
Look, everyone. There is no point trying to create sql statements even more inefficent code to delete rows. This guy wasn't even trying and he's beat us all already.
No.
What we REALLY need is procedural SQL with unidirectional cursors and a big outer repeat loop until the select count(*) from the table is zero to take it to the next level.
Maybe lots and lots of commits just take make it extra special.
Admin
ah! I found the bug
it should've been:
DELETE FROM HashIndex
<FONT size=+0>WHERE</FONT> isnull(ItemHash, 0) >= (<FONT size=+0>SELECT MIN</FONT>(isnull(ItemHash, 0)) <FONT size=+0>FROM</FONT> HashIndex (nolock))
duh!!!
Admin
Oh, and we should set all of the fields to the default value before deleting the row, to be more secure.
And instead of hardcoding the fields in the SQL statement, we should query the system catalogs directly to find the field names. Via a nested cursor. Which should be deleted and recreated for each row.
And to avoid excessive CPU load, there should be WAITFOR(...) statements on every other line.
Admin
My personal favorite is: select 1 from dual/favorite-table where null = null
Admin
Ahhh, you are bringing me Oracle nightmares!!?!?!!?!!
Admin
There are still better ways to delete everything:
Admin
this code make my pet lead block look smart... I even feel like giving it a name.
Admin
I have succeded in naming my pet block of lead, as inspired by this code snip.
I call it:
"Unnamed Pet Block of Lead 1"
Admin
Just a note, truncate table, although effecient, requires some serious db rights. In Sql Server requires more permissions then I am willing to give any application
From books online
Permissions
TRUNCATE TABLE permissions default to the table owner, members of the sysadmin fixed server role, and the db_owner and db_ddladmin fixed database roles, and are not transferable
The reason why truncate table is so effecient is because the action or deletes are non-logged. Which also means you cannot use truncate table on a database that is being replicated. Also I have seen bugs in SQL Server version 7.0 transaction replication that when "delete from table" is run, not all of the deletes from the table are properly logged and perhaps the where clause was added to force the transaction log reader to see all of the deletes. (Not that I am trying to defend the code)
Admin
Admin
Actually, this is closer to truth than you think, at least in Oracle.
Consider the situation where
TRUNCATE TABLE
is not possible, e.g. because of constraints. If the table is referenced by foreign key constraints, truncating is not possible, even if the referencing table is already empty. (You could disable the constraints, though)DROP TABLE+CREATE TABLE
is also a bad idea for a lot of reasons.So, the easiest way to go is
DELETE FROM MyTable
without aWHERE
clause.If you try that on table with 10000000 records, your rollback segments are most likely to small to do it.
So, a working solution could look like that:
This practice is even more common for
UPDATE
statements affecting more rows than the rollback segments can handle.Admin
my fault, once again
Admin
This is logical as null basically means the absence of a value or an unknown/unspecified/undefined value. Comparing null to itself is like saying, "does some undefined value equal some other undefined value", which is indeterminate.
As far as ordering goes, lets assume for a minute that null was less than or equal to a given value. Where exactly in the set of ordered values would null go?
...-3,-2,-1,null,0,1,2,3...?
or
...-1,...,-0.1,...,-0.001,...,-0.000000001,...,null,0,...?
Admin
Null is 22. I thought everyone knew that. I don't know what's wrong with language designers but I'm always having to use #define null 22 or public static final int null = 22. You'd think someone would get a clue! In the same way Empty is 22/3 and Nothing is -22/7.
Admin
how about making it consistent with order by and making it less than every non-null value?
select 1 foo from dual union select -1 from dual union select null from dual order by foo
will put the null at the very top. That sure looks like null is "less than the minimum value". Which brings us full circle to null remains after deleting everything greater than or equal to the minimum [*-)]
Admin
Pffft... mud is easy. Back in my day, we only had one cell. That's right, one cell. Try keeping state on that.
Damn newbies.
Admin
I prefer this:
Select ItemHash from HashIndex where ItemHash >= (Select Miin(ItemHash) From HashIndex) into cursor hashesToDelete
// forgive my non ansi sql, but I think you get the picture
do until hashesToDelete.EOF
delete from HashIndex where ItemHash = hashesToDelete.ItemHash
hashesToDelete.fetchNext
loop
Admin
And I always thought null should be 42.
Admin
Encountered this at one site (sorry, syntax will be wrong)
define cursor @table_del select id from table
declare @id varchar(10)
fetch @table_del into id
while @@fetch_status=0 begin
delete from table where id=@id
fetch @table_del into id
end
I'm sure it also had stuff to make sure the cursor was unaffected etc. by the changes. It took me several minutes of reading it before I realized what it was.
Oliver Townshend