Comment On Classic WTF - And I think I'll call it .... "Referential Integrity" !

One thing I absolutely hate about working with databases is when you have to use more than one table. Don't get me wrong, I'm usually able to shove all of my data in one table, but some times you just have no choice. Thanks to Jason Strate, I'm going to be prepared next time I use multiple tables. His colleague was able to figure out a way to ensure that no one goes adding rows willy-nilly. It's sheer brilliance! [expand full text]
« PrevPage 1 | Page 2Next »

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:46 • by Richard Cutts
Bring back capital punishment.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:47 • by Paul Bowman
Buy a dog a bark yourself!

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:53 • by xrT
Jake Vinson:

One thing I absolutely hate about working with databases is when you have to use more than one table. Don't get me wrong, I'm usually able to shove all of my data in one table, but some times you just have no choice. Thanks to Jason Strate, I'm going to be prepared next time I use multiple tables. His colleague was able to figure out a way to ensure that no one goes adding rows willy-nilly. It's sheer brilliance!






NOT THOSE CURSORS AGAIN...

how could anyone who know triggers and table joins do this?

oh man...



Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:55 • by JBL
All your person root action customer campaign are belong to us. (I wish I could think of something more witty or sensible, but the data do not, as yet, appear to support any such conclusions.)

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:57 • by HardCode
Nothing like a "person customer" entity, as opposed to ... I guess ... a robot customer, or an animal customer?

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 11:59 • by tster
79912 in reply to 79910
Alex,
you mis-spelled brillance.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:07 • by Bustaz Kool

What a distinctly unique approach.  I, for one, am delighted to see a database engineer who is unconstrained by convention.  His primary concern here is the application of key business rules.  Instead of simply reading the answer out of a text book or a set of references, he was able to commit to solid principles which allowed the solution to coalesce.


You must grant me, had this problem done been solved in a normal fashion, it would have been a real clustered f*#%...

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:14 • by nneonneo
Great job, guys. Sheer brilliance.

Another example of why I won't be doing business programming any time soon!

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:17 • by bob

I worked with a guy who SWORE by doing all the refInt via triggers because (near quote) "The referential integrity error message are terrible! With triggers, I can put in really nice errors that explain the problem."


Apparently- the concept of making your code handle exceptions, and making it so that ref. integrity can't be violated to begin with was lost on him.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:18 • by MisterPleasant

We don't need no stinkin' foreign key constraints!


In the old pre-SQL Server 6.x days when constraints were not available, real men knew how to code triggers to enforce referential integrity.  However, this ain't how it was done.  Double shame on this yahoo for using a cursor in a trigger.  What RDBMS does he think he is working with... Oracle?  Modern RDBMS's support set based processing.  Like for the last 15+ years.


Jeez.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:18 • by GeneralPF
I'm pretty sure this is because old versions of SQL Server didn't have built-in referential integrity.  Tools like ERwin would generate code exactly like this when creating the database from the physical model.

It's not really a WTF, it's just old code brought forward into an RDBMS that now has this functionality built in.

UPDATED: Duh, the ERwin code would do a SELECT, not use a CURSOR.  WTF indeed!

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:19 • by Mark H
79920 in reply to 79906
xrT:

NOT THOSE CURSORS AGAIN...

how could anyone who know triggers and table joins do this?

oh man...



maybe its written for some ancient version of oracle which doesn't have RI built-in?

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:21 • by Ron
It's amazing how someone can both know what they are doing and have no idea at the same time.



Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:22 • by twks
Forget what all the SQL Server experts say.  Always use cursors - even when a simple select and conditional statement would do the trick.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 12:48 • by JBL
79924 in reply to 79920
Anonymous:
xrT:

NOT THOSE CURSORS AGAIN...

how could anyone who know triggers and table joins do this?

oh man...



maybe its written for some ancient version of oracle which doesn't have RI built-in?
Yes, the one at Delphi. (Not Borland Delphi... the ORIGINAL Oracle at Delphi.)

"Cursors, foiled again."

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:04 • by Drarok
79926 in reply to 79906
I don't get it - almost all of the stored procedures I have at work are like this - most are worse!

Where's the WTF? The fact that I can't see one after having so many shoved down my throat over the last year?

http://www.drarok.com/Stored.txt

Really, what's the point in that SP!?!?

captcha - hacker :D

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:05 • by db-newbie

Just a newbie question, but couldn't the same thing be accomplished (without iterating) with a select/join/exists type test?

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:06 • by Phil the ruler of heck

Jake Vinson:
Don't get me wrong, I'm usually able to shove all of my data in one table, but some times you just have no choice.


As I'm doing SQL only on rare occasions, I'm not quite sure I can follow what's going on in this trigger.  Why did they heap the Self-Referential Identity on top of the Referential Integrity?  I mean what is that


where [action].action_number = [action].root_action_number


supposed to do?  Is the real WTF here that the [action] table is not normalized, I mean, that they put almost all of their data in the [action] table but just could not seem to fit the [customer_product] stuff in there too?  Could they have turned that Self-Referential Identity into a Referential Integrity constraint between the [root_action] and [sub_action] tables?  (I'm just guessing here, I might be completely misunderstanding something...)

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:07 • by Enric Naval

Well, at least he DOES checks for foreign constraints.


I'm too used to using no constraints nor foreign keys, and then coding the website that relies on that database so that it handles correctly the inconsistencies instead of pucking every time it finds something not normalized.


Like an article whose author no longer exists on the database. The "author" field has an author_id instead of a NULL, and there is no row with that id on the author table. So what? There *was* an author at some point in time. It just that his data is no longer reachable. Of course this is bad, but for small sites it works fine :) Just make sure that you won't issue new authors with old ids.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:12 • by Vincent
79930 in reply to 79928
Doesn't the where [action].action_number = [action].root_action_number
mean that you test the "foreign key" only in that case? How do you do a
foreign key that is only checked if two fields are equal? (of course if
you need to do that it probably means that the design of the database
is wrong, but...)

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:16 • by Phil the ruler of heck
79931 in reply to 79927

db-newbie:
Just a newbie question, but couldn't the same thing be accomplished (without iterating) with a select/join/exists type test?


I'm not exactly an expert in these matters either, but...  almost certainly, the obvious WTF would seem to be that opening a cursor, actually requesting the data, and then iterating over the returned records is pointless if you just want to know whether or not there is at least one record matching the WHERE clause.  The Sybase way to do it would probably have been


IF EXISTS (SELECT 1 FROM ... WHERE ...)


if I recall that correctly, other DBMS's might use a slightly different syntax...

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:39 • by Rick DeBay
79937 in reply to 79929
Enric Naval:

Well, at least he DOES checks for foreign constraints.


I'm too used to using no constraints nor foreign keys, and then coding the website that relies on that database so that it handles correctly the inconsistencies instead of pucking every time it finds something not normalized.


Like an article whose author no longer exists on the database. The "author" field has an author_id instead of a NULL, and there is no row with that id on the author table. So what? There *was* an author at some point in time. It just that his data is no longer reachable. Of course this is bad, but for small sites it works fine :) Just make sure that you won't issue new authors with old ids.



A foreign key from the article to the author would have PREVENTED some schmuck from deleting the author from the database while his articles were still in the system.  Or you could let it delete the articles as well if you want to purge the system of the author and all his articles, or the database could even set the "author" field in the article to NULL.  It's all up the how the foreign key is defined.  What's worse is having a random pointer in the article.

Rick DeBay

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:44 • by Bob Smith
Jeff S:
lots of WTF's:

1) use of cursor instead of NOT EXISTS() as mentioned
2) the trigger is for updated and inserted -- updated is ignored, only inserted rows are checked
3) the trigger checks to see if at least 1 row in inserted is valid. if that 1 row is valid, the trigger succeeds for all rows. It needs to check all rows, as INSERTED can be a set not just 1 row.
4) foreign key constraints can be comprised of more than 1 column. logically, if this constraint cannot be expressed as a simple FK constraint then the table structure is probably not normalized.

It is kind of hard to figure out the true business rule this person is trying acheive here, but I'm sure there's lots of WTF's all over the place in this system based on this trigger.

(lon -- he was being sarcastic saying everything should always be stored in 1 table)


this was posted, as comment when this was originally posted (see if a "classic" not posted by alex)

CAPTCHA : enterprisey

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 13:50 • by Philbert Desanex
Alternately, this WTF could have been entitled "Who gives a FK?"

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:04 • by snoofle
79944 in reply to 79940

Anonymous:
Alternately, this WTF could have been entitled "Who gives a FK?"


*bows in awe of your comment*

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:06 • by David
79945 in reply to 79902
Umm Yeah they never got rid of capital punishment.  I think you mean corporal punishment (after all it is rather harsh to kill somebody for bad code).

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:16 • by Wants to know
79947 in reply to 79945

Anonymous:
Umm Yeah they never got rid of capital punishment.  I think you mean corporal punishment (after all it is rather harsh to kill somebody for bad code).


Why?

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:16 • by PikeStrider
79948 in reply to 79910

Anonymous:
Nothing like a "person customer" entity, as opposed to ... I guess ... a robot customer, or an animal customer?


 


I am guessing that this is to distinguish between individuals and retailers. If you have a company that sells through direct and also via retailers you would need this distinction.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:35 • by squirrel
79951 in reply to 79931
Phil the ruler of heck:

db-newbie:
Just a newbie question, but couldn't the same thing be accomplished (without iterating) with a select/join/exists type test?


I'm not exactly an expert in these matters either, but...  almost certainly, the obvious WTF would seem to be that opening a cursor, actually requesting the data, and then iterating over the returned records is pointless if you just want to know whether or not there is at least one record matching the WHERE clause.  The Sybase way to do it would probably have been


IF EXISTS (SELECT 1 FROM ... WHERE ...)


if I recall that correctly, other DBMS's might use a slightly different syntax...




This is the key. It's not enough to implement a foreign key constiant by hand. You have to join two tables, and iterate over the results, to see if there's a hit.

Because, well, the inserted record should have a foreign key value, and just a "select * from foreign_table where id = @key" would be too direct and obvious. Best to (a) join the two tables, thereby causing the database to do extra work, and (b) open a cursor for good measure.

Truly awful on a few levels, but the "why was this done at all?" is outshone by "and done so badly".

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:45 • by some moron
79956 in reply to 79945
Septic?:
Umm Yeah they never got rid of capital punishment.  I think you mean corporal punishment (after all it is rather harsh to kill somebody for bad code).


maybe our friend doesn't come from your country?

we don't all execute "bad people".

i wish i knew more sql so i could figure out what's going on today... i'm guessing that a cursor iterates along a row? why is it frowned upon?

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:45 • by ammoQ
A referential integrity constraint generally requires a primary key constraint on the referenced table (maybe some database systems handle that differently...). Which, in fact, implies "not null" and "unique". This trigger might be necessary because those requirements are not met. Which would in turn be another WTF, but that's another story.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:46 • by Rob Banzai
79958 in reply to 79951
We can just send this user to the "fuffycat" website for all their SQL/cursor needs:

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 14:47 • by rbanzai
79959 in reply to 79958
Ate my link..... :P

http://www.fluffycat.com/SQL/Cursor-Oracle/

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:03 • by RevEng
79963 in reply to 79926
http://www.drarok.com/Stored.txt

Seriously, that made me scream out loud. That's scarier than most horror films I've seen.


"Who gives a FK?"

Best comment yet. I want you to start writing the headlines. :)


Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:16 • by ammoQ
79966 in reply to 79959
rbanzai:
Ate my link..... :P

http://www.fluffycat.com/SQL/Cursor-Oracle/


Well, PL/SQL allows for a more direct approach:

FOR v_ampie IN (SELECT film_title FROM film_table WHERE film_title LIKE 'American Pie%') LOOP
 v_american_pie_count := v_american_pie_count + 1; /* just an example, normally we would somehow process v_ampie */
END LOOP;


No need to explicitely declare, fetch and close the cursor.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:19 • by seymore15074
79968 in reply to 79963
Anonymous:

"Who gives a FK?"

Best comment yet. I want you to start writing the headlines. :)



I concur.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:29 • by byte_lancer
79970 in reply to 79963
Anonymous:
http://www.drarok.com/Stored.txt

Seriously, that made me scream out loud. That's scarier than most horror films I've seen.


"Who gives a FK?"

Best comment yet. I want you to start writing the headlines. :)



Heh. That's normal for me. My co's enterprisey WTF has those kind of Stored Procs as the base minimum. You should see the core of the system : 4 to 10 times more complex and worse, undocumented.
One can find random comments like - "why in the devil's name do we have to change this ?"
Code repository comments include - "Kent added..."

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:40 • by Kodi
Did I see Paula just go by

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 15:46 • by my name is missing
79974 in reply to 79970
At my previous job we had a case-tool managed AS400 "database" with a DB2 relational database engine on top of it which all web apps were forced to use. Since the AS400 RPG code reads/writes the "tables" without going through the DB2 engine, any referential integrity you might want in a database was ignored. Thus we had to code around such wonderous things as multiple rows returned on primary key queries, non-unique unique columns, seven kinds of dates (and none of them date type columns), etc. So this is quite normal-but-still-stupid looking to me...

Amazing what crap people come up with...


Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 16:01 • by emurphy
79975 in reply to 79956
Anonymous:
Septic?:
Umm Yeah they never got rid of capital punishment.  I think you mean corporal punishment (after all it is rather harsh to kill somebody for bad code).


maybe our friend doesn't come from your country?

we don't all execute "bad people".

i wish i knew more sql so i could figure out what's going on today... i'm guessing that a cursor iterates along a row? why is it frowned upon?


Not only is the cursor iteration unneeded, but the entire trigger logic is unneeded.  What you're supposed to do is make the referential integrity constraint part of the table definition, something like:

constraint some_constraint foreign key (x_key) references table_x(x_key) on delete cascade

("on delete" says what to do if someone tries to delete the row in table_x being referenced; similarly "on update")

In this case, the campaign must match a "root action" i.e. a row in the 'action' table for which action_number = root_action_number, so you create a view that embodies that condition:

create view root_action as select * from action where action_number = root_action_number

and then reference the root_action view in the customer_products constraint.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 16:26 • by Bob Smith
79979 in reply to 79975
emurphy:
Anonymous:
Septic?:
Umm Yeah they never got rid of capital punishment.  I think you mean corporal punishment (after all it is rather harsh to kill somebody for bad code).


maybe our friend doesn't come from your country?

we don't all execute "bad people".

i wish i knew more sql so i could figure out what's going on today... i'm guessing that a cursor iterates along a row? why is it frowned upon?


Not only is the cursor iteration unneeded, but the entire trigger logic is unneeded.  What you're supposed to do is make the referential integrity constraint part of the table definition, something like:

constraint some_constraint foreign key (x_key) references table_x(x_key) on delete cascade

("on delete" says what to do if someone tries to delete the row in table_x being referenced; similarly "on update")

In this case, the campaign must match a "root action" i.e. a row in the 'action' table for which action_number = root_action_number, so you create a view that embodies that condition:

create view root_action as select * from action where action_number = root_action_number

and then reference the root_action view in the customer_products constraint.



yeah but you wouldnt need to reference the friggen view in the first place if you just enforced a foreign key constraint

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 16:32 • by Mikademus
79981 in reply to 79968
seymore15074:

I concur.


I hope you're serialized.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 16:51 • by FredSaw

"person customer" -- reminds me of that line in CSN's "Southern Cross": 


Searching for that woman girl
Who knows love can endure


As opposed to a man girl, I guess.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 17:06 • by Dash Riprock
79984 in reply to 79982
Wait until he has to localize the error messages.

Captcha: wtf.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 18:25 • by Ryan
79996 in reply to 79929

Enric Naval wrote the following post at 06-30-2006 1:07 PM:


...The "author" field has an author_id instead of a NULL, and there is no row with that id on the author table. So what? There *was* an author at some point in time. It just that his data is no longer reachable. Of course this is bad, but for small sites it works fine :)


Except when the invoice_header is missing for a bunch of invoice_lines, wihch would be really bad for even a "small site". Referential integrity is there to prevent logically corrupt data from entering the database. Even small sites require this. Not using RI for a DB is just as bad as putting "On Error Resume Next" on top of every ASP page you write.


Enric, you're essentially advocating two extremely dangerous programming practices. Not validating input and improperly handling or ignoring errors are the #1 and #2 causes of security vulnerabilties, and probably also the #1 and #2 causes of non-security bugs in my experience. The "size" of the site doesn't really matter much when it's 0wned or horribly broken because of bad data. Think of the issues that could arise from not using DR between a "users" table and a "user_permissions" table, even in a simple application.



Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 19:21 • by emurphy
80002 in reply to 79979
Anonymous:

yeah but you wouldnt need to reference the friggen view in the first place if you just enforced a foreign key constraint


I think you're wrong about this (unless FK constraints allow more options than I realize).  By implication (and if this isn't a WTF in itself), the 'action' table is conceptually a set of trees, with the 'root_action_number' column defining parent/child relationships, e.g.

action_number / description / root_action_number
1 / Foo / 1
2 / Bar / 1
3 / Baz / 2
4 / Qux / 2
5 / Abc / 5
6 / Def / 5
7 / Ghi / 5
8 / Jkl / 6
9 / Mno / 6
10 / Prs / 7
11 / Tuv / 7
12 / Wxy / 7

Note that the business logic in the original WTF does not let you reference any row in this table, only one that is a root of a tree, i.e. its root_action_number points to its own action_number (so in my example, only 1 and 5 are valid targets).  Hence a view that presents only those rows.

Re: Classic WTF - And I think I'll call it .... "Referential Integrity" !

2006-06-30 22:30 • by MB
80007 in reply to 80002

emurphy:

<...snip...>
Note that the business logic in the original WTF does not let you reference any row in this table, only one that is a root of a tree, i.e. its root_action_number points to its own action_number (so in my example, only 1 and 5 are valid targets).  Hence a view that presents only those rows.


Which is why the trigger is needed. AFAIK, you can't have foreign keys on views. So, basically, the choice here is change the data model (which may be possible, but there's not enough info to know if that's the best way here...a heirarchial table is unusual, but necessary/desirable in some cases) or enforce referential integrity through a trigger.


Now, the opening of a cursor to check for a row is inexcusable, but otherwise, I don't see a problem. Just change it to a NOT EXISTS (SELECT 1...) statement and you're good to go.

Re: Classic WTF - And I think I'll call it .... &quot;Referential Integrity&quot; !

2006-06-30 22:32 • by MB
80008 in reply to 79957

ammoQ:
A referential integrity constraint generally requires a primary key constraint on the referenced table (maybe some database systems handle that differently...). Which, in fact, implies "not null" and "unique". This trigger might be necessary because those requirements are not met. Which would in turn be another WTF, but that's another story.


Well, it implies "only 1 null" and "unique" if the PK is on a nullable column.

Re: Classic WTF - And I think I'll call it .... &quot;Referential Integrity&quot; !

2006-06-30 22:41 • by MB
80009 in reply to 79938

Anonymous:
Jeff S:
lots of WTF's:

1) use of cursor instead of NOT EXISTS() as mentioned
2) the trigger is for updated and inserted -- updated is ignored, only inserted rows are checked


3) the trigger checks to see if at least 1 row in inserted is valid. if that 1 row is valid, the trigger succeeds for all rows. It needs to check all rows, as INSERTED can be a set not just 1 row.
4) foreign key constraints can be comprised of more than 1 column. logically, if this constraint cannot be expressed as a simple FK constraint then the table structure is probably not normalized.

It is kind of hard to figure out the true business rule this person is trying acheive here, but I'm sure there's lots of WTF's all over the place in this system based on this trigger.

(lon -- he was being sarcastic saying everything should always be stored in 1 table)



this was posted, as comment when this was originally posted (see if a "classic" not posted by alex)

CAPTCHA : enterprisey


The updated table is the same as inserted. You just have a deleted table as well. Of course, he could have saved some work by checking for IF UPDATE(customer_number) OR UPDATE(campaign_number), but still that's not too terribly bad.


The set based and cursor comments are both justified though...AAMOF, I didn't catch the fact that he wasn't looping the cursor.

Re: Classic WTF - And I think I'll call it .... &quot;Referential Integrity&quot; !

2006-07-01 03:01 • by Dazed
80011 in reply to 80009
Anonymous:

The set based and cursor comments are both justified though...AAMOF, I didn't catch the fact that he wasn't looping the cursor.



Cursors have featured more than once on this site.
Having never used them, or felt the need to, could someone give an example of where they are actually appropriate?
« PrevPage 1 | Page 2Next »

Add Comment