Starting to play around with SQL server at work and this is my question:
In the query design mode in access I can make one of the fields an expression that is driven by a built-in switch function.
i.e. Switch([CategoryName] Like "Beverage","Drink",[CategoryName] Like "Cheese","Dairy")
This results in the additional column field I created to display "Drink" for each record that has the CategoryName = "Beverage", and "Dairy" for "Cheese".
Can I do something like this in SQL server in the view designer itself, or do I need to make a user defined function and call it?
Thanks in advance for any help.Use the CASE statement in SQL Server.|||Can I do this in the view design mode or do I need to make a user defined function?
Any sample code would be really appreciated.|||CASE WHEN [CategoryName] = 'Beverage' THEN 'Drink'
WHEN [CategoryName] = 'Cheese' THEN 'Dairy'
ELSE 'Unknown'
END AS DerivedColumnName
Showing posts with label design. Show all posts
Showing posts with label design. Show all posts
Monday, March 19, 2012
Cascading path problem
Hello,
The following SQL code produces the famous multiple cascading paths problem.
How should I design the tables to have the below functionality, but keep the
cascading paths? A Doc doesn't necessarily have to be related to a Folder,
but must be related to a Cust.
Changing ON UPDATE to NO ACTION would solve it partly, but it just doesn't
feel right.
Thanks for any help!
cheers,
Jonah
CREATE TABLE Cust (
usr_name varchar(20) NOT NULL,
usr_pwd varchar(40) NOT NULL,
customer_name nvarchar(50) NOT NULL,
created_date datetime default getdate() NOT NULL,
change_date datetime default getdate() NOT NULL,
deactivate_date datetime default getdate() NULL
) ON [PRIMARY]
GO
ALTER TABLE Cust ADD CONSTRAINT
PK_Cust PRIMARY KEY CLUSTERED
(
usr_name
) ON [PRIMARY]
GO
CREATE TABLE Folders (
folder_id int NOT NULL ,
folder_name nvarchar(20) NOT NULL ,
folder_description nvarchar(150) NULL ,
usr_name varchar(20) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE Folders ADD CONSTRAINT
PK_Folders PRIMARY KEY CLUSTERED
(
folder_id
) ON [PRIMARY]
GO
ALTER TABLE Folders ADD CONSTRAINT
FK_Folders_Cust FOREIGN KEY
(
usr_name
) REFERENCES Cust
(
usr_name
) ON UPDATE CASCADE
GO
CREATE TABLE Docs (
doc_id int NOT NULL,
header nvarchar(255) not null,
created_date datetime default getdate() NOT NULL,
updated_date datetime default getdate() NOT NULL,
usr_name varchar(20) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE Docs ADD CONSTRAINT
PK_Docs PRIMARY KEY CLUSTERED
(
doc_id
) ON [PRIMARY]
GO
ALTER TABLE Docs ADD CONSTRAINT
FK_Cust_Docs FOREIGN KEY
(
usr_name
) REFERENCES Cust
(
usr_name
) ON UPDATE CASCADE
ON DELETE NO ACTION
GO
CREATE TABLE DocsInFolders
(
doc_id int NOT NULL,
folder_id int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
PK_DocsInFolders PRIMARY KEY CLUSTERED
(
doc_id,
folder_id
) ON [PRIMARY]
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
FK_DocsInFolders_Folders FOREIGN KEY
(
folder_id
) REFERENCES Folders
(
folder_id
) ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
FK_DocsInFolders_Docs FOREIGN KEY
(
doc_id
) REFERENCES Docs
(
doc_id
) ON UPDATE CASCADE
ON DELETE CASCADE
GOYou say 'A Doc *doesn't necessarily have to be* related to a Folder,
but *must be* related to a Cust.'
Keep cascading on FK_DocsInFolders_Docs, but manage the Cust<--Docs
relationship in procedures. You make it sound as if the importance of the
Cust<--Docs relationship supercedes the importance of the Folders<--Docs
relationship.
Vital relationships should not be cascading.
ML|||Correct. The Cust<--Docs relationship is more importance, but that's why I
have only ON UPDATE CASCADE (to make possible usr_name changes up to date)
and not ON DELETE because I don't want Custs having Docs deleted by mistake.
An SP takes care of that.
So what you are saying is that I should change the ON CHANGE to NO ACTION as
well?
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:601F4976-E669-4865-9D92-FBAF9A16CA8F@.microsoft.com...
> You say 'A Doc *doesn't necessarily have to be* related to a Folder,
> but *must be* related to a Cust.'
> Keep cascading on FK_DocsInFolders_Docs, but manage the Cust<--Docs
> relationship in procedures. You make it sound as if the importance of the
> Cust<--Docs relationship supercedes the importance of the Folders<--Docs
> relationship.
> Vital relationships should not be cascading.
>
> ML|||If usr_name can be changed then using it as a primary key (and/or referencin
g
it from a foreign key table) is really bad practice. Either disallow usr_nam
e
changes or use a better kandidate key.
I wouldn't allow cascades for this one.
ML|||OK. So if I disallow cascades for usr_name, you would consider the design to
be correct?
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:90F300A3-7104-4924-A594-E28AC05D645D@.microsoft.com...
> If usr_name can be changed then using it as a primary key (and/or
> referencing
> it from a foreign key table) is really bad practice. Either disallow
> usr_name
> changes or use a better kandidate key.
> I wouldn't allow cascades for this one.
>
> ML|||As far as I can see, the design is fine. I would, however, do something abou
t
the Folders and Docs entities. Right now you allow a single document to exis
t
in more than one folder, which can lead to problems. The same goes for
folders - you should focus on preventing circular references.
Oh, and if any given document cannot exist in more than one folder, then the
DocsInFolders table is obsolete. You could simply add a nullable folder_id
foreign key to the Docs table (nullable since you've mentioned that a
document need not exist in any folder).
I hope you started on paper. :) And in case you haven't, maybe you'll do it
next time.
ML|||My design question applied to the cascading paths, not the business rules
themselves. One Doc may actually exist in several Folders.
- One Cust may have zero or more Folders
- One Cust may have zero or more Docs not connected to a Folder
- One Folder may have zero or more Docs related
Thus, my question was only related to if there's a better way of designing
the relations and tables to avoid circular references, which now occurs.
FYI, I didn't start on paper. I use Visio.
Thank you,
Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:F981A87A-893F-4940-9EBD-566C385CF1CB@.microsoft.com...
> As far as I can see, the design is fine. I would, however, do something
> about
> the Folders and Docs entities. Right now you allow a single document to
> exist
> in more than one folder, which can lead to problems. The same goes for
> folders - you should focus on preventing circular references.
> Oh, and if any given document cannot exist in more than one folder, then
> the
> DocsInFolders table is obsolete. You could simply add a nullable folder_id
> foreign key to the Docs table (nullable since you've mentioned that a
> document need not exist in any folder).
> I hope you started on paper. :) And in case you haven't, maybe you'll do
> it
> next time.
>
> ML|||No pun intended.
You are right - there is a better way to avoid circular references. You
might find more answers studying trees and hierarchies. Consider this model:
ItemInstance : ItemID : BelongsToInstance : ItemType
ItemInstance is unique.
ItemID can be either cust_id, folder_id or doc_id.
BelongsToInstance is a foreign key referencing ItemInstance.
ItemType designates whether ItemID is customer, folder or document.
Valid relationships are:
1) Customer/Folder/Document
2) Customer/Document
3) Folder/Folder (<-- not sure about this one, but seems logical, however:
parent folder_id must should be equal to child folder_id).
A customer can only exist as a root element (BelongsToInstance is null).
A Document can only exist as a leaf element (its ItemInstance is never
referenced in a BelongsToInstance).
The above constraints could be reinforced through the use of indexed views.
ItemInstance and BelongsToInstance prevent circular references while still
allowing all possible relationships between the three entities.
ML|||Thank you for your detailed answer.
I do have a copy of a trees and hierarchies book which I could take a closer
look into (Joe Celko's Trees and Hierarchies in SQL for Smarties). Maybe I
can find some more answers and examples there.
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:D5B9F5D8-4790-4088-BF18-14DE5119891D@.microsoft.com...
> No pun intended.
> You are right - there is a better way to avoid circular references. You
> might find more answers studying trees and hierarchies. Consider this
> model:
> ItemInstance : ItemID : BelongsToInstance : ItemType
> ItemInstance is unique.
> ItemID can be either cust_id, folder_id or doc_id.
> BelongsToInstance is a foreign key referencing ItemInstance.
> ItemType designates whether ItemID is customer, folder or document.
> Valid relationships are:
> 1) Customer/Folder/Document
> 2) Customer/Document
> 3) Folder/Folder (<-- not sure about this one, but seems logical, however:
> parent folder_id must should be equal to child folder_id).
> A customer can only exist as a root element (BelongsToInstance is null).
> A Document can only exist as a leaf element (its ItemInstance is never
> referenced in a BelongsToInstance).
> The above constraints could be reinforced through the use of indexed
> views.
> ItemInstance and BelongsToInstance prevent circular references while still
> allowing all possible relationships between the three entities.
>
> ML|||What about using a nested sets model for the hierarchy? I am not a big
fanof misxed node trees, but this case is pretty easy:
1) If it is the root node, it is a Customer
2) If it is a leaf node, it is a document
3) other it is a folder
CREATE TABLE DocumentHierarchy
(customer_id INTEGER NOT NULL
REFERENCES Customers
ON UPDATE CASCADE
ON DELETE CASCADE,
folder_id INTEGER -- null means no folder
REFERENCES Folders (folder_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
document_id INTEGER -- null means no document
REFERENCES Documents(doc_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
lft INTEGER NOT NULL CHECK (lft >0),
rgt INTEGER NOT NULL CHECK (rgt >lft),
PRIMARY KEY (customer_id, lft, rgt));
untested. You can also get a copy of TREES & HIERARCHIES IN SQL for
more ideas.
The following SQL code produces the famous multiple cascading paths problem.
How should I design the tables to have the below functionality, but keep the
cascading paths? A Doc doesn't necessarily have to be related to a Folder,
but must be related to a Cust.
Changing ON UPDATE to NO ACTION would solve it partly, but it just doesn't
feel right.
Thanks for any help!
cheers,
Jonah
CREATE TABLE Cust (
usr_name varchar(20) NOT NULL,
usr_pwd varchar(40) NOT NULL,
customer_name nvarchar(50) NOT NULL,
created_date datetime default getdate() NOT NULL,
change_date datetime default getdate() NOT NULL,
deactivate_date datetime default getdate() NULL
) ON [PRIMARY]
GO
ALTER TABLE Cust ADD CONSTRAINT
PK_Cust PRIMARY KEY CLUSTERED
(
usr_name
) ON [PRIMARY]
GO
CREATE TABLE Folders (
folder_id int NOT NULL ,
folder_name nvarchar(20) NOT NULL ,
folder_description nvarchar(150) NULL ,
usr_name varchar(20) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE Folders ADD CONSTRAINT
PK_Folders PRIMARY KEY CLUSTERED
(
folder_id
) ON [PRIMARY]
GO
ALTER TABLE Folders ADD CONSTRAINT
FK_Folders_Cust FOREIGN KEY
(
usr_name
) REFERENCES Cust
(
usr_name
) ON UPDATE CASCADE
GO
CREATE TABLE Docs (
doc_id int NOT NULL,
header nvarchar(255) not null,
created_date datetime default getdate() NOT NULL,
updated_date datetime default getdate() NOT NULL,
usr_name varchar(20) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE Docs ADD CONSTRAINT
PK_Docs PRIMARY KEY CLUSTERED
(
doc_id
) ON [PRIMARY]
GO
ALTER TABLE Docs ADD CONSTRAINT
FK_Cust_Docs FOREIGN KEY
(
usr_name
) REFERENCES Cust
(
usr_name
) ON UPDATE CASCADE
ON DELETE NO ACTION
GO
CREATE TABLE DocsInFolders
(
doc_id int NOT NULL,
folder_id int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
PK_DocsInFolders PRIMARY KEY CLUSTERED
(
doc_id,
folder_id
) ON [PRIMARY]
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
FK_DocsInFolders_Folders FOREIGN KEY
(
folder_id
) REFERENCES Folders
(
folder_id
) ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE DocsInFolders ADD CONSTRAINT
FK_DocsInFolders_Docs FOREIGN KEY
(
doc_id
) REFERENCES Docs
(
doc_id
) ON UPDATE CASCADE
ON DELETE CASCADE
GOYou say 'A Doc *doesn't necessarily have to be* related to a Folder,
but *must be* related to a Cust.'
Keep cascading on FK_DocsInFolders_Docs, but manage the Cust<--Docs
relationship in procedures. You make it sound as if the importance of the
Cust<--Docs relationship supercedes the importance of the Folders<--Docs
relationship.
Vital relationships should not be cascading.
ML|||Correct. The Cust<--Docs relationship is more importance, but that's why I
have only ON UPDATE CASCADE (to make possible usr_name changes up to date)
and not ON DELETE because I don't want Custs having Docs deleted by mistake.
An SP takes care of that.
So what you are saying is that I should change the ON CHANGE to NO ACTION as
well?
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:601F4976-E669-4865-9D92-FBAF9A16CA8F@.microsoft.com...
> You say 'A Doc *doesn't necessarily have to be* related to a Folder,
> but *must be* related to a Cust.'
> Keep cascading on FK_DocsInFolders_Docs, but manage the Cust<--Docs
> relationship in procedures. You make it sound as if the importance of the
> Cust<--Docs relationship supercedes the importance of the Folders<--Docs
> relationship.
> Vital relationships should not be cascading.
>
> ML|||If usr_name can be changed then using it as a primary key (and/or referencin
g
it from a foreign key table) is really bad practice. Either disallow usr_nam
e
changes or use a better kandidate key.
I wouldn't allow cascades for this one.
ML|||OK. So if I disallow cascades for usr_name, you would consider the design to
be correct?
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:90F300A3-7104-4924-A594-E28AC05D645D@.microsoft.com...
> If usr_name can be changed then using it as a primary key (and/or
> referencing
> it from a foreign key table) is really bad practice. Either disallow
> usr_name
> changes or use a better kandidate key.
> I wouldn't allow cascades for this one.
>
> ML|||As far as I can see, the design is fine. I would, however, do something abou
t
the Folders and Docs entities. Right now you allow a single document to exis
t
in more than one folder, which can lead to problems. The same goes for
folders - you should focus on preventing circular references.
Oh, and if any given document cannot exist in more than one folder, then the
DocsInFolders table is obsolete. You could simply add a nullable folder_id
foreign key to the Docs table (nullable since you've mentioned that a
document need not exist in any folder).
I hope you started on paper. :) And in case you haven't, maybe you'll do it
next time.
ML|||My design question applied to the cascading paths, not the business rules
themselves. One Doc may actually exist in several Folders.
- One Cust may have zero or more Folders
- One Cust may have zero or more Docs not connected to a Folder
- One Folder may have zero or more Docs related
Thus, my question was only related to if there's a better way of designing
the relations and tables to avoid circular references, which now occurs.
FYI, I didn't start on paper. I use Visio.
Thank you,
Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:F981A87A-893F-4940-9EBD-566C385CF1CB@.microsoft.com...
> As far as I can see, the design is fine. I would, however, do something
> about
> the Folders and Docs entities. Right now you allow a single document to
> exist
> in more than one folder, which can lead to problems. The same goes for
> folders - you should focus on preventing circular references.
> Oh, and if any given document cannot exist in more than one folder, then
> the
> DocsInFolders table is obsolete. You could simply add a nullable folder_id
> foreign key to the Docs table (nullable since you've mentioned that a
> document need not exist in any folder).
> I hope you started on paper. :) And in case you haven't, maybe you'll do
> it
> next time.
>
> ML|||No pun intended.
You are right - there is a better way to avoid circular references. You
might find more answers studying trees and hierarchies. Consider this model:
ItemInstance : ItemID : BelongsToInstance : ItemType
ItemInstance is unique.
ItemID can be either cust_id, folder_id or doc_id.
BelongsToInstance is a foreign key referencing ItemInstance.
ItemType designates whether ItemID is customer, folder or document.
Valid relationships are:
1) Customer/Folder/Document
2) Customer/Document
3) Folder/Folder (<-- not sure about this one, but seems logical, however:
parent folder_id must should be equal to child folder_id).
A customer can only exist as a root element (BelongsToInstance is null).
A Document can only exist as a leaf element (its ItemInstance is never
referenced in a BelongsToInstance).
The above constraints could be reinforced through the use of indexed views.
ItemInstance and BelongsToInstance prevent circular references while still
allowing all possible relationships between the three entities.
ML|||Thank you for your detailed answer.
I do have a copy of a trees and hierarchies book which I could take a closer
look into (Joe Celko's Trees and Hierarchies in SQL for Smarties). Maybe I
can find some more answers and examples there.
/Jonah
"ML" <ML@.discussions.microsoft.com> skrev i meddelandet
news:D5B9F5D8-4790-4088-BF18-14DE5119891D@.microsoft.com...
> No pun intended.
> You are right - there is a better way to avoid circular references. You
> might find more answers studying trees and hierarchies. Consider this
> model:
> ItemInstance : ItemID : BelongsToInstance : ItemType
> ItemInstance is unique.
> ItemID can be either cust_id, folder_id or doc_id.
> BelongsToInstance is a foreign key referencing ItemInstance.
> ItemType designates whether ItemID is customer, folder or document.
> Valid relationships are:
> 1) Customer/Folder/Document
> 2) Customer/Document
> 3) Folder/Folder (<-- not sure about this one, but seems logical, however:
> parent folder_id must should be equal to child folder_id).
> A customer can only exist as a root element (BelongsToInstance is null).
> A Document can only exist as a leaf element (its ItemInstance is never
> referenced in a BelongsToInstance).
> The above constraints could be reinforced through the use of indexed
> views.
> ItemInstance and BelongsToInstance prevent circular references while still
> allowing all possible relationships between the three entities.
>
> ML|||What about using a nested sets model for the hierarchy? I am not a big
fanof misxed node trees, but this case is pretty easy:
1) If it is the root node, it is a Customer
2) If it is a leaf node, it is a document
3) other it is a folder
CREATE TABLE DocumentHierarchy
(customer_id INTEGER NOT NULL
REFERENCES Customers
ON UPDATE CASCADE
ON DELETE CASCADE,
folder_id INTEGER -- null means no folder
REFERENCES Folders (folder_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
document_id INTEGER -- null means no document
REFERENCES Documents(doc_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
lft INTEGER NOT NULL CHECK (lft >0),
rgt INTEGER NOT NULL CHECK (rgt >lft),
PRIMARY KEY (customer_id, lft, rgt));
untested. You can also get a copy of TREES & HIERARCHIES IN SQL for
more ideas.
Subscribe to:
Posts (Atom)