Home All Groups Group Topic Archive Search About

Identity keys in a One-to-Zero-or-Many relationship

Author
29 Jun 2006 3:19 PM
Richard Carpenter
Considering the following:

CREATE TABLE CustomerTypes
    (
    PKCustomerType INT IDENTITY (1,1) NOT NULL,
    CustomerTypeDesc VARCHAR(30)
    )
GO

INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail')
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale')
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate')

CREATE TABLE Customers
    (
    PKCustomer INT IDENTITY (1,1) NOT NULL,
    CustomerID VARCHAR(20),
    FKCustomerType INT
    )
GO

INSERT Customers (CustomerID, FKCustomerType) Values ('CUST001', 1)
INSERT Customers Values ('CUST002', 3)
INSERT Customers Values ('CUST003', 2)

How should I handle a case where I don't want to specify a customer
type for whatever reason? Perhaps it is unknown or not applicable in
some cases. I could add a 'None or N/A' record in the CustomerTypes
table for that purpose, but when validating the data in an INSERT
stored procedure, for example, I would like to have a value to use as
default in the case of a missing of invalid field value being passed
for FKCustomerType. If it weren't an identity field in the
CustomerTypes table, I could just create a CustomerType record with a
PKCustomerType value of 0 and always use that value in such cases. With
it being an identity field, however, I can't count on a specific value
for that purpose. It seems I have two options:

1) Create the CustomerTypes table without PKCustomerType being an
identity field...insert the 'None or N/A' record, assigning it a
PKCustomerType value of, say, 0...alter the table to make
PKCustomerType and identity field (1,1)

2) Merely use NULL in Customers where CustomerType isn't specified.

Is there a better way? If not, any insight on why one approach would be
better than the other? I'm leaning toward option 2 at this point.

Author
29 Jun 2006 3:35 PM
Aaron Bertrand [SQL Server MVP]
> 2) Merely use NULL in Customers where CustomerType isn't specified.

If CustomerType is not specified because it is unknown, then this may be a
valid approach.

However, you may want to give users the option of saying Unknown, and have
it be a value in the CustomerTypes table.  Then if you later want to
differentiate between unknown and unspecified, you can add an option.

There is no reason to hard-code the default value in the parameter to the
stored procedure.  Have the application generate its dropdown from the
CustomerTypes table, and you are done.

A
Author
30 Jun 2006 3:41 AM
Richard Carpenter
Aaron Bertrand [SQL Server MVP] wrote:
> > 2) Merely use NULL in Customers where CustomerType isn't specified.
>
> If CustomerType is not specified because it is unknown, then this may be a
> valid approach.
>
> However, you may want to give users the option of saying Unknown, and have
> it be a value in the CustomerTypes table.  Then if you later want to
> differentiate between unknown and unspecified, you can add an option.
>
> There is no reason to hard-code the default value in the parameter to the
> stored procedure.  Have the application generate its dropdown from the
> CustomerTypes table, and you are done.
>

That's part of my quandry. I *would* generate the drop-down list from
the CustomerTypes table, but how would I establish a default selection
when an identity key is used?
Author
30 Jun 2006 4:08 AM
Aaron Bertrand [SQL Server MVP]
> That's part of my quandry. I *would* generate the drop-down list from
> the CustomerTypes table, but how would I establish a default selection
> when an identity key is used?

Have a column that tells you whether or not this value is the default.  If
you are manually entering "none" as the name/description value, surely you
can change default=0 to default=1 in the extra column.  Now, the app can
pull the list of potential values, and select the value where default=1
(until the user overrides it).
Author
30 Jun 2006 1:54 PM
Richard Carpenter
Aaron Bertrand [SQL Server MVP] wrote:
> > That's part of my quandry. I *would* generate the drop-down list from
> > the CustomerTypes table, but how would I establish a default selection
> > when an identity key is used?
>
> Have a column that tells you whether or not this value is the default.  If
> you are manually entering "none" as the name/description value, surely you
> can change default=0 to default=1 in the extra column.  Now, the app can
> pull the list of potential values, and select the value where default=1
> (until the user overrides it).

Hmm. That would be one way to manage it. However, adding an additional
column to track a piece of information that will be the same for all
but one row doesn't seem like the optimal solution either.

You've given me an idea, though. I think what I'm going to do is
enforce RI and provide a system setup screen in the application whereby
the system administrator can specify the default selection for all such
drop-down lists.

Thanks!
Rich
Author
30 Jun 2006 4:30 PM
Richard Carpenter
Richard Carpenter wrote:
> Aaron Bertrand [SQL Server MVP] wrote:
> > > That's part of my quandry. I *would* generate the drop-down list from
> > > the CustomerTypes table, but how would I establish a default selection
> > > when an identity key is used?
> >
> > Have a column that tells you whether or not this value is the default.  If
> > you are manually entering "none" as the name/description value, surely you
> > can change default=0 to default=1 in the extra column.  Now, the app can
> > pull the list of potential values, and select the value where default=1
> > (until the user overrides it).
>

Also, how would you go about enforcing the rule that only one row in
that table may have a value of 1 for that extra field?

Thanks.
Rich
Author
30 Jun 2006 4:35 PM
Aaron Bertrand [SQL Server MVP]
> Also, how would you go about enforcing the rule that only one row in
> that table may have a value of 1 for that extra field?

Assuming that you disallow direct updates / inserts to the table, then in
the stored procedure that sets the default row, it first sets the value to 0
for all rows.

If you need it to be an active constraint, you could easily use a trigger,
but like most things, there are trade-offs.

A
Author
29 Jun 2006 5:20 PM
--CELKO--
>> Considering the following: <<

Let's fix what you posted so that it follows the most basic RDBMS
design principles.  For example, why do you have no keys?  Why did you
think that IDENTITY is every used?  Why did you use PK- prefixes in
violation of ISO-11179 rules?

CREATE TABLE CustomerTypes
(customer_type INTEGER NOT NULL PRIMARY KEY,
customer_type_desc VARCHAR(30) NOT NULL);

I see from the use of IDENTITY that you did not bother with designing
an encoding scheme.  You might want to learn how to do that

CREATE TABLE Customers
(customer_id VARCHAR(20) NOT NULL PRIMARY KEY,
(customer_type INTEGER NOT NULL
  REFERENCES CustomerTypes (customer_type)
  ON UPDATE CASCADE,
.. );

VARCHAR(20) is a bit long, but by the definition of an identifier, this
has to be your key.  Frankly, I would look for a DUNS number or some
indusrty standard code.

Stop putting prefixes that tell you **how** a data element is used in a
table.  The name of a data element is supposed to tell you **what** it
is.

>> How should I handle a case where I don't want to specify a customer type for whatever reason? Perhaps it is unknown or not applicable in some cases. <<

Then you need codes for those situations if they are logically
different. For example, the ICD codes for disease have '000.000' which
means "undiagnosed" and '999.999' which means "we did all the test and
still don't know!" -- very different kinds of missing data!  VERY
IMPORTANT to distinguish them!! Matter of life and death, in fact.

>> I could add a 'None or N/A' record [sic] in the CustomerTypes table for that purpose, but when validating the data in an INSERT stored procedure, for example, I would like to have a value to use as default in the case of a missing of invalid field [sic] value being passed for FKCustomerType [sic]. <<

Now we are getting to your REAL problem.  Let's get back to the basics
of an RDBMS. Rows are not records; fields are not columns; tables are
not files; there is no sequential access or ordering in an RDBMS, so
faking a record number or the lines on a piece of paper with a
proprietary IDENTITY property is dead wrong.  You do not have the right
mindset, and all you are going to get on a Newsgroup is a few kludges
to help you fake it for a long period of time before the collapse.

>> If it weren't an identity field [sic] in the CustomerTypes table, I could just create a CustomerType record [sic] with a PKCustomerType value of 0 and always use that value in such cases. With it being an identity field [sic], however, I can't count on a specific value for that purpose. <<

Surprise! Surprise! Surprise!  See how non-relational, non-verifiable,
non-portable proprietary extensions screw up things?

>> It seems I have two options: <<

Yes; do it right or kludge it :)

>> 1) Create the CustomerTypes table without PKCustomerType [sic] being an identity field [sic] ...insert the 'None or N/A' record, assigning it a PKCustomerType [sic] value of, say, 0...alter the table to makePKCustomerType and identity field [sic] (1,1) <<

Almost!  Stop using IDENTITY.  This is an RDBMS and not a sequential
file system.

>> 2) Merely use NULL in Customers where CustomerType isn't specified. <<

Maybe; do you need to know anything about the missing values?  Or just
that it is missing?  Get a copy of SQL PROGRAMMING STYLE, SQL FOR
SMARTIES or DATA & DATABASES and then read the chapters on scales &
measurements, and how to design encoding schemes.  The research pattern
is simple:

1) Look for industry standards (Google it!)

2) Look for company standards (see the accounting department for help)

3) In the remaining 5% of the cases where you have to invent something,
pick a type of encoding and follow the rules for good design.  My guess
in this example is a hierachy or vector code because customers break
down into tax/tax exempt, domestic/foreign and so forth within
retailers and wholesalers.
Author
29 Jun 2006 5:55 PM
Tony Rogerson
> design principles.  For example, why do you have no keys?  Why did you
> think that IDENTITY is every used?  Why did you use PK- prefixes in

Why do you think SURROGATE KEYS are never used? It would appear you are one
of the only people in the industry who do not use them.

Perhaps its an implementation experience thing compared to theory.

> Almost!  Stop using IDENTITY.  This is an RDBMS and not a sequential
> file system.

Your bias and misunderstanding of how IDENTITY works is embarrasing - READ
THE MANUAL!

> that it is missing?  Get a copy of SQL PROGRAMMING STYLE, SQL FOR
> SMARTIES or DATA & DATABASES and then read the chapters on scales &

Only if you want theory, for practical advice get a SQL Server specific
book.

--
Tony Rogerson
SQL Server MVP
http://sqlblogcasts.com/blogs/tonyrogerson - technical commentary from a SQL
Server Consultant
http://sqlserverfaq.com - free video tutorials


Show quote
"--CELKO--" <jcelko***@earthlink.net> wrote in message
news:1151601604.581696.66800@75g2000cwc.googlegroups.com...
>>> Considering the following: <<
>
> Let's fix what you posted so that it follows the most basic RDBMS
> design principles.  For example, why do you have no keys?  Why did you
> think that IDENTITY is every used?  Why did you use PK- prefixes in
> violation of ISO-11179 rules?
>
> CREATE TABLE CustomerTypes
> (customer_type INTEGER NOT NULL PRIMARY KEY,
> customer_type_desc VARCHAR(30) NOT NULL);
>
> I see from the use of IDENTITY that you did not bother with designing
> an encoding scheme.  You might want to learn how to do that
>
> CREATE TABLE Customers
> (customer_id VARCHAR(20) NOT NULL PRIMARY KEY,
> (customer_type INTEGER NOT NULL
>  REFERENCES CustomerTypes (customer_type)
>  ON UPDATE CASCADE,
> .. );
>
> VARCHAR(20) is a bit long, but by the definition of an identifier, this
> has to be your key.  Frankly, I would look for a DUNS number or some
> indusrty standard code.
>
> Stop putting prefixes that tell you **how** a data element is used in a
> table.  The name of a data element is supposed to tell you **what** it
> is.
>
>>> How should I handle a case where I don't want to specify a customer type
>>> for whatever reason? Perhaps it is unknown or not applicable in some
>>> cases. <<
>
> Then you need codes for those situations if they are logically
> different. For example, the ICD codes for disease have '000.000' which
> means "undiagnosed" and '999.999' which means "we did all the test and
> still don't know!" -- very different kinds of missing data!  VERY
> IMPORTANT to distinguish them!! Matter of life and death, in fact.
>
>>> I could add a 'None or N/A' record [sic] in the CustomerTypes table for
>>> that purpose, but when validating the data in an INSERT stored
>>> procedure, for example, I would like to have a value to use as default
>>> in the case of a missing of invalid field [sic] value being passed for
>>> FKCustomerType [sic]. <<
>
> Now we are getting to your REAL problem.  Let's get back to the basics
> of an RDBMS. Rows are not records; fields are not columns; tables are
> not files; there is no sequential access or ordering in an RDBMS, so
> faking a record number or the lines on a piece of paper with a
> proprietary IDENTITY property is dead wrong.  You do not have the right
> mindset, and all you are going to get on a Newsgroup is a few kludges
> to help you fake it for a long period of time before the collapse.
>
>>> If it weren't an identity field [sic] in the CustomerTypes table, I
>>> could just create a CustomerType record [sic] with a PKCustomerType
>>> value of 0 and always use that value in such cases. With it being an
>>> identity field [sic], however, I can't count on a specific value for
>>> that purpose. <<
>
> Surprise! Surprise! Surprise!  See how non-relational, non-verifiable,
> non-portable proprietary extensions screw up things?
>
>>> It seems I have two options: <<
>
> Yes; do it right or kludge it :)
>
>>> 1) Create the CustomerTypes table without PKCustomerType [sic] being an
>>> identity field [sic] ...insert the 'None or N/A' record, assigning it a
>>> PKCustomerType [sic] value of, say, 0...alter the table to
>>> makePKCustomerType and identity field [sic] (1,1) <<
>
> Almost!  Stop using IDENTITY.  This is an RDBMS and not a sequential
> file system.
>
>>> 2) Merely use NULL in Customers where CustomerType isn't specified. <<
>
> Maybe; do you need to know anything about the missing values?  Or just
> that it is missing?  Get a copy of SQL PROGRAMMING STYLE, SQL FOR
> SMARTIES or DATA & DATABASES and then read the chapters on scales &
> measurements, and how to design encoding schemes.  The research pattern
> is simple:
>
> 1) Look for industry standards (Google it!)
>
> 2) Look for company standards (see the accounting department for help)
>
> 3) In the remaining 5% of the cases where you have to invent something,
> pick a type of encoding and follow the rules for good design.  My guess
> in this example is a hierachy or vector code because customers break
> down into tax/tax exempt, domestic/foreign and so forth within
> retailers and wholesalers.
>
Author
30 Jun 2006 3:00 AM
Richard Carpenter
Good gravy! I'll try to respond to your individual points without
taking too much offense to your abrasive tone...

--CELKO-- wrote:
> >> Considering the following: <<
>
> Let's fix what you posted so that it follows the most basic RDBMS
> design principles.

Really, don't trouble yourself. It was a simple example I threw
together to try and illustrate my question. Nothing more. I wasn't
shooting for theoretical precision. I didn't (and still don't, as I
will explain in a moment) think it that necessary in this case.

Show quote
> For example, why do you have no keys?  Why did you
> think that IDENTITY is every used?  Why did you use PK- prefixes in
> violation of ISO-11179 rules?
>
> CREATE TABLE CustomerTypes
> (customer_type INTEGER NOT NULL PRIMARY KEY,
>  customer_type_desc VARCHAR(30) NOT NULL);
>
> I see from the use of IDENTITY that you did not bother with designing
> an encoding scheme.  You might want to learn how to do that
>
> CREATE TABLE Customers
> (customer_id VARCHAR(20) NOT NULL PRIMARY KEY,
> (customer_type INTEGER NOT NULL
>   REFERENCES CustomerTypes (customer_type)
>   ON UPDATE CASCADE,
>  .. );
>
> VARCHAR(20) is a bit long, but by the definition of an identifier, this
> has to be your key.  Frankly, I would look for a DUNS number or some
> indusrty standard code.

It is what it is. If my particular (hypothetical, I might add) business
process requires the use of specific proprietary customer types, then
why complicate it?

> Stop putting prefixes that tell you **how** a data element is used in a
> table.  The name of a data element is supposed to tell you **what** it
> is.

I really don't see the significance of the distinction. The fact that
the name of the field starts with PK *does* tell me what it is. I
really think this one is a matter of personal preference.

> >> How should I handle a case where I don't want to specify a customer type for whatever reason? Perhaps it is unknown or not applicable in some cases. <<
>
> Then you need codes for those situations if they are logically
> different. For example, the ICD codes for disease have '000.000' which
> means "undiagnosed" and '999.999' which means "we did all the test and
> still don't know!" -- very different kinds of missing data!  VERY
> IMPORTANT to distinguish them!! Matter of life and death, in fact.

A bit dramatic, but I hear what you're saying. However, my question
really doesn't have anything to do with what values are available to
the user, but how to handle it when the user doesn't feel inclined to
specify a fact that is not strictly required. On the application's data
entry screen, the user may only need to worry about some of the
available fields. There is no reason to force them to touch every one
when not all are relevant in every case. My question is, how to best
handle that foreign key [column] value in that case.

> >> I could add a 'None or N/A' record [sic] in the CustomerTypes table for that purpose, but when validating the data in an INSERT stored procedure, for example, I would like to have a value to use as default in the case of a missing of invalid field [sic] value being passed for FKCustomerType [sic]. <<
>
> Now we are getting to your REAL problem.  Let's get back to the basics
> of an RDBMS. Rows are not records; fields are not columns; tables are
> not files; there is no sequential access or ordering in an RDBMS, so
> faking a record number or the lines on a piece of paper with a
> proprietary IDENTITY property is dead wrong.  You do not have the right
> mindset, and all you are going to get on a Newsgroup is a few kludges
> to help you fake it for a long period of time before the collapse.

Yeah, I'm guilty of referring to them in the very manner that makes a
certain type of person grit their teeth. I think that since we both
know exactly what I mean, then it really isn't an issue worth allowing
to cloud the matter. Wouldn't you agree?

> >> If it weren't an identity field [sic] in the CustomerTypes table, I could just create a CustomerType record [sic] with a PKCustomerType value of 0 and always use that value in such cases. With it being an identity field [sic], however, I can't count on a specific value for that purpose. <<
>
> Surprise! Surprise! Surprise!  See how non-relational, non-verifiable,
> non-portable proprietary extensions screw up things?
>

Hence my original question. Again, I really don't understand why it has
to be this difficult. How would *you* go about it, if forcing the user
to touch every field on the data entry form is *not* acceptable?

> >> It seems I have two options: <<
>
> Yes; do it right or kludge it :)
>
> >> 1) Create the CustomerTypes table without PKCustomerType [sic] being an identity field [sic] ...insert the 'None or N/A' record, assigning it a PKCustomerType [sic] value of, say, 0...alter the table to makePKCustomerType and identity field [sic] (1,1) <<
>
> Almost!  Stop using IDENTITY.  This is an RDBMS and not a sequential
> file system.

There is nothing sequential about the requirements I've established
here. I don't care if the key is sequentially numbered, random
alpha-numeric or caveman hieroglyphics. All I require is that it be
guaranteed to be unique and generated automatically.

Show quote
> >> 2) Merely use NULL in Customers where CustomerType isn't specified. <<
>
> Maybe; do you need to know anything about the missing values?  Or just
> that it is missing?  Get a copy of SQL PROGRAMMING STYLE, SQL FOR
> SMARTIES or DATA & DATABASES and then read the chapters on scales &
> measurements, and how to design encoding schemes.  The research pattern
> is simple:
>
> 1) Look for industry standards (Google it!)
>
> 2) Look for company standards (see the accounting department for help)
>
> 3) In the remaining 5% of the cases where you have to invent something,
> pick a type of encoding and follow the rules for good design.  My guess
> in this example is a hierachy or vector code because customers break
> down into tax/tax exempt, domestic/foreign and so forth within
> retailers and wholesalers.

Honestly, that just seemed like a whole lot of unnecessary nit-picking
and tangent traversal than was really required here. I can understand
if you feel in your infinite wisdom that it is better to suggest to me
where else I might direct my search to find the answer than give it to
me directly, but to put so much effort into avoiding answering my
question while at the same time trying to educate me (or, arguably more
accurate, indoctrinate me according to your own personal opinions) in
related regards does make me wonder who's best interest you have at
heart here.
Author
30 Jun 2006 10:18 PM
--CELKO--
>> I'll try to respond to your individual points without taking too much offense to your abrasive tone... <<

Good, that is the way to handle it.

>>  Really, don't trouble yourself. It was a simple example I threw together to try and illustrate my question. Nothing more. I wasn't shooting for theoretical precision... I didn't (and still don't, as I will explain in a moment) think it that necessary in this case.  <<

What you missed was PRACTICAL precision.  Do you think it took any
longer for me to re-type and correct your code than it took you to
write it?  Nope.  A professional should be doing good work as a reflex,
not as a super-human effort.  You are not at the point where you can
write clean SQL without effort nor do youy know about data design.

>> It is what it is. If my particular (hypothetical, I might add) business process requires the use of specific proprietary customer types, then why complicate it? <<

I treated this as a real problem.  "Entia non sunt multiplicanda
praeter necessitatem." (No more things should be presumed to exist than
are absolutely necessary) -- William Occam (c. 1280-1349).

>> I really don't see the significance of the distinction. The fact that the name of the field [sic] starts with PK *does* tell me what it is. <<

NO!  That is how it is used in that table.  If it appears in another
table where it is a foreign key, are you going to re-name it?  What if
it appears twice in a table?  What is the fundamental rule of data
element names?  One and only one name per data element.

>> I really think this one is a matter of personal preference. <<

No.  It is a matter of ISO-11179 Standards and the last 20 years of
data modeling.  Do you also invent your own private language when you
write English?  Probably not.

>> A bit dramatic, but I hear what you're saying. However, my question really doesn't have anything to do with what values are available to the user, but how to handle it when the user doesn't feel inclined to specify a fact that is not strictly required. <<

LOL!  I have a mental picture of a snotty french waiter doing data
entry anouncing, "I do not feel inclined to allow that fact to exist!
Pooh!"   A fact is required for a consistent model; values may vary.

>> On the application's data entry screen, the user may only need to worry about some of the available fields. There is no reason to force them to touch every one when not all are relevant in every case. My question is, how to best handle that foreign key [column] value in that case. <<

How the front end handles entry is not a data base question.  It is
free to provide values via some business rules and mechanisms as long
as the inputs do not violate constraints.  But defaults and constraints
are a data base question.


>
> > >> I could add a 'None or N/A' record [sic] in the CustomerTypes table for that purpose, but when validating the data in an INSERT stored procedure, for example, I would like to have a value to use as default in the case of a missing of invalid field [sic] value being passed for FKCustomerType [sic]. <<

>> Yeah, I'm guilty of referring to them in the very manner that makes a certain type of person grit their teeth. I think that since we both know exactly what I mean, then it really isn't an issue worth allowing to cloud the matter. Wouldn't you agree? <<

No, I don't.  Google thru this newsgroup and see how many stupid
questions are posted because someone is still building file systems in
SQL.  This place is full of cursors, bit flags, attribute splitting,
temp tables to mimic scratch tape files, contigous and sequential
storage assumptions, etc.

If this were an automobile newsgroup and someone kept referring to the
"legs" on his car instead of "wheels" because he used to ride a horse,
would you think that he was -- be nice -- a bit out of step?  Probably
not able to figure out how to do an oil change? Etc.

>> How would *you* go about it, if forcing the user to touch every field on the data entry form is *not* acceptable? <<

Default values in the schema (NULL is the default DEFAULT, but try to
avoid it), and some business rules in the front end (this company is a
wholey-owned subsidary of company X, so it inherits some values from
its parent, etc.)

>> There is nothing sequential about the requirements I've established here. I don't care if the key is sequentially numbered, random alpha-numeric or caveman hieroglyphics.<<

If you were a professional, you would care.  You would be worried about
verification and validation, industry standards, maintaining the
system, etc. but instead ...

>> All I require is that it be guaranteed to be unique and generated automatically. <<

all you are after is a quicky, magical, no-brains kludge to get over
the hump.

>> Honestly, that just seemed like a whole lot of unnecessary nit-picking and tangent traversal than was really required here. <<

Sorry, I mistook you for someone who cares about his work.  I want you
to be a  better RDBMS programmer than you want yourself to be.

>> I can understand if you feel in your infinite wisdom that it is better to suggest to me where else I might direct my search to find the answer than give it to me directly, but to put so much effort into avoiding answering my question while at the same time trying to educate me (or, arguably more accurate, indoctrinate me according to your own personal opinions) in related regards does make me wonder who's best interest you have at heart here.  <<

First of all, I am the "Standards & Best Practices ober alles" guy.  I
actually have very few pure opinions that are not backed up by ANSI,
ISO, a major authority like Dr. Codd or a few years of research of some
kind.   You asked a "wheels on a horse" kind of question, so it looked
like you needed a real answer and not a kludge.
Author
1 Jul 2006 1:36 AM
Richard Carpenter
--CELKO-- wrote:
>
> >> How would *you* go about it, if forcing the user to touch every field on the data entry form is *not* acceptable? <<
>
> Default values in the schema (NULL is the default DEFAULT, but try to
> avoid it), and some business rules in the front end (this company is a
> wholey-owned subsidary of company X, so it inherits some values from
> its parent, etc.)
>

Ya know, in your two replies and well over 1000 words this is as close
as you've come to actually answering my question. Ya know what else?
I've decided the quality of the answer does not come close to
justifying the crap you sling at people - well, at me anyway. I've not
spent enough time around here to have a feel on whether it's personal
or not.

It is plain to see that you are extremely knowledgeable in the area of
database design standards and theory. The trouble is, such prowess in
that respect must have come at the terrible expense of any sort of
social skills, as I have never in my life seen anyone so full of
themself and so disdainful of those around them who don't worship the
same pagan god of referential integrity.

I simply asked how a certain scenario should be handled. I honestly
*wanted* you to correct me where I may have been going about it wrong.
What is wrong with giving me what you feel is the correct design
approach and telling me why? Instead, you have to pick at everything
about my post in the most obnoxioiusly critical way possible
(embellishing on more than one point in a blatant act of grandstanding,
I might add). Do you approach *every* minor situation with such
stick-up-the-rear-endedness? You seem to have some sort of delusional
superiority complex.

I do appreciate the time you've given me to this point as I understand
that you were probably actually trying to be helpful in your own
caustic sort of way, but quite frankly, you seem to bring out the worst
in me, so I'd appreciate it if you could just ignore me from this point
forward, and I'll return the favor. I'll be more than happy to waltz
into your killfile, as this has been little more than a big waste of
both of our time.

Regards,
Rich
Author
29 Jun 2006 6:01 PM
Tony Rogerson
> How should I handle a case where I don't want to specify a customer
> type for whatever reason? Perhaps it is unknown or not applicable in

It should be NULL because its not specified, if you want to give it a value
you really ought to have a CustomerType of 'Not Specified'.

Show quote
> CREATE TABLE CustomerTypes
>    (
>    PKCustomerType INT IDENTITY (1,1) NOT NULL,
>    CustomerTypeDesc VARCHAR(30)
>    )
> GO
>
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate')
>
> CREATE TABLE Customers
>    (
>    PKCustomer INT IDENTITY (1,1) NOT NULL,
>    CustomerID VARCHAR(20),
>    FKCustomerType INT
>    )
> GO
>
> INSERT Customers (CustomerID, FKCustomerType) Values ('CUST001', 1)
> INSERT Customers Values ('CUST002', 3)
> INSERT Customers Values ('CUST003', 2)

You probably need to have a slight rethink on the constraints.....


CREATE TABLE CustomerTypes
   (
   id INT IDENTITY (1,1) NOT NULL    constraint sk_customertypes unique
clustered,
   CustomerTypeDesc VARCHAR(30) constraint pk_customertype primary key
nonclustered
   )

INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail')
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale')
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate')

CREATE TABLE Customers
   (
    id INT IDENTITY (1,1) NOT NULL    constraint sk_customer unique
clustered,
    CustomerID VARCHAR(20)    not null constraint pk_customer primary key
nonclustered,
    CustomerType_id INT    NULL references CustomerTypes( id )
    )

INSERT Customers (CustomerID, CustomerType_id) Values ('CUST001', 1)
INSERT Customers (CustomerID, CustomerType_id) Values ('CUST003', NULL)

Tony.

--
Tony Rogerson
SQL Server MVP
http://sqlblogcasts.com/blogs/tonyrogerson - technical commentary from a SQL
Server Consultant
http://sqlserverfaq.com - free video tutorials


Show quote
"Richard Carpenter" <rumble***@hotmail.com> wrote in message
news:1151594340.887702.165300@b68g2000cwa.googlegroups.com...
> Considering the following:
>
> CREATE TABLE CustomerTypes
>    (
>    PKCustomerType INT IDENTITY (1,1) NOT NULL,
>    CustomerTypeDesc VARCHAR(30)
>    )
> GO
>
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate')
>
> CREATE TABLE Customers
>    (
>    PKCustomer INT IDENTITY (1,1) NOT NULL,
>    CustomerID VARCHAR(20),
>    FKCustomerType INT
>    )
> GO
>
> INSERT Customers (CustomerID, FKCustomerType) Values ('CUST001', 1)
> INSERT Customers Values ('CUST002', 3)
> INSERT Customers Values ('CUST003', 2)
>
> How should I handle a case where I don't want to specify a customer
> type for whatever reason? Perhaps it is unknown or not applicable in
> some cases. I could add a 'None or N/A' record in the CustomerTypes
> table for that purpose, but when validating the data in an INSERT
> stored procedure, for example, I would like to have a value to use as
> default in the case of a missing of invalid field value being passed
> for FKCustomerType. If it weren't an identity field in the
> CustomerTypes table, I could just create a CustomerType record with a
> PKCustomerType value of 0 and always use that value in such cases. With
> it being an identity field, however, I can't count on a specific value
> for that purpose. It seems I have two options:
>
> 1) Create the CustomerTypes table without PKCustomerType being an
> identity field...insert the 'None or N/A' record, assigning it a
> PKCustomerType value of, say, 0...alter the table to make
> PKCustomerType and identity field (1,1)
>
> 2) Merely use NULL in Customers where CustomerType isn't specified.
>
> Is there a better way? If not, any insight on why one approach would be
> better than the other? I'm leaning toward option 2 at this point.
>
Author
29 Jun 2006 7:21 PM
Anith Sen
Why not use a referential integrity constraint?

Unknown and Inapplicable are distinct reasons attributed for missing data.
And therefore, if your business demands that distinction, it makes sense to
use separate values to represent them in a table.

--
Anith
Author
29 Jun 2006 7:31 PM
Anith Sen
Just to add, inapplicable attributes are best addressed using an entity
super-type/sub-type relationship. However, commonly people use to kludge
them with NULLs as an easy workaround.

--
Anith
Author
30 Jun 2006 3:25 AM
Richard Carpenter
Anith Sen wrote:
> Why not use a referential integrity constraint?
>
> Unknown and Inapplicable are distinct reasons attributed for missing data.
> And therefore, if your business demands that distinction, it makes sense to
> use separate values to represent them in a table.
>

That would be my typical thinking as well, but RI doesn't work if the
value is not required unless a default constraint is specified. With an
identity key, the default value for the foreign key column cannot be
specified in the table definition.

On second thought, a better illustration of my question would be a name
suffix (Jr., Sr. III, etc.). A person won't necessarily *have* a suffix
in their name, yet forcing the user to select "None" from a list is
perhaps a bit cumbersome from a UI standpoint. If that suffix column in
the Customers table is a foreign key referencing the primary key column
in a reference table, and that primary key column is an identity type
key, then it would seem that the only workable foreign key value would
be NULL.
Author
30 Jun 2006 3:30 AM
Aaron Bertrand [SQL Server MVP]
> suffix (Jr., Sr. III, etc.). A person won't necessarily *have* a suffix
> in their name, yet forcing the user to select "None" from a list is
> perhaps a bit cumbersome from a UI standpoint.

Why does the user have to actively select "none"?  This can be the default,
pre-loaded choice, and used *unless* the user actively specified something
different.
Author
30 Jun 2006 3:58 AM
Richard Carpenter
Aaron Bertrand [SQL Server MVP] wrote:
> > suffix (Jr., Sr. III, etc.). A person won't necessarily *have* a suffix
> > in their name, yet forcing the user to select "None" from a list is
> > perhaps a bit cumbersome from a UI standpoint.
>
> Why does the user have to actively select "none"?  This can be the default,
> pre-loaded choice, and used *unless* the user actively specified something
> different.

Right. However, how do you establish a default value when the primary
key on which it is based is an identity column?

If I were generating my own keys - character values, for example - I
might establish the key value for 'Unspecified' as something like
'[_NONE_]' in a NameSuffixes table. In that case, I could design the
data access layer of the application to always use that key value for
unspecified suffixes. This would never change, not even from one
implementation to the next. Obviously, in the case of identity columns,
you have little control over what values are assigned beyond the first
one.

All that said, would it be a better design decision to allow for null
values in the foreign key column or should the tables be designed
differently?

Rich
Author
30 Jun 2006 4:07 AM
Aaron Bertrand [SQL Server MVP]
> Right. However, how do you establish a default value when the primary
> key on which it is based is an identity column?

Well, who says you have to use an IDENTITY column?  This doesn't sound like
something that grows infinitely, but rather a defined and finite set.

So, set the values up manually.  0 = none, 1 = jr., 2 = sr., etc.  When you
need to add a suffix to the available list, which should happen rarely,
instead of just blindly inserting the value, you take the current max(id)
and add 1.

You can also add a column called [default] which tells you which value is
the default.

A
Author
30 Jun 2006 5:41 AM
Tony Rogerson
It sounds like order is an entity in his business model so perhaps another
column called display_order.....

--
Tony Rogerson
SQL Server MVP
http://sqlblogcasts.com/blogs/tonyrogerson - technical commentary from a SQL
Server Consultant
http://sqlserverfaq.com - free video tutorials


Show quote
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@dnartreb.noraa> wrote in message
news:%236o2qq$mGHA.4212@TK2MSFTNGP04.phx.gbl...
>> Right. However, how do you establish a default value when the primary
>> key on which it is based is an identity column?
>
> Well, who says you have to use an IDENTITY column?  This doesn't sound
> like something that grows infinitely, but rather a defined and finite set.
>
> So, set the values up manually.  0 = none, 1 = jr., 2 = sr., etc.  When
> you need to add a suffix to the available list, which should happen
> rarely, instead of just blindly inserting the value, you take the current
> max(id) and add 1.
>
> You can also add a column called [default] which tells you which value is
> the default.
>
> A
>
Author
30 Jun 2006 2:03 PM
Richard Carpenter
Aaron Bertrand [SQL Server MVP] wrote:
> > Right. However, how do you establish a default value when the primary
> > key on which it is based is an identity column?
>
> Well, who says you have to use an IDENTITY column?  This doesn't sound like
> something that grows infinitely, but rather a defined and finite set.
>
> So, set the values up manually.  0 = none, 1 = jr., 2 = sr., etc.  When you
> need to add a suffix to the available list, which should happen rarely,
> instead of just blindly inserting the value, you take the current max(id)
> and add 1.

I like identity columns for obvious reasons - mostly because they
handle the key generation for me. Also, and please correct me if I'm
wrong here, I've always thought they served to minimize concurrency
issues where new records are concerned.

> You can also add a column called [default] which tells you which value is
> the default.

Hmm. That's a couple of people now who have suggested adding a column
just to denote default status for one row. Is that consistent with the
basic rules of normalization?
Author
30 Jun 2006 2:23 PM
Aaron Bertrand [SQL Server MVP]
> I like identity columns for obvious reasons - mostly because they
> handle the key generation for me. Also, and please correct me if I'm
> wrong here, I've always thought they served to minimize concurrency
> issues where new records are concerned.

Well, you seem to be waffling between caring what the value is (not a good
property of identity) and doing less work (a good property of identity).
So, it really is up to you.

> Hmm. That's a couple of people now who have suggested adding a column
> just to denote default status for one row. Is that consistent with the
> basic rules of normalization?

The other way you could look at it is, you are denoting non-default status
for all but one row.

I try to make a design that makes sense, is easy to work with, and is
scalable.  I can't say that any of my top ten priorities in any project I've
ever worked on have included what form of some textbook definition of
normalization I am complying with.

A
Author
30 Jun 2006 4:27 PM
Richard Carpenter
Aaron Bertrand [SQL Server MVP] wrote:
Show quote
> > I like identity columns for obvious reasons - mostly because they
> > handle the key generation for me. Also, and please correct me if I'm
> > wrong here, I've always thought they served to minimize concurrency
> > issues where new records are concerned.
>
> Well, you seem to be waffling between caring what the value is (not a good
> property of identity) and doing less work (a good property of identity).
> So, it really is up to you.
>
> > Hmm. That's a couple of people now who have suggested adding a column
> > just to denote default status for one row. Is that consistent with the
> > basic rules of normalization?
>
> The other way you could look at it is, you are denoting non-default status
> for all but one row.
>
> I try to make a design that makes sense, is easy to work with, and is
> scalable.  I can't say that any of my top ten priorities in any project I've
> ever worked on have included what form of some textbook definition of
> normalization I am complying with.
>

Thanks. That sounds like very practical advice.
Author
29 Jun 2006 8:09 PM
David Portas
Show quote
"Richard Carpenter" <rumble***@hotmail.com> wrote in message
news:1151594340.887702.165300@b68g2000cwa.googlegroups.com...
> Considering the following:
>
> CREATE TABLE CustomerTypes
>    (
>    PKCustomerType INT IDENTITY (1,1) NOT NULL,
>    CustomerTypeDesc VARCHAR(30)
>    )
> GO
>
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale')
> INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate')
>
> CREATE TABLE Customers
>    (
>    PKCustomer INT IDENTITY (1,1) NOT NULL,
>    CustomerID VARCHAR(20),
>    FKCustomerType INT
>    )
> GO
>
> INSERT Customers (CustomerID, FKCustomerType) Values ('CUST001', 1)
> INSERT Customers Values ('CUST002', 3)
> INSERT Customers Values ('CUST003', 2)
>
> How should I handle a case where I don't want to specify a customer
> type for whatever reason? Perhaps it is unknown or not applicable in
> some cases. I could add a 'None or N/A' record in the CustomerTypes
> table for that purpose, but when validating the data in an INSERT
> stored procedure, for example, I would like to have a value to use as
> default in the case of a missing of invalid field value being passed
> for FKCustomerType. If it weren't an identity field in the
> CustomerTypes table, I could just create a CustomerType record with a
> PKCustomerType value of 0 and always use that value in such cases. With
> it being an identity field, however, I can't count on a specific value
> for that purpose. It seems I have two options:
>
> 1) Create the CustomerTypes table without PKCustomerType being an
> identity field...insert the 'None or N/A' record, assigning it a
> PKCustomerType value of, say, 0...alter the table to make
> PKCustomerType and identity field (1,1)
>
> 2) Merely use NULL in Customers where CustomerType isn't specified.
>
> Is there a better way? If not, any insight on why one approach would be
> better than the other? I'm leaning toward option 2 at this point.
>

If you add some keys to the CustomerTypes table you will be able to identify
the "Unknown" value by its logical key instead of the surrogate.

The "Inapplicable" case would probably be better handled by decomposing the
Customers table.

CREATE TABLE CustomerTypes
    (
    PKCustomerType INT IDENTITY (1,1) NOT NULL
     CONSTRAINT PK_CustomerTypes PRIMARY KEY,
    CustomerTypeDesc VARCHAR(30) NOT NULL
     CONSTRAINT AK1_CustomerTypes UNIQUE
    );
GO
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Retail');
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Wholesale');
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Corporate');
INSERT CustomerTypes (CustomerTypeDesc) VALUES ('Unknown');

--
David Portas, SQL Server MVP

Whenever possible please post enough code to reproduce your problem.
Including CREATE TABLE and INSERT statements usually helps.
State what version of SQL Server you are using and specify the content
of any error messages.

SQL Server Books Online:
http://msdn2.microsoft.com/library/ms130214(en-US,SQL.90).aspx
--

AddThis Social Bookmark Button