Database Design and Relational Theory
Normal Forms and All That Jazz
C. J. Date
Database Design and Relational Theory by C. J. Date Copyright © 2012 C. J. Date. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472 O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/institutional sales department: (800) 998-9938 or
[email protected]. Printing History: April 2012: First Edition. Revision History: 2012-04-09 First release See http://oreilly.com/catalog/errata.csp?isbn=0636920025276 for release details.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Database Design and Relational Theory: Normal Forms and All That Jazz and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
ISBN: 978-1-449-32801-6 [LSI]
In computing, elegance is not a dispensable luxury but a quality that decides between success and failure. ─Edsger W. Dijkstra The ill design is most ill for the designer. ─Hesiod It is to be noted that when any part of this paper is dull there is design in it. ─Sir Richard Steele The idea of a formal design discipline is often rejected on account of vague cultural / philosophical condemnations such as “stifling creativity”; this is more pronounced … where a romantic vision of “the humanities” in fact idealizes technical incompetence … [We] know that for the sake of reliability and intellectual control we have to keep the design simple and disentangled. ─Edsger W. Dijkstra My designs are strictly honorable. ─Anon.
─── ♦♦♦♦♦ ───
To my wife Lindy and my daughters Sarah and Jennie with all my love
About the Author C. J. Date is an independent author, lecturer, researcher, and consultant, specializing in relational database technology. He is best known for his book An Introduction to Database Systems (8th edition, Addison-Wesley, 2004), which has sold some 850,000 copies at the time of writing and is used by several hundred colleges and universities worldwide. He is also the author of many other books on database management, including most recently: n
From Addison-Wesley: Databases, Types, and the Relational Model: The Third Manifesto (3rd edition, coauthored with Hugh Darwen, 2006)
n
From Trafford: Logic and Databases: The Roots of Relational Theory (2007)
n
From Apress: The Relational Database Dictionary, Extended Edition (2008)
n
From Trafford: Database Explorations: Essays on The Third Manifesto and Related Topics (coauthored with Hugh Darwen, 2010)
n
From Ventus: Go Faster! The TransRelational™ Approach to DBMS Implementation (2011)
n
From O’Reilly: SQL and Relational Theory: How to Write Accurate SQL Code (2nd edition, 2012)
Mr. Date was inducted into the Computing Industry Hall of Fame in 2004. He enjoys a reputation that is second to none for his ability to explain complex technical subjects in a clear and understandable fashion.
Contents Preface
xi
PART I
SETTING THE SCENE
Chapter 1
Preliminaries
1
3
Some quotes from the literature A note on terminology 5 The running example 6 Keys 7 The place of design theory 8 Aims of this book 11 Concluding remarks 12 Exercises 12 Chapter 2
Prerequisites
3
15
Overview 15 Relations and relvars 16 Predicates and propositions More on suppliers and parts Exercises 22
18 20
PART II
FUNCTIONAL DEPENDENCIES, BOYCE/CODD NORMAL FORM, AND RELATED MATTERS 25
Chapter 3
Normalization: Some Generalities Normalization serves two purposes Update anomalies 31 The normal form hierarchy 32 Normalization and constraints 34 Concluding remarks 35 Exercises 36
Chapter 4
FDs and BCNF (Informal) First normal form 37 Functional dependencies 40 Keys revisited 42 Second normal form 43 Third normal form 45 Boyce/Codd normal form 45 Exercises 47
37
27 29
vi
Contents
Chapter 5
FDs and BCNF (Formal)
49
Preliminary definitions 49 Functional dependencies 50 Boyce/Codd normal form 52 Heath’s Theorem 54 Exercises 56 Chapter 6
Preserving FDs
59
An unfortunate conflict 60 Another example 63 ... And another 64 ... And still another 66 A procedure that works 67 Identity decompositions 71 More on the conflict 72 Independent projections 73 Exercises 74 Chapter 7
FD Axiomatization
75
Armstrong’s axioms 75 Additional rules 76 Proving the additional rules 78 Another kind of closure 79 Exercises 80 Chapter 8
Denormalization
83
“Denormalize for performance”? 83 What does denormalization mean? 84 What denormalization isn’t (I) 86 What denormalization isn’t (II) 88 Denormalization considered harmful (I) 90 Denormalization considered harmful (II) 91 A final remark 92 Exercises 92
Contents
PART III
JOIN DEPENDENCIES, FIFTH NORMAL FORM, AND RELATED MATTERS 95
Chapter 9
JDs and 5NF (Informal)
97
Join dependencies─the basic idea 98 A relvar in BCNF and not 5NF 100 Cyclic rules 103 Concluding remarks 104 Exercises 105 Chapter 10
JDs and 5NF (Formal)
107
Join dependencies 107 Fifth normal form 109 JDs implied by keys 110 A useful theorem 113 FDs aren’t JDs 114 Update anomalies revisited Exercises 116 Chapter 11
Implicit Dependencies
114
117
Irrelevant components 117 Combining components 118 Irreducible JDs 119 Summary so far 121 The chase algorithm 123 Concluding remarks 127 Exercises 127 Chapter 12
MVDs and 4NF
129
An introductory example 129 Multivalued dependencies (informal) 131 Multivalued dependencies (formal) 132 Fourth normal form 133 Axiomatization 134 Embedded dependencies 135 Exercises 136
vii
viii
Contents
Chapter 13
Additional Normal Forms
139
Equality dependencies 139 Sixth normal form 141 Superkey normal form 143 Redundancy free normal form 144 Domain-key normal form 149 Concluding remarks 150 Exercises 152 PART IV
ORTHOGONALITY
155
Chapter 14
The Principle of Orthogonal Design
157
Two cheers for normalization 157 A motivating example 159 A simpler example 160 Tuples vs. propositions 163 The first example revisited 166 The second example revisited 168 The final version 168 A clarification 168 Concluding remarks 170 Exercises 171 PART V
REDUNDANCY
173
Chapter 15
We Need More Science
175
A little history 177 Database design is predicate design Example 1 180 Example 2 181 Example 3 181 Example 4 181 Example 5 182 Example 6 183 Example 7 185 Example 8 187 Example 9 188 Example 10 189 Example 11 190 Example 12 190
178
Contents
Managing redundancy 191 Refining the definition 193 Concluding remarks 200 Exercises 200 APPENDIXES Appendix A
201
Primary Keys Are Nice but Not Essential
203
Arguments in favor of the PK:AK distinction 204 Relvars with more than one key 206 The invoices and shipments example 208 One primary key per entity type? 211 The applicants and employees example 212 Concluding remarks 214 Appendix B
Redundancy Revisited
Appendix C
Historical Notes
Appendix D
Answers to Exercises Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 Chapter 6 Chapter 7 Chapter 8 Chapter 9 Chapter 10 Chapter 11 Chapter 12 Chapter 13 Chapter 14 Chapter 15 Index
255
223 224 227 227 232 235 237 240 242 244 245 247 250 253 253
215
219 223
ix
Preface This book began life as a comparatively short chapter in a book called Database in Depth: Relational Theory for Practitioners (O’Reilly, 2005). That book was superseded by SQL and Relational Theory: How to Write Accurate SQL Code (O’Reilly, 2009), where the design material, since it was somewhat tangential to the main theme of the book, ceased to be a chapter as such and became a (somewhat longer) appendix instead. I subsequently began work on a second edition of this latter book.1 During the course of that work, I found there was so much that needed to be said on the subject of design that the appendix threatened to grow out of all proportion to the rest of the book. Since the topic was, as I’ve indicated, rather out of line with the major emphasis of that book anyway, I decided to cut the Gordian knot and separate the material out into a book of its own: the one you’re looking at right now. Three points arise immediately from the foregoing: n
First, the present book does assume you’re familiar with material covered in the SQL and Relational Theory book (in particular, it assumes you know exactly what relations, attributes, and tuples are). I make no apology for this state of affairs, however, since the present book is aimed at database professionals and database professionals ought really to be familiar with most of what’s in that earlier book, anyway.
n
Second, the previous point notwithstanding, there’s unavoidably a small amount of overlap between this book and that earlier book. I’ve done my best to keep that overlap to a minimum, however.
n
Third, there are, again unavoidably, many references in this book to that earlier one. Now, most references in this book to other publications are given in full, as in this example: Ronald Fagin: “Normal Forms and Relational Database Operators,” Proc. 1979 ACM SIGMOD Int. Conf. on Management of Data, Boston, Mass. (May/June 1979).
In the case of references to the earlier book in particular, however, from this point forward I’ll give them in the form of the abbreviated title SQL and Relational Theory alone. What’s more, I’ll take that abbreviated title to mean the second edition specifically (where it makes any difference). Actually I’ve published several short pieces over the years, in one place or another, on various aspects of design theory, and the present book is intended among other things to preserve the good parts of those earlier writings. But it’s not just a cobbling together of previously published material, and I sincerely hope it won’t be seen as such. For one thing, it contains much new material. For another, it presents a more coherent, and I think much better, perspective on the subject as a whole (I’ve learned a lot myself over the years!). Indeed, even when some portion of the text is based on some earlier publication, the material in question has been totally rewritten and, I trust, improved. Now, there’s no shortage of books on database design; so what makes this one different? In fact I don’t think there’s a book quite like this one on the market. There are many books (of considerably varying quality, in my opinion) on design practice, but those books (again, in my not unbiased opinion) usually don’t do a very good job of explaining the underlying theory. And there are a few books on design theory, too, but they tend to be aimed at theoreticians, not practitioners, and to be rather academic in tone. What I want to do is bridge the gap; in other words, I want to explain the theory in a way that practitioners should be able to understand, and I want to show why
1
Now (2012) available from O’Reilly.
xii
Preface
that theory is of considerable practical importance. What I’m not trying to do is be exhaustive; I don’t want to discuss the theory in every last detail, I want to concentrate on what seem to me the important parts (though, naturally, my treatment of the parts I do cover is meant to be precise and accurate, as far as it goes). Also, I’m aiming at a judicious blend of the formal and the informal; in other words, I’m trying to provide a gentle introduction to the theory, so that: a.
You can use important theoretical results to help you actually do design, and
b.
You’ll be able, if you’re so inclined, to go to the more academic texts and understand them.
In the interest of readability, I’ve deliberately written a fairly short book, and I’ve deliberately made each chapter fairly short, too. (I’m a great believer in doling out information in digestible chunks.) Also, every chapter includes a set of exercises (answers to most of which are given in Appendix D at the back of the book), and I do recommend that you have a go at some of those exercises if not all. Some of them are intended to show how to apply the theoretical ideas in practice; others provide (in the answers if not in the exercises as such) additional information on the subject matter, over and above what’s covered in the main body of the text; and still others are meant—for example, by asking you to prove some simple theoretical result—to get you to gain some understanding as to what’s involved in “thinking like a theoretician.” Overall, I’ve tried to give some insight into what design theory is and why it is the way it is. Prerequisites My target audience is database professionals: more specifically, database professionals with a more than passing interest in database design. In particular, therefore, I assume you’re reasonably familiar with the relational model, or at least with certain aspects of that model (Chapter 2 goes into more detail on these matters). As already indicated, familiarity with the SQL and Relational Theory book would be a big help. Note: I'd like to mention that I also have a live seminar available based on this book. See www.justsql.co.uk/chris_date/chris_date.htm for further details. Logical vs. Physical Design This book is about design theory; by definition, therefore, it’s about logical design, not physical database design. Of course, I’m not saying physical design is unimportant (of course not); but I am saying it’s a distinct activity, separate from and subsequent to logical design. To spell the point out, the “right” way to do design is as follows: 1.
Do a clean logical design first. Then, as a separate and subsequent step:
2.
Map that logical design into whatever physical structures the target DBMS happens to support.2
Note, therefore, that the physical design should be derived from the logical design and not the other way around. (Ideally, in fact, the system should be able to derive the physical design “automatically” from the logical design, without the need for human involvement in the process at all.) To repeat, the book is about design theory. So another thing it’s not about is the various ad hoc design methodologies—entity/relationship modeling and the like—that have been proposed over the years, at one time or 2
DBMS = database management system. Note that there’s a logical difference between a DBMS and a database! Unfortunately, the industry very commonly uses the term database when it means either some DBMS product, such as Oracle, or the particular copy of such a product that happens to be installed on a particular computer. I do not follow that usage in this book. The problem is, if you call the DBMS a database, what do you call the database?
Preface
xiii
another. Of course, I realize that certain of those methodologies are fairly widely used in practice, but the fact remains that they enjoy comparatively little by way of a solid theoretical basis. As a result, they’re mostly beyond the scope of a book like this one. However, I do have a few remarks here and there on such methodologies (especially in Chapters 8 and 15 and Appendix A). Acknowledgments I’d like to thank Hugh Darwen, Ron Fagin, David McGoveran, and Andy Oram for their meticulous reviews of earlier drafts of this book. Each of these reviewers helped correct a number of misconceptions on my part (rather more such, in fact, than I like to think). Of course, it goes without saying that any remaining errors are my responsibility. I’d also like to thank Chris Adamson for help with certain technical questions, and my wife Lindy for her support throughout the production of this book, as well as all of its predecessors.
C. J. Date Healdsburg, California 2012
Part I
SETTING THE SCENE
This part of the book consists of two chapters, the titles of which (“Preliminaries” and “Prerequisites,” respectively) are more or less self-explanatory.
Chapter 1
Preliminaries (On being asked what jazz is:) Man, if you gotta ask, you’ll never know —Louis Armstrong (attrib.)
This book has as subtitle Normal Forms and All That Jazz. Clearly some explanation is needed! First of all, of course, I’m talking about design theory, and everybody knows normal forms are a major component of that theory; hence the first part of my subtitle. But there’s more to the theory than just normal forms, and that fact accounts for that subtitle’s second part. Third, it’s unfortunately the case that—from the practitioner’s point of view, at any rate—design theory is riddled with terms and concepts that seem to be difficult to understand and don’t seem to have much to do with design as actually done in practice. That’s why I framed the latter part of my subtitle in colloquial (not to say slangy) terms; I wanted to convey the idea, or impression, that although we’d necessarily be dealing with “difficult” material on occasion, the treatment of that material would be as undaunting and unintimidating as I could make it. But whether I’ve succeeded in that aim is for you to judge, of course. I’d also like to say a little more on the question of whether design theory has anything to do with design as done in practice. Let me be clear: Nobody could, or should, claim that designing databases is easy. But a sound knowledge of theory can only help. In fact, if you want to do design properly—if you want to build databases that are as robust, flexible, and accurate as they’re supposed to be—then you simply have to come to grips with design theory. There’s just no alternative: at least, not if you want to claim to be a professional. Design theory is the scientific foundation for database design, just as the relational model is the scientific foundation for database technology in general. And just as anyone professionally involved in database technology in general needs to be familiar with the relational model, so anyone involved in database design in particular needs to be familiar with design theory. Proper design is so important! After all, the database lies at the heart of so much of what we do in the computing world; so if it’s badly designed, the negative impacts can be extraordinarily widespread.
SOME QUOTES FROM THE LITERATURE Since we’re going to be talking quite a lot about normal forms, I thought it might be—well, not enlightening, perhaps, but entertaining (?)—to begin with a few quotes from the literature. The starting point for the whole concept of normal forms is, of course, first normal form (1NF), and so an obvious question is: Do you know what 1NF is? As the following quotes demonstrate (sources omitted to protect the guilty), a lot of people don’t: n
To achieve first normal form, each field in a table must convey unique information.
n
An entity is said to be in the first normal form (1NF) when all attributes are single valued.
n
A relation is in 1NF if and only if all underlying domains contain atomic values only.
n
If there are no repeating groups of attributes, then [the table] is in 1NF.
4
Chapter 1 / Preliminaries
Now, it might be argued that some if not all of these quotes are at least vaguely correct—but they’re all hopelessly sloppy, even when they’re generally on the right lines. (In case you’re wondering, I’ll be giving a precise and accurate definition of 1NF in Chapter 4.) Let’s take a closer look at what’s going on here. Here again is the first of the foregoing quotes, now given in full: n
To achieve first normal form, each field in a table must convey unique information. For example, if you had a Customer table with two columns for the telephone number, your design would violate first normal form. First normal form is fairly easy to achieve, since few folks would see a need for duplicate information in a table.
OK, so apparently we’re talking about a design that looks something like this: ┌────────┬──────────┬──────────┬─────┐ │ CUSTNO │ PHONENO1 │ PHONENO2 │ ... │ ├════════┼──────────┼──────────┼─────┤ Now, I can’t say whether this is a good design or not, but it certainly doesn’t violate 1NF. (I can’t say whether it’s a good design because I don’t know exactly what “two columns for the telephone number” means. The phrase “duplicate information in a table” suggests we’re recording the same phone number twice, but such an interpretation is absurd on its face. But even if that interpretation is correct, it still wouldn’t constitute a violation of 1NF as such.) Here’s another one: n
First Normal Form ... means the table should have no “repeating groups” of fields ... A repeating group is when you repeat the same basic attribute (field) over and over again. A good example of this is when you wish to store the items you buy at a grocery store ... [and the writer goes on to give an example, presumably meant to illustrate the concept of a repeating group, of a table called Item Table with columns called Customer, Item1, Item2, Item3, and Item4]:
┌──────────┬───────┬───────┬───────┬───────┐ │ CUSTOMER │ ITEM1 │ ITEM2 │ ITEM3 │ ITEM4 │ ├══════════┼───────┼───────┼───────┼───────┤ Well, this design is almost certainly bad—what happens if the customer doesn’t purchase exactly four items?—but the reason it’s bad isn’t that it violates 1NF; like the previous example, in fact, it’s a 1NF design. And while it’s true that 1NF does mean, loosely, “no repeating groups,” a repeating group is not “when you repeat the same basic attribute over and over again.” (What it really is I’ll explain in Chapter 4, when I explain what 1NF really is.) How about this one (a cry for help found on the Internet)? I’m quoting it absolutely verbatim, except that I’ve added some boldface: n
I have been trying to find the correct way of normalizing tables in Access. From what I understand, it goes from the 1st normal form to 2nd, then 3rd. Usually, that’s as far as it goes, but sometimes to the 5th and 6th. Then, there’s also the Cobb 3rd. This all makes sense to me. I am supposed to teach a class in this starting next week, and I just got the textbook. It says something entirely different. It says 2nd normal form is only for tables with a multiple-field primary key, 3rd normal form is only for tables with a single-field key. 4th normal form can go from 1st to 4th, where there are no independent one-to-many relationships between primary key and non-key fields. Can someone clear this up for me please?
Preliminaries / Chapter 1
5
And one more (this time with a “helpful” response): n
> It’s not clear to me what “normalized” means. Can you be specific about what normalization rules you are > referring to? In what way is my schema not normalized? Normalization: The process of replacing duplicate things with a reference to the original thing. For example, given “john is-a person” and “john obeys army,” one observes that the “john” in the second sentence is a duplicate of “john” in the first sentence. Using the means provided by your system, the second sentence should be stored as “->john obeys army.”
A NOTE ON TERMINOLOGY As I’m sure you noticed, the quotes in the previous section were expressed for the most part in the familiar “user friendly” terminology of tables, rows, and columns (or fields). In this book, by contrast, I’ll tend to favor the more formal terms relation, tuple (usually pronounced to rhyme with couple), and attribute. I apologize if this decision on my part makes the text a little harder to follow, but I do have my reasons. As I said in SQL and Relational Theory:1 I’m generally sympathetic to the idea of using more user friendly terms, if they can help make the ideas more palatable. In the case at hand, however, it seems to me that, regrettably, they don’t make the ideas more palatable; instead, they distort them, and in fact do the cause of genuine understanding a grave disservice. The truth is, a relation is not a table, a tuple is not a row, and an attribute is not a column. And while it might be acceptable to pretend otherwise in informal contexts—indeed, I often do exactly that myself—I would argue that it’s acceptable only if we all understand that the more user friendly terms are just an approximation to the truth and fail overall to capture the essence of what’s really going on. To put it another way, if you do understand the true state of affairs, then judicious use of the user friendly terms can be a good idea; but in order to learn and appreciate that true state of affairs in the first place, you really do need to come to grips with the formal terms.
To the foregoing, let me add that (as I said in the preface) I do assume you know exactly what relations, attributes, and tuples are!—though in fact formal definitions of these constructs can be found in Chapter 5. There’s another terminological matter I need to get out of the way, too. The relational model is, of course, a data model. Unfortunately, however, this latter term has two quite distinct meanings in the database world.2 The first and more fundamental one is this: n
Definition: A data model (first sense) is an abstract, self-contained, logical definition of the data structures, data operators, and so forth, that together make up the abstract machine with which users interact.
This is the meaning we have in mind when we talk about the relational model in particular: The data structures in the relational model are relations, of course, and the data operators are the relational operators projection, join, and
1 I remind you from the preface that throughout this book I use SQL and Relational Theory as an abbreviated form of reference to my book SQL and Relational Theory: How to Write Accurate SQL Code (2nd edition, O’Reilly, 2012). 2 This observation is undeniably correct. However, one reviewer wanted me to add that the two meanings can be thought of as essentially the same concept at different levels of abstraction.
6
Chapter 1 / Preliminaries
the rest. (As for that “and so forth” in the definition, it covers such matters as keys, foreign keys, and various related concepts.) The second meaning of the term data model is as follows: n
Definition: A data model (second sense) is a model of the data—especially the persistent data—of some particular enterprise.
In other words, a data model in the second sense is just a (logical, and possibly somewhat abstract) database design. For example, we might speak of the data model for some bank, or some hospital, or some government department. Having explained these two different meanings, I’d like to draw your attention to an analogy that I think nicely illuminates the relationship between them: n
A data model in the first sense is like a programming language, whose constructs can be used to solve many specific problems but in and of themselves have no direct connection with any such specific problem.
n
A data model in the second sense is like a specific program written in that language—it uses the facilities provided by the model, in the first sense of that term, to solve some specific problem.
It follows from all of the above that if we’re talking about data models in the second sense, then we might reasonably speak of “relational models” in the plural, or “a” relational model (with an indefinite article). But if we’re talking about data models in the first sense, then there’s only one relational model, and it’s the relational model (with the definite article). Now, as you probably know, most writings on database design, especially if their focus is on pragma rather than the underlying theory, use the term “model,” or “data model,” exclusively in the second sense. But—please note carefully!—I don’t follow this practice in the present book; in fact, I don’t use the term “model” at all, except occasionally to refer to the relational model as such.
THE RUNNING EXAMPLE Now let me introduce the example I’ll be using as a basis for most of the discussions in the rest of the book: the familiar—not to say hackneyed—suppliers-and-parts database. (I apologize for dragging out this old warhorse yet one more time, but I believe that using essentially the same example in a variety of different books and publications can help, not hinder, learning.) Sample values are shown in Fig. 1.1.3 To elaborate: n
Suppliers: Relvar S denotes suppliers.4 Each supplier has one supplier number (SNO), unique to that supplier; one name (SNAME), not necessarily unique (though the SNAME values in Fig. 1.1 do happen to be unique); one status value (STATUS), representing some kind of ranking or preference level among suppliers; and one location (CITY).
3 For reasons that will become clear later, the values shown in Fig. 1.1 differ in two small respects from those in other books of mine: The status for supplier S2 is shown as 30 instead of 10, and the city for part P3 is shown as Paris instead of Oslo. 4
If you don’t know what a relvar is, for now you can just take it to be a table in the usual database sense. See Chapter 2 for further explanation.
Preliminaries / Chapter 1
7
n
Parts: Relvar P denotes parts (more accurately, kinds of parts). Each kind of part has one part number (PNO), which is unique; one name (PNAME), not necessarily unique; one color (COLOR); one weight (WEIGHT); and one location where parts of that kind are stored (CITY).
n
Shipments: Relvar SP denotes shipments (it shows which parts are supplied, or shipped, by which suppliers). Each shipment has one supplier number (SNO), one part number (PNO), and one quantity (QTY). Also, I assume for the sake of the example that there’s at most one shipment at any one time for a given supplier and a given part, and so each shipment has a supplier-number/part-number combination that’s unique. S ┌─────┬───────┬────────┬────────┐ │ SNO │ SNAME │ STATUS │ CITY │ ├═════┼───────┼────────┼────────┤ │ S1 │ Smith │ 20 │ London │ │ S2 │ Jones │ 30 │ Paris │ │ S3 │ Blake │ 30 │ Paris │ │ S4 │ Clark │ 20 │ London │ │ S5 │ Adams │ 30 │ Athens │ └─────┴───────┴────────┴────────┘ P ┌─────┬───────┬───────┬────────┬────────┐ │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY │ ├═════┼───────┼───────┼────────┼────────┤ 12.0 │ London │ │ │ Red │ P1 │ Nut 17.0 │ Paris │ │ P2 │ Bolt │ Green │ │ P3 │ Screw │ Blue │ 17.0 │ Paris..│ │ P4 │ Screw │ Red │ 14.0 │ London │ 12.0 │ Paris │ │ Blue │ │ P5 │ Cam │ P6 │ Cog │ Red │ 19.0 │ London │ └─────┴───────┴───────┴────────┴────────┘
SP ┌─────┬─────┬─────┐ │ SNO │ PNO │ QTY │ ├═════┼═════┼─────┤ │ S1 │ P1 │ 300 │ │ S1 │ P2 │ 200 │ │ S1 │ P3 │ 400 │ │ S1 │ P4 │ 200 │ │ S1 │ P5 │ 100 │ │ S1 │ P6 │ 100 │ │ S2 │ P1 │ 300 │ │ S2 │ P2 │ 400 │ │ S3 │ P2 │ 200 │ │ S4 │ P2 │ 200 │ │ S4 │ P4 │ 300 │ │ S4 │ P5 │ 400 │ └─────┴─────┴─────┘
Fig. 1.1: The suppliers-and-parts database—sample values
KEYS Before going any further, I need to review the familiar concept of keys, in the relational sense of that term. First of all, as I’m sure you know, every relvar has at least one candidate key. A candidate key is basically just a unique identifier; in other words, it’s a combination of attributes—often but not always a “combination” consisting of just a single attribute—such that every tuple in the relvar has a unique value for the combination in question. For example, with respect to the database of Fig. 1.1: n
Every supplier has a unique supplier number and every part has a unique part number, so {SNO} is a candidate key for S and {PNO} is a candidate key for P.
n
As for shipments, given the assumption that there’s at most one shipment at any one time for a given supplier and a given part, {SNO,PNO} is a candidate key for SP.
Note the braces, by the way; to repeat, candidate keys are always combinations, or sets, of attributes (even when the set in question contains just one attribute), and the conventional representation of a set on paper is as a commalist of elements enclosed in braces. Note: The useful term commalist can be defined as follows: Let xyz be some syntactic construct (for example, “attribute name”). Then the term xyz commalist denotes a sequence of zero
8
Chapter 1 / Preliminaries
or more xyz’s in which each pair of adjacent xyz’s is separated by a comma (as well as, optionally, one or more spaces before or after the comma or both). Next, as I’m sure you also know, a primary key is a candidate key that’s been singled out in some way for some kind of special treatment. Now, if the relvar in question has just one candidate key, then it doesn’t make any real difference if we call that key primary. But if the relvar has two or more candidate keys, then it’s usual to choose one of them to be primary, meaning it’s somehow “more equal than the others.” Suppose, for example, that suppliers always have both a unique supplier number and a unique supplier name, so that {SNO} and {SNAME} are both candidate keys. Then we might choose {SNO}, say, to be the primary key. Observe now that I said it’s usual to choose a primary key. Indeed it is usual—but it’s not 100 percent necessary. If there’s just one candidate key, then there’s no choice and no problem; but if there are two or more, then having to choose one and make it primary smacks a little bit of arbitrariness, at least to me. (Certainly there are situations where there don’t seem to be any good reasons for making such a choice. There might even be good reasons for not doing so. Appendix A elaborates on such matters.) For reasons of familiarity, I’ll usually follow the primary key discipline myself in this book—and in pictures like Fig. 1.1 I’ll indicate primary key attributes by double underlining—but I want to stress the fact that it’s really candidate keys, not primary keys, that are significant from a relational point of view, and indeed from a design theory point of view as well. Partly for such reasons, from this point forward I’ll use the term key, unqualified, to mean any candidate key, regardless of whether the candidate key in question has additionally been designated as primary. (In case you were wondering, the special treatment enjoyed by primary keys over other candidate keys is mainly syntactic in nature, anyway; it isn’t fundamental, and it isn’t very important.) More terminology: First, a key involving two or more attributes is said to be composite (and a noncomposite key is sometimes said to be simple). Second, if a given relvar has two or more keys and one is chosen as primary, then the others are sometimes said to be alternate keys (see Appendix A). Third, a foreign key is a combination, or set, of attributes FK in some relvar R2 such that each FK value is required to be equal to some value of some key K in some relvar R1 (R1and R2 not necessarily distinct).5 With reference to Fig. 1.1, for example, {SNO} and {PNO} are both foreign keys in relvar SP, corresponding to keys {SNO} and {PNO} in relvars S and P, respectively.
THE PLACE OF DESIGN THEORY To repeat something I said in the preface, by the term design I mean logical design, not physical design. Logical design is concerned with what the database looks like to the user (which means, loosely, what relvars exist and what constraints apply to those relvars); physical design, by contrast, is concerned with how a given logical design maps to physical storage.6 And the term design theory refers specifically to logical design, not physical design—the point being that physical design is necessarily dependent on aspects (performance aspects in particular) of the target DBMS, whereas logical design is, or should be, DBMS independent. Throughout this book, then, the unqualified term design should be understood to mean logical design specifically, barring explicit statements to the contrary. Now, design theory as such isn’t part of the relational model; rather, it’s a separate theory that builds on top of that model. (It’s appropriate to think of it as part of relational theory in general, but it’s not, to repeat, part of the relational model per se.) Thus, design concepts such as further normalization are themselves based on more fundamental notions—e.g., the projection and join operators of the relational algebra—that are part of the relational model. (All of that being said, it could certainly be argued that design theory is a logical consequence of the 5 This definition is deliberately a little simplified (though it’s good enough for present purposes). A better one can be found in SQL and Relational Theory. 6 Be warned, however, that other writers (a) use the terms logical design and physical design to mean something else and (b) use other terms to mean what I mean by them. Caveat lector.
Preliminaries / Chapter 1
9
relational model, at least in part. In other words, it would be inconsistent to agree with the relational model in general but not to agree with the design theory that’s based on it.) The overall objective of logical design is to achieve a design that’s (a) hardware independent, for obvious reasons; (b) operating system and DBMS independent, again for obvious reasons; and finally, and perhaps a little controversially, (c) application independent (in other words, we’re concerned primarily with what the data is, rather than with how it’s going to be used). Application independence in this sense is desirable for the very good reason that it’s normally—perhaps always—the case that not all uses to which the data will be put are known at design time; thus, we want a design that’ll be robust, in the sense that it won’t be invalidated by the advent of application requirements that weren’t foreseen at the time of the original design. Observe that one important consequence of this state of affairs is that we aren’t (or at least shouldn’t be) interested in making design compromises for physical performance reasons. Design theory should never be driven by performance considerations. Back to design theory as such. As we’ll see, that theory includes a number of formal theorems, theorems that provide practical guidelines for designers to follow. So if you’re a designer, you need to be familiar with those theorems. Let me quickly add that I don’t mean you have to know how to prove those theorems (though in fact the proofs are often quite simple); what I mean is, you have to know what the theorems say—i.e., you have to know the results—and you have to be prepared to apply those results. That’s the nice thing about theorems: Once somebody’s proved them, their results become available for anybody to use whenever they need to. Now, it’s sometimes claimed, not entirely unreasonably, that all design theory really does is bolster up your intuition. What do I mean by this remark? Well, consider the suppliers-and-parts database. The obvious design for that database is the one illustrated in Fig. 1.1; I mean, it’s “obvious” that three relvars are necessary, that attribute STATUS belongs in relvar S, that attribute COLOR belongs in relvar P, that attribute QTY belongs in relvar SP, and so on. But why exactly are these things obvious? Well, suppose we try a different design; suppose we move the STATUS attribute out of relvar S, for example, and into relvar SP (intuitively the wrong place for it, since status is a property of suppliers, not shipments). Fig. 1.2 below shows a sample value for this revised shipments relvar, which I’ll call STP to avoid confusion:7 ┌─────┬────────┬─────┬─────┐ STP │ SNO │ STATUS │ PNO │ QTY │ ├═════┼────────┼═════┼─────┤ │ S1 │ 20 │ P1 │ 300 │ │ S1 │ 20 │ P2 │ 200 │ │ S1 │ 20 │ P3 │ 400 │ │ S1 │ 20 │ P4 │ 200 │ │ S1 │ 20 │ P5 │ 100 │ │ S1 │ 20 │ P6 │ 100 │ │ S2 │ 30 │ P1 │ 300 │ │ S2 │ 30 │ P2 │ 400 │ │ S3 │ 30 │ P2 │ 200 │ │ S4 │ 20 │ P2 │ 200 │ │ S4 │ 20 │ P4 │ 300 │ │ S4 │ 20 │ P5 │ 400 │ └─────┴────────┴─────┴─────┘ Fig. 1.2: Relvar STP—sample value
7
For obvious reasons I use T, not S, as an abbreviation for STATUS, here and throughout this book.
10
Chapter 1 / Preliminaries
A glance at the figure is sufficient to show what’s wrong with this design: It’s redundant, in the sense that every tuple for supplier S1 tells us S1 has status 20, every tuple for supplier S2 tells us S2 has status 30, and so on.8 And design theory tells us that not designing the database in the obvious way will lead to such redundancy, and tells us also (albeit implicitly) what the consequences of such redundancy will be. In other words, design theory is largely about reducing redundancy, as we’ll see. (As an aside, I remark that—partly for such reasons—the theory has been described, perhaps a little unkindly, as a good source of bad examples.) Now, if design theory really does just bolster up your intuition, then it might be (and indeed has been) criticized on the grounds that it’s really all just common sense anyway. By way of example, consider relvar STP again. As I’ve said, that relvar is obviously badly designed; the redundancies are obvious, the consequences are obvious too, and any competent human designer would “naturally” avoid such a design, even if that designer had no explicit knowledge of design theory at all. But what does “naturally” mean here? What principles are being applied by that human designer in opting for a more “natural” (and better) design? The answer is: They’re exactly the principles that design theory talks about (the principles of normalization, for example). In other words, competent designers already have those principles in their brain, as it were, even if they’ve never studied them formally and can’t put a name to them or articulate them precisely. So yes, the principles are common sense—but they’re formalized common sense. (Common sense might be common, but it’s not always easy to say exactly what it is!) What design theory does is state in a precise way what certain aspects of common sense consist of. In my opinion, that’s the real achievement—or one of the real achievements, anyway—of the theory: It formalizes certain commonsense principles, thereby opening the door to the possibility of mechanizing those principles (that is, incorporating them into computerized design tools). Critics of the theory often miss this point; they claim, quite rightly, that the ideas are mostly just common sense, but they don’t seem to realize it’s a significant achievement to state what common sense means in a precise and formal way. As a kind of postscript to the foregoing, I note that common sense might not always be that common anyway. The following lightly edited extract from a paper by Robert R. Brown of Hughes Aircraft9 illustrates the point. The author begins by giving “a simplified real example”—his words—involving an employee file (with fields for employee number, employee name, phone number, department number, and manager name) and a department file (with fields for department number, department name, manager name, and manager’s phone number), all with the intuitively obvious meanings. Then he continues: The actual database on which this example is based had many more files and fields and much more redundancy. When the designer was asked his reasons for such a design, he cited performance and the difficulty of doing joins. Even though the redundancy should be clear to you in my example, it was not that evident in the design documentation. In large databases with many more files and fields, it is impossible to find the duplications without doing extensive information analysis and without having extended discussions with the experts in the user organizations.
Incidentally, there’s another quote I like a lot—in fact, I used it as an epigraph in SQL and Relational Theory—that supports my contention that practitioners really do need to know the theoretical foundations of their field. It’s from Leonardo da Vinci (and is thus some 500 years old!), and it goes like this (I’ve added the boldface): Those who are enamored of practice without theory are like a pilot who goes into a ship without rudder or compass and never has any certainty where he is going. Practice should always be based upon a sound knowledge of theory.
8 You might notice another problem, too: The design can’t properly represent suppliers like supplier S5 who currently supply no parts at all. Such “update anomalies” are discussed in Chapter 3. 9 Robert R. Brown: “Database Systems in Engineering: Key Problems, and Potential Solutions,” in the proceedings of a database symposium held in Sydney, Australia (November 15th-17th, 1984).
Preliminaries / Chapter 1
11
AIMS OF THIS BOOK If you’re like me, you’ll have encountered lots of design theory terms in the literature and live presentations and the like—terms such as projection-join normal form, the chase, join dependency, FD preservation, and many others—and I’m sure you’ve wondered from time to time exactly what they all mean. Thus, it’s one of my aims in this book to explain such terms: to define them carefully and accurately, to explain their relevance and applicability, and generally to remove any air of mystery that might seem to surround them. And if I’m successful in that aim, I’ll have gone a good way to explaining what design theory is and why it’s important (indeed, a possible alternative title for the book would be Database Design Theory: What It Is and Why You Should Care). Overall, it’s my goal to provide a painless introduction to design theory for database professionals. More specifically, what I want to do is: n
Review, though from a possibly unfamiliar perspective, aspects of design you should already be familiar with
n
Explore in depth aspects you’re probably not already familiar with
n
Provide clear and accurate explanations and definitions (with plenty of examples) of all pertinent concepts
n
Not spend a lot of time on material that’s widely understood already, such as 2NF and 3NF10
All of that being said, I should say too that database design is not my favorite subject. The reason it’s not is that much of that subject is still somewhat ... well, subjective. As I said earlier, design theory is the scientific foundation for database design. Sadly, however, there are numerous design issues that the theory simply doesn’t address at all (yet). Thus, while the formal principles I’ll be describing in this book do represent the scientific part of design, there are other parts that, as I’ve put it elsewhere, are still more in the nature of an artistic endeavor. Indeed, one message of the book is precisely that we need more science in this field. To put a more positive spin on matters, I’d like to draw your attention to the following. Design theory is (at least in part) about capturing the meaning of data, and as Codd himself once said in connection with that notion:11 [The] task of capturing (in a reasonably formal way) more of ... the meaning of data is a never-ending one ... The goal is nevertheless an extremely important one, because even small successes can bring understanding and order into the field of database design.
In fact, I’ll go further: If your design violates any of the known science, then, as I’ve written elsewhere (in a slightly different context), the one thing you can be sure of is that things will go wrong. And though it might be hard to say exactly what will go wrong, and it might be hard to say whether things will go wrong in a major or minor way, you know—it’s guaranteed—that they will go wrong. Theory is important.
10 However, I will at least give precise definitions of those familiar concepts for reasons of completeness. Since I’m sure they really are familiar, however, I’ll take the liberty of appealing to them from time to time even before we get to the definitions. 11 The quote is from Codd’s paper “Extending the Database Relational Model to Capture More Meaning,” ACM TODS 4, No. 4, 1979 (the italics are mine). Ted Codd was, of course, the inventor of the relational model; he was also the person who first defined the concept of normalization in general, as well as the first three normal forms (1NF, 2NF, 3NF) in particular.
12
Chapter 1 / Preliminaries
CONCLUDING REMARKS This book grew in the writing; it turns out that, despite the slightly negative tone of some of the remarks in the previous section, there’s really quite a lot of good material to cover. What’s more, the material builds. Thus, while the first few chapters might seem to be going rather slowly, I think you’ll find the pace picks up later on. Part of the point is the number of terms and concepts that need to be introduced; the ideas aren’t really difficult, but they can seem a little overwhelming, at least until you’re comfortable with the terminology. For that reason, at least in some parts of the book, I’ll be presenting the material twice—first from an informal perspective, and then again from a more formal one. (As Bertrand Russell once memorably said: Writing can be either readable or precise, but not at the same time. I’m trying to have my cake and eat it too.) It seems appropriate to close this chapter with another quote from Bertrand Russell:12 I have been accused of a habit of changing my opinions ... I am not myself in any degree ashamed of [that habit]. What physicist who was already active in 1900 would dream of boasting that his opinions had not changed during the last half century? ... The kind of philosophy that I value and have endeavoured to pursue is scientific, in the sense that there is some definite knowledge to be obtained and that new discoveries can make the admission of former error inevitable to any candid mind. For what I have said, whether early or late, I do not claim the kind of truth which theologians claim for their creeds. I claim only, at best, that the opinion expressed was a sensible one to hold at the time ... I should be much surprised if subsequent research did not show that it needed to be modified. [Such opinions were not] intended as pontifical pronouncements, but only as the best I could do at the time towards the promotion of clear and accurate thinking. Clarity, above all, has been my aim.
I’ve quoted this extract elsewhere: in the preface to my book An Introduction to Database Systems (8th edition, Addison-Wesley, 2004) in particular. The reason I mention this latter book is that it includes among other things a tutorial treatment of some of the material covered in more depth in the present book. But the world has moved on; my own understanding of the theory is, I hope, better than it was when I wrote that earlier book, and there are aspects of the treatment in that book that I would frankly now like to revise. One problem with that earlier treatment was that I attempted to make the material more palatable by adopting the fiction that any given relvar has just one key, which could then harmlessly be regarded as the primary key. But a consequence of that simplifying assumption was that several of the definitions I gave (e.g., of 2NF and 3NF) were less than fully accurate. This fact has led to a certain amount of confusion—partly my fault, I freely admit, but partly also the fault of people who took the definitions out of context.
EXERCISES The purpose of these exercises is to give some idea of the scope of the chapters to come, and also perhaps to test the extent of your existing knowledge. They can’t be answered from material in the present chapter alone. 1.1
Is it true that the relational model doesn’t require relvars to be in any particular normal form?
1.2
Should data redundancy always be eliminated? Can it be?
12 The quote is from the preface to The Bertrand Russell Dictionary of Mind, Matter and Morals (ed., Lester E. Denonn; Citadel Press, 1993). I’ve edited it just slightly here.
Preliminaries / Chapter 1
1.3
What’s the difference between 3NF and BCNF?
1.4
Is it true that every “all key” relvar is in BCNF?
1.5
Is it true that every binary relvar is in 4NF?
1.6
Is it true that every “all key” relvar is in 5NF?
1.7
Is it true that every binary relvar is in 5NF?
1.8
Is it true that if a relvar has just one key and just one other attribute, then it’s in 5NF?
1.9
Is it true that if a relvar is in BCNF but not 5NF, then it must be all key?
1.10
Can you give a precise definition of 5NF?
1.11
Is it true that if a relvar is in 5NF, then it’s redundancy free?
1.12
What precisely is denormalization?
1.13
What’s Heath’s Theorem, and why is it important?
1.14
What’s The Principle of Orthogonal Design?
1.15
What makes some JDs irreducible and others not?
1.16
What’s dependency preservation, and why is it important?
1.17
What’s the chase?
1.18
How many normal forms can you name?
13
Chapter 2
Prerequisites The world is everything that is the case —Ludwig Wittgenstein: Tractatus Logico-Philosophicus
You’re supposed to be a database professional, by which I mean someone who (a) is a database practitioner and (b) has a reasonable degree of familiarity with relational theory. Please note that—I’m sorry to have to say this, but it’s true—a knowledge of SQL, no matter how deep, is not sufficient to satisfy part (b) of this requirement. As I said in SQL and Relational Theory: I’m sure you know something about SQL; but—and I apologize for the possibly offensive tone here—if your knowledge of the relational model derives only from your knowledge of SQL, then I’m afraid you won’t know the relational model as well as you should, and you’ll probably know some things that ain’t so. I can’t say it too strongly: SQL and the relational model aren’t the same thing.
The purpose of this chapter, then, is to tell you some things I hope you already know. If you do, then the chapter will serve as a refresher; if you don’t, then I hope it’ll serve as an adequate tutorial. More specifically, what I want to do is spell out in some detail certain fundamental aspects of relational theory that I’ll be relying on heavily in the pages ahead. The aspects in question are ones that, in my experience, database practitioners often aren’t aware of (at least, not explicitly). Of course, there are other aspects of relational theory I’ll be relying on as well, but I’ll elaborate on those, if I think it necessary, when I come to make use of them.
OVERVIEW Let me begin by giving a quick summary (mainly for purposes of subsequent reference) of those fundamental aspects of relational theory just mentioned: n
Any given database consists of relation variables (relvars for short).
n
The value of any given relvar at any given time is a relation value (relation for short).
n
Every relvar represents a certain predicate.
n
Within any given relvar, every tuple represents a certain proposition.
n
In accordance with The Closed World Assumption, relvar R at time T contains all and only those tuples that represent instantiations of the predicate corresponding to relvar R that evaluate to TRUE at time T.
16
Chapter 2 / Prerequisites
The next two sections (which are heavily based on material from SQL and Relational Theory) elaborate on these ideas.
RELATIONS AND RELVARS Take another look at Fig. 1.1, the suppliers-and-parts database, in Chapter 1. That figure shows three relations: namely, the relations that happen to exist in the database at some particular time. But if we were to look at the database at some different time, we would probably see three different relations appearing in their place. In other words, S, P, and SP are really variables—relation variables, to be precise—and just like variables in general, they have different values at different times. And since they’re relation variables specifically, their values at any given time are, of course, relation values. As a basis for examining these ideas further, consider Fig. 2.1 below. That figure shows (a) on the left, a very much reduced version of the shipments relation from Fig. 1.1; (b) on the right, the relation that results after a certain update has been performed. Using the terminology of the previous paragraph, then, we can say, that (a) on the left of the figure we see the relation value that’s the value of relation variable SP at some particular time T1; (b) on the right, we see the relation value that’s the value of that same relation variable at some presumably later time T2, after an additional tuple has been inserted. relvar SP at time T2 relvar SP at time T1 ┌─────┬─────┬─────┐ ┌─────┬─────┬─────┐ │ SNO │ PNO │ QTY │ │ SNO │ PNO │ QTY │◄─── heading ├═════┼═════┼─────┤ ├═════┼═════┼─────┤◄──┐ │ S1 │ P1 │ 300 │ │ S1 │ P1 │ 300 │ │ │ S2 │ P1 │ 300 │ │ S2 │ P1 │ 300 │ ├─ body │ │ S1 │ P2 │ 200 │ └─────┴─────┴─────┘ └─────┴─────┴─────┘◄──┘ ▲ │ ▲ └───────────────────────────┘ relations Supplier SNO supplies part PNO in quantity QTY Predicate: Propositions: Supplier S1 supplies part P1 in quantity 300 (etc.) Fig. 2.1: Relation values and variables—an example
So there’s a logical difference between relation values and relation variables. The trouble is, the database community has historically used the same term, relation, to stand for both concepts, and that practice has certainly led to confusion (not least in contexts that are the subject of the present book, such as further normalization). In this book, therefore, I’ll distinguish very carefully between the two from this point forward—I’ll talk in terms of relation values when I mean relation values and relation variables when I mean relation variables. However, I’ll also abbreviate relation value, most of the time, to just relation (exactly as we abbreviate integer value most of the time to just integer). And I’ll abbreviate relation variable most of the time to relvar; for example, I’ll say the suppliersand-parts database contains three relvars (more precisely, three base relvars; views are relvars too, but I have little to say about views as such in this book). Aside: Actually, there’s one thing I do want to say about views. The Principle of Interchangeability (of views and base relvars) says, in effect, that—at least as far as the user is concerned—views are supposed to look and feel just like base relvars. (I don’t mean views that are defined as mere shorthands, I mean views
Prerequisites / Chapter 2
17
that are intended to insulate the user from the “real” database in some way. See Chapter 15 for an elaboration of this point.) In general, in fact, the user interacts not with a database that contains base relvars only (the “real” database), but rather with what might be called a user database that contains some mixture of base relvars and views. But that user database is supposed to look and feel just like the real database as far as the user is concerned; thus, all of the design principles to be discussed in this book—e.g., the principles of normalization—apply equally well to such user databases, not just to the real database. For this reason, I’ll feel free to use the unqualified term relvar throughout this book, relying on context to indicate whether the term refers equally to base relvars and views or just to base relvars (or just to views) specifically. End of aside. Let’s get back to Fig. 2.1. As that figure indicates, relations have two parts, a heading and a body. Basically, the heading is a set of attributes, and the body is a set of tuples that conform to that heading. For example, the two relations shown in Fig. 2.1 both have a heading consisting of three attributes; also, the relation on the left of that figure has a body consisting of two tuples and the one on the right has a body consisting of three. Note, therefore, that a relation doesn’t really contain tuples, at least not directly (it contains a body, and that body in turn contains the tuples). In practice, however, we do usually talk as if relations contained tuples directly, for simplicity. Points arising: n
The terminology of headings and bodies extends in the obvious way to relvars too. Of course, the heading of a relvar (like that of a relation) never changes—it’s identical to the heading of all possible relations that might ever be assigned to the relvar in question. By contrast, the body does change; to be specific, it changes as updates are performed on the relvar in question.
n
When I get to the more formal treatment in Part II of this book, I’m going to (re)define a heading as a set of attribute names. The difference between the two definitions isn’t important for present purposes, however.
n
In fact, it would be still more correct to define a heading as a set of attribute-name/type-name pairs (and to require the attribute names in question all to be distinct). For example, I’m going to assume in examples throughout this book that attributes SNO and PNO are each of type CHAR (character strings of arbitrary length) and attribute QTY is of type INTEGER (integers).1 And when I talk about tuples conforming to some heading, I mean each attribute value within the tuple in question must be a value of the pertinent type. For example, in order for a tuple to conform to the heading of relvar SP, it must have attributes SNO, PNO, and QTY (and no others), and the values of those attributes must be of types CHAR, CHAR, and INTEGER, respectively. (All of that being said, I must now say too that types aren’t very important for the purposes of relational design theory. That’s why I feel free in this book to simplify my definition of what a heading is. What’s more, I’ll also feel free, in many of my sample relvar definitions, to give the attribute names only and not even mention the types.)
n
The number of attributes in a given heading is the degree of that heading. It’s also the degree of any relation or relvar with that heading. Likewise, the number of tuples in a given body is the cardinality of that body, and it’s also the cardinality of any relation or relvar with that body.2 Note: The term degree is also used in connection with both tuples and keys (including foreign keys). For example, the tuples of relvar SP are all,
1 It would be more appropriate to define QTY to be of type NONNEGATIVE_INTEGER (with the obvious semantics), but few DBMSs if any support such a type. Of course, we could introduce it as a user defined type, but I don’t want to get into details of user defined types in this book. 2 I say “any” relation with that body, but actually two distinct relations can have the same body if and only if the body in question is empty. If it isn’t, then there’s exactly one relation having that body (see the formal definition of relation in Chapter 5).
18
Chapter 2 / Prerequisites
like that relvar itself, of degree three, the sole key of that relvar is of degree two, and the two foreign keys in that relvar, {SNO} and {PNO}, are each of degree one. n
The degree (of a heading or relation or ...) can be any nonnegative integer. Degree 1 is said to be unary; degree 2, binary; degree 3, ternary; ... and, more generally, degree n is said to be n-ary.
PREDICATES AND PROPOSITIONS Again consider the shipments relvar SP. Like all relvars, that relvar is supposed to represent some portion of the real world. In fact, I can be more precise: The heading of that relvar represents a certain predicate, meaning it’s a kind of generic statement about some portion of the real world (it’s generic because it’s parameterized, as I’ll explain in a moment). The predicate in question is quite simple: Supplier SNO supplies part PNO in quantity QTY. This predicate is the intended interpretation—in other words, the meaning—for relvar SP. Aside: Perhaps I should say a little more about the way I use the term predicate in this book. First of all, you’re probably familiar with the term already, since SQL uses it extensively to refer to boolean or truth valued expressions (it talks about comparison predicates, IN predicates, EXISTS predicates, and so on). However, while this usage on SQL’s part isn’t exactly incorrect, it does usurp a very general term—one that’s extremely important in database contexts—and give it a rather specialized meaning, which is why I prefer not to follow that usage myself. Second, I should explain in the interest of accuracy that a predicate isn’t really a statement as such; rather, it’s the assertion made by that statement. For example, the predicate for relvar S is what it is, regardless of whether it’s expressed in English or Spanish or whatever. For simplicity, however, I’ll assume in what follows that a predicate is indeed just a statement per se, typically expressed in natural language. Note: Analogous remarks apply to propositions also (see below). Finally, I’ve now explained what I mean by the term, but you should be aware that—the previous paragraph notwithstanding—there seems to be little consensus, even among logicians, as to exactly what a predicate is. In particular, some writers regard a predicate as a purely formal construct that has no meaning in itself, and regard what I’ve called the intended interpretation as something distinct from the predicate as such. I don’t want to get into arguments about such matters here; for further discussion, I refer you to the article “What’s a Predicate?” in Database Explorations: Essays on The Third Manifesto and Related Topics, by C. J. Date and Hugh Darwen (Trafford, 2010). End of aside. You can think of a predicate, a trifle loosely, as a truth valued function. Like all functions, it has a set of parameters; it returns a result when it’s invoked; and (because it’s truth valued) that result is either TRUE or FALSE. In the case of the predicate just shown, for example, the parameters are SNO, PNO, and QTY (corresponding of course to the attributes of the relvar), and they stand for values of the applicable types (CHAR, CHAR, and INTEGER, respectively, in this simple example). And when we invoke the function—when we instantiate the predicate, as the logicians say—we substitute arguments for the parameters. Suppose we substitute the arguments S1, P1, and 300, respectively. Then we obtain the following statement: Supplier S1 supplies part P1 in quantity 300.
Prerequisites / Chapter 2
19
This statement is in fact a proposition, which in logic is something that evaluates to either TRUE or FALSE, unconditionally. Here are a couple of examples: 1.
Edward Abbey wrote The Monkey Wrench Gang.
2.
William Shakespeare wrote The Monkey Wrench Gang.
The first of these is true and the second false. Don’t fall into the common trap of thinking that propositions must always be true! However, the ones I’m talking about at the moment are supposed to be true ones, as I now explain: n
First of all, every relvar has an associated predicate, called the relvar predicate for the relvar in question. (So the predicate shown above—Supplier SNO supplies part PNO in quantity QTY—is the relvar predicate for relvar SP.)
n
Let relvar R have predicate P. Then every tuple t appearing in R at some given time T can be regarded as representing a certain proposition p, derived by invoking (or instantiating) P at that time T with the attribute values from t as arguments.
n
And (very important!) we assume by convention that each proposition p obtained in this manner evaluates to TRUE.
Given the sample value shown for relvar SP on the left of Fig. 2.1, for example, we assume the following propositions both evaluate to TRUE at time T1: Supplier S1 supplies part P1 in quantity 300. Supplier S2 supplies part P1 in quantity 300. What’s more, we go further: If at some given time T a certain tuple plausibly could appear in some relvar but doesn’t, then we’re entitled to assume the corresponding proposition is false at that time T. For example, the tuple ( ‘S1’ , ‘P2’ , 200 ) (to adopt an obvious shorthand notation) is certainly a plausible SP tuple; but it doesn’t appear in relvar SP at time T1—I’m referring to Fig. 2.1 again—and so we’re entitled to assume it’s not the case that the following proposition is true at time T1: Supplier S1 supplies part P2 in quantity 200. (On the other hand, this proposition is true at time T2.) To sum up: A given relvar R contains, at any given time, all and only the tuples that represent true propositions (true instantiations of the relvar predicate for R) at the time in question—or, at least, that’s what we always assume in practice. In other words, in practice we adopt what’s called The Closed World Assumption. And since that assumption is so crucial—it underlies just about everything we do when we use a database, even though it’s seldom acknowledged explicitly—I’d like to spell it out here for the record: n
Definition: Let relvar R have predicate P. Then The Closed World Assumption (CWA) says (a) if tuple t appears in R at time T, then the instantiation p of P corresponding to t is assumed to be true at time T;
20
Chapter 2 / Prerequisites
conversely, (b) if tuple t plausibly could appear in R at time T but doesn’t, then the instantiation p of P corresponding to t is assumed to be false at time T. In other words (albeit a trifle loosely): Tuple t appears in relvar R at a given time if and only if it satisfies the predicate for R at that time.
MORE ON SUPPLIERS AND PARTS Now let’s get back to the suppliers-and-parts database as such, with sample values as shown in Fig. 1.1 in the previous chapter. Here now are definitions of the three relvars in that database, expressed in a language called Tutorial D (see further explanation following the definitions): VAR S BASE RELATION { SNO CHAR , SNAME CHAR , STATUS INTEGER , CITY CHAR } KEY { SNO } ; VAR P BASE RELATION { PNO CHAR , PNAME CHAR , COLOR CHAR , WEIGHT RATIONAL , CITY CHAR } KEY { PNO } ; VAR SP BASE RELATION { SNO CHAR , PNO CHAR , QTY INTEGER } KEY { SNO , PNO } FOREIGN KEY { SNO } REFERENCES S FOREIGN KEY { PNO } REFERENCES P ; As I said, these definitions are expressed in a language called Tutorial D. Now, I believe that language is pretty much self-explanatory; however, a comprehensive description can be found if needed in the book Databases, Types, and the Relational Model: The Third Manifesto (3rd edition), by C. J. Date and Hugh Darwen (AddisonWesley, 2006).3 Note: As its title suggests, that book also introduces and explains The Third Manifesto, a precise though somewhat formal definition of the relational model and a supporting type theory (including, incidentally, a comprehensive model of type inheritance). In particular, it uses the name D as a generic name for any language that conforms to the principles laid down by The Third Manifesto. Any number of distinct languages could qualify as a valid D; sadly, however, SQL isn’t one of them, which is why examples in this book are expressed (where it makes any difference) in Tutorial D and not SQL. (Of course, Tutorial D is a valid D; in fact, it was explicitly designed to be suitable as a vehicle for illustrating and teaching the ideas of The Third Manifesto.) Aside: This is as good a point as any to mention that the terminology used in the present book is based on that of the Manifesto. As a consequence, it does differ on occasion from that found in some of the design theory literature. For example, that literature typically doesn’t talk about relational headings; instead, it uses the term relation schema.4 Nor does it talk about relation variables (relvars); instead, what this book refers to as a (relation) value that’s assigned to some relation variable it calls an instance of the corresponding schema. End of aside. 3 Actually Tutorial D has been revised and extended somewhat since that book was first published. A description of the revised version (which is the version I’ll be using throughout the present book) can be found both in Database Explorations: Essays on The Third Manifesto and Related Topics, by C. J. Date and Hugh Darwen (Trafford, 2010) and on the website www.thethirdmanifesto.com (which, as its name suggests, also contains much current information regarding The Third Manifesto as such). 4 I mustn’t give the impression that headings and (relational) schemas are exactly the same thing. Rather, a schema is the combination of a heading and certain dependencies (including but not necessarily limited to functional and join dependencies in particular, which are discussed in detail later in this book).
Prerequisites / Chapter 2
21
Back to the relvar definitions. As you can see, each of those definitions includes a KEY specification, which means that every relation that might ever be assigned to any of those relvars is required to satisfy the corresponding key constraint. (Recall from Chapter 1 that every relvar does have at least one key.) For example, every relation that might ever be assigned to relvar S is required to satisfy the constraint that no two distinct tuples in that relation have the same SNO value. What’s more, I’m going to assume throughout this book, barring explicit statements to the contrary, that the following functional dependency (FD) also holds in relvar S: { CITY } → { STATUS } You can read this FD, informally, as STATUS is functionally dependent on CITY, or as CITY functionally determines STATUS, or more simply as just CITY arrow STATUS. What it means is that every relation that might ever be assigned to relvar S is required to satisfy the constraint that if two tuples in that relation have the same CITY value, then they must also have the same STATUS value.5 Observe that the sample value of relvar S given in Fig. 1.1 does indeed satisfy this constraint. Note: I’ll have a great deal more to say about FDs later in Parts II and III of this book, but I’m sure you’re already familiar with the basic idea anyway. Now, just as KEY specifications are used to declare key constraints, so we need some kind of syntax in order to be able to declare FD constraints. Tutorial D provides no specific syntax for that purpose, however6 (nor does SQL, come to that). It does allow them to be expressed in a somewhat roundabout fashion—for example: CONSTRAINT XCT COUNT ( S { CITY } ) = COUNT ( S { CITY , STATUS } ) ; Explanation: In Tutorial D, an expression of the form r{A1,...,An} denotes the projection of relation r on attributes A1, ..., An. If the current value of relvar S is s (a relation), therefore, (a) the expression S{CITY} denotes the projection of s on CITY; (b) the expression S{CITY,STATUS} denotes the projection of s on CITY and STATUS; and (c) the constraint overall—which I’ve named, arbitrarily, XCT—requires the cardinalities (COUNT) of those two projections to be equal. (If it’s not obvious that requiring these two counts to be equal is equivalent to requiring the desired FD constraint to hold, try interpreting it in terms of the sample data in Fig. 1.1.) Aside: In case you feel those appeals to COUNT in the formulation of constraint XCT are somehow a little inelegant, here’s an alternative formulation that avoids them: CONSTRAINT XCT WITH ( CT := S { CITY , STATUS } ) : AND ( JOIN { CT , CT RENAME { STATUS AS X } } , STATUS = X ) ; Explanation: First, the WITH specification (“WITH (…):”) serves merely to introduce a name, CT, that can be used repeatedly later in the overall expression to avoid having to write out several times the expression it stands for. Second, the Tutorial D RENAME operator is more or less self-explanatory (but is defined anyway, in the answer to Exercise 2.15 in Appendix D). Third, the Tutorial D expression AND(rx,bx),
5 This example of what FDs mean also serves to show why such dependencies are called functional. To elaborate: A function in mathematics is a mapping from one set A to some set B, not necessarily distinct from A, with the property that each element in A maps to just one element in B (but any number of distinct elements in A can map to the same element in B). In the example, therefore, we could say there’s a mapping from the set of CITY values in S to the set of STATUS values in S, and that mapping is indeed a mathematical function. 6 One reason it doesn’t is that if the design recommendations discussed in the present book are followed, there should rarely be a need to declare FDs explicitly anyway.
22
Chapter 2 / Prerequisites
where rx is a relational expression and bx is a boolean expression, returns TRUE if and only if the condition denoted by bx evaluates to TRUE for every tuple in the relation denoted by rx. End of aside. The foregoing state of affairs notwithstanding, I’ll assume throughout this book that FDs can be stated using the simpler arrow notation illustrated earlier. Analogous remarks apply to other kinds of dependencies also (in particular, to join dependencies and multivalued dependencies, which are introduced in Chapters 9 and 12, respectively). I’ll close this chapter with a little teaser. Assuming the only constraints that apply to the suppliers-and-parts database are the foregoing FD and the specified key (and foreign key) constraints, then we can say that relvars S, P, and SP are in second, fifth, and sixth normal form, respectively. To understand the significance of these observations, please read on!
EXERCISES The purpose of these exercises is to test your knowledge of relational theory. Most of them can’t be answered from material in the present chapter alone. However, everything mentioned here, and in the answers to these exercises in Appendix D, is discussed in detail in SQL and Relational Theory. 2.1
What’s The Information Principle?
2.2
Which of the following statements are true?
a.
Relations (and hence relvars) have no ordering to their tuples.
b.
Relations (and hence relvars) have no ordering to their attributes.
c.
Relations (and hence relvars) never have any unnamed attributes.
d.
Relations (and hence relvars) never have two or more attributes with the same name.
e.
Relations (and hence relvars) never contain duplicate tuples.
f.
Relations (and hence relvars) never contain nulls.
g.
Relations (and hence relvars) are always in 1NF.
h.
The types over which relational attributes are defined can be arbitrarily complex.
i.
Relations (and hence relvars) themselves have types.
2.3
Which of the following statements are true?
a.
Every subset of a heading is a heading.
b.
Every subset of a body is a body.
Prerequisites / Chapter 2
c.
23
Every subset of a tuple is a tuple.
2.4 The term domain is usually found in texts on relational theory, but it wasn’t mentioned in the body of the chapter. What do you make of this fact? 2.5
Define the terms proposition and predicate. Give examples.
2.6
State the predicates for relvars S, P, and SP from the suppliers-and-parts database.
2.7 Let DB be any database you happen to be familiar with and let R be any relvar in DB. What’s the predicate for R? Note: The point of this exercise is to get you to apply some of the ideas discussed in the body of this chapter to your own data, in an attempt to get you thinking about data in general in such terms. Obviously the exercise has no unique right answer. 2.8 Explain The Closed World Assumption in your own terms. Could there be such a thing as The Open World Assumption? 2.9
Give definitions, as precise as you can make them, of the terms tuple and relation.
2.10
State as precisely as you can what it means for (a) two tuples to be equal; (b) two relations to be equal.
2.11 A tuple is a set (a set of components); so do you think it might make sense to define versions of the usual set operators (union, intersection, etc.) that apply to tuples? 2.12 To repeat, a tuple is a set of components. But the empty set is a legitimate set; thus, we could define an empty tuple to be a tuple where the pertinent set of components is empty. What are the implications? Can you think of any uses for such a tuple? 2.13 A key is a set of attributes and the empty set is a legitimate set; thus, we could define an empty key to be a key where the pertinent set of attributes is empty. What are the implications? Can you think of any uses for such a key? 2.14 A predicate has a set of parameters and the empty set is a legitimate set; thus, a predicate could have an empty set of parameters. What are the implications? 2.15 The normalization discipline makes heavy use of the relational operators projection and join. Give definitions, as precise as you can make them, of these two operators. Also, have a go at defining the attribute renaming operator (RENAME in Tutorial D). 2.16
The operators of the relational algebra form a closed system. What do you understand by this remark?
Part II
FUNCTIONAL DEPENDENCIES, BOYCE/CODD NORMAL FORM, AND RELATED MATTERS
Although normal forms as such aren’t the whole of design theory, it’s undeniable that they’re a very large part of that theory, and they form the principal topic of Parts II and III of this book. The present part takes the story as far as Boyce/Codd normal form (BCNF), which is “the” normal form with respect to functional dependencies (FDs).
Chapter 3
Normalization: Some Generalities Normal: see abnormal —from an early IBM PL/I reference manual
In this chapter, I want to clarify certain general aspects of further normalization before we start getting into specifics (which we’ll do in the next chapter). I’ll begin by taking a closer look at the sample value of relvar S from Fig. 1.1 (repeated for convenience in Fig. 3.1 below). ┌───────┐ S ┌─────┬───────┬────▼───┬───┼────┐ │ SNO │ SNAME │ STATUS │ CITY │ ├═════┼───────┼────────┼────────┤ │ S1 │ Smith │ 20 │ London │ │ S2 │ Jones │ 30 │ Paris │ │ S3 │ Blake │ 30 │ Paris │ 20 │ London │ │ S4 │ Clark │ │ S5 │ Adams │ 30 │ Athens │ └─────┴───────┴────────┴────────┘ Fig. 3.1: The suppliers relvar—sample value
Recall now that the functional dependency (FD) { CITY } → { STATUS } holds in this relvar (I’ve included an arrow in the figure to suggest this fact). Because that FD holds,1 it turns out that the relvar is in second normal form (2NF) but not third (3NF). As a consequence, the relvar suffers from redundancy; to be specific, the fact that a given city has a given status appears many times, in general. And the discipline of further normalization—which from this point on I’ll abbreviate most of the time to just normalization, unqualified—would therefore suggest that we decompose the relvar into two relvars SNC and CT of lesser degree,
1
And, to be precise about the matter, because no other FDs hold apart from ones implied by the sole key {SNO}. See Chapter 4.
28
Chapter 3 / Normalization: Some Generalities
as indicated in Fig. 3.2 (which shows, of course, values for those relvars corresponding to the sample value shown for relvar S in Fig. 3.1). SNC ┌─────┬───────┬────────┐ │ SNO │ SNAME │ CITY │ ├═════┼───────┼────────┤ │ S1 │ Smith │ London │ │ S2 │ Jones │ Paris │ │ S3 │ Blake │ Paris │ │ S4 │ Clark │ London │ │ S5 │ Adams │ Athens │ └─────┴───────┴────────┘
CT ┌────────┬────────┐ │ CITY │ STATUS │ ├════════┼────────┤ 30 │ │ Athens │ │ London │ 20 │ │ Paris │ 30 │ └────────┴────────┘
Fig. 3.2: Relvars SNC and CT—sample values
Points arising from this example: n
First, the decomposition certainly eliminates the redundancy—the fact that a given city has a given status now appears exactly once.
n
Second, the decomposition process is basically a process of taking projections—the relations shown in Fig. 3.2 are each projections of the relation shown in Fig. 3.1.2 In fact, we can write a couple of equations: SNC CT
= =
S { SNO , SNAME , CITY } S { CITY , STATUS }
(Recall from Chapter 2 that the Tutorial D syntax for projection takes the form r{A1,...,An}, where r is some relational expression and A1, ..., An are attribute names.)3 n
Third, the decomposition process is nonloss (also called lossless)—no information is lost in the process, because the relation shown in Fig. 3.1 can be reconstructed by taking the join of the relations shown in Fig. 3.2: S
=
JOIN { SNC , CT }
(Tutorial D syntax again.) Thus, we can say the relation in Fig. 3.1 and the pair of relations in Fig. 3.2 are information equivalent—or, to state the matter more precisely, for any query that can be performed against the relation of Fig. 3.1, there’s a corresponding query that can be performed against the relations of Fig. 3.2
2 Other kinds of decomposition are possible, but I’ll assume until further notice that “decomposition,” unqualified, means decomposition via projection specifically. 3 Tutorial D also supports syntax of the form R{ALL BUT B1,...,Bm}, which denotes the projection of r on all of its attributes except B1, ..., Bm. For example, the projection corresponding to SNC in the example could alternatively be expressed thus: S {ALL BUT STATUS}.
Normalization: Some Generalities / Chapter 3
29
(and vice versa) that produces the same result. Clearly, such “losslessness” of decompositions is an important property; whatever we do by way of normalization, we certainly mustn’t lose any information when we do it. n
It follows from the foregoing that just as projection is the decomposition operator (with respect to normalization as conventionally understood), so join is the corresponding recomposition operator.
NORMALIZATION SERVES TWO PURPOSES So far, so good; this is all very familiar stuff. But now I want to point out that if you’ve been paying careful attention, you might reasonably accuse me of practicing a tiny (?) deception ... To be specific, I’ve considered what it means for a decomposition of relations to be nonloss; but normalization, which is what we’re supposed to be talking about, isn’t a matter of decomposing relations, it’s a matter of decomposing relvars. Suppose we do decide to perform the suggested decomposition of relvar S into relvars SNC and CT. Observe now that I really am talking about relvars and not relations; for definiteness, however, let’s assume those relvars have the sample values shown in Figs. 3.1 and 3.2, respectively. For definiteness again, let’s focus on relvar CT specifically. Well, that relvar is indeed a relvar—I mean, it’s a variable—and so we can update it. For example (using the shorthand notation for tuples introduced in Chapter 2), we might insert the tuple: ( ‘Rome’ , 10 ) But after that update, relvar CT contains a tuple that had no counterpart in relvar S (it doesn’t have a counterpart in relvar SNC either, come to that). Now, such a possibility is often used—indeed, Codd used it himself in his very first papers on normalization (see Appendix C)—as an argument in favor of doing the normalization in the first place: The normalized, two-relvar design is capable of representing certain information that the original one-relvar design isn’t. (In the case at hand, it can represent status information for cities that currently have no supplier located in them.) But that same fact also means that the two designs aren’t really information equivalent after all, and moreover that relvar CT isn’t exactly a “projection” of relvar S after all4—it contains a tuple that isn’t a projection of, or otherwise derived from, any tuple in relvar S.5 Or rather (and perhaps more to the point), CT isn’t a projection of the join of SNC and CT, either, and so that join “loses information,” in a sense; to be specific, it loses the information that the status for Rome is 10.6 A similar situation arises if we delete the tuple ( ‘S5’ , ‘Adams’ , ‘Athens’ )
4
See later in this section for an explanation of why I place the term “projection” in quotation marks here.
5
Regarding the idea that one tuple might be a projection of another, see the answer to Exercise 2.11 in Appendix D.
6
Joins such as that of SNC and CT are sometimes called lossy joins for this very reason. However, this term is probably best avoided, because it could also be used to refer to joins such as the join of the projections of S on{SNO,SNAME,STATUS} and {CITY,STATUS}, which lose information for a different reason. See the discussion of this latter example in Chapter 5; see also Exercise 3.2.
30
Chapter 3 / Normalization: Some Generalities
from relvar SNC. After that update, we could say, a trifle loosely,7 that relvar S contains a tuple that has no counterpart in relvar SNC (though it does have one in relvar CT). So again the two designs aren’t really information equivalent; and this time relvar S isn’t exactly a “join” of relvars SNC and CT, since it contains a tuple that doesn’t correspond to any tuple in relvar SNC. The two designs are thus not information equivalent after all. But didn’t I say earlier that “losslessness” of decompositions is an important property? Don’t we generally assume that if Design B is produced by normalizing Design A, then Design B and Design A are supposed to be information equivalent? What exactly is going on here? In order to answer these questions, it’s helpful to look at the relvar predicates. The predicate for SNC is: Supplier SNO is named SNAME and is located in city CITY. And the predicate for CT is: City CITY has status STATUS. Now suppose it’s possible for a city to have a status even if no supplier is located in that city; in other words, suppose it’s possible for relvar CT to contain a tuple such as (Rome,10) that has no counterpart in relvar SNC.8 Then the design consisting of just relvar S is simply incorrect. That is, if it’s possible for a true instantiation to exist of the predicate City CITY has status STATUS without there existing—at the same time and with the same CITY value—a true instantiation of the predicate Supplier SNO is named SNAME and is located in city CITY, then a design consisting just of relvar S doesn’t faithfully reflect the state of affairs in the real world (because that design is incapable of representing the status for a city in which no supplier is located). Similarly, suppose it’s possible for a supplier to be located in a city even if that city has no status; in other words, suppose it’s possible for relvar SNC to contain a tuple, say (S6,Lopez,Madrid), that has no counterpart in relvar CT. Then, again, the design consisting just of relvar S is simply incorrect, because it requires every city in which a supplier is located to have some status. Here’s another way to look at the foregoing argument. Suppose the design consisting just of relvar S did faithfully reflect the state of affairs in the real world after all. Then relvars SNC and CT would be subject to the following integrity constraint (“Every city in SNC appears in CT and vice versa”): CONSTRAINT ... SNC { CITY } = CT { CITY } ; But this constraint—which is an example of what I’m later going to be calling an equality dependency or EQD— manifestly isn’t satisfied in the example under discussion. Note: For simplicity, I haven’t bothered to give this constraint a name, as you can see. Indeed, I’ll omit such names from all of my examples in this book from this point forward, except where there’s some compelling reason to do otherwise. To sum up, we see that normalization can be (and is) used to address two rather different problems:
7
8
In effect, by pretending relvars S, SNC, and CT all coexist (living alongside one another, as it were).
Here I’m adopting a sloppy convention by which the single quotes that ought really to enclose character string values are omitted in regular text, thereby writing (Rome,10) instead of (‘Rome’,10). What’s more, I’ll adhere to this convention from this point forward.
Normalization: Some Generalities / Chapter 3
31
1.
It can be used to fix a logically incorrect design, as in the example discussed earlier in this section. Exercise: Do issues analogous to those raised in that example apply to the STP example from the section “The Place of Design Theory” in Chapter 1? (Answer: Yes, they do.)
2.
It can be used to reduce redundancy in an otherwise logically correct design. (Obviously a design doesn’t have to be logically incorrect in the foregoing sense in order to display redundancy.)
Much confusion arises in practice because these two cases are often not clearly distinguished. Indeed, most of the literature focuses on Case 2—and for definiteness I’ll assume Case 2 myself in what follows, where it makes any difference—but please don’t lose sight of Case 1, which in practice is at least as important, if not more so. I should point out further that, strictly speaking, the terminology of projections and joins applies only to Case 2. That’s because in Case 1, as we’ve seen, the “new” relvars aren’t necessarily projections of the “old” one, nor is the “old” one necessarily the join of the “new” ones (if you see what I mean). In fact, what does it mean to talk about projections and joins of relvars (as opposed to relations) anyway? Well, as I’ve written elsewhere:9 By definition, the operators projection, join, and so on apply to relation values specifically. In particular, of course, they apply to the values that happen to be the current values of relvars. It thus clearly makes sense to talk about, e.g., the projection of relvar S on attributes {CITY,STATUS}, meaning the relation that results from taking the projection on those attributes of the relation that’s the current value of that relvar S. In some contexts, however (normalization, for example), it turns out to be convenient to use expressions like “the projection of relvar S on attributes {CITY,STATUS}” in a slightly different sense. To be specific, we might say, loosely but very conveniently, that some relvar, CT, is the projection of relvar S on attributes {CITY,STATUS}—meaning, more precisely, that the value of relvar CT at all times is the projection on those attributes of the value of relvar S at the time in question. In a sense, therefore, we can talk in terms of projections of relvars per se, rather than just in terms of projections of current values of relvars. Analogous remarks apply to all of the relational operations.
In other words, we do still use the projection/join terminology, even in Case 1. Such talk is somewhat inappropriate—not to say sloppy—but it is at least succinct. But it would really be more accurate to say, not that decomposition is a process of taking projections as such, but rather that it’s a process that’s reminiscent of, but not quite the same as, what we do when we take projections (and similarly for recomposition and join).
UPDATE ANOMALIES The concept of update anomalies is frequently mentioned in connection with normalization. Now, it should be clear that redundancy of any kind can always lead to anomalies—because redundancy means, loosely, that some piece of information is represented twice, and so there’s always the possibility that the two representations don’t agree (i.e., if one is updated and the other isn’t). More specifically, let’s consider the case of relvar S, where the following FD holds:
9
E.g., in The Relational Database Dictionary, Extended Edition (Apress, 2008).
32
Chapter 3 / Normalization: Some Generalities
{ CITY } → { STATUS } The redundancy, as such, that this FD gives rise to—viz., the fact that a given city has a given status appears many times—has already been discussed. It leads to anomalies like the following (these examples assume the sample value shown for relvar S in Fig. 3.1.): n
Insertion anomaly: We can’t insert the fact that the status for Rome is 10 until there’s a supplier in Rome.
n
Deletion anomaly: If we delete the only supplier in Athens, we lose the fact that the status for Athens is 30.
n
Modification anomaly: We can’t change (“modify”) the city for a given supplier without changing the status for that supplier as well (in general). Likewise, we can’t modify the status for a given supplier without making the same modification for all suppliers in the pertinent city.
Replacing relvar S by the two “projection” relvars SNC and CT solves these problems (how, exactly?). Moreover, let me state for the record that relvar S is (as previously noted) in second normal form and not third, while relvars SNC and CT are both in third normal form, and in fact in BCNF as well. In general, BCNF is the solution to the problems caused by the kinds of anomalies listed above.
THE NORMAL FORM HIERARCHY As you know, there are many different normal forms. Fig. 3.3 is our first take on the normal form hierarchy (but please note immediately that I’ll be expanding the hierarchy later in this book—in Chapter 13, to be specific). Note: You might think the hierarchy is upside down, since it shows the highest normal form at the bottom and the lowest at the top. I don’t want to argue the point; let me just say that showing it the way the figure does fits better (in my view) with the fact that, e.g., all 2NF relvars are in 1NF but some 1NF relvars aren’t in 2NF. To elaborate on the figure: n
There are several different normal forms: first, second, third, and so on. The figure shows six such, but as you can see they aren’t labeled first, ..., sixth (not quite)—there’s an interloper, BCNF, between third and fourth.10 I’ll explain the reason for this terminological oddity in Chapter 4; for now, let me just say that the name BCNF is short for Boyce/Codd normal form. Note: Despite the BCNF exception, it’s convenient to use the term nth normal form to refer generically to the different levels of normalization, and I’ll adopt that usage from time to time in what follows.
n
In general, the higher the level of normalization the better, from a design point of view—because the higher the level of normalization, the more redundancies are prevented and the fewer update anomalies can occur.
10 There’s also a gap between BCNF and 4NF, to reflect the fact that there’s a kind of conceptual jump in the hierarchy between the first four normal forms and the last two. See Part III of this book.
Normalization: Some Generalities / Chapter 3
33
1NF 2NF 3NF BCNF 4NF 5NF BCNF and 5NF are the important ones (at least until further notice) Fig. 3.3: The normal form hierarchy (I)
n
All of the normal forms apart from 1NF are defined in terms of certain dependencies (in this context, just another term for integrity constraints). The principal dependencies are functional dependencies (FDs) and join dependencies (JDs). Note: The terms dependence and dependency are used interchangeably in the literature. I’ll stick with dependency in this book.
n
To elaborate briefly on the previous point: FDs are the basis for defining BCNF, and JDs are the basis for defining 5NF. As the figure states, BCNF and 5NF are the most important normal forms (at least until further notice).
n
It’s possible for a relvar to be in nth normal form and not in (n+1)st (n = 1, …, 4).
n
If relvar R is in (n+1)st normal form, then it’s certainly in nth (n = 1, …, 4). In other words, fifth normal form (5NF) implies fourth normal form (4NF), and so on. It follows that to say that, e.g., relvar R is in BCNF doesn’t preclude the possibility that R is in 5NF as well. In practice, however, it’s common for statements to the effect that relvar R is in, say, BCNF to be taken to mean that R is in BCNF and not in any higher normal form. Please note carefully, therefore, that I do not adopt this usage in this book.
n
If relvar R is in nth normal form and not in (n+1)st (n = 1, …, 4), then it can always be decomposed via projection, in a nonloss way, such that (a) the projections are, typically, in (n+1)st normal form and (b) R is equal to the join of those projections.
n
Finally, it follows from the previous point that any given relvar R can always be decomposed into 5NF projections in particular. In other words, 5NF is always achievable.
A note on the concept of redundancy: In Chapter 1, I said design theory is largely about reducing redundancy, and I’ve referred to the concept repeatedly in the present chapter; in particular, I’ve said the higher the level of normalization, the more redundancy is prevented. But coming up with a precise definition of redundancy seems to be quite difficult—much more so, in fact, than I think is appropriate for this early point in the book. For
34
Chapter 3 / Normalization: Some Generalities
that reason, I’m not even going to try to define it here; I’m just going to assume until further notice that we can at least recognize it when we see it (though even that’s a pretty big assumption, actually). Chapter 15 examines the concept in depth.
NORMALIZATION AND CONSTRAINTS There’s another issue that arises in connection with normalization, one that’s often overlooked. Again consider the example of decomposing relvar S into its projections SNC on {SNO,SNAME,CITY} and CT on {CITY,STATUS}. Then there are three cases to consider: 1.
Suppose the original design, consisting of just relvar S, was at least logically correct (i.e., it merely suffered from redundancy). As I pointed out in the section “Normalization Serves Two Purposes,” then, there’s a certain constraint (an “equality dependency”) that holds between the two projections: CONSTRAINT ... SNC { CITY } = CT { CITY } ; (“every city in SNC appears in CT and vice versa”).
2.
Alternatively, suppose as we did earlier that it’s possible for CT to contain a tuple such as (Rome,10) that has no counterpart in SNC. Moreover, suppose it’s not possible for the converse to be true—SNC can never contain a tuple that has no counterpart in CT. In that case, a foreign key constraint holds between those two projections (from SNC to CT): FOREIGN KEY { CITY } REFERENCES CT
3.
The third possibility (perhaps less likely than the first two) is that CT and SNC might both be allowed to contain tuples with no counterpart in the other. For example, it might be the case that—let’s say—supplier S6, with name Lopez, is located in Madrid but Madrid has no status. In this case a perfectly reasonable design would involve the appearance of the tuple (S6,Lopez,Madrid) in SNC without the appearance of a tuple for Madrid in CT; clearly, therefore, no constraint involving cities holds between the two relvars at all (at least, let’s agree not for the sake of the example).
Now, simplifying somewhat, I’ve said that a relvar R in nth normal form can always be nonloss decomposed into projections in (n+1)st normal form. As the foregoing discussion indicates, however, such decomposition usually means there’s at least one new constraint that now needs to be maintained. What makes matters worse is that the constraint in question is a multirelvar constraint (i.e., it spans two relvars, or possibly more than two). So there’s a tradeoff: Do we want the benefits of decomposition, or do we want to avoid that multirelvar constraint?11
11 Of course, maintaining that constraint, if it has to be done, should be done by the system and not the user─but the constraint will at least have to be defined, and users will have to be aware of it.
Normalization: Some Generalities / Chapter 3
35
Aside: It might be argued, at least in the SNC and CT example, that the decomposition also means there’s a constraint that now doesn’t have to be maintained: viz., the FD {CITY} → {STATUS}. But this argument isn’t entirely valid—all the decomposition does, in this respect, is move that constraint from one relvar to another (actually from relvar S to relvar CT, where it’s maintained as a side effect of maintaining the constraint that {CITY} is a key). End of aside. Now, in the simple example under discussion, the benefits of doing the decomposition almost certainly outweigh the benefits of not doing so. But such is not always the case; indeed, the question of whether or not to decompose, in more complicated situations, can be a fairly vexing one. In what follows, in order to avoid a lot of repetitive text, I’ll tend to assume we do always want to do the decomposition—but please don’t forget there can sometimes be persuasive arguments for not doing so, especially in examples more complex than the one at hand, such as are discussed in Part III of this book.
CONCLUDING REMARKS I’d like to close this chapter by addressing a question I haven’t discussed in this book at all so far. It’s a matter of terminology. To be specific: Why are 1NF, 2NF, and the rest called normal forms, anyway? Come to that, why is normalization called normalization? The answers to these questions derive from mathematics (though the ideas spill over into several related disciplines, including the computing discipline in particular—think of floating point numbers, for example). In mathematics, we often find ourselves having to deal with some large, possibly even infinite, set of objects of some kind: for example, the set of all matrices, or the set of all rational numbers, or—coming a little closer to home—the set of all relations. In such a situation, it’s desirable to find a set of canonical forms for the objects in question. Here’s a definition: n
Definition: Given a set s1, together with a defined notion of equivalence among elements of that set, subset s2 of s1 is a set of canonical forms for s1 if and only if every element x1 of s1 is equivalent to just one element x2 of s2 under that notion of equivalence (and that element x2 is the canonical form for the element x1).12 Various “interesting” properties that apply to x1 also apply to x2; thus, we can study just the small set s2, not the large set s1, in order to prove a variety of “interesting” theorems or results.
As a trivial illustration of this notion, let s1 be the set of nonnegative integers {0,1,2,...}, and let two such integers be equivalent if and only if they leave the same remainder on division by five. Then we can define s2 to be the set {0,1,2,3,4}. As for an “interesting” theorem that applies in this example, let x1, y1, and z1 be any three elements of s1 (i.e., any three nonnegative integers), and let their canonical forms in s2 be x2, y2, and z2, respectively; then the product y1 * z1 is equivalent to x1 if and only if the product y2 * z2 is equivalent to x2.
12 It’s reasonable to require also that every element x2 of s2 be equivalent to at least one element x1 of s1. Let me also draw your attention to the following remarks, paraphrased from the answer to Exercise 2.3 in Appendix D: Throughout this book, expressions of the form “B is a subset of A” must be understood to include the possibility that B and A might be equal. For example, the set {x,y,z} is a subset of itself. When I want to exclude such a possibility, I’ll talk explicitly in terms of proper subsets; for example, the set {x,z} is a proper subset of the set {x,y,z}. Of course, no set is a proper subset of itself.
36
Chapter 3 / Normalization: Some Generalities
Now, normal form is just another term for canonical form. So when we talk about normal forms in the database context, we’re talking about a canonical representation for data. To spell the point out: Any given collection of data can be represented relationally in many different ways, as we know. Of course, all of those ways are—in fact, must be—information equivalent; that is, information equivalence is the kind of equivalence we appeal to in this particular context. However, some of those ways (of representing the given information) are preferred over others for various reasons. And those preferred ways are, of course, the relational normal forms that are the subject of much of this book. As for the term normalization, it simply refers to the general process of mapping some given object into its canonical equivalent. In the database context in particular, therefore, it’s used (as we know) to refer to the process of mapping some given relvar into a collection of relvars that (a) when considered together, are information equivalent to the original relvar, but (b) are each individually in some preferred normal form. To the foregoing I should perhaps add the following. As far as I know, Codd himself never mentioned, in his early writings on the subject, his reasons for introducing the terminology of normal forms or normalization. But many years afterward, he did go on record with his own explanation:13 Interviewer: Where did “normalization” come from? Codd: It seemed to me essential that some discipline be introduced into database design. I called it normalization because then President Nixon was talking a lot about normalizing relations with China. I figured that if he could normalize relations, so could I.
EXERCISES 3.1 Consider the STP example from the section “The Place of Design Theory” in Chapter 1. Give examples of the update anomalies that can arise with that example. Also give an appropriate decomposition, and show how that decomposition avoids those anomalies. Nonloss decomposition is based on the idea that a relation can be decomposed into projections in such a way 3.2 that the original relation can be recovered by joining those projections back together again. In fact, if projections r1 and r2 of relation r are such that every attribute of r is retained in at least one of r1 and r2, then joining r1 and r2 will always produce every tuple of r. Prove this assertion. (It follows from this fact that the problem with a decomposition that’s not nonloss isn’t that the join loses tuples—rather, it’s that it produces additional, or “spurious,” tuples. Since we have no way in general of knowing which if any of the tuples in the join are spurious and which are genuine, the decomposition has lost information.) 3.3 “Normalization serves two purposes.” Explain this remark in your own words. Do you think the point is widely understood?
13
In “A Fireside Chat: Interview with Dr. Edgar F. Codd” (DBMS Magazine 6, No. 13, December 1993).
Chapter 4
FDs and BCNF (Informal) It is downright sinful to teach the abstract before the concrete —Z. A. Melzak: Companion to Concrete Mathematics
As we saw in the previous chapter, Boyce/Codd normal form (BCNF for short) is defined in terms of functional dependencies. In fact, BCNF is really the normal form with respect to functional dependencies (just as—to get ahead of ourselves for a moment—5NF is really the normal form with respect to join dependencies). The overall purpose of the present chapter is to explain this observation; as the chapter title indicates, however, the various explanations and associated definitions are all (intentionally, of course) a little informal at this stage. (Informal, but not inaccurate; I won’t tell any deliberate lies.) A more formal treatment of the material appears in the next chapter. FIRST NORMAL FORM To begin at the beginning: Let relation r have attributes A1, ..., An, of types T1, ..., Tn, respectively. By definition, then, if tuple t appears in relation r, then the value of attribute Ai in t is of type Ti (i = 1, ..., n). For example, if r is the current value of the shipments relvar SP (see Fig. 1.1 in Chapter 1), then every tuple in r has an SNO value that’s of type CHAR, a PNO value that’s also of type CHAR, and a QTY value that’s of type INTEGER. Now I can give a precise definition of first normal form:1 n
Definition: Let relation r have attributes A1, ..., An, of types T1, ..., Tn, respectively. Then r is in first normal form (1NF) if and only if, for all tuples t appearing in r, the value of attribute Ai in t is of type Ti (i = 1, ..., n).
In other words, every relation is in 1NF, by definition! To say it in different words, 1NF just means each tuple in the relation contains exactly one value, of the appropriate type, for each attribute. Observe in particular that 1NF places no limitations on what those attribute types are allowed to be.2 They can even be relation types; that is, relations with relation valued attributes—RVAs for short—are legal (you might be surprised to hear this, but it’s true). An example is given in Fig. 4.1.
1 One reviewer accused me of rewriting history with this definition. Guilty as charged, perhaps─but I do have my reasons; to be specific, earlier “definitions” of the concept were all, in my opinion, either too vague to be useful or flat out wrong. See SQL and Relational Theory for further discussion. 2 The relational model does, though. To paraphrase the answer to Exercise 2.2 in Appendix D, there are two small exceptions, both of which I’ll simplify just slightly here: First, no relation in the database can have an attribute of any pointer type; second, if relation r is of type T, then no attribute of r can itself be of type T (think about it!). However, these exceptions have nothing to do with 1NF as such.
38
Chapter 4 / FDs and BCNF (Informal)
┌─────┬─────────────┐ │ SNO │ PQ │ ├═════┼─────────────┤ .. ......... │ │┌─────┬─────┐│ │ S2 ││ PNO │ QTY ││ │ │├═════┼─────┤│ │ ││ P1 │ 300 ││ │ ││ P2 │ 400 ││ │ │└─────┴─────┘│ │ │┌─────┬─────┐│ │ S3 ││ PNO │ QTY ││ │ │├═════┼─────┤│ │ ││ P2 │ 200 ││ │ │└─────┴─────┘│ .. ......... └─────┴─────────────┘ Fig. 4.1: A relation with a relation valued attribute
I’ll have more to say about RVAs in just a moment, but first I need to get a couple of small points out of the way. To start with, I need to define what it means for a relation to be normalized: n
Definition: Relation r is normalized if and only if it’s in 1NF.
In other words, normalized and first normal form mean exactly the same thing—all normalized relations are in 1NF, all 1NF relations are normalized. The reason for this slightly strange state of affairs is that normalized was the original (historical) term; the term 1NF wasn’t introduced until people started talking about 2NF and higher levels of normalization, when a term was needed to describe relations that weren’t in one of those higher normal forms. Of course, it’s common nowadays for the term normalized to be used to mean some higher normal form (often 3NF specifically); indeed, I’ve used it that way myself in earlier chapters, as you might have noticed. Strictly speaking, however, that usage is sloppy and incorrect, and it’s probably better avoided unless there’s no chance of confusion. Turning to my second “small point”: Observe now that all of the discussions in this section so far (the definitions in particular) have been framed in terms of relations, not relvars. But since every relation that can ever be assigned to a relvar is in 1NF by definition, no harm is done if we extend the 1NF concept in the obvious way to apply to relvars as well—and it’s desirable to do so, because (as we’ll see) all of the other normal forms are defined to apply to relvars, not relations. In fact, it could be argued that the reason 1NF is defined in terms of relations and not relvars has to do with the fact that it was, regrettably, many years before that distinction (i.e., the distinction between relations and relvars) was explicitly drawn, anyway. Back to RVAs. I’ve said, in effect, that relvars with RVAs are legal; but now I need to add that from a design point of view, at least, such relvars are usually (not always) contraindicated. Now, this fact doesn’t mean you should avoid RVAs entirely (in particular, there’s no problem with query results that include RVAs)—it just means we don’t usually want RVAs “designed into the database,” as it were. I don’t want to get into a lot of detail on this issue in this book; let me just say that relvars with RVAs tend to look very much like the hierarchic structures found in older, nonrelational systems like IMS,3 and all of the old problems that used to arise with hierarchies therefore raise their head once again. Here for reference is a list of some of those problems:
3
And, perhaps more to the point, newer ones like XML (see Exercise 4.12).
FDs and BCNF (Informal) / Chapter 4
39
n
The fundamental point is that hierarchies are asymmetric; thus, while they might make some tasks “easier,” they certainly make others more difficult.
n
As a specific illustration of the previous point, queries in particular are asymmetric, as well as being more complicated than their symmetric counterparts. For example, consider what’s involved in formulating the queries “Get part numbers for parts supplied by supplier S2” and “Get supplier numbers for suppliers who supply part P2” against the relation of Fig. 4.1. The natural language versions of these queries are symmetric with respect to each other, but their formulations in SQL—or Tutorial D, or some other formal language— most certainly aren’t (exercise for the reader).
n
Similar remarks apply to integrity constraints.
n
Similar remarks apply to updates, but more so.
n
There’s no guidance, in general, as to how to choose the “best” hierarchy.
n
Even “natural” hierarchies like organization charts and bill of materials structures are still best represented, usually, by nonhierarchic designs.
Well, by now you might be wondering, if all relvars are in 1NF by definition, what it might possibly mean not to be in 1NF. Perhaps surprisingly, this question does have a sensible answer. The point is, today’s commercial DBMSs don’t properly support relvars (or relations) at all—instead, they support a construct that for convenience I’ll call a table, though by that term I don’t necessarily mean to limit myself to the kinds of tables found in SQL systems specifically. And tables, as opposed to relvars, might indeed not be in 1NF. To elaborate: n
Definition: A table is in first normal form (1NF)—equivalently, such a table is normalized—if and only if it’s a direct and faithful representation of some relvar.
So of course the question is: What does it mean for a table to be a direct and faithful representation of a relvar? There are five basic requirements, all of which are immediate consequences of the fact that the value of a relvar at any given time is (of course) always a relation specifically: 1.
There’s no top to bottom ordering to the rows.
2.
There’s no left to right ordering to the columns.
3.
There are no duplicate rows.
4.
Every row and column intersection contains exactly one value of the applicable type, and nothing else.
5.
All columns are regular (see below).
Requirements 1-3 are self-explanatory,4 but the other two merit a little more explanation, perhaps. Here’s an example of a table that violates Requirement 4: 4
Though I note in passing that Requirement 2 in particular effectively means SQL tables are never normalized─except, possibly, if they happen to have just one column. However, the disciplines recommended in SQL and Relational Theory allow you, among other things, to treat such tables (for the most part) as if they were normalized after all.
40
Chapter 4 / FDs and BCNF (Informal)
┌─────┬──────────────┐ │ SNO │ PNO │ ├═════┼──────────────┤ │ S1 │ P1 , P2 │ │ S1 │ P2 │ │ S1 │ P2 , P4 , P5 │ └─────┴──────────────┘ The violation occurs because values in the PNO column aren’t individual part numbers as such but, rather, groups of part numbers (the group for S2 contains two part numbers, that for S3 contains one, and that for S4 contains three). Note: The violation of Requirement 4 in the foregoing example would perhaps be clearer if column PNO, instead of being defined to be of type CHAR, was defined to be of some user defined type, perhaps also called PNO. Then it might be more obvious that values in that column weren’t of that type per se but were rather of type “PNO group.” Such considerations point the way to a reasonably precise definition of the term repeating group: n
Definition: Column C is a repeating group column (also known as a multivalued attribute) if and only if it’s defined to be of type T but the values that appear in that column aren’t values of type T but are, rather, groups (in other words, sets or lists or arrays or ...) of values of type T.
If you’re still confused over the difference between repeating group columns and RVAs, take another look at Fig. 4.1. The RVA in that figure—viz., attribute PQ—is not a repeating group column (relations don’t allow repeating groups!). Rather, it’s an attribute whose type happens to be a certain relation type—to be specific, and using Tutorial D syntax, the relation type RELATION { PNO CHAR , QTY INTEGER } —and values of that attribute are, precisely, relations of this type. So the relation in that figure does abide by the definition of 1NF. Incidentally, Requirement 4 also means nulls are prohibited (nulls aren’t values). Turning now to Requirement 5 (“All columns are regular”): What this requirement means is, first, that every column has a name, unique among the column names that apply to the table in question; second, that no row is allowed to contain anything extra, over and above the regular column values prescribed under Requirement 4. For example, there are no “hidden” columns that can be accessed only by special operators instead of by regular column references (i.e., by column name), and there are no columns that cause invocations of regular operators on rows to have irregular effects. In particular, therefore, there are no identifiers other than regular key values (no hidden row IDs or “object IDs,” as are unfortunately found in some SQL products today), and no hidden timestamps as are found in certain “temporal database” proposals in the literature. To sum up: If any of the five requirements are violated, the table in question doesn’t “directly and faithfully” represent a relvar, and all bets are off. In particular, relational operators such as join are no longer guaranteed to work as expected (as you’ll already know if, as I assume, you’re familiar with SQL). The relational model deals with relations (meaning, more precisely, relation values and relation variables), and relations only.
FUNCTIONAL DEPENDENCIES So much for 1NF; now I can begin to discuss some of the higher normal forms. Now, I’ve already said that Boyce/Codd normal form (BCNF) is defined in terms of functional dependencies, and in fact the same is true of second normal form (2NF) and third normal form (3NF) as well. Here then is a definition:
FDs and BCNF (Informal) / Chapter 4
n
41
Definition: Let X and Y be subsets of the heading of relvar R; then the functional dependency (FD) X→Y holds in R if and only if, whenever two tuples of R agree on X, they also agree on Y. X and Y are the determinant and the dependant, respectively, and the FD overall can be read as either “X functionally determines Y” or “Y is functionally dependent on X,” or more simply just as “X arrow Y.”
For example, the FD {CITY} → {STATUS} holds in relvar S, as we know. Note the braces, by the way; X and Y in the definition are subsets of the heading of R, and are therefore sets (of attributes), even when, as in the example, they happen to be singleton sets. By the same token, X and Y values are tuples, even when, as in the example, they happen to be tuples of degree one. By way of another example, the FD {SNO} → {SNAME,STATUS} also holds in relvar S, because {SNO} is a key—in fact, the only key—for that relvar, and there are always “arrows out of keys” (see the section “Keys” immediately following this one). Note: In case it isn’t obvious, I use the term “arrow out of X” to mean there exists some Y such that the FD X → Y holds in the pertinent relvar (where X and Y are subsets of the heading of that relvar). + Now here’s a useful thing to remember: If the FD X → Y holds in relvar R, then the FD X → Y also holds + + in relvar R for all supersets X of X and all subsets Y of Y (just so long as X is still a subset of the heading, of course). In other words, you can always add attributes to the determinant or subtract them from the dependant, and what you get will still be an FD that holds in the relvar in question. For example, here’s another FD that holds in relvar S: { SNO , CITY } → { STATUS } (I started with the FD {SNO} → {SNAME,STATUS}, added CITY to the determinant, and dropped SNAME from the dependant.) I also need to explain what it means for an FD to be trivial: n
Definition: The FD X → Y is trivial if and only if there’s no way it can be violated. For example, the following FDs all hold trivially for any relvar with attributes called STATUS and CITY:5 { { { {
CITY CITY CITY CITY
, STATUS } → { , STATUS } → { } → { } → {
CITY } STATUS } CITY } }
To elaborate briefly (but considering just the first of these examples, for simplicity): If two tuples have the same value for CITY and STATUS, they certainly have the same value for CITY. In fact, it’s easy to see the FD X → Y is trivial if and only if Y is a subset of X. Now, when we’re doing database design, we don’t usually bother with trivial FDs because they’re, well, trivial; but when we’re trying to be formal and precise about these matters—
5
In connection with the last of these examples in particular, see Exercise 4.10.
42
Chapter 4 / FDs and BCNF (Informal)
in particular, when we’re trying to develop a theory of design—then we need to take all FDs into account, trivial ones as well as nontrivial.
KEYS REVISITED I discussed the concept of keys in general terms in Chapter 1, but it’s time to get a little more precise about the matter and to introduce some more terminology. First, here for the record is a precise definition of the term candidate key: n
Definition: Let K be a subset of the heading of relvar R. Then K is a candidate key (or just key for short) for R if and only if it possesses both of the following properties: 1.
Uniqueness: No valid value for R contains two distinct tuples with the same value for K.
2.
Irreducibility: No proper subset of K has the uniqueness property.
Aside: This is the first definition we’ve encountered that involves some kind of irreducibility, but we’ll meet several more in the pages ahead—irreducibility of one kind or another is ubiquitous, and important, throughout the field of design theory in general, as we’ll see. Regarding key irreducibility in particular, one reason (not the only one) why it’s important is that if we were to specify a “key” that wasn’t irreducible, the DBMS wouldn’t be able to enforce the proper uniqueness constraint. For example, suppose we told the DBMS (lying!) that {SNO,CITY} was a key, and in fact the only key, for relvar S. Then the DBMS couldn’t enforce the constraint that supplier numbers are “globally” unique; instead, it could enforce only the weaker constraint that supplier numbers are “locally” unique, in the sense that they’re unique within the pertinent city. End of aside. I’m not going to discuss the foregoing definition any further here, since the concept is so familiar6—but observe how the next few definitions depend on it: n
Definition: A key attribute for relvar R is an attribute of R that’s part of at least one key of R.
n
Definition: A nonkey attribute for relvar R is an attribute of R that’s not part of any key of R.7
For example, in relvar SP, SNO and PNO are key attributes and QTY is a nonkey attribute. n
Definition: A relvar is “all key” if and only if the entire heading is a key (in which case it’s the only key, necessarily)—equivalently, if and only if no proper subset of the entire is a key. Note: If a relvar is “all key,” then it certainly has no nonkey attributes, but the converse is false—a relvar can be such that all of its attributes are key attributes and yet not be “all key” (right?).
6 Do note, however, that there’s no suggestion that relvars have just one key. Au contraire, in fact: A relvar can have any number of distinct keys, subject only to a limit that’s a logical consequence of the degree of the relvar in question. See Exercise 4.9. 7 As a historical note, I remark that key and nonkey attributes were called prime and nonprime attributes, respectively, in Codd’s original normalization papers (see Appendix C).
FDs and BCNF (Informal) / Chapter 4
n
43
Definition: Let SK be a subset of the heading of relvar R. Then SK is a superkey for R if and only if it possesses the following property: 1.
Uniqueness: No valid value for R contains two distinct tuples with the same value for SK.
More succinctly, a superkey for R is a subset of the heading of R that’s unique but not necessarily irreducible. In other words, we might say, loosely, that a superkey is a superset of a key (“loosely,” because of course the superset in question must still be a subset of the pertinent heading). Observe, therefore, that all keys are superkeys, but “most” superkeys aren’t keys. Note: A superkey that isn’t a key is sometimes said to be a proper superkey. It’s convenient to define the notion of a subkey also: n
Definition: Let SK be a subset of the heading of relvar R. Then SK is a subkey for R if and only if it’s a subset of at least one key of R. Note: A subkey that isn’t a key is sometimes said to be a proper subkey.
By way of example, consider relvar SP, which has just one key, {SNO,PNO}. That relvar has: a.
Two superkeys: { SNO , PNO } { SNO , PNO , QTY } Note that the heading is always a superkey for any relvar R.
b.
Four subkeys: { { { {
SNO , PNO } SNO } PNO } }
Note that the empty set of attributes is always a subkey for any relvar R. To close this section, note that if H and SK are the heading and a superkey, respectively, for relvar R, then the FD SK → H holds in R, necessarily; equivalently, the FD SK → Y holds in R for all subsets Y of H. The reason is that if two tuples of R have the same value for SK, then they must in fact be the very same tuple, in which case they obviously must have the same value for Y. Of course, all of these remarks apply in the important special case in which SK is not just a superkey but a key; as I put it earlier (very loosely, of course), there are always arrows out of keys. In fact, we can now make a more general statement: There are always arrows out of superkeys.
SECOND NORMAL FORM I need to introduce one more concept, FD irreducibility (a second kind of irreducibility, observe), before I can get on to the definitions of 2NF, 3NF, and BCNF: n
Definition: The FD X → Y is irreducible with respect to relvar R (or just irreducible, if R is understood) if and only if it holds in R and X → Y doesn’t hold in R for any proper subset X of X.
44
Chapter 4 / FDs and BCNF (Informal)
For example, the FD {SNO,PNO} → {QTY} is irreducible with respect to relvar SP. Note: This kind of irreducibility is sometimes referred to more explicitly as left irreducibility (since it’s really the left side of the FD that we’re talking about), but I’ve chosen to elide that “left” here for simplicity. Now—at last, you might be forgiven for thinking—I can define 2NF: n
Definition: Relvar R is in second normal form (2NF) if and only if, for every key K of R and every nonkey attribute A of R, the FD K → {A} (which holds in R, necessarily) is irreducible.
Note: The following definition is logically equivalent to the one just given (see Exercise 4.5 at the end of the chapter) but can sometimes be more useful: n
Definition: Relvar R is in second normal form (2NF) if and only if, for every nontrivial FD X → Y that holds in R, at least one of the following is true: (a) X is a superkey; (b) Y is a subkey; (c) X is not a subkey. Points arising:
n
It would be extremely unusual to regard 2NF as the ultimate goal of the design process. In fact, both 2NF and 3NF are mainly of historical interest; they’re both regarded at best as stepping stones on the way to BCNF, which is of much more pragmatic (as well as theoretical) interest.
n
Definitions of 2NF in the literature often take the form “R is in 2NF if and only if it’s in 1NF and ... .” However, such definitions are usually based on a mistaken understanding of what 1NF is. As we’ve seen, all relvars are in 1NF, and the words “it’s in 1NF and” therefore add nothing.
Let’s look at an example. Actually, it’s usually more instructive with the normal forms to look at a counterexample rather than an example per se. Consider, therefore, a revised version of relvar SP—let’s call it SCP—that has an additional attribute CITY, representing the city of the applicable supplier. Here are some sample tuples: ┌─────┬────────┬─────┬─────┐ │ PNO │ QTY │ SCP │ SNO │ CITY ├═════┼────────┼═════┼─────┤ │ S1 │ London │ P1 │ 300 │ │ S1 │ London │ P2 │ 200 │ │ S1 │ London │ P3 │ 400 │ │ .. │ ...... │ .. │ ... │ │ S2 │ Paris │ P1 │ 300 │ │ S2 │ Paris │ P2 │ 400 │ │ .. │ ...... │ .. │ ... │ This relvar clearly suffers from redundancy: Every tuple for supplier S1 tells us S1 is in London, every tuple for supplier S2 tells us S2 is in Paris, and so on. And the relvar isn’t in 2NF—its sole key is {SNO,PNO}, and the FD {SNO,PNO} → {CITY} therefore certainly holds, but that FD isn’t irreducible: We can drop PNO from the determinant and what remains, {SNO} → {CITY}, is still an FD that holds in the relvar. Equivalently, we can say the FD {SNO} → {CITY} holds and is nontrivial; moreover, (a) {SNO} isn’t a superkey, (b) {CITY} isn’t a subkey, and (c) {SNO} is a subkey, and so—appealing now to the second of the definitions given above—the relvar isn’t in 2NF.
FDs and BCNF (Informal) / Chapter 4
45
THIRD NORMAL FORM n
Definition: Relvar R is in third normal form (3NF) if and only if, for every nontrivial FD X → Y that holds in R, either (a) X is a superkey or (b) Y is a subkey. Points arising:
n
To repeat something I said in the previous section (and contrary to popular opinion, perhaps), 3NF is mainly of historical interest—it should be regarded at best as no more than a stepping stone on the way to BCNF. Note: The reason I say contrary to popular opinion, perhaps is that many of the “definitions” of 3NF commonly found (at least those in the popular literature) are actually definitions of BCNF—and BCNF, as I’ve already indicated, is important. Caveat lector.
n
Definitions of 3NF in the literature often take the form “R is in 3NF if and only if it’s in 2NF and ...”; I prefer a definition that makes no mention of 2NF. Note, however, that my definition of 3NF can in fact be derived from the second of the definitions I gave for 2NF by dropping condition (c) (“X is not a subkey”). It follows that 3NF implies 2NF—that is, if a relvar is in 3NF, then it’s certainly in 2NF.
We’ve already seen an example of a relvar that’s in 2NF but not 3NF: namely, the suppliers relvar S (see Fig. 3.1 in Chapter 3). To elaborate: The nontrivial FD {CITY} → {STATUS} holds in that relvar, as we know; moreover, {CITY} isn’t a superkey and {STATUS} isn’t a subkey, and so the relvar isn’t in 3NF. (It’s certainly in 2NF, however. Exercise: Confirm this claim!)
BOYCE/CODD NORMAL FORM As I said earlier, Boyce/Codd normal form (BCNF) is the normal form with respect to FDs—but now I can define it precisely: n
Definition: Relvar R is in Boyce/Codd normal form (BCNF) if and only if, for every nontrivial FD X → Y that holds in R, X is a superkey. Points arising:
n
It follows from the definition that the only FDs that hold in a BCNF relvar are either trivial ones (we can’t get rid of those, obviously) or arrows out of superkeys (we can’t get rid of those, either). Or as some people like to say: Every fact is a fact about the key, the whole key, and nothing but the key—though I must immediately add that this informal characterization, intuitively attractive though it is, isn’t really accurate, because it assumes among other things that there’s just one key.
n
The definition makes no reference to 2NF or 3NF. Note, however, that the definition can be derived from the 3NF definition by dropping condition (b) (“Y is a subkey”). It follows that BCNF implies 3NF—that is, if a relvar is in BCNF, then it’s certainly in 3NF.
46
Chapter 4 / FDs and BCNF (Informal)
By way of an example of a relvar that’s in 3NF but not BCNF, consider a revised version of the shipments relvar—let’s call it SNP─that has an additional attribute SNAME, representing the name of the applicable supplier. Suppose also that supplier names are necessarily unique (i.e., no two suppliers ever have the same name at the same time). Here then are some sample tuples: ┌─────┬───────┬─────┬─────┐ SNP │ SNO │ SNAME │ PNO │ QTY │ ├─────┼───────┼─────┼─────┤ │ S1 │ Smith │ P1 │ 300 │ │ S1 │ Smith │ P2 │ 200 │ │ S1 │ Smith │ P3 │ 400 │ │ .. │ ..... │ .. │ ... │ │ S2 │ Jones │ P1 │ 300 │ │ S2 │ Jones │ P2 │ 400 │ │ .. │ ..... │ .. │ ... │ Once again we observe some redundancy: Every tuple for supplier S1 tells us S1 is named Smith, every tuple for supplier S2 tells us S2 is named Jones, and so on; likewise, every tuple for Smith tells us Smith’s supplier number is S1, every tuple for Jones tells us Jones’s supplier number is S2, and so on. And the relvar isn’t in BCNF. First of all, it has two keys, {SNO,PNO} and {SNAME,PNO}.8 Second, every subset of the heading—{QTY} in particular—is (of course) functionally dependent on both of those keys. Third, however, the FDs {SNO} → {SNAME} and {SNAME} → {SNO} also hold; these FDs are certainly not trivial, nor are they arrows out of superkeys, and so the relvar isn’t in BCNF (though it is in 3NF). Finally, as I’m sure you know, the normalization discipline says: If relvar R isn’t in BCNF, then decompose it into projections that are. In the case of relvar SNP, either of the following decompositions will meet this objective: n
Projecting on {SNO,SNAME} and {SNO,PNO,QTY}
n
Projecting on {SNO,SNAME} and {SNAME,PNO,QTY}
By the way, I can now explain why BCNF is the odd man out, as it were, in not having a name of the form “nth normal form.” I quote from the paper in which Codd first described this new normal form:9 More recently, Boyce and Codd developed the following definition: A [relvar] R is in third normal form if it is in first normal form and, for every attribute collection C of R, if any attribute not in C is functionally dependent on C, then all attributes in R are functionally dependent on C [i.e., C is a superkey].
So Codd was giving here what he regarded as a “new and improved” definition of third normal form. The trouble was, the new definition was, and is, strictly stronger than the old one; that is, any relvar that’s in 3NF by the new definition is certainly in 3NF by the old one, but the converse isn’t true—a relvar can be in 3NF by the old definition and not in 3NF by the new one (relvar SNP, discussed above, is a case in point). So what that “new and improved” definition defined was really a new and stronger normal form, which therefore needed a distinctive name
8 That’s why I didn’t show any double underlining when I showed the sample tuples─there are two candidate keys, and there doesn’t seem to be any good reason to make either of them “more equal than the other.” 9
E. F. Codd: “Recent Investigations into Relational Data Base Systems,” Proc. IFIP Congress, Stockholm, Sweden (1974).
FDs and BCNF (Informal) / Chapter 4
47
of its own. However, by the time this point was sufficiently recognized, Fagin had already defined what he called fourth normal form, so that name wasn’t available.10 Hence the anomalous name Boyce/Codd normal form.
EXERCISES 4.1
How many FDs hold in relvar SP? Which ones are trivial? Which are irreducible?
4.2
Is it true that the concept of FD relies on the notion of tuple equality?
4.3 Give examples from your own work environment of (a) a relvar not in 2NF; (b) a relvar in 3NF but not 2NF; (c) a relvar in BCNF but not 3NF. 4.4
Prove the two definitions of 2NF given in the body of the chapter are logically equivalent.
4.5
Is it true that if a relvar isn’t in 2NF, then it must have a composite key?
4.6
Is it true that every binary relvar is in BCNF?
4.7
(Same as Exercise 1.4.) Is it true that every “all key” relvar is in BCNF?
4.8 Write Tutorial D CONSTRAINT statements to express the FDs {SNO} → {SNAME} and {SNAME} → {SNO} that hold in relvar SNP (see the section “Boyce/Codd Normal Form”). Note: This is the first exercise in any chapter that asks you to give an answer in Tutorial D. Of course, I realize you might not be completely conversant with that language; in all such exercises, therefore—for example, Exercises 4.14 and 4.15 below—please just do the best you can. I do think it worth your while at least to attempt the exercises in question. Let R be a relvar of degree n. What’s the maximum number of FDs that can possibly hold in R (trivial as 4.9 well as nontrivial)? What’s the maximum number of keys it can have? 4.10
Given that X and Y in the FD X → Y are both sets of attributes, what happens if either is the empty set?
4.11
Can you think of a situation in which it really would be reasonable to have a base relvar with an RVA?
4.12 There’s a lot of discussion in the industry at the time of writing of XML databases. But XML documents are inherently hierarchic in nature; so do you think the criticisms of hierarchies in the body of the chapter apply to XML databases? (Well, yes, they do, as I indicated in a footnote earlier in the chapter. So what do you conclude?) 4.13 In Chapter 1, I said I’d be indicating primary key attributes, in tabular pictures of relations, by double underlining. At that point, however, I hadn’t properly discussed the difference between relations and relvars; and now we know that keys in general apply to relvars, not relations. Yet we’ve seen several tabular pictures since then that represent relations as such (I mean, relations that aren’t just a sample value for some relvar)—see, e.g., Fig. 4.1
10 Actually, when Raymond Boyce first came up with what became that “new and improved” normal form, he did call it fourth normal form! (The paper in which he first described the concept─IBM Technical Disclosure Bulletin 16, No. 1 (June 1973)─had the title “Fourth Normal Form and its Associated Decomposition Algorithm.”) I don’t know why that name was subsequently rejected (though I have my suspicions).
48
Chapter 4 / FDs and BCNF (Informal)
for three examples11—and I’ve certainly been using the double underlining convention in those pictures. So what can we say about that convention now? 4.14 (Repeated from the body of the chapter.) Give Tutorial D formulations of the following queries against the relation shown in Fig. 4.1: a.
Get part numbers for parts supplied by supplier S2.
b.
Get supplier numbers for suppliers who supply part P2.
4.15 Suppose we need to update the database to show that supplier S2 supplies part P5 in a quantity of 500. Give Tutorial D formulations of the required update against (a) the non RVA design of Fig. 1.1, (b) the RVA design of Fig. 4.1. 4.16 Here are some definitions of 1NF from the technical literature. In view of the explanations given in the body of the present chapter, do you have any comments on them?
11
n
First normal form (1NF) … states that the domain of an attribute must include only atomic (simple, indivisible) values and that the value of any attribute in a tuple must be a single value from the domain of that attribute … 1NF disallows having a set of values, a tuple of values, or a combination of both as an attribute value for a single tuple … 1NF disallows “relations within relations” or “relations as attribute values within tuples” … the only attribute values permitted by 1NF are single atomic (or indivisible) values (Ramez Elmasri and Shamkant B. Navathe, Fundamentals of Database Systems, 4th edition, Addison-Wesley, 2004)
n
A relation is in first normal form if every field contains only atomic values, that is, no lists or sets (Raghu Ramakrishnan and Johannes Gehrke, Database Management Systems, 3rd edition, McGraw-Hill, 2003)
n
First normal form is simply the condition that every component of every tuple is an atomic value (Hector Garcia-Molina, Jeffrey D. Ullman, and Jennifer Widom, Database Systems: The Complete Book, Prentice Hall, 2002)
n
A domain is atomic if elements of the domain are considered to be indivisible units … we say that a relation schema R is in first normal form (1NF) if the domains of all attributes of R are atomic (Abraham Silberschatz, Henry F. Korth, and S. Sudarshan, Database System Concepts, 4th edition, McGraw-Hill, 2002)
n
A relation is said to be in first normal form (abbreviated 1NF) if and only if it satisfies the condition that it contains scalar values only (C. J. Date, An Introduction to Database Systems, 6th edition, Addison-Wesley, 1995)
Yes, I do mean three.
Chapter 5
FDs and BCNF (Formal) What’s formal is normal What’s not so is not And if normal is formal, Informal is what? —Anon: Where Bugs Go
Now I want to step back, take a deep breath as it were, and consider FDs and BCNF all over again—but this time I want to do it properly (with apologies for the small amount of repetition involved). As you’ll quickly see, the treatment in this chapter is rather more abstract than that in the previous one; it shouldn’t be difficult to follow, if you’re fully comfortable with the material of that previous chapter, but it’ll certainly be more formal. For that reason, I don’t want you to look at this chapter at all until you’ve absorbed everything in the previous one. (Of course, that shouldn’t be hard to do, since most of what was in that chapter was surely familiar to you anyway.) One general point up front: Since BCNF is the normal form with respect to FDs, I won’t have anything to say in this chapter regarding 2NF or 3NF (or indeed 1NF). As I’ve more or less said already, 2NF and 3NF just aren’t all that interesting in themselves.
PRELIMINARY DEFINITIONS In this section I simply give definitions, with little by way of further elaboration, of a few familiar but absolutely fundamental concepts—definitions that are rather more precise than the ones typically found in the literature (as well as being more precise, in some cases, than ones given earlier in this book). Production of examples to illustrate the definitions is left as an exercise. n
Definition: A heading H is a set of attribute names. Note: I remind you that this definition is deliberately not quite the same as the one I gave in Chapter 2, q.v. Also, for reasons that aren’t important here, The Third Manifesto uses {H}, not H, to denote a heading; however, the simpler form H is more convenient for the purposes of this book.
n
Definition: A tuple with heading H is a set of ordered pairs (one such pair for each attribute name A appearing in H), where v is a value. Note: The phrase tuple with heading H can be abbreviated to just tuple, if H is either understood or irrelevant for the purpose at hand.
n
Definition: Let t be a tuple with heading H and let X be a subset of H. Then the (tuple) projection t{X} of t on the attributes of X is a tuple with heading X—namely, that subset of t containing just those pairs
50
Chapter 5 / FDs and BCNF (Formal)
such that A appears in X.1 Note: Here I’m defining a version of the usual relational projection operator that applies to individual tuples (see Exercise 2.11). Observe that every projection of a tuple is itself a tuple. n
Definition: A relation r is an ordered pair , where h is a set of tuples (the body of r) all having heading H. H is the heading of r and the attributes of H are the attributes of r. The tuples of h are the tuples of r.
n
Definition: Let r be the relation and let X be a subset of H. Then the (relational) projection r{X} of r on the attributes of X is the relation <X,x>, where x is the set of all tuples t{X} such that t is a tuple of h.
n
Definition: Let relations r1, ..., rn (n ≥ 0) be joinable—i.e., let them be such that attributes with the same name are of the same type. Then the join of r1, ..., rn, JOIN {r1,...,rn}, is a relation with (a) heading the union of the headings of r1, ..., rn and (b) body the set of all tuples t such that t is the union of a tuple from r1, ..., and a tuple from rn. Note: This version of join is what’s sometimes called, more explicitly, the natural join. Note that it’s an n-adic operator, not a dyadic operator merely (n = 2 is just a common special case; as for n < 2, see Exercise 3.1). Note also that join degenerates to cartesian product in the important special case in which the operand relations r1, ..., rn have no attributes with the same name.
n
Definition: A relation variable or relvar with heading H is a variable R such that a value r can be assigned to that variable only if that value r is a relation with heading H. The attributes of H are the attributes of R. Also, if relation r is assigned to R, then the body and tuples of r are the body and tuples of R, respectively, under that assignment. Note: As the definition says, relation r can be assigned to relvar R only if (emphasis added) it has the same heading as R. In fact, relation r can be assigned to relvar R if and only if (a) it has the same heading as R and(b) it satisfies all of the constraints that apply to R—where “all of the constraints that apply to R” includes FDs that hold in R but (in general) isn’t limited to such FDs alone.
FUNCTIONAL DEPENDENCIES Now I’m in a position to deal properly with the concept of functional dependencies. Again I’ll be presenting precise definitions—but in this section I’ll have rather more to say about those definitions and some of their implications. n
Definition: Let H be a heading; then a functional dependency (FD) with respect to H is an expression of the form X → Y, where X (the determinant) and Y (the dependant) are both subsets of H. Note: The phrase FD with respect to H can be abbreviated to just FD, if H is understood. Here are a couple of examples: { CITY } → { STATUS } { CITY } → { SNO }
1
There’s a tiny notational complication here. If X is a subset of H, then X is a set of attribute names, {A1,...,An} say, and the projection t{X}of t on X would thus apparently have to be written with double braces, like this: t{{A1,...,An}}. Of course we don’t do this, and I’m going to ignore this complication throughout the remainder of the book. However, I should at least explain why it arises. Basically, it does so because we’re conflating two distinct interpretations of the symbol X. On the one hand, we’re using that symbol to mean the set as such─i.e., the set whose elements are A1, ..., An; on the other hand, we’re using it to mean the commalist of attribute names A1, ... An as physically written that represents those elements (on paper, say). The former is what the symbol X actually denotes; the latter is the way we express that denotation in concrete syntax.
FDs and BCNF (Formal) / Chapter 5
51
Note carefully that FDs are defined with respect to some heading, not with respect to some relation or some relvar. The two FDs just shown, for example, are defined with respect to any heading that contains attributes CITY, STATUS, and SNO (and others as well, possibly). Note too that from a formal point of view, an FD is just an expression: an expression that, when interpreted with respect to some specific relation, becomes a proposition that, by definition, evaluates to either TRUE or FALSE. For example, if the two FDs shown above are interpreted with respect to the relation that’s the current value of relvar S (Fig. 1.1), then the first evaluates to TRUE and the second to FALSE. Of course, it’s common informally to define such an expression to be an FD, in some specific context, only if it evaluates to TRUE in that context; but such a definition leaves no way of saying a given relation fails to satisfy, or violates, some FD. Why so? Because, by that informal definition, an FD that isn’t satisfied wouldn’t be an FD in the first place! For example, we wouldn’t be able to say the relation that’s the current value of relvar S violates the second of the FDs shown above. I really can’t stress the foregoing point strongly enough. For most people, it represents a shift in thinking; but it’s a shift that has to be made if you’re ever to understand what design theory is all about. The point is this: Most writings on FDs—including the early research papers that first introduced the concept—don’t actually define the concept of an FD, as such, at all! Instead, they say something along the lines of “Y is functionally dependent on X if and only if, whenever two tuples agree on X, they also agree on Y.” Which is perfectly true, of course—but it’s not a definition of an FD; instead, it’s a definition of what it means for an FD to be satisfied. But if we want to develop a theory of FDs as such, then we clearly need to be able to talk about FDs as objects in their own right, divorced from the context of some particular relation or relvar. More specifically, we need to divorce the concept of an FD as such from the concept that it might have some interpretation, or meaning, in some context. In fact, design theory can be regarded as a small piece of logic, and logic isn’t about meaning at all—it’s about formal manipulations. To continue with the definitions: n
Definition: Let relation r have heading H and let X → Y be an FD, F say, with respect to H. If all pairs of tuples t1 and t2 of r are such that whenever t1{X} = t2{X}, then t1{Y} = t2{Y}, then r satisfies F; otherwise r violates F.
Observe that it’s relations, not relvars, that satisfy or violate some given FD. For example, the relation that’s the current value of relvar S satisfies both of these FDs— { CITY } → { STATUS } { SNAME } → { CITY } —and violates this one: { CITY } → { SNO } n
Definition: The FD F holds in relvar R (equivalently, relvar R is subject to the FD F) if and only if every relation that can be assigned to relvar R satisfies F. The FDs that hold in relvar R are the FDs of R.
Important: Please note the terminological distinction I’m drawing here—FDs are satisfied (or violated) by relations, but hold (or don’t hold) in relvars. Please note too that I’ll adhere to this distinction throughout this book. By way of example, the following FD holds in relvar S— { CITY }
→ { STATUS }
52
Chapter 5 / FDs and BCNF (Formal)
—and these ones don’t: { SNAME } → { CITY } { CITY } → { SNO } (Contrast the examples following the previous definition.) So now, at last, we know precisely what it means for a given relvar to be subject to a given FD.
BOYCE/CODD NORMAL FORM With a proper understanding of FDs under our belt, as it were, I can now go on to tackle the question of what it means for a relvar to be in BCNF. Again I proceed by means of a series of precise definitions. n
Definition: Let X → Y be an FD, F say, with respect to heading H. Then F is trivial if and only if it’s satisfied by every relation with heading H.
Now, in Chapter 4 I defined a trivial FD to be one that can’t possibly be violated. There’s nothing wrong with that definition, of course; however, the one just given is preferable because it explicitly mentions the pertinent heading. I also said in Chapter 4 that it’s easy to see the FD X → Y is trivial if and only if Y is a subset of X. Well, that’s true too; but I can now say that this latter fact isn’t really a definition but rather a theorem, easily proved from the definition as such. (On the other hand, the definition as such isn’t very helpful in determining whether a given FD is trivial, whereas the theorem is. For that reason, we might regard the theorem as an operational definition, inasmuch as it does provide an effective test that can easily be applied.)2 Let me state the theorem explicitly for the record: n
Theorem: Let X → Y be an FD, F say. Then F is trivial if and only if the dependant Y is a subset of the determinant X. Now back to the definitions:
n
Definition: A superkey of relvar R is a subset SK of the heading H of R such that the FD SK → H holds in R (“is an FD of R”). That FD is a superkey constraint on R. For example, {SNO}, {SNO,CITY}, and {SNO,CITY,STATUS} are all superkeys for relvar S.
n
Definition: The FD X → Y is irreducible with respect to relvar R (or just irreducible, if R is understood) if and only if it holds in R and X → Y doesn’t hold in R for any proper subset X of X.
For example, the FD {CITY} → {STATUS} is irreducible with respect to relvar S. By contrast, the FD {CITY,SNO} → {STATUS}, though certainly an FD of S, is reducible with respect to S. Observe that while FDs as such are defined with respect to some heading, FD irreducibility is defined with respect to some relvar. In other
2 Distinctions like the one I’m drawing here are sometimes characterized as semantic vs. syntactic distinctions. To spell the point out: The original definition—F is trivial if and only if it’s satisfied by every relation with the pertinent heading—is semantic, because it defines what the concept means; by contrast, what I’ve called the “operational” definition—F is trivial if and only if Y is a subset of X—is syntactic, because it provides a check that can be performed in a purely syntactic way. (We’ll be meeting this distinction, between semantic and syntactic notions, many times in the pages ahead. In fact, one case in point arises almost immediately in connection with the notion of FD irreducibility, q.v.)
FDs and BCNF (Formal) / Chapter 5
53
words, FDs as such are just a syntactic notion (an FD is just an expression that takes a certain syntactic form), while FD irreducibility is a matter of semantics (it has to do with what the pertinent relvar means). Note: I won’t assume in what follows that the FDs we’re talking about are irreducible ones only, though in practice we typically do. n
Definition: A key of relvar R is a subset K of the heading H of R such that the FD K → H is an irreducible FD of R. That FD is a key constraint on R. Note the appeal to FD irreducibility in the foregoing definition.
n
Definition: Let relvar R have heading H and let X → Y be an FD, F say, with respect to H. Then F is implied by the keys of R if and only if every relation r that satisfies R’s key constraints also satisfies F.
This definition requires some elaboration. First of all, to say some relation satisfies some key constraint is to say it satisfies the applicable uniqueness requirement; and if it satisfies the uniqueness requirement for the set of attributes that constitute some key, it certainly also satisfies the uniqueness requirement for every superset of that set of attributes (just so long as that superset is a subset of the pertinent heading, of course)—in other words, for every corresponding superkey. Thus, the phrase “satisfies R’s key constraints” in the definition could be replaced by the phrase “satisfies R’s superkey constraints” without making any significant difference. Likewise, the concept “implied by keys” could just as well be “implied by superkeys,” again without making any significant difference. Second, what happens if the FD F mentioned in the definition is trivial? Well, in that case, by definition, F is satisfied by every relation r with heading H, and so F is certainly satisfied by every relation r that satisfies R’s key constraints, a fortiori. So trivial FDs are always “implied by keys,” trivially. Third, then, suppose F is nontrivial. Then it’s easy to prove the following theorem: n
Theorem: Let F be an FD that holds in relvar R. Then F is implied by the keys of R if and only if it’s a superkey constraint on R.
In other words, it’s like that business with trivial FDs: The formal definition as such isn’t very helpful in determining whether a given FD is implied by keys, but the theorem is. For that reason, we can regard the theorem as an operational definition, since it does provide an effective test that can easily be applied in practice. And now, at last, I can define BCNF: n
Definition: Relvar R is in Boyce-Codd normal form (BCNF) if and only if every FD of R is implied by the keys of R.
However, given the various definitions and theorems already discussed in this section, we can see that the following “operational” definition is valid too: n
Definition: Relvar R is in Boyce-Codd normal form (BCNF) if and only for every nontrivial FD X → Y that holds in R, X is a superkey for R.
As I put it in Chapter 4, it follows from this definition that the only FDs that hold in a BCNF relvar are either trivial ones (we can’t get rid of those, obviously) or arrows out of superkeys (we can’t get rid of those, either). Though now I’d like to add that when I talk about “getting rid of” some FD, I fear I’m being—I hope uncharacteristically—a little sloppy ... For example, consider relvar S. That relvar is subject to the FD {CITY} → {STATUS}, among others; as explained in Chapter 3, therefore, the recommendation is to decompose the relvar into its projections SNC on {SNO,SNAME,CITY} and CT on {CITY,STATUS}. But if we do, then the FD {SNO} →
54
Chapter 5 / FDs and BCNF (Formal)
{STATUS}, which also holds in relvar S, “disappears,” in a sense; thus we have indeed “gotten rid of it.” But what does it mean to say the FD has disappeared? The answer is: It’s been replaced by a multirelvar constraint (that is, a constraint that spans two or more relvars). So the constraint certainly still exists—it just isn’t an FD any more.3 Similar remarks apply whenever I talk, elsewhere in this book, of “getting rid of” some dependency.
HEATH’S THEOREM Consider relvar S once again, with its FD {CITY} → {STATUS}. Suppose we decompose that relvar, not as in Chapter 3 into relvars SNC and CT, but instead into relvars SNT and CT—where CT is the same as before, but SNT has heading {SNO,SNAME,STATUS} instead of {SNO,SNAME,CITY}. Sample values for SNT and CT corresponding to the value shown for S in Fig. 1.1 are shown in Fig. 5.1 below. From that figure, I hope you can see that: n
Relvars SNT and CT are both in BCNF (the keys are {SNO} and {CITY}, respectively, and the only nontrivial FDs that hold in those relvars are “arrows out of superkeys”).
n
Unlike the decomposition in Chapter 3, however, this decomposition is not nonloss but lossy. For example, we can’t tell from Fig. 5.1 whether supplier S2 is in Paris or Athens—note what happens if we join the two projections together4—and so we’ve lost information. SNT ┌─────┬───────┬────────┐ │ SNO │ SNAME │ STATUS │ ├═════┼───────┼────────┤ │ S1 │ Smith │ 20 │ 30 │ │ S2 │ Jones │ │ S3 │ Blake │ 30 │ │ S4 │ Clark │ 20 │ │ S5 │ Adams │ 30 │ └─────┴───────┴────────┘
CT ┌────────┬────────┐ │ CITY │ STATUS │ ├════════┼────────┤ │ Athens │ 30 │ 20 │ │ London │ │ Paris │ 30 │ └────────┴────────┘
Fig. 5.1: Relvars SNT and CT─sample values
Let’s take a slightly closer look at this example. First of all, here are the predicates for relvars SNT and CT: n
SNC:
Supplier SNO is named SNAME and has status STATUS.
n
CT:
City CITY has status STATUS.
So the predicate for the join of those two relvars is: Supplier SNO is named SNAME and has status STATUS and city CITY has status STATUS.
3 Well ... it is an FD, but one that holds in the join of two relvars, viz., SNC and CT, rather than in an individual relvar as such. Note, however, that enforcing the key constraints on those two relvars will enforce that multirelvar constraint “automatically”; that is, the multirelvar constraint in question is implied by, or is a logical consequence of, certain explicitly declared constraints. 4
See the remarks on lossy joins in a footnote in the section “Normalization Serves Two Purposes” in Chapter 3.
FDs and BCNF (Formal) / Chapter 5
55
Now recall the predicate for relvar S (see the answer to Exercise 2.6 in Appendix D): Supplier SNO is named SNAME and is located in city CITY, which has status STATUS. This latter predicate is clearly not the same as the predicate for the join. To be more precise, if some given tuple t satisfies it, then that tuple t also satisfies the predicate for the join, but the converse isn’t true. That’s why the join “loses information” or “is lossy”—just because some tuple appears in the join, we can’t assume it also appears in the original relvar S. So what exactly is it that makes some decompositions nonloss and others lossy? This is the question that lies at the heart of normalization theory. It can be stated formally thus: Let r be a relation and let r1, ..., rn be projections of r. What conditions must be satisfied in order for r to be equal to the join of those projections? (By the way, note the tacit assumption here that—as noted earlier— join is an n-adic operator.) An important, albeit partial, answer to this question was provided by Ian Heath in 1971 when he proved the following theorem: n
Heath’s Theorem (for relations): Let relation r have heading H and let X, Y, and Z be subsets of H such that the union of X, Y, and Z is equal to H. Let XY denote the union of X and Y, and similarly for XZ. If r satisfies the FD X → Y, then r is equal to the join of its projections on XY and XZ.
By way of example, consider the suppliers relation once again (i.e., the current value of relvar S as shown in Fig. 1.1). That relation satisfies the FD {CITY} → {STATUS}. Thus, taking X as {CITY}, Y as {STATUS}, and Z as {SNO,SNAME}, Heath’s Theorem tells us that the decomposition of that relation into its projections on {CITY,STATUS} and {CITY,SNO,SNAME}5 is nonloss—as indeed we already know. Now, it’s important to understand that (to repeat) Heath’s answer to the original question was only partial. I’ll explain what this means in terms of the foregoing example. Basically, the theorem does tell us the decomposition into projections SNC and CT (see Fig. 3.2 in Chapter 3) is nonloss; however, it doesn’t tell us the one into SNT and CT (see Fig. 5.1) is lossy. In other words, if we decompose on the basis of an FD, as we did in the example of Fig. 3.2, then Heath’s Theorem says the decomposition will be nonloss; but if we decompose on some other basis, as we did in the example of Fig. 5.1, then the theorem has nothing to say on the matter. Thus, the theorem gives a sufficient condition, but not a necessary one, for a given (binary) decomposition to be nonloss. It follows that it might be possible to decompose relation r in a nonloss way into its projections on XY and XZ even if it doesn’t satisfy the FD X → Y. Note: I’ll be describing a stronger form of Heath’s Theorem, giving both necessary and sufficient conditions, later in this book (see Chapter 12). As an aside, I remark that in the paper in which he proved his theorem, Heath also gave a definition of what he called “third” normal form that was in fact a definition of BCNF. Since that definition preceded Boyce and Codd’s own definition by some three years, it seems to me that BCNF ought by rights to be called Heath normal form. But it isn’t. Now, in Chapter 3, in the section “Normalization Serves Two Purposes,” I said something like the following: If you’ve been paying careful attention, you might reasonably accuse me of practicing a tiny deception in the foregoing discussion. To be specific, I’ve considered what it means for a decomposition of relations to be nonloss; but
5 Or, as we would “more naturally” tend to write them, interchanging the two sets of attributes and specifying the individual attributes in a “more natural” order, on {SNO,SNAME,CITY} and {CITY,STATUS}.
56
Chapter 5 / FDs and BCNF (Formal)
normalization, which is what we’re supposed to be talking about, isn’t a matter of decomposing relations, it’s a matter of decomposing relvars.
These remarks apply here too! So let’s get back to relvars ... Consider relvar S once again. Suppose we do decide to perform the recommended decomposition into “projection” relvars SNC and CT; moreover, suppose we want that decomposition to be nonloss, as indeed we surely do. In other words, what we want is for the decomposition to be such that, at all times, the current value of relvar S is equal to the join of the current values of SNC and CT.6 That is, we want S to be subject to the following integrity constraint (I’ll call it YCT): CONSTRAINT YCT S = JOIN { S { SNO , SNAME , CITY } , S { CITY , STATUS } } ; Now, recall from Chapter 2 that S is certainly subject to the following constraint (XCT): CONSTRAINT XCT COUNT ( S { CITY } ) = COUNT ( S { CITY , STATUS } ) ; Just to remind you, this constraint merely says the FD {CITY} → {STATUS} holds in S. Appealing to Heath’s Theorem, therefore, we see that every possible value of relvar S, since it necessarily satisfies constraint XCT, certainly satisfies constraint YCT as well. And it follows that constraint XCT implies constraint YCT (meaning, to spell the point out, that if relvar S is subject to XCT—which it is—then it’s certainly subject to YCT as well). So constraint YCT does hold, and the decomposition of relvar S into relvars SNC and CT is indeed nonloss, as required. It follows that we can take Heath’s Theorem as applying to relvars after all, not just to relations. So let’s restate it accordingly: n
Heath’s Theorem (for relvars): Let relvar R have heading H and let X, Y, and Z be subsets of H such that the union of X, Y, and Z is equal to H. Let XY denote the union of X and Y, and similarly for XZ. If R is subject to the FD X → Y, then R can be nonloss decomposed into its projections on XY and XZ.
There’s one further point I want to make on the general topic of nonloss decomposition (to BCNF or otherwise). Once again consider relvar S, with its FD {CITY} → {STATUS}. By Heath’s Theorem, that relvar can be nonloss decomposed into its projections on {SNO,SNAME,CITY} and {CITY,STATUS}. However, it can clearly also be nonloss decomposed into those two projections together with (say) the projection on {SNAME,STATUS}; that is, if we join all three of those projections together, we get back to where we started. (Check this claim for yourself, using our usual sample value for relvar S, if it isn’t immediately obvious.) However, that third projection clearly isn’t needed in the process of reconstructing the original relvar. Now, when we’re doing database design, for obvious reasons we usually consider only decompositions for which every projection is needed in the reconstruction process—but in this book I’m discussing decompositions in general, and I won’t limit myself to those for which every projection is needed (barring explicit statements to the contrary, of course). EXERCISES 5.1 The version of join defined in the body of the chapter is an n-adic operator, not just a dyadic one. But what happens if n = 1? Or n = 0?
6
Here I’m adopting the convenient fiction again that relvars S, SNC, and CT all coexist (living alongside one another, as it were).
FDs and BCNF (Formal) / Chapter 5
5.2
Define as precisely as you can what it means for a relvar to be subject to a functional dependency.
5.3
Consider the following FDs:
a. b. c. d. e. f. g. h.
{ { { { { { { {
57
CITY } → { STATUS } SNO , CITY } → { STATUS } SNO } → { SNO } SNO , CITY } → { SNO } SNO } → { SNO , CITY } SNAME , SNO } → { STATUS , CITY } SNO } → { STATUS } SNAME } → { STATUS , SNO }
Which of these FDs are trivial? Which ones are satisfied by the current value of relvar S as given in Fig. 1.1? Which hold in relvar S? Which are irreducible with respect to relvar S? 5.4 Prove Heath’s Theorem. Prove also that the converse of that theorem isn’t valid. Note: In this connection, see also Exercise 11.3 in Chapter 11. 5.5
What exactly does it mean to say an FD is implied by a superkey? Or a key?
5.6 Here’s a predicate: On day d during period p, student s is attending lesson l, which is being taught by teacher t in classroom c (where d is a day of the week—Monday to Friday—and p is a period—1 to 8—within the day). Lessons are one period in duration and have a lesson identifier l that’s unique with respect to all lessons taught in the week. Design a set of BCNF relvars for this database. What are the keys? 5.7 Design a database for the following. The entities to be represented are employees and programmers. Every programmer is an employee, but some employees aren’t programmers. Employees have an employee number, name, and salary. Programmers have a (single) programming language skill. What difference would it make if programmers could have an arbitrary number of such skills? The definition of key given in the body of the chapter is somewhat different in form from the definition given 5.8 in Chapter 4. Are those definitions logically equivalent?
Chapter 6
Preserving FDs Nature does require Her times of preservation —William Shakespeare: Henry VIII
Once again consider our usual suppliers relvar S. Since {SNO} is a key, that relvar is certainly subject to the FD {SNO} → {STATUS}. Thus, taking X as {SNO}, Y as {STATUS}, and Z as {SNAME,CITY}, Heath’s Theorem tells us we can decompose that relvar into relvars SNC and ST, where SNC has heading {SNO,SNAME,CITY} and ST has heading {SNO,STATUS}. Sample values for SNC and ST corresponding to the value shown for S in Fig. 1.1 are shown in Fig. 6.1. SNC ┌─────┬───────┬────────┐ │ │ SNO │ SNAME │ CITY ├═════┼───────┼────────┤ │ S1 │ Smith │ London │ │ S2 │ Jones │ Paris │ │ S3 │ Blake │ Paris │ │ S4 │ Clark │ London │ │ S5 │ Adams │ Athens │ └─────┴───────┴────────┘
ST ┌─────┬────────┐ │ SNO │ STATUS │ ├═════┼────────┤ │ S1 │ 20 │ │ S2 │ 30 │ │ S3 │ 30 │ │ S4 │ 20 │ │ S5 │ 30 │ └─────┴────────┘
Fig. 6.1: Relvars SNC and ST─sample values
In this decomposition: n
Relvars SNC and ST are both in BCNF—{SNO} is the key for both, and the only nontrivial FDs that hold in those relvars are “arrows out of superkeys.”
n
What’s more, the decomposition is certainly nonloss (as is in fact guaranteed by Heath’s Theorem)—if we join SNC and ST together, we get back to S.
n
However, the FD {CITY} → {STATUS} has been lost─by which I mean, of course, that it’s been replaced by a certain multirelvar constraint, as explained in the previous chapter.1 The constraint in question can be stated as follows: CONSTRAINT ... COUNT ( ( JOIN { SNC , ST } ) { CITY } ) = COUNT ( ( JOIN { SNC , ST } ) { CITY , STATUS } ) ;
1 To say an FD is “lost” in such circumstances is usual but a trifle inappropriate─all that’s happened is (to repeat) that the FD in question has been replaced by another constraint. But the point is, that other constraint isn’t an FD as such.
60
Chapter 6 / Preserving FDs
Explanation: What this constraint says is, if we join SNC and ST, we get a result—call it S—in which the number of distinct cities is equal to the number of distinct city / status pairs. And the fact that this latter property holds is equivalent to saying the FD {CITY} → {STATUS} holds in the original relvar S. So we’ve “lost” an FD. What are the implications? Well, certainly the multirelvar constraint that replaces it is harder to state, as we’ve just seen. More to the point, perhaps, it’s harder to enforce (harder, that is, than it would have been with the preferred decomposition into projections SNC and CT, as illustrated in Fig. 3.2 in Chapter 3).2 For example, suppose we update relvar SNC to change the city for supplier S1 from London to Athens; then we must also update relvar ST to change the status for supplier S1 from 20 to 30—because if we don’t, then joining SNC and ST back together will produce a result that isn’t a legitimate value for relvar S. (By contrast, if we update relvar SNC to change the city for supplier S2 from Paris to Athens, then we don’t have to update relvar ST as well— but we still have to inspect relvar ST in order to determine that fact.) Aside: It might be possible, given a well architected DBMS, to get the system to do that necessary inspection of relvar ST “automatically,” instead of the user having to do it. It might even be possible to get the system to perform any necessary additional updates “automatically,” too. Even given such a system, however, it’s still the case that the constraint is harder to enforce (i.e., more work still has to be done, even if it’s done by the system and not the user). In any case, such possibilities are just a pipedream at the time of writing— today’s commercial products typically don’t allow multirelvar constraints even to be stated, in general; the foregoing possibilities are out of reach today, and dealing with (and in particular enforcing) such constraints is thus the user’s responsibility. End of aside. So the message is: Try to choose a decomposition that preserves FDs instead of losing them. (In the case at hand, replacing the projection on {SNO,STATUS} by that on {CITY,STATUS} solves the problem.) Loosely speaking, in other words, if the FD X → Y holds in the original relvar, try not to choose a decomposition in which X winds up in one relvar and Y in another. Note: Of course, I’m assuming here that the decomposition isn’t being done on the basis of that FD X → Y itself—because if it is, we’ll effectively wind up with two X’s, one of which will be in the same relvar as Y (necessarily so) and the other won’t. I’m also assuming, tacitly, that X → Y is part of what’s called an irreducible cover for the total set of FDs that hold in the original relvar. I’ll be discussing irreducible covers later in this chapter.
AN UNFORTUNATE CONFLICT The basic idea of FD preservation is straightforward; unfortunately, however, there’s quite a bit more that needs to be said on the subject. First of all, I want to present what some people might regard as a pathological example. We’re given a relvar SJT with attributes S (student), J (subject), and T (teacher), and predicate Student S is taught subject J by teacher T. The following business rules apply:3
2 There might be performance penalties, too. Now, I shouldn’t really mention this fact; as I indicated in Chapter 1, I never want performance considerations to be the driving force behind my logical design. But in the case at hand, performance is just an additional point that happens to reinforce my main argument. 3 A business rule is a statement, usually in natural language, that’s supposed to capture some aspect of what the data in the database means or how it’s constrained. There’s no consensus on any more precise definition of the term, though most writers would at least agree that relvar predicates are an important special case.
Preserving FDs / Chapter 6
n
For each subject, each student of that subject is taught by only one teacher.
n
Each teacher teaches only one subject.
n
Each student studies several subjects, and hence is taught by several teachers (in general).
n
Each subject is studied by several students (in general).
n
Each subject is taught by several teachers (in general).
n
Distinct students of the same subject might or might not be taught that subject by the same teacher.
61
A sample value for this relvar that conforms to these rules is shown in Fig. 6.2. ┌───────┬─────────┬─────────────┐ │ S │ J │ T │ ├───────┼─────────┼─────────────┤ │ Smith │ Math │ Prof. White │ │ Smith │ Physics │ Prof. Green │ │ Jones │ Math │ Prof. White │ │ Jones │ Physics │ Prof. Brown │ └───────┴─────────┴─────────────┘ Fig. 6.2: Sample value for relvar SJT
What are the FDs for relvar SJT? From the first business rule, we have {S,J} → {T}. From the second, we have {T} → {J}. A careful analysis of the remaining rules will show that no other FDs hold other than ones that are either trivial or reducible (or both). Thus, the only nontrivial, irreducible FDs that hold are these two: { S , J } → { T } { T } → { J } So what are the keys? Well, {S,J} is a key, since the entire heading is clearly functionally dependent on {S,J} and not on any proper subset of {S,J}. Also, {S,T} is a key, because: a.
It’s certainly the case, given that the FD {T} → {J} holds, that the entire heading is functionally dependent on {S,T}.
b.
It’s also the case, given that the FDs {S} → {J} and {T} → {S} do not hold, that the entire heading isn’t functionally dependent on any proper subset of {S,T}.
So there are two keys, {S,J} and {S,T}.4 Perhaps more to the point, {T} is not a key, and so relvar SJT is subject to an FD that’s not “an arrow out of a key” (i.e., it’s not implied by keys, to state the matter a trifle more formally). As a consequence, the relvar isn’t in BCNF, though it is in 3NF. (Exercise: Check this claim.) And it suffers from redundancy; for example, given the sample value shown in Fig. 6.2, the fact that Professor White teaches Math appears twice. As you would expect, it also suffers from update anomalies; for example, with respect
4 Which overlap, as you can see. By the way, as with relvar SNP in Chapter 4, I’ve chosen not to make either of those keys primary, which is why there’s no double underlining in Fig. 6.2.
62
Chapter 6 / Preserving FDs
to Fig. 6.2 again, we can’t delete the fact that Jones is studying Physics without losing the information that Professor Brown teaches Physics. Now, we can get over these problems by decomposing the relvar appropriately. Applying Heath’s Theorem to the FD {T} → {J} (take X, Y, and Z to be {T}, {J}, and {S}, respectively), we obtain the following nonloss decomposition: TJ { T , J } KEY { T } TS { T , S } KEY { T , S } I’ll leave it as an exercise to show the values of these two relvars corresponding to the value of SJT shown in Fig. 6.2, to show they’re in BCNF, and to check that the decomposition does in fact avoid the redundancy and update anomalies mentioned above. Observe in particular that the FD {T} → {J} becomes a key constraint in this decomposition; in the original design, by contrast, it had to be stated and enforced separately. There’s another problem, though. The fact is, although the decomposition into TJ and TS does avoid certain anomalies, it unfortunately introduces others. To be specific, the FD { S , J } → { T } is lost (certainly it isn’t implied by the FD {T} → {J}, which is the only nontrivial FD to hold in the result of the decomposition). As a consequence, relvars TJ and TS can’t be independently updated. For example, an attempt to insert the tuple ( Smith , Prof. Brown ) into TS must be rejected, because Professor Brown teaches Physics and Smith is already being taught Physics by Professor Green; yet this fact can’t be detected without inspecting TJ. To sum up, what the foregoing example illustrates is as follows: There are two objectives we typically aim for in nonloss decomposition, BCNF projections and FD preservation, and, sadly, these objectives can be in conflict with one another (i.e., it isn’t always possible to achieve both). Now, at this point in an earlier draft of this chapter, I wrote the following: So which objective do we give up on? Well, I’d tell you if I could, but I can’t. What the SJT example demonstrates is that the theory of normalization, important though it is, isn’t enough as it stands; I mean, there are questions it doesn’t answer. So the message is: We need more science! Normalization theory is certainly scientific, but it doesn’t solve all design problems.
At the prompting of one of my reviewers, however, I’ve come to the conclusion that this paragraph is probably overstated. It’s not so much more science we need here, it’s better implementations! That is, the main argument for tolerating a less than properly normalized design, in cases like the one at hand, is the fact that today’s DBMSs make it quite awkward to deal with multirelvar constraints like the “lost” FD in the example. So let me set a stake in the
Preserving FDs / Chapter 6
63
ground and state categorically that in my opinion, FD preservation is the objective to give up on, in those cases in which there’s a conflict.5
ANOTHER EXAMPLE I suggested at the beginning of the previous section that the SJT example might be considered pathological. Now, however, I’m going to claim it’s not, not entirely; I’m going to give several more examples that I think demonstrate that the issue of FD preservation arises more often than you might think. Normalization as commonly perceived is a process of stepping from 1NF to 2NF to 3NF (etc.) in sequence. Let’s agree to refer to that process as commonly perceived—i.e., stepping from 1NF to 2NF to 3NF (etc.) in sequence—as “the conventional normalization procedure.” In this section and the next two, then, I want to present a series of examples to demonstrate that the conventional normalization procedure isn’t necessarily a good idea if followed too blindly. My first example involves a relvar that looks like this: RX1 { SNO , PNO , CITY , STATUS , QTY } The name RX1 stands for “relvar example 1”; the predicate is Supplier SNO is located in city CITY, which has status STATUS, and supplies part PNO in quantity QTY. Assume the following FDs hold in this relvar: → { CITY } { SNO } { CITY } → { STATUS } { SNO , PNO } → { QTY } It’s intuitively obvious that the following FDs hold too, implicitly:6 → { STATUS } { SNO } { SNO , PNO } → { CITY , STATUS } In fact, the second of these can be expanded to {SNO,PNO} → H, where H is the entire heading; in other words, {SNO,PNO} is a key for relvar RX1. Recall now that a relvar R is in 2NF if and only if, for every key K and every nonkey attribute A, the FD K → {A} is irreducible. Clearly, then, RX1 isn’t in 2NF, because the FD {SNO,PNO} → {CITY} is an FD of RX1 but isn’t irreducible; to be specific, it isn’t irreducible because the FD {SNO} → {CITY} also holds in that relvar. The conventional normalization procedure would thus recommend that we decompose the relvar by applying Heath’s Theorem to that FD {SNO} → {CITY}. But if we do, this is what we get: RX1A { SNO , CITY } KEY { SNO } RX1B { SNO , PNO , STATUS , QTY } KEY { SNO , PNO }
5 In the case at hand, of course, we must decompose the relvar as indicated if we want to be able to record the fact that (say) Professor Black teaches physics even though Professor Black has no students at the moment. 6
I’ll have quite a lot more to say on the question of FDs that hold implicitly (“implicit FDs”) in the next chapter, also in Chapter 11.
64
Chapter 6 / Preserving FDs
Observe now that the FD {CITY} → {STATUS} is lost in this decomposition. So one immediate lesson is that the issue of FD preservation can be relevant to the step from 1NF to 2NF—not just to the step from 3NF to BCNF, which is the step illustrated by the SJT example in the previous section. Aside: Relvar RX1A here is certainly in 2NF. By contrast, relvar RX1B isn’t, because the FD {SNO,PNO} → {STATUS} is reducible. So we can apply Heath’s Theorem again to decompose it into its projections on {SNO,STATUS} and {SNO,PNO,QTY}, both of which are in 2NF; however, the damage has already been done, as it were─the FD {CITY} → {STATUS} has already been lost. End of aside. How can we preserve the FD in this example? One answer is: By decomposing not on the basis of the FD {SNO} → {CITY}, but rather on the basis of the FD {SNO} → {CITY,STATUS}. Note, however, that this FD isn’t one of the FDs originally listed explicitly, nor is it one of the ones I said were obviously implied by those explicit ones; it’s thus unlikely to have been chosen as a basis for decomposition. Nevertheless, suppose we do choose it and perform the corresponding decomposition. Here’s the result: RX1A′ { SNO , CITY , STATUS } KEY { SNO } RX1B′ { SNO , PNO , QTY } KEY { SNO , PNO } In this decomposition, STATUS appears in the relvar with key {SNO} and not the relvar with key {SNO,PNO}, and the FD {CITY} → {STATUS} is thereby preserved. Note: Of course, relvar RX1A′ here is still not in 3NF, so we would probably want to decompose it further. Again, however, we need to be a little careful; to be specific, we need to decompose on the basis of the FD {CITY} → {STATUS}, not {SNO} → {STATUS}, or we’ll lose an FD again. But {CITY} → {STATUS} is the FD the conventional normalization procedure would tell us to use, so there shouldn’t be a problem here. An alternative to the foregoing would be to decompose the original relvar RX1 on the basis of the FD {CITY} → {STATUS}: RX1A′′ { CITY , STATUS } KEY { CITY } RX1B′′ { SNO , PNO , CITY , QTY } KEY { SNO , PNO } This decomposition also preserves the FD {CITY} → {STATUS}. Note, however, that this FD isn’t the one that causes the 2NF violation (it isn’t “an arrow out of a proper subkey”); again, therefore, it’s quite unlikely in practice, if we’re following the conventional normalization procedure, that we would have chosen it as a basis for decomposition at this stage. Note also that relvar RX1B′′ here is still not in 3NF, so we would probably want to decompose it further. I’ll leave the details of that further decomposition for you to think about.
… AND ANOTHER Let’s look at another example. Suppose suppliers are partitioned into classes (C1, C2, etc.), so we have a relvar RX2 that looks like this (as I did with RX1, I’ll ignore supplier names for simplicity):
Preserving FDs / Chapter 6
65
RX2 { SNO , CLASS , CITY , STATUS } KEY { SNO } The predicate is Supplier SNO is in class CLASS, is located in city CITY, and has status STATUS. Suppose also that (a) each class has just one associated status, and (b) each city has just one associated status as well, but (c) classes and cities are otherwise quite independent of each other. Then the following FDs hold: { CLASS } → { STATUS } { CITY } → { STATUS } Note: I’m also assuming there’s a business rule in effect that says that, for any given supplier, the city status is equal to the class status (that’s why we’re able to get away with just one STATUS attribute). Recall now that a relvar R is in 3NF if and only if, for every nontrivial FD X → Y that holds in R, X is a superkey or Y is a subkey. Clearly, then, RX2 isn’t in 3NF, because in the FD {CITY} → {STATUS}, {CITY} isn’t a superkey and {STATUS} isn’t a subkey. The conventional normalization procedure would thus recommend that we decompose the relvar by applying Heath’s Theorem to that FD {CITY} → {STATUS}. But if we do, this is what we get (two projection relvars both in 3NF): RX2A { CITY , STATUS } KEY { CITY } RX2B { SNO , CLASS , CITY } KEY { SNO } Observe now that the FD {CLASS} → {STATUS} is lost in this decomposition. (Of course, if we had done the decomposition on the basis of that FD instead of the FD {CITY} → {STATUS}, then this latter FD would have been lost instead.) So now we see the issue of FD preservation can also be relevant to the step from 2NF to 3NF. Now, we can preserve the FD in this example by decomposing on the basis of the FD {SNO} → {CLASS,CITY}—though once again this FD is unlikely to have been chosen as a basis for decomposition, since it wasn’t stated explicitly.7 Be that as it may, here’s the result: RX2A′ { CLASS , CITY , STATUS } KEY { CLASS , CITY } RX2B′ { SNO , CLASS , CITY } KEY { SNO } In this decomposition, {CLASS,CITY} is a (composite) foreign key in RX2B′, referencing RX2A′. Relvar RX2B′ is in 3NF. However, relvar R2XA′ isn’t even in 2NF, since the FD {CLASS,CITY} → {STATUS} is clearly reducible. So if we decide to keep that relvar, the FDs {CLASS} → {STATUS} and {CITY} → {STATUS} will have to be separately stated and enforced. Alternatively, we could decompose the relvar into its projections on {CLASS,STATUS} and {CITY,STATUS}, in which case an appropriate multirelvar constraint will have to be separately stated and enforced. Exercise for the reader: What would that constraint look like?
7 Nor is it likely to have been, either, since {SNO} is a key (in fact the only key) for relvar RX2. If anything, we might expect to see two FDs stated separately, viz., {SNO} → {CLASS} and {SNO} → {CITY}.
66
Chapter 6 / Preserving FDs
… AND STILL ANOTHER Consider now a revised version of the example from the previous section in which suppliers are again partitioned into classes, but each class has just one associated city (where each city in turn has just one associated status, as before). So we have a relvar RX3 that looks like this (again I’ll ignore supplier names for simplicity): RX3 { SNO , CLASS , CITY , STATUS } In fact, of course, RX3 has the same heading as RX2 did, but the predicate is different: Supplier SNO is part of class CLASS, which has associated city CITY, which has status STATUS. The following FDs hold among others: → { CLASS } { SNO } { CLASS } → { CITY } { CITY } → { STATUS } Relvar RX3 isn’t in 3NF, because in the FD {CLASS} → {CITY}, {CLASS} isn’t a superkey and {CITY} isn’t a subkey. (The same goes for {CITY} → {STATUS}, mutatis mutandis.) The conventional normalization procedure would thus recommend that we decompose the relvar by applying Heath’s Theorem to that FD {CLASS} → {CITY}. But if we do, this is what we get: RX3A { CLASS , CITY } KEY { CLASS } RX3B { SNO , CLASS , STATUS } KEY { SNO } RX3A is in 3NF but RX3B is only in 2NF─and as you can see, the FD {CITY} → {STATUS} is lost. In fact, it would have been better to decompose on the basis of the FD {CITY} → {STATUS}: RX3A′ { CITY , STATUS } KEY { CITY } RX3B′ { SNO , CLASS , CITY } KEY { SNO } RX3A′ is in 3NF while RX3B′ is only in 2NF, but at least the FD {CITY} → {STATUS} has been preserved. What’s more, we can now go on to decompose RX3B′ on the basis of the FD {CLASS} → {CITY} to obtain: RX3BA′ { CLASS , CITY } KEY { CLASS } RX3BB′ { SNO , CLASS } KEY { SNO } These relvars are both in 3NF. So now we’ve seen four different examples of decompositions in which FDs are or might be lost. There’s more that could be said on the topic, but one clear message is: The conventional normalization procedure—in fact, the one that’s often taught in practice—is inadequate in several respects. To be specific:
Preserving FDs / Chapter 6
67
n
Conventional wisdom has it that FD preservation is relevant only to the step from 3NF to BCNF, but as we’ve seen such isn’t necessarily the case.
n
The FDs typically suggested by the conventional procedure as the basis for decomposition aren’t necessarily the best ones to use.
n
That procedure also assumes the best design can be found by stepping from 1NF to 2NF to 3NF (etc.) in sequence.
Of course, the very nomenclature of “first,” “second,” etc. reinforces this last perception ... but that nomenclature is really nothing more than a historical accident, in a way. I mean, if the first of the normal forms to be defined had been BCNF—which it easily could have been, since the definition is so conceptually simple, involving as it does no mention of FD irreducibility, nonkey attributes, subkeys, 1NF, 2NF, or 3NF—then there would really never have been any need to call out 2NF and 3NF as specific normal forms, as such, at all.8
A PROCEDURE THAT WORKS Here now is a procedure that’s guaranteed to produce a decomposition in which all relvars are in 3NF (though not necessarily BCNF) and all FDs are preserved.9 For convenience, I’ll refer to it in what follows as the 3NF procedure. The input is a relvar R and what’s called an irreducible cover, C say, for the FDs that hold in R. I’ll explain what an irreducible cover is in a few moments—by the way, there’s that word irreducible again—but let me state the procedure first: 1.
Let S be a set of headings. Initialize S to the empty set, {}.
2.
Let X be the left side (the determinant) of some FD in C; let the complete set of FDs in C with left side X be X → Y1, ..., X → Yn; and let the union of Y1, ... Yn be Y. Add the union of X and Y to S. Perform this step for each distinct X.
3.
Let U be the set of attributes of R not contained in any element of S. If U is nonempty, add U to S.
4.
If no element of S is a superkey for R, add some key K of R to S.
At the conclusion of this procedure, the elements of S are the headings of a set of 3NF relvars into which R can be nonloss decomposed without losing any FDs. Note in particular that the procedure makes no explicit mention of 2NF, not even as some kind of stepping stone. So how does it work? Clearly, the notion of an irreducible cover is important. In order to explain that notion, let me first call out something I’ve appealed to several times already in passing: namely, the fact that some FDs imply others. As a simple example, the FDs X → Y and Y → Z together imply the FD X → Z─by which I mean, if the first two FDs are satisfied by relation r, then the third one must be satisfied as well. Or, perhaps more to the point: If the first two hold in relvar R, then the third one must hold as well. We saw an illustration in the
8 In support of this contention, I’d like to quote something Codd himself had to say in the paper in which he introduced 2NF and 3NF (see Appendix C): “The basic ideas underlying [these] normal forms are simple, but they have many subtle ramifications. The author has found that numerous examples are needed to explain and motivate the precise definitions of these normal forms.” 9
I give this procedure partly for historical reasons. You can skip it if you like.
68
Chapter 6 / Preserving FDs
previous section, in relvar RX3, where the FDs {CLASS} → {CITY} and {CITY} → {STATUS} both held and so the FD {CLASS} → {STATUS} held as well. So some FDs imply others. Given a set F of FDs, then, we can sensibly talk about a cover for F. Here’s the definition: n
Definition: A cover for a set F of FDs is a set C of FDs such that every FD in F is implied by the FDs in C. As a trivial example, let F be the set: { X → Y , Y → Z , X → Z }
Then the following are both covers for F: { X → Y , Y → Z } { X → Y , Y → Z , X → Z } This example illustrates two points: First, covers aren’t unique, in general; second, any set of FDs is certainly a cover for itself, because among other things every FD implies itself. A third and more important point is the following: Enforcing the FDs in a cover C for a given set F will “automatically” enforce those in that set F. Thus, given some set F of FDs that need to be enforced, it’s sufficient to find some cover C for F and enforce the FDs in C instead. (In particular, it’s sufficient to enforce the FDs in an irreducible cover for F, as will quickly become clear.) Now I can define what it means for a cover to be irreducible: n
Definition: A cover C for a set F of FDs is irreducible if and only if it possesses all of the following properties: 1.
Singleton dependant: Every FD in C has just one attribute on the right side.
2.
Irreducible determinant: Every FD in C is itself irreducible. Note: I’m being a trifle sloppy here. Recall from Chapters 4 and 5 that FD irreducibility is defined only with respect to some relvar─but I haven’t said anything here about the FDs in F as holding in any relvar, and there’s thus no context that would allow us to talk legitimately about FDs being irreducible. What I mean, however, is that no attribute can be discarded from the left side without losing the property that C is a cover for F.
3.
No redundant FDs: No FD can be discarded from C without losing the property that C is a cover for F.
The obvious question arises: Given some specific set of FDs, how can we find an irreducible cover for that set? I’ll answer this question properly in the next chapter. For now, let me just give an example—namely, an irreducible cover for the FDs that hold in our usual suppliers relvar S: { SNO } → { SNAME } { SNO } → { CITY } { CITY } → { STATUS }
Preserving FDs / Chapter 6
69
To elaborate briefly: It’s certainly the case that every FD that holds in S is implied by these three taken together, so these three certainly constitute a cover. Also, each of the three has a singleton dependant; no attribute can be dropped from any of the determinants; and none of the FDs can be discarded. It follows that the cover is in fact an irreducible one. By contrast, the following sets of FDs are covers for the FDs that hold in S but aren’t irreducible (in each case, why not?): { SNO } → { SNAME , CITY } { CITY } → { STATUS } { SNO , SNAME } → { CITY } { SNO } → { SNAME } { CITY } → { STATUS } { { { {
SNO } SNO } CITY } SNO }
→ → → →
{ { { {
SNAME } CITY } STATUS } STATUS }
Now let’s get back to the 3NF procedure. In particular, let’s see how it works out for the SJT example.10 Just to remind you, the relvar had attributes S, J, and T; keys {S,J} and {S,T}; and was subject to the FD {T} → {J}. So these FDs hold: { S , J } → { T } { S , T } → { J } { T } → { J } It’s easy to see, however, that the FD {S,T} → {J} is redundant here—in fact, I effectively assumed as much when I first discussed this example earlier in the chapter—and hence that the other two FDs together form an irreducible cover (which I’ll call C): { S , J } → { T } → { J } { T } Now we can apply the 3NF procedure. We start with an empty set of headings S. The second step does two things: It gathers together FDs in C that have the same left side—something that’s effectively already been done in the example—and then adds the sets (actually headings) { S , J , T } { T , J } to S. The third step has no effect, since every attribute of the original relvar is now contained in at least one element of S. The last step also has no effect, since the element {S,J,T} of S is a superkey for the original relvar. Overall, therefore, the 3NF procedure tells us that relvar S can be nonloss decomposed, in an FD preserving way, into its projections on {S,J,T} and {T,J}. Points arising:
10 Of course SJT is already in 3NF, but we can still apply the procedure to it─and I have my reasons, which will become apparent later, for wanting to do so.
70
Chapter 6 / Preserving FDs
n
The projection on {S,J,T} is of course identical to the original relvar!—in other words, it’s an identity projection (see the section immediately following this one), and there isn’t much decomposition, as such, going on here.
n
There doesn’t actually seem to be much point in maintaining the second relvar (i.e., the projection on {T,J}) as well as the original one, unless we want to be able to say that, e.g., Professor Black teaches Physics without there existing, at the same time, some student who’s actually being taught by Professor Black. If we don’t want this ability, we probably won’t want to maintain that second relvar. Thus, the decomposition produced by the 3NF isn’t necessarily a recommended one—but, to repeat, it’s one in which all relvars are in 3NF and all FDs are preserved.
I’ll leave it as an exercise (Exercise 6.3) to show what happens when the 3NF procedure is applied to relvars RX1, RX2, and RX3. Meanwhile, I’d like to close this section with a few words regarding BCNF. First, we can add another (fifth) step to the 3NF procedure, as follows: 5.
Let Z be an element of S such that the projection P of relvar R on the attributes of Z is not in BCNF; let X → Y be an element of C (i.e., an FD) that holds in P; and let X not be a superkey for P. Replace Z in S by (a) the union of X and Y and (b) the difference Z - Y between Z and Y (in that order). Perform this step for each distinct Z and each distinct X.
Now, the 3NF procedure applied to relvar SJT produced a set S consisting of the headings {T,J} and {S,J,T}. The projection of SJT on {T,J} is in BCNF, but the (identity) projection of SJT on {S,J,T} isn’t, because the FD {T} → {J} holds in this latter projection and {T} isn’t a superkey. Applying Step 5, therefore, we delete the heading {S,J,T} and insert (a) the union of {T} and {J}—but this insertion has no effect, since that union is already an element of S—and (b) the difference between {S,J,T} and {J}, in that order. Thus, S winds up with the following headings as elements: { S , T } { T , J } These are the headings of a set of BCNF relvars into which SJT can be nonloss decomposed (the keys for those relvars are {S,T} and {T}, respectively). As you can see, therefore, adding Step 5 to the 3NF procedure converts it into a BCNF procedure, though without any guarantee that FDs will be preserved. (In fact, of course, it’s impossible to provide any such guarantee, since we already know that BCNF and FD preservation can be conflicting objectives.) However, any FDs lost are ones that can’t be preserved without violating BCNF. Actually we can simplify matters somewhat and go straight to BCNF—i.e., bypassing 3NF—as follows (the input is as for the 3NF procedure; i.e., it consists of a relvar R and an irreducible cover C for the FDs that hold in R): 1.
Initialize S to contain just the heading of R.
2.
(Same as Step 2 of the 3NF procedure.) Let X be the left side (the determinant) of some FD in C; let the complete set of FDs in C with left side X be X → Y1, ..., X → Yn; and let the union of Y1, ... Yn be Y. Add the union of X and Y to S. Perform this step for each distinct X.
3.
Let Z be an element of S such that the projection P of R on the attributes of Z is not in BCNF; let X → Y be an FD of C that holds in P; and let X not be a superkey for P. Replace Z in S by (a) the union of X and Y and (b) the difference Z - Y between Z and Y (in that order). Perform this step for each distinct Z and each distinct X.
Preserving FDs / Chapter 6
71
At the conclusion of this procedure, the elements of S are the headings of a set of BCNF relvars into which R can be nonloss decomposed, though not necessarily without losing FDs. Also, let me point out for the record that the procedure makes no mention of either 2NF or 3NF.
IDENTITY DECOMPOSITIONS It’s a bit of a digression from the main theme of this chapter, but I’d like to elaborate briefly on the concept of an identity projection. Here’s a definition (I define it for relvars, but of course an analogous concept applies to relations as well): n
Definition: The identity projection of a given relvar is the projection of that relvar on all of its attributes.
Now, it should be obvious that any relvar can be nonloss decomposed, albeit trivially, into its identity projection. However, some people don’t like to think of such a decomposition as being a decomposition, as such, at all (as I said in connection with the SJT example, “there isn’t much decomposition, as such, going on here”). If you happen to be one of those people, then, you might prefer the following way of looking at the matter. Let relvar R have heading H. Then it’s certainly true that the FD {} → {} holds in R, where {} is the empty set of attributes (this FD is trivial, of course, and holds in every relvar). By Heath’s Theorem, therefore—take X, Y, and Z to be {}, {}, and H, respectively—R can be nonloss decomposed into its projections R1 and R2, where: 1.
The heading XY of R1 is the union of {} and {}, which reduces to just {}; i.e., R1 is the projection of R on no attributes at all, and its value is either TABLE_DUM, if R is empty, or TABLE_DEE otherwise.11
2.
The heading XZ of R2 is the union of {} and H, which reduces to just H; i.e., R2 is the projection of R on all of its attributes, or in other words the identity projection of R.
I hope it’s clear that this decomposition is nonloss—R is certainly equal to the join of R1 and R2. (On the other hand, it’s also true that the combination of R1 and R2 fails to meet the usual requirement that both projections should be needed in the reconstruction process.) While I’m on the subject of what might be called identity decompositions, let me remark that any relvar can also always be decomposed (again trivially, but this time “horizontally” instead of “vertically”) into the corresponding identity restriction.12 Here’s a definition (again I define it for relvars, but of course an analogous concept applies to relations as well): n
Definition: The identity restriction of a given relvar R is any restriction of R in which the restriction condition is identically true—in other words, any restriction of R that’s logically equivalent to one of the following form: R WHERE TRUE
11 TABLE_DUM and TABLE_DEE are pet names for, respectively, the unique relation with no attributes and no tuples and the unique relation with no attributes and one tuple. (We’ve met these relations before, in the answer to Exercise 2.8 in Appendix D.) For further discussion, see SQL and Relational Theory. 12
For precise definitions of restriction and the associated notion of a restriction condition, see the answer to Exercise 13.13 in Appendix D.
72
Chapter 6 / Preserving FDs
Note: In logic, something that’s identically true, such as the boolean expression CITY = CITY, is called a tautology. Thus, we can say the identity restriction of relvar R is any restriction in which the restriction condition is a tautology. I remark in passing that any given relvar R also always has an empty restriction, which we can denote thus: R WHERE FALSE The (disjoint!) union of the identity restriction and the empty restriction of a given relvar R is of course identically equal to R. Note: In logic, something that’s identically false, such as the boolean expression CITY ≠ CITY, is called a contradiction; thus, we can say the empty restriction of relvar R is any restriction in which the restriction condition is a contradiction.13
MORE ON THE CONFLICT To revert to the main theme of the chapter: By now we’ve seen several examples in which FDs might be lost. In most of those examples, we could avoid losing the FD by being careful; in one case, however (the SJT example), the objectives of preserving FDs and BCNF decomposition were genuinely in conflict with each other. So the obvious question arises: Can we characterize those cases where there really is a conflict? The answer is yes; in fact, it’s easy to do so. Let R be the relvar we’re dealing with, and let C be an irreducible cover for the FDs that hold in R. Construct an FD graph as follows: 1.
Construct a node for each attribute of R.
2.
Let X → Y be an FD in C for which X involves two or more attributes; construct a “supernode” containing just the nodes for the attributes named in X. (If you’re doing this on paper, you could draw a circle enclosing the individual attribute nodes.) Supernodes are considered to be nodes. Repeat this step for each FD in C for which the determinant is composite.
3.
Let X → Y be an FD in C. Draw a directed arc from the node for X to the node for Y. Repeat this step for each FD in C.
4.
If and only if the finished graph contains any cycles (where a cycle is a sequence of directed arcs from a node to itself), then R cannot be nonloss decomposed into BCNF projections without losing an FD.
As an exercise, try applying the foregoing procedure to the various examples discussed earlier in the chapter. When you do, you’ll quickly understand (if you haven’t done so already) what’s really going on here. To spell the point out: There’s a genuine conflict only if the relvar involves a pattern of FDs akin to the pattern that obtains in the SJT example.
13 The term contradiction doesn’t mean quite the same in logic as it does in ordinary discourse, but the difference isn’t important for present purposes.
Preserving FDs / Chapter 6
73
INDEPENDENT PROJECTIONS To close this chapter, I’d like to return to the example I opened it with. Just to remind you, that example involved the nonloss decomposition of our usual suppliers relvar S into its projections SNC (on {SNO,SNAME,CITY}) and ST (on {SNO,STATUS}). That decomposition lost the FD {CITY} → {STATUS}, with the consequence that updates to either of the projections sometimes required updates to the other, in order to enforce the constraint that each city has just one status. By contrast, the “sensible” decomposition into projections SNC (on {SNO,SNAME,CITY}) and CT (on {CITY,STATUS}) suffers from no such problem—updates can be made to either projection without regard to the other.14 For the sake of the present discussion, let me refer to decompositions like the one into SNC and ST as bad and decompositions like the one into SNC and CT as good. As we’ve seen, then, the projections in a good decomposition can be updated independently of each other; for that reason, they’re sometimes referred to explicitly as independent projections. By contrast, the projections in a bad decomposition aren’t independent in that same sense. So we can say that in order to preserve FDs, we want a decomposition in which the projections are independent. And there’s a theorem, due to Jorma Rissanen, that can help in this regard. Before I state that theorem, however, let me give a precise definition of what it means for two projections to be independent: n
Definition: Projections R1 and R2 of relvar R are independent if and only if every FD that holds in R also holds in the join of R1 and R2. Here now is the theorem:
n
Rissanen’s Theorem: Let relvar R, with heading H, have projections R1 and R2, with headings H1 and H2, respectively; further, let H1 and H2 both be proper subsets of H, let their union be equal to H, and let their intersection not be empty.15 Then projections R1 and R2 are independent if and only if (a) their common attributes constitute a superkey for at least one of them and (b) every FD that holds in R is implied by those that hold in at least one of them.
Consider the “good” decomposition of S into its projections SNC and CT. Those two projections are independent, because (a) the set of common attributes is just {CITY} and {CITY} is a (super)key for CT, and (b) every FD that holds in S either holds in one of the two projections or is implied by those that do (see the next chapter). By contrast, consider the “bad” decomposition into the projections SNC and ST. Here the projections aren’t independent, because the FD {CITY} → {STATUS} can’t be inferred from those holding in those projections—although it’s at least true that the set of common attributes, {SNO}, is a key for both. As a historical note, it was Rissanen’s work on independent projections (which was done, or at least published, in 1977) that laid the foundation for the theory of what we now call FD preservation.
14
15
Except that there might be a foreign key constraint, or even an equality dependency, between {CITY} in CT and {CITY} in SNC.
The condition that the intersection of H1 and H2 not be empty is as in Rissanen’s original statement of the theorem but appears to be unnecessary.
74
Chapter 6 / Preserving FDs
EXERCISES 6.1 Relvar SJT from the section “An Unfortunate Conflict” is subject to the FD {S,J} → {T}. Write a CONSTRAINT statement in Tutorial D to express the multirelvar constraint that replaces this FD if we decompose SJT into its projections TJ on {T,J} and TS on {T,S}. 6.2 (Repeated from the body of the chapter.) Suppose relvar RX2A′ from section “... And Another” is decomposed into its projections on {CLASS,STATUS} and {CITY,STATUS}. As noted in that section, an appropriate multirelvar constraint will now have to be separately stated and enforced. What does that constraint look like? 6.3
The following relvar is intended to represent a set of United States addresses: ADDR { STREET , CITY , STATE , ZIP }
A typical tuple might look like this (Tutorial D syntax): TUPLE { STREET ‘1600 Pennsylvania Ave.’ , CITY ‘Washington’ , STATE ‘DC’ , ZIP ‘20500’ } } Assume, not entirely unreasonably, that the following FDs hold in this relvar and are irreducible: { STREET , CITY , STATE } → { ZIP } { ZIP } → { CITY , STATE } How would you decompose this relvar? 6.4 Show the effects of applying the 3NF procedure to relvars RX1, RX3, and RX2 (note the sequence here!) from the body of the chapter. 6.5 Here’s a predicate: Star S plays role R in movie M, which was directed by director D and released in year Y; further, star S was born on date B and therefore has zodiac sign Z and Chinese zodiac C, and Z and C together determine S’s horoscope H. Give a set of FDs that capture the foregoing state of affairs. State any assumptions you make regarding “business rules” that might be in effect. Also, apply the BCNF procedure to obtain an appropriate set of BCNF relvars. Does that procedure lose any FDs?
Chapter 7
FD Axiomatization [The] true and solid and living axioms —Francis Bacon: The New Organon
I’ve touched on the point several times already that some FDs imply others; now it’s time to get more specific. First of all, however, I need to introduce some notation—notation that (a) reduces the number of keystrokes required in formal proofs and the like and (b) can also help, sometimes, to see the forest as well as the trees, as it were. As you might recall, the statement of Heath’s Theorem in Chapter 5 included the following sentence: Let XY denote the union of X and Y, and similarly for XZ. The notation I want to introduce is basically just an extension of this simple idea (it’s a trifle illogical, but it’s very convenient). To be specific, the notation uses expressions of the form XY to mean: n
The union of {X} and {Y}, if X and Y denote individual attributes (i.e., are individual attribute names)
n
The union of X and Y, if X and Y denote sets of attributes (i.e., are sets of attribute names)
It also allows {X} to be abbreviated to just X (e.g., in an FD) if X denotes an individual attribute. Note: For convenience, I’ll refer to this notation from this point forward as Heath notation.
ARMSTRONG’S AXIOMS We’ve seen that, formally speaking, an FD is just an expression of the form X → Y, where X and Y are sets (actually sets of attribute names, but from a formal point of view it really doesn’t matter what the sets consist of). Now, suppose we’re given some set (F, say) of FDs. Then we can apply certain formal rules of inference to derive further FDs from the ones in F—FDs that are implied by the ones in F, meaning that if the ones in F hold in some relvar R, then the derived ones do so too. The rules in question were first stated by Armstrong in 1974 and for that reason are usually referred to as Armstrong’s inference rules or (more commonly) Armstrong’s axioms. They can be stated in a variety of equivalent ways, of which the following is perhaps the simplest: 1.
If Y is a subset of X, then X → Y (“reflexivity”).
2.
If X → Y, then XZ → YZ (“augmentation”).
3.
If X → Y and Y → Z, then X → Z (“transitivity”).
Observe that these rules are intuitively reasonable, given the intended interpretation of an FD. That is, since we know what FDs “mean,” we can easily see that, e.g., if the FDs X → Y and Y → Z both hold in relvar R, then the FD X → Z must do so too. Note: The suppliers relvar S illustrates this particular rule—the FDs {SNO} → {CITY} and {CITY} → {STATUS} both hold in that relvar, and therefore the FD {SNO} → {STATUS} does so, too.
76
Chapter 7 / FD Axiomatization
So the rules are reasonable. But what’s more important is that they’re both sound and complete. Soundness and completeness are concepts frequently encountered in connection with formal systems in general. In the formal system under consideration here, this is what they mean: n
Completeness: If an FD f is implied by the ones in the given set F, then it can be derived from the ones in F by means of the rules. (To repeat, to say some FD f is implied by the FDs in some set F is to say that if the FDs in F hold, then f holds too.)
n
Soundness: If an FD f isn’t implied by the ones in the given set F, then it can’t be derived from the ones in F by means of the rules.1
The rules thus form what’s called an axiomatization for FDs. As a consequence, they can be used to derive what’s called the closure F+of any given set F of FDs. Here’s a definition: n
Definition: Let F be a set of FDs. Then the closure F+ of F is the set of all FDs implied by those in F.
What’s more, the derivation process can be mechanized; that is, Armstrong’s rules can be incorporated into (e.g.) a design tool that, given a set F of FDs that hold in some relvar R, will be able to compute the closure F+ of that set F, or in other words the complete set of all FDs that hold in that relvar. The significance of this fact should be obvious.
ADDITIONAL RULES Several additional inference rules can be derived from the original three, the following among them. Such additional rules can be used to simplify the practical task of computing F+ from F. Here are some examples: 4.
X → X (“self determination”).
5.
If X → Y and X → Z, then X → YZ (“union”).
6.
If X → Y and Z → W, then XZ → YW (“composition”).
7.
If X → YZ, then X → Y and X → Z (“decomposition”).2
In the next section, I’ll show how these four rules can be derived from the original three. First, however, let me give a couple of examples to show how the rules (original and/or additional) can be used. By way of a first example, suppose we’re given a relvar R with attributes A, B, C, D, E, F, and we’re told the following FDs hold in that relvar:
1
If you have a background in logic, you might like the following characterization: Soundness means all theorems are tautologies; completeness means all tautologies are theorems. Or more intuitively (and with acknowledgments to Hugh Darwen): Soundness means if you can prove it, it’s true; completeness means if it’s true, you can prove it. 2 Two points: First, don’t confuse this kind of decomposition with nonloss decomposition as discussed at length elsewhere in this book. Second, observe that composition and decomposition as here defined aren’t quite inverses of each other; to be specific, the inverse of decomposition is that special case of composition in which Z is replaced by X and W is replaced by Z.
FD Axiomatization / Chapter 7
77
A → BC B → E CD → EF I’ll now show the FD AD → F also holds in R (a fact that, I think you’ll agree, isn’t immediately obvious).3 Here’s the proof: 1. 2. 3. 4. 5. 6.
A A AD CD AD AD
→ → → → → →
BC C CD EF EF F
(given) (1, decomposition) (2, augmentation) (given) (3 and 4, transitivity) (5, decomposition)
For a second example, recall from Chapter 6 the notion of an irreducible cover. Just to remind you, (a) a cover for a given set F of FDs is a set C of FDs such that every FD in F is implied by those in C, and (b) that cover C is irreducible if and only if it possesses all of the following properties: 1.
Singleton dependant: Every FD in C has just one attribute on the right side.
2.
Irreducible determinant: No attribute can be discarded from the left side without losing the property that C is a cover for F.
3.
No redundant FDs: No FD can be discarded from C without losing the property that C is a cover for F.
Now, I assumed in the previous chapter (tacitly) that every set F of FDs had an irreducible cover. In fact, this is easy to see: n
Thanks to the decomposition rule, we can assume without loss of generality that every FD in F has a singleton right side.
n
Next, for each FD in F, examine each attribute A on the left side; if deleting A from that left side has no effect on the closure F+, delete A from that left side.
n
For each FD remaining in F, if deleting that FD from F has no effect on the closure F+, delete that FD from F.
The final version of F is irreducible and is a cover for the original version. Here then is a concrete example to illustrate the process of actually finding an irreducible cover. Let the given set of FDs (which all presumably hold in some relvar R with attributes A, B, C, D) be as follows: A B A AB AC 3
→ → → → →
BC C B C D
If you’d prefer a more concrete example, take A as employee number, B as department number, C as manager’s employee number, D as project number for a project directed by that manager (unique within manager), E as department name, and F as percentage of time spent by the specified manager on the specified project. The FDs A → BC, B → E, and CD → EF are then all intuitively reasonable. (And what about AD → F?)
78
Chapter 7 / FD Axiomatization
Then the following procedure will produce an irreducible cover for this given set. 1.
First, rewrite the FDs such that each has a singleton right side: A A B A AB AC
→ → → → → →
B C C B C D
Observe now that the FD A → B occurs twice, so one occurrence can be dropped. 2.
Attribute C can be dropped from the left side of the FD AC → D, because we have A → C, so A → AC by augmentation, and we’re given AC → D, so A → D by transitivity; thus the C on the left side of AC → D is redundant.
3.
The FD AB → C can be dropped, because again we have A → C, so AB → CB by augmentation, so AB → C by decomposition.
4.
The FD A → C is implied by the FDs A → B and B → C, so it can be dropped.
We’re left with: A → B B → C A → D This set is irreducible.
PROVING THE ADDITIONAL RULES As promised, in this section I show how to derive Rules 4-7 from the original Rules 1-3. 4.
X → X (“self determination”). Proof: Immediate by reflexivity.
5.
If X → Y and X → Z, then X → YZ (“union”). Proof: X → Y (given), hence X → XY by augmentation; also X → Z (given), hence XY → YZ by augmentation; hence X → YZ by transitivity.
6.
If X → Y and Z → W, then XZ → YW (“composition”). Proof: X → Y (given), hence XZ → YZ by augmentation; likewise, Z → W (given), hence YZ → YW by augmentation; hence XZ → YW by transitivity.
FD Axiomatization / Chapter 7
7.
79
If X → YZ, then X → Y and X → Z (“decomposition”). Proof: X → YZ (given) and YZ → Y by reflexivity; hence X → Y by transitivity (and likewise for X → Z).
ANOTHER KIND OF CLOSURE To recap, the closure F+ of a set F of FDs is the set of all FDs implied by those in F. Now, in principle we could compute F+ from F by repeatedly applying Armstrong’s rules (and/or rules derived therefrom) until they stop producing new FDs. In practice, however, there’s little need to compute F+ per se (which is just as well, perhaps, since the procedure just outlined is hardly very efficient). But now I want to show how we can compute a certain subset of F+: namely, that subset consisting of all FDs with a given determinant. More precisely, I’ll show how, given a heading H, a subset Z of H, and a set F of FDs with respect to H, we can compute what’s called the closure Z+ of Z under F. Here’s a definition: n
Definition: Let H be a heading, let F be a set of FDs with respect to H, and let Z be a subset of H. Then the closure Z+ of Z under F is the maximal subset C of H such that Z → C is implied by the FDs in F.
By the way, note that we now have two kinds of closure (try not to confuse them!): closure of a set of FDs, and closure of a set of attributes under a set of FDs.4 Note too that we use the same “superscript plus” notation for both. Here then is a simple pseudocode algorithm for computing the closure Z+of Z under F: +
Z := Z ; do “forever” ; for each FD X → Y in F do ; + if X is a subset of Z + + then replace Z by the union of Z and Y ; end ; + if Z did not change on this iteration then quit ; /* computation complete */ end ; Let’s do an example. Suppose the given heading is ABCDEG and we want to compute the closure AB+ of the set of attributes AB under the following set F of FDs: A E B CD
→ → → →
BC CG E EG
Let’s now step through the algorithm: 1.
4
First of all, we initialize the result AB+ to the set of attributes AB.
Not to mention the kind of closure that applies to the operators of the relational algebra.
80
Chapter 7 / FD Axiomatization
2.
We now go round the inner loop four times, once for each of the given FDs. On the first iteration (for the FD A → BC), we find that the determinant A is indeed a subset of AB+ as computed thus far, so we add attributes (B and) C to the result. AB+ is now the set ABC.
3.
On the second iteration (for the FD E → CG), we find that the determinant E is not a subset of the result as computed so far, which thus remains unchanged.
4.
On the third iteration (for the FD B → E), we add E to AB+, which thus now has the value ABCE.
5.
On the fourth iteration (for the FD CD → EG), AB+ remains unchanged.
6.
Now we go round the inner loop four times again. On the first iteration, the result remains unchanged; on the second, it expands to ABCEG; on the third and fourth, it remains unchanged.
7.
Now we go round the inner loop four times again. The result remains unchanged, and so the whole process terminates, with AB+ = ABCEG.
Well, I hope you can see from this example that computing Z+ given H, F, and Z is essentially straightforward. And the important thing is this: Given some set F of FDs (with respect to some heading H), we can easily tell whether some specific FD X → Y (with respect to that same heading H) is implied by F, because it will be so if and only if Y is a subset of the closure X+ of X under F. In other words, we now have a simple way of determining whether a given FD X → Y is in the closure F+ of F without actually having to compute F+. It also follows from the definition (of closure of a set of attributes) that the superkeys for a relvar R are precisely those subsets SK of the heading of R such that the closure SK+ of SK—under the pertinent set of FDs—is the entire heading of R.
EXERCISES 7.1
What does it mean to say that Armstrong’s rules are sound? Complete?
7.2
What’s the closure of a set of FDs? Show the closure of the set of FDs that hold in the shipments relvar SP.
7.3 Given the definition of what it means for an FD to be satisfied, show that the reflexivity, augmentation, and transitivity rules are reasonable. (Try this exercise without referring back to the body of the chapter.) Prove that the three rules of the 7.4 previous exercise imply the self determination, union, composition, and decomposition rules. 7.5 n
The following theorem is due to Hugh Darwen:5 If X → Y and Z → W, then XV → YW, where V = Z - Y.
5 Hugh Darwen: “The Role of Functional Dependence in Query Decomposition,” in C. J. Date and Hugh Darwen, Relational Database Writings 1989-1991 (Addison-Wesley, 1992).
FD Axiomatization / Chapter 7
81
Prove this theorem. Which rules from the previous two exercises did you use? Which rules from those exercises can be derived as special cases of the theorem? 7.6
Find an irreducible cover for the following set of FDs: AB C BC ACD
7.7
→ → → →
C A D B
BE CE CF D
→ → → →
C FA BD EF
Consider the following FDs: A → B BC → DE AEF → G
Is the FD ACF → DG implied by this set? 7.8
Two sets of FDs are equivalent if and only if each is a cover for the other. Are the following sets equivalent? { A → B , AB → C , D → AC , D → E } { A → BC , D → AE }
Note that any given set F of FDs is certainly equivalent to a set C if C is an irreducible cover for F, and further that two sets are equivalent if and only if they have the same irreducible cover. 7.9
Relvar R has attributes A, B, C, D, E, F, G, H, I, and J, and is subject to the following FDs: ABD → E AB → G B → F
C → J CJ → I G → H
Is this set reducible? What keys does R have?
Chapter 8
Denormalization What’s normal, anyway? —Anon.: Where Bugs Go
I want to say a few words about denormalization. Now, I haven’t considered, so far in this book, any level of normalization higher than BCNF (at least, not in detail). But denormalization, if it means anything at all, can’t apply just to BCNF specifically; I mean, it can’t refer just to dropping back to some level of normalization that’s lower than BCNF specifically. Rather, it has to mean dropping back from any given level of normalization to some lower one. That said, however, I need to say too that relvars that are in BCNF and not in some higher normal form are comparatively unusual (though not completely unknown, I hasten to add). In practice, therefore, denormalization does usually refer quite specifically to dropping back to some level of normalization below BCNF; hence the inclusion of this chapter in this part of the book.
“DENORMALIZE FOR PERFORMANCE”? Ever since SQL products first came on the market, the claim that it’s necessary to “denormalize for performance” has been widely promulgated. The (specious!) supporting argument goes something like this: 1.
Normalization means lots of relvars.
2.
Lots of relvars means lots of stored files.
3.
Lots of stored files means lots of I/O.
In the case of suppliers and parts, for example, a request to get details for suppliers who supply red parts involves two dyadic joins—suppliers to shipments first, perhaps, and then the result of that join to parts. And if the three relvars correspond to three physically separate stored files, then those two joins will require lots of I/O and will therefore perform badly. As already noted, this argument is specious, at least in principle. The reason is that the relational model nowhere stipulates that relvars must map one for one to stored files. In the case of suppliers and parts, for example, there’s no logical reason why we couldn’t physically store the join of the three relvars—possibly even redundantly—as one single stored file on the disk,1 which could reduce the amount of I/O significantly for the query under consideration. The point is irrelevant for present purposes, however, because:
1 I’m speaking pretty loosely here, of course. In particular, I’m ignoring the possibility that there might be some suppliers or some parts with no corresponding shipments.
84
Chapter 8 / Denormalization
n
First, this area is one in which most DBMS vendors have seriously let us down; most SQL products do indeed map relvars one for one to stored files, pretty much.2 Even the exceptions fail to provide us with as much data independence as we might like, or as much as relational systems are theoretically capable of. As a practical matter, therefore, that “specious” argument is, sadly, valid for most SQL products today.
n
Second, even if relvars didn’t map one for one to stored files, denormalization might still be desirable at the stored file level. Indeed, a major reason why mappings that aren’t one for one would be desirable is precisely that they would permit denormalization to be done at the physical level, where it belongs, without it having to show through to—and thereby corrupt—the logical level.
So I’ll assume for the sake of discussion that denormalization does sometimes have to be done, at some level or other. But what is denormalization?
WHAT DOES DENORMALIZATION MEAN? Curiously, for a practice that’s so widely advocated, there seems to be considerable confusion over what denormalization actually consists of. (The textbooks aren’t much help, either, even those that specialize in design topics; most of them don’t even mention it, and those that do rarely offer a definition, and they certainly don’t discuss the matter in much depth.) For example, a while back I had occasion to read a paper specifically devoted to the question of denormalization in commercial SQL products.3 I’ll refer to that paper as “the denormalization paper” in what follows. Now, the author begins by arguing against denormalization. To quote: I think the normalization principles should be treated as commandments ... unless you’re faced with performance problems that money, hardware scalability, current SQL technology, network optimization, parallelization, or other performance techniques can’t resolve [slightly reworded, boldface added].
I couldn’t agree more with this position. Indeed, I’m on record as saying very much the same thing myself: In a paper I wrote in 1990 on the use of SQL systems in practice,4 I recommended denormalization as a performance tactic “only if all else fails.” Unfortunately, however, the rest of the denormalization paper tends to suggest that the author doesn’t really know what denormalization is; after the opening position statement quoted above, the paper goes on to give some eight examples of “designing for performance,” all but one of which have absolutely nothing to do with denormalization at all! In the author’s defense, however, I say again that it does seem to be difficult to find a precise definition of denormalization in the literature. Of course, it could be argued that no such definition is needed, given that (a) denormalization, whatever else it might be, must surely be the inverse of normalization, and (b) normalization in turn certainly is precisely defined. For the record, however, I’ll give some idea as to what a precise definition of denormalization might look like in just a moment. Before I do, however, let me make it clear that I have no particular quarrel with the specific design tactics suggested in the denormalization paper; indeed, I suggested several
2 I realize the mapping from relvars to stored files isn’t always exactly one to one as I’m suggesting here─for example, some products allow several relvars to share the same stored file, and some allow a single relvar to span several stored files. But these facts don’t significantly affect the bigger picture, and I ignore them here for simplicity. 3
Sam Hamdan: “Denormalization and SQL-DBMS,” SQL Forum 4, No. 1 (January/February 1995).
4
“SQL Dos and Don’ts,” in Relational Database Writings 1985-1989 (Addison-Wesley, 1990).
Denormalization / Chapter 8
85
of those same tactics in a paper I wrote myself back in 1982.5 My quarrel is only with the fact that it refers to them as denormalization tactics specifically. So here’s my own definition, for what it’s worth (and I apologize if it seems a little lengthy). I start with the observation that normalizing relvar R means decreasing redundancy by: 1.
Replacing R by a set of projections R1, ..., Rn such that at least one of R1, ..., Rn is at a higher level of normalization than R, and such that also
2.
For all possible values r of R, if the corresponding values r1, ..., rn of R1, ..., Rn (respectively) are joined back together again, then the result of that join is equal to r.
Hence the following definition: n
Definition: Denormalizing a set of relvars R1, ..., Rn means increasing redundancy by: 1.
Replacing R1, ..., Rn by their join R such that R is at a lower level of normalization than at least one of R1, ..., Rn, and such that also
2.
For all possible values r1, ..., rn of R1, ..., Rn (respectively), the result of projecting the corresponding value r of R over the attributes of Ri is equal to ri (i = 1, ..., n).
Points arising: n
Observe that denormalization is a process that applies to a set of relvars, not to an individual relvar considered in isolation. For example, consider relvars SNC and CT, with headings {SNO,SNAME,CITY} and {CITY,STATUS}, respectively (see Fig. 3.2 for some sample values). These two relvars are in BCNF. If we join them together, we get the suppliers relvar S (which is only in 2NF, not in 3NF, and therefore not in BCNF either), and so relvar S can be regarded as a denormalization of relvars SNC and CT. What’s more, of course, relvar S involves more redundancy than relvars SNC and CT do.
n
If (a) R1, ..., Rn were obtained by taking projections of R in the first place—in other words, if the denormalization is really undoing an earlier normalization, so to speak, as in the suppliers example in the previous bullet item—and if also (b) that earlier normalization was done purely to decrease redundancy and not to fix a logically incorrect design (see the remarks in Chapter 3 on the difference between these two possibilities), then (c) the requirement that for all possible values r of R, projecting r over the attributes of Ri must yield ri (i = 1, ..., n) will be met automatically.
The argument in favor of denormalization is basically that it makes retrievals easier to express and makes them perform better.6 To what extent this argument might be valid I’ll examine in a later section. First, however, I’d like to point out that once we make the decision to denormalize, we’ve embarked on a very slippery slope. The question is: Where do we stop? The situation is different with normalization, where there are clear logical reasons for continuing the process until we reach the highest possible normal form. Do we then conclude that with denormalization we should proceed until we reach the lowest possible normal form? Surely not; yet there are no logical criteria for deciding exactly where the process should stop. In choosing to denormalize, in other words, 5
“A Practical Approach to Database Design,” in Relational Database: Selected Writings (Addison-Wesley, 1986).
6
It’s also sometimes claimed to make the database easier to understand. Exercise 8.2 addresses this particular issue.
86
Chapter 8 / Denormalization
we’ve backed off from a position that does at least have some solid science and logical theory behind it, and replaced it by one that’s purely pragmatic in nature (as well as being based, typically, on a somewhat narrow perspective on the overall problem).
WHAT DENORMALIZATION ISN’T (I) I’ve said that denormalization means increasing redundancy. But it doesn’t follow that increasing redundancy means denormalization! This is one of the traps the denormalization paper falls into; the design tactics it describes do increase redundancy (usually), but they’re not—with, as noted earlier, one sole exception—applications of denormalization per se. (In logic, if p implies q is true, it doesn’t follow that q implies p is true, and to argue otherwise is a well known example of faulty reasoning: so well known, in fact, that it enjoys a special name, The Fallacy of False Conversion.) Let’s examine a few of the examples from the denormalization paper. In one, we’re given relvars ITEM and SALES that look like this: ITEM
{ INO , INAME } KEY { INO }
SALES { SNO , INO , QTY } KEY { SNO , INO } FOREIGN KEY { INO } REFERENCES ITEM The predicates are Item INO has name INAME and Quantity QTY of item INO were sold in store SNO, respectively. For performance reasons, the paper suggests adding a TOTAL_QTY attribute to the ITEM relvar, whose value for any given item is the total sales of that item taken over all stores. But although it’s true that the resulting design involves some redundancy, the fact remains that both relvars are still in BCNF (note in particular that the FD {INO} → {TOTAL_QTY} holds in the revised version of relvar ITEM). In other words, there’s no denormalization, as such, in this example. A second example involves what the paper calls “an internal array”: EMP { ENO , JAN_PAY , FEB_PAY , ..., DEC_PAY } KEY { ENO } The predicate is Employee ENO was paid an amount JAN_PAY in January, ..., and an amount DEC_PAY in December. And presumably, though the paper doesn’t say as much explicitly, this “tuple wise” design is meant to be contrasted with—and for performance reasons, possibly preferred to—the following “attribute wise” analog: EMP { ENO , MONTH , PAY } KEY { ENO , MONTH } But both designs are in BCNF. Again, there’s no denormalization here; in fact, to get ahead of myself for a moment (see Chapter 15), I would say there’s no increase in redundancy, either. (On the other hand, the original “tuple wise” design is probably bad, as you’ll see if you consider the query “Get employees whose salary was less than 5K in at least one month, together with the months in question.”) Yet another example involves splitting a RESELLERS relvar “horizontally” into two separate relvars, ACTIVE_RESELLERS and INACTIVE_RESELLERS. In other words, the original relvar is decomposed via restriction (not projection), and is reconstructed from the two restrictions via union (not join). So we’re clearly not
Denormalization / Chapter 8
87
talking about normalization in the classical sense here at all; a fortiori, therefore, we’re not talking about classical denormalization either.7 I’ll give one more example from the denormalization paper. This one starts with STORE and EMP relvars as follows: STORE { SNO , REGION , STATE , ... } KEY { SNO , REGION , STATE } EMP
{ ENO , SNO , REGION , STATE , ... } KEY { ENO } FOREIGN KEY { SNO , REGION , STATE } REFERENCES STORE
The predicates are Store SNO is located in region REGION within state STATE and Employee ENO is employed at store SNO within region REGION within state STATE. The redundancies are obvious, and so the suggestion is to introduce a surrogate identifier for stores, SID say, and thereby modify the design as follows: STORE { SID , SNO , REGION , STATE , ... } KEY { SID } KEY { SNO , REGION , STATE } EMP
{ ENO , SID , ... } KEY { ENO } FOREIGN KEY { SID } REFERENCES STORE
But this revised design not only involves no denormalization, it actually decreases redundancy!8—because the association of a given SNO with a given REGION and STATE now appears just once, instead of once for every employee of the store in question. (To spell the point out, it’s obviously not denormalization because—among other things—the one thing surely everybody agrees on is that denormalization is supposed to increase redundancy.) By the way, I’m aware this last example might give the impression that I think surrogates are a good idea. Sadly, however, they aren’t always a good idea. The fact is, surrogates, while they might solve some problems, can also introduce further problems of their own. See Exercise 8.3, also Chapter 15, for further discussion. In closing this section, I’d like to make it very clear that the foregoing discussions are in no way intended as an attack on the denormalization paper or its author. Indeed, the following quote from that paper should make it clear that the author and I are really on the same side on the bigger issues: [We should] stop criticizing the relational model and make a clear distinction between what’s SQL and what’s relational ... The two are totally different.
I couldn’t agree more with this position, nor with the implication that the only reason we have to worry about such matters as denormalizing at the logical level is because of failures on the part of today’s SQL products. As I’ve written elsewhere, in fact:9 In an ideal system, we would never have to denormalize at all, at the logical level. Even
7 It’s true that it might be possible to define a new kind of normalization, based on restriction and union instead of projection and join (I’ll have more to say about this possibility in Part IV of this book). And if we did, well, I suppose we’d have a new kind of denormalization on our hands also. But I’m pretty sure that such considerations aren’t what the denormalization paper was referring to with its RESELLERS example. 8
Or does it? Again, see Chapter 15, which includes further discussion of the use of surrogates in particular.
9 E.g., in my book An Introduction to Database Systems (8th edition, Addison-Wesley, 2004). For further discussion, see my book Go Faster! The TransRelationaltm Approach to DBMS Implementation (Ventus Publishing, 2002, 2011).
88
Chapter 8 / Denormalization
in today’s systems, which are typically much less than ideal, I believe we should denormalize only as a last resort. That is, we should back off from a fully normalized design only if all other strategies for improving performance have failed, somehow, to meet requirements. (Of course, I’m going along here with the usual assumption that normalization has performance implications—as indeed it does, typically, in current SQL products.)
WHAT DENORMALIZATION ISN’T (II) So far in this chapter I’ve given what I think is a reasonable definition of what denormalization is, and I’ve given some examples of what it isn’t. However, perhaps it was simply a mistake on my part to think the term ought to be used in any kind of precise or logical sense. Certainly it’s used very imprecisely in the industry at large; in fact, it seems to be used—especially in a data warehouse context—to refer to just about anything that could be regarded as bad design practice. What’s more, the practices in question are often explicitly recommended! (by the people who talk that way, that is). Examples of such bad practice include: n
Using repeating groups
n
Permitting duplicate rows
n
Using nulls; worse (?), allowing nulls in keys
n
Mixing different kinds of information in the same column (using a separate “flag” column to specify the type of individual values in the column in question)
n
Using a single text column to represent what ought logically to be distinct columns
I’d like to add a note here on star schemas, since the “star schema” concept and “denormalization” are often mentioned together.10 The basic idea behind this concept as follows. Suppose we wish to collect a history of business transactions for analysis purposes; for example, suppose in the case of suppliers and parts that we wish to record, for each shipment, the particular time interval in which that shipment occurred. Thus, we might identify time intervals by a time interval identifier (TINO), and introduce another relvar TI to relate those identifiers to the corresponding time intervals per se. The revised shipments relvar SP and the new time intervals relvar TI might look as shown in Fig. 8.1. In star schema terminology, SP is the fact table and TI is a dimension table. The suppliers relvar S and the parts relvar P are also dimension tables (see Fig. 8.2).11 And the overall structure is referred to as a “star schema” because of a fancied resemblance of the corresponding entity/relationship diagram to a star, with the fact table being surrounded by—and connected by “spokes” or “rays” to—the dimension tables, as shown in Fig. 8.2. (Those “spokes” or “rays” represent foreign key references, of course.)
10 At least one authority claims it’s misleading to refer to star schemas as denormalized, however. “[The] use of denormalized when describing a star implies that the design started out as normalized. Most designs are not produced in such a manner. Not normalized would be a better description” (from Star Schema: The Complete Reference, by Chris Adamson, McGraw-Hill, 2010). 11 For simplicity I choose to ignore (just for the sake of thye present discussion) the fact that the FD {CITY} → {STATUS} is supposed to hold in relvar S, and hence that relvar S is less than fully normalized.
Denormalization / Chapter 8
SP ┌─────┬─────┬──────┬─────┐ │ SNO │ PNO │ TINO │ QTY │ ├═════┼═════┼══════┼─────┤ │ S1 │ P1 │ T13 │ 300 │ │ S1 │ P1 │ T15 │ 100 │ │ S1 │ P2 │ T11 │ 200 │ │ S1 │ P3 │ T12 │ 400 │ │ S1 │ P4 │ T11 │ 200 │ │ S1 │ P5 │ T15 │ 100 │ │ S1 │ P6 │ T14 │ 100 │ │ S2 │ P1 │ T13 │ 300 │ │ S2 │ P2 │ T14 │ 400 │ │ S3 │ P2 │ T11 │ 200 │ │ S3 │ P2 │ T13 │ 200 │ │ S4 │ P2 │ T11 │ 200 │ │ S4 │ P4 │ T13 │ 200 │ │ S4 │ P5 │ T12 │ 400 │ │ S4 │ P5 │ T11 │ 400 │ └─────┴─────┴──┴───┴─────┘
89
TI ┌──────┬──────┬────┐ │ TINO │ FROM │ TO │ ├══════┼──────┼────┤ │ TI1 │ t0 │ t1 │ │ TI2 │ t2 │ t3 │ │ TI3 │ t4 │ t5 │ │ TI4 │ t6 │ t7 │ │ TI5 │ t8 │ t9 │ └──────┴──────┴────┘
Fig. 8.1: Sample fact table (SP) and dimension table (TI)
.
┌─────┬───────┬────────┬──────┐ ┌──────┬──────┬────┐ S │ SNO │ SNAME │ STATUS │ CITY │ T1 │ TINO │ FROM │ TO │ └══▲══┴───────┴────────┴──────┘ └═══▲══┴──────┴────┘ └───────────────┐ ┌─────────┘ ┌──┼──┬─────┬───┼──┬─────┐ SP │ SNO │ PNO │ TINO │ QTY │ └═════┴══╪══┴══════┴─────┘ ┌───────────┘ ┌──▼──┬───────┬───────┬────────┬──────┐ P │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY │ └═════┴───────┴───────┴────────┴──────┘ Fig. 8.2: Star schema for suppliers and parts (with time intervals)
. Now, you might be wondering what the difference is between a star schema and a conventional relational design. In fact, a star schema for a simple example like the one under discussion is likely to be identical to a good relational design. In more complex situations, however, the dimension tables are often less than fully normalized (the objective here apparently being to avoid joins).12 What's more, other relational design recommendations are often violated, too (see the bullet list earlier in this section). Detailed discussion of star schemas and related matters is beyond the scope of this book; you can find a slightly more extended discussion in my book An Introduction to Database Systems (8th edition, Addison-Wesley, 2004).
12
In this connection, consider this advice from a book on data warehouses: “[Resist] normalization ... Efforts to normalize any of the tables in a dimensional database solely in order to save disk space [sic!] are a waste of time ... The dimension tables must not be normalized ... Normalized dimension tables destroy the ability to browse” (from Ralph Kimball, The Data Warehouse Toolkit, John Wiley & Sons, 1996).
90
Chapter 8 / Denormalization
DENORMALIZATION CONSIDERED HARMFUL (I) In this section, I’d like to present an argument—a logical argument, that is, and one you might not have seen before—in support of the position that you should denormalize only as a last resort. Essentially, the argument is that while (as is well known) denormalization can be logically bad for update, it can be logically bad for retrieval as well, in the sense that it can make certain queries harder to formulate. (Alternatively, it can make them easier to formulate incorrectly, meaning that, if they execute, you’re getting answers that might be correct in themselves but are answers to the wrong questions.) Let me illustrate. Once again consider relvar S, with its FD {CITY} → {STATUS}. As noted earlier, that relvar can be regarded as the result of denormalizing relvars SNC (with attributes SNO, SNAME, and CITY) and CT (with attributes CITY and STATUS). Now consider the query “Get the average supplier city status value.” Given the sample values in Fig. 3.2, the status values for Athens, London, and Paris are 30, 20, and 30, respectively, and so the average is 80/3, which is 26.667 to three decimal places. Here then are some attempts at formulating this query in SQL (I’ll assume for simplicity that S is nonempty, so we don’t have to worry about what happens in SQL if we try to apply the AVG operator to an empty set):13 1.
SELECT AVG ( STATUS ) AS RESULT FROM S Result (incorrect): 26. The problem here is that London’s status and Paris’s status have both been counted twice. Perhaps we need a DISTINCT inside the AVG invocation? Let’s try that:
2.
SELECT AVG ( DISTINCT STATUS ) AS RESULT FROM S Result (incorrect): 25. No, it’s distinct cities we need to examine, not distinct status values. We can do that by grouping:
3.
SELECT CITY , AVG ( STATUS ) AS RESULT FROM S GROUP BY CITY Result (incorrect): (Athens,30), (London,20), (Paris,30). This formulation gives average status per city, not the overall average. Perhaps what we want is the average of the averages?─
4.
SELECT CITY , AVG ( AVG ( STATUS ) ) AS RESULT FROM S GROUP BY CITY Result: Syntax error—the SQL standard quite rightly doesn’t allow “set function” invocations to be nested in this manner.14 One more attempt:
13
14
What changes would be needed to the various SQL expressions if we couldn’t make that assumption?
I say “quite rightly” only because we’re in the SQL context specifically; a more orthodox language such as Tutorial D would certainly let us nest such invocations (or its analog of such invocations, rather). Let me explain. Consider the SQL expression SELECT SUM(QTY) AS RESULT FROM SP WHERE QTY > 100 (I deliberately switch to a different example for reasons of clarity). The argument to the SUM invocation here is really what’s denoted by the expression QTY FROM SP WHERE QTY > 100, and a more orthodox language would therefore enclose that whole expression in parentheses. But SQL doesn’t. As a consequence, an expression of the form AVG(SUM(QTY)) has to be illegal, because SQL can’t figure out which portions of the surrounding expression have to do with the AVG argument and which with the SUM argument.
Denormalization / Chapter 8
5.
91
SELECT AVG ( TEMP.STATUS ) AS RESULT FROM ( SELECT DISTINCT S.CITY , S.STATUS FROM S ) AS TEMP Result (correct at last): 26.667. But note how complicated this expression is compared to its analog on the fully normalized design (relvars SNC and CT):
6.
SELECT AVG ( STATUS ) AS RESULT FROM CT
DENORMALIZATION CONSIDERED HARMFUL (II) I said earlier that the argument in favor of denormalization was that it makes retrievals easier to express and makes them perform better. But does this argument really stand up to careful analysis? Let’s take a closer look. First of all, it clearly isn’t true across the board that retrievals are easier to express; the previous section presented a detailed counterexample, but the point can be made with much simpler examples. By way of illustration, consider what’s involved in formulating the query “Get all supplier details” against (a) the normalized design of Fig. 1.1 and (b) a denormalized design in which relvars S, SP, and P are replaced by a single “joined” relvar called, say, SSPP. Here are Tutorial D formulations: a.
S
b.
SSPP { SNO , SNAME , STATUS , CITY }
Or if you prefer SQL: a.
SELECT * FROM S
b.
SELECT DISTINCT SNO , SNAME , STATUS , CITY FROM SSPP
The next point is that many queries are likely to perform worse, too. There are several reasons for this state of affairs. One is that denormalization leads to redundancy, which in turn can lead to a need to do duplicate elimination (note that DISTINCT in the second of the foregoing SQL formulations!). Another is as follows: n
Suppose again that the join of suppliers, shipments, and parts is represented as one single stored file. Also, assume for simplicity that any given stored file consists of a physically contiguous collection of stored records, one for each tuple currently appearing in the relvar the stored file represents.
n
Let’s suppose too for the sake of the argument that the query “Get details for suppliers who supply red parts” will perform reasonably well against this physical structure. OK; but the query “Get all supplier details” will perform worse than it would against the structure in which the three relvars map to three physically separate stored files! Why? Because in the latter design, all supplier stored records will be physically contiguous, whereas in the former design they’ll effectively be spread over a wider area, and will therefore require more
92
Chapter 8 / Denormalization
I/O. Analogous remarks apply to any query that accesses suppliers only, or parts only, or shipments only, instead of performing some kind of join. n
Note too that denormalization, again because it increases redundancy, will most likely lead to bigger stored records, and this fact too can lead to more I/O, not less. For example, a 4K page can hold two 2K stored records but only one 3K stored record; hence, a denormalization that increases redundancy by 50 percent could increase I/O by 100 percent (I’m speaking pretty loosely here, of course).
My next observation is that even if we accept the claim that denormalization makes retrievals easier to express and perform better, it certainly makes updates harder to express and perform worse. Now, this point is (as I said before) widely understood; however, what’s not so widely understood is that denormalization opens the door to integrity violations, too. For example, in relvar S (as opposed to the projection relvars SNC and CT), someone— either the system or the user, and in current practice probably the latter—is going to have to be responsible for maintaining the FD {CITY} → {STATUS}; and if that maintenance isn’t done, integrity is lost. (By contrast, in the two-relvar design, all that has to be done is to enforce the key constraint on CT—which will definitely be done by the system, not the user—and the fact that each city has one status will then be maintained “automatically.”) My final point is this: Regardless of whether we’re talking about a.
True denormalization, which is done at the physical level only, or
b.
The kind of denormalization we have to do in most of today’s SQL products, which affects the logical level as well,
the point isn’t widely enough appreciated that when people say “denormalize for performance,” they’re really referring to the performance of specific applications. As I put it earlier, denormalization is typically based on a somewhat narrow perspective on the overall problem. Any given physical design is likely to be good for some applications but bad for others (in terms of its performance implications, that is).
A FINAL REMARK In this chapter, I’ve given some strong arguments in favor of not denormalizing; in effect, therefore, I’ve given arguments in favor of normalizing.15 And it’s certainly true that good designs are usually fully normalized. But it’s important to understand that the opposite isn’t necessarily true! That is, a design can be fully normalized and yet still be bad. For example, the projection ST of relvar S on attributes SNO and STATUS is certainly in BCNF—in fact, it’s in the highest possible normal form, as we’ll see in Part III of this book—but it’s clearly not a good design, as we saw in Chapter 6.
EXERCISES 8.1 It’s sometimes claimed that one advantage of binary relvars over the general n-ary relvars supported by the relational model is that binary relvars are always in BCNF (implying among other things that we don’t need to
15 One reviewer noted that another advantage of normalization is that it tends to simplify the formulation of complex queries, in that it makes expressions more modular through nesting of simple subexpressions.
Denormalization / Chapter 8
93
worry about normalization and denormalization, perhaps). Either prove the correctness of this claim or show that it’s incorrect by producing a counterexample. 8.2 The following is an excerpt from a published interview with a database consultant.16 It begins with a statement from the consultant: Consultant: The problems ... largely result from normalizing data across multiple [relvars] ... Many queries, however, are much easier to understand if the data is denormalized ... Interviewer: Doesn’t denormalization potentially lower data integrity and reduce flexibility in supporting unanticipated queries? Consultant: Normalization, and its emphasis on elimination of redundant storage, is purely a transaction processing issue. When users view data, they see it in a redundant form. In order to transform data into a form that is useful to users, it must be denormalized by means of a join, which is essentially a way of dynamically denormalizing data for greater ease of use. The problem is that users can’t tolerate the time and cost of joins. To address the problem, companies replicate data in an ever increasing number of decision support databases, which represent denormalized views of the data.
What in your opinion is wrong (if anything) with the opinions expressed? 8.3 The possibility of using surrogate identifiers or keys was mentioned in the body of the chapter. Indeed, many designers recommend the use of such artifical or surrogate keys in place of what are sometimes called “natural” keys. For example, we might add an attribute SPNO, say, to our usual shipments relvar (making sure it has the uniqueness property, of course) and then make {SPNO} a surrogate key for that relvar. (Note, however, that {SNO,PNO} would still be a key; it just wouldn’t be the only one any longer.) Thus, surrogate keys are keys in the usual relational sense, but (a) they always involve exactly one attribute and (b) their values serve solely as surrogates for the entities they stand for (i.e., they serve merely to represent the fact that those entities exist—they carry absolutely no additional meaning or baggage of any kind). Ideally, those surrogate values would be system generated, but whether they’re system or user generated has nothing to do with the basic idea of surrogate keys as such. Two questions: Are surrogate keys the same thing as tuple IDs? And do you think they’re a good idea? 8.4 If two designs are information equivalent, it must be possible to use operations of the relational algebra to convert them into one another. Consider, therefore, the following competing designs for an employees relvar from the body of the chapter: EMP { ENO , JAN_PAY , FEB_PAY , ..., DEC_PAY } KEY { ENO } EMP { ENO , MONTH , PAY } KEY { ENO , MONTH } Using Tutorial D or SQL (or your own preferred database language), show how each of these designs can be converted into the other.
16
It’s from Data Base Newsletter 22, No. 5 (September/October 1994).
Part III
JOIN DEPENDENCIES, FIFTH NORMAL FORM, AND RELATED MATTERS
This part of the book does for join dependencies and fifth normal form what the previous part did for functional dependencies and Boyce/Codd normal form. It also ties up a number of loose ends having to do with normalization, as a major component of design theory, in general.
Chapter 9
JDs and 5NF (Informal) If you can’t beat them, join them ─Anon.
Just as Boyce/Codd normal form is defined in terms of functional dependencies, so fifth normal form (5NF) is defined in terms of join dependencies (JDs);1 as noted in Chapter 4, in fact, 5NF is the normal form with respect to JDs, just as BCNF is the normal form with respect to FDs. And the treatment of these ideas in this part of the book therefore parallels the treatment of BCNF and FDs in Part II. In other words, I plan to treat the material both formally, in Chapter 10, and informally in the present chapter. Let me immediately add that although 5NF is indeed “the” normal form with respect to JDs, this state of affairs shouldn’t be taken to mean that 5NF is the ultimate goal of the normalization process. Au contraire, in fact: There are at least two other normal forms that have a better claim to that title, as we’ll see in Chapter 13. From a pedagogical point of view, however─as well as from a historical one─I think it’s desirable to discuss 5NF in detail first. (I mention this point simply in order to avoid giving a false impression; one of my reviewers felt I should have presented the material in a different sequence, but I don’t agree.) Now, in previous writings I’ve tended to regard JDs as if they were just a generalized kind of FD. I now think this perception is wrong, or at least misleading; I now think it’s better to regard JDs as a completely different phenomenon. Of course, FDs and JDs are both dependencies (i.e., constraints), and they do resemble each other in certain respects; in particular, the fact that a certain JD holds in relvar R implies that R can be nonloss decomposed in certain ways, just as the fact that a certain FD holds in relvar R also implies that R can be nonloss decomposed in certain ways. It’s also true that every FD implies a JD, so that if some FD F holds in relvar R, a certain JD J holds in R also. But not all JDs are implied by FDs; in fact, to speak very loosely─but I must emphasize that what I’m about to say is extremely imprecise─we might say that 5NF has to do with JDs that aren’t implied by FDs. That is, it’s if some relvar R is in BCNF, but is subject to some JD that’s not implied by FDs, that the notion of 5NF might be relevant. Now, a relvar is in BCNF if and only if all FDs to which it’s subject are implied by keys. As you’d probably expect, therefore, a relvar is in 5NF if and only if all JDs to which it’s subject are implied by keys.2 However, this latter notion─i.e., the notion of JDs being implied by keys─is a bit trickier to pin down than its FD counterpart; in fact, there’s a very rich theory surrounding these ideas, as we’ll soon see, and some of that theory can be a little overwhelming (not to say confusing) at first. You need to keep a clear head! As someone much more knowledgeable in these matters than I am once said to me: JDs are very mysterious.
1
So is 4NF, but I’m going to ignore 4NF (mostly) until Chapter 12.
2
This very informal definition is the only one I’ll be giving for 5NF in the present chapter.
98
Chapter 9 / JDs and 5NF (Informal)
So much for the preamble; now let’s get down to specifics.
JOIN DEPENDENCIES─THE BASIC IDEA Most of the time in this book so far, I’ve been making a tacit assumption: namely, I’ve been assuming that when we decompose some relvar, we always do so by replacing that relvar by exactly two of its projections.3 (Note that Heath’s Theorem, which provides the formal underpinning for most of what I’ve had to say so far regarding nonloss decomposition, specifically addresses decomposition into exactly two projections.) What’s more, that assumption was fully warranted, so long as our target was only BCNF─in other words, it successfully carried us as far as that specific target. So you might be surprised to learn that there exist relvars that can’t be nonloss decomposed into two projections but can be nonloss decomposed into three (or maybe more than three). As an aside, I note that, remarkably enough, Codd gave an example in 1969, in his very first paper on the relational model (see Appendix C), that showed he was aware of this possibility. However, that example was apparently overlooked by most of the paper’s original readers; certainly it seems to have come as a surprise to the research community when the possibility was rediscovered several years later (in 1977, to be precise). Now, I said earlier, albeit loosely, that 5NF had to do with JDs that aren’t implied by FDs. I can now add, though again speaking very loosely, that it has to do with relvars that can’t be nonloss decomposed into two projections but can be nonloss decomposed into three or more. In other words, it’s when these circumstances arise─i.e., when there are JDs that aren’t implied by FDs, and relvars that can only be nonloss decomposed into more than two projections─that you do really have to come to grips with JDs and 5NF. So what exactly do we mean when we say some JD holds in some relvar? Here’s a definition: n
Definition: Let X1, ..., Xn be subsets of the heading H of relvar R; then the join dependency (JD) R { X1 , ... , Xn } holds in R if and only if R can be nonloss decomposed into its projections on X1, ..., Xn (i.e., if and only if every legal value r of R is equal to the join of the corresponding projections r1, ..., rn). X1, ..., Xn are the components of the JD, and the JD overall can be read as “star X1, ..., Xn” or “join X1, ..., Xn”─though I hasten to add that “join” really isn’t the mot juste here, because the join operator (at least as usually understood) joins relations, and X1, ..., Xn aren’t relations but headings.
By way of a simple example, consider the suppliers relvar S once again. As we know, that relvar is subject to the FD {CITY} → {STATUS}, and so Heath’s Theorem tells us it can be nonloss decomposed into its projections on {SNO,SNAME,CITY} and {CITY,STATUS}. In other words, the following JD holds in that relvar: R { { SNO , SNAME , CITY } , { CITY , STATUS } } Points arising:
3 Of course, I’m referring here to an individual step in the overall process. Clearly, repeated steps─i.e., repeated individual decompositions─will yield a result consisting of more than two projections, in general, even if each individual decomposition is into just two.
JDs and 5NF (Informal) / Chapter 9
99
n
Note that it follows from the definition that the union of the components X1, ..., Xn must be equal to H (i.e., every attribute of H must appear in at least one of those components), for otherwise R couldn’t possibly be equal to the join of the projections that correspond to those components.
n
Different writers use different symbols to denote a JD; I use a special kind of star, but the symbol ⋈ (“bow tie”) is more frequently encountered in the research literature.
n
It might help to point out that to say some JD holds is equivalent to saying that if we join the indicated projections together, we’ll never get any “spurious” tuples (as Exercise 3.2 called them).
n
The following observation might also be helpful. I’ll explain it in terms of a simple, though slightly abstract, example. Let relvar R have attributes A, B, C, and D (only), and let the JD R{AB,BC,CD} (“Heath notation”—see Chapter 7) hold in R. Also, let me use the symbol “∈” to mean “appears in” (as in the answer to Exercise 5.4 in Appendix D). Then to say the given JD holds in R is equivalent to saying the following:4 if
then
EXISTS c1 ( EXISTS d1 ( ( a , b , c1 , d1 ) ∈ R ) ) AND EXISTS a2 ( EXISTS d2 ( ( a2 , b , c , d2 ) ∈ R ) ) AND EXISTS a3 ( EXISTS b3 ( ( a3 , b3 , c , d ) ∈ R ) ) ( a , b , c , d ) ∈ R
Explanation: Let there be a tuple in R with A = a and B = b and a tuple in R with B = b and C = c and a tuple in R with C = c and D = d. Then the tuples (a,b), (b,c), and (c,d) will appear in the projections of R on AB, BC, and CD, respectively, and so the tuple (a,b,c,d) will appear when we join these three projections together. Moreover, the converse is clearly true as well: If the tuple (a,b,c,d) appears in R, then the tuples (a,b), (b,c), and (c,d) will certainly appear in those three projections (and so that If in the foregoing formal statement could in fact be replaced by If and only if). As a simple illustration of this last point, to say the following JD holds in relvar S— R { { SNO , SNAME , CITY } , { CITY , STATUS } } —is to say the tuple (s,n,t,c) appears in S if and only if there’s a tuple in S with SNO = s and SNAME = n and CITY = c and there’s a tuple in S with CITY = c and STATUS = t. To continue with this example for a moment, the fact that the specified JD holds in relvar S is a logical consequence of Heath’s Theorem, as we know. In fact, we can now restate Heath’s Theorem as follows: n
Heath’s Theorem (for relvars, restated in terms of JDs): Let relvar R have heading H and let X, Y, and Z be subsets of H such that the union of X, Y, and Z is equal to H. Let XY denote the union of X and Y, and similarly for XZ. If R is subject to the FD X → Y, then R is subject to the JD R{XY,XZ}.
As stated earlier, therefore, FDs imply JDs─but not all JDs are implied by FDs, as we’ll see. Before I elaborate on this point, however, let me stress the requirement that the union of the components of a given JD must be equal to the pertinent heading. No analogous requirement applies to FDs; with FDs, the left and right sides don’t have to be such that their union is equal to the pertinent heading, they only have to be subsets of that heading. This 4 The keyword EXISTS in the following definition denotes the existential quantifier. Refer to SQL and Relational Theory if you need a tutorial on such matters.
100
Chapter 9 / JDs and 5NF (Informal)
distinction might help to illustrate the point (at least intuitively) that JDs and FDs really are different in kind, in a sense. Now, the JD in the foregoing example─ R { { SNO , SNAME , CITY } , { CITY , STATUS } } ─is binary: It has two components, and it corresponds to a nonloss decomposition into two projections. Here by contrast is another JD that holds in relvar S: R { { SNO , SNAME } , { SNO , CITY } , { CITY , STATUS } } This one is ternary, but it’s derived, in effect, by “cascading” two binary ones: n
First, we already know the binary JD R{{SNO,SNAME,CITY},{CITY,STATUS} holds in S.
n
But the FD {SNO} → {SNAME} holds in the projection of S on {SNO,SNAME,CITY} (corresponding to one of the components of that binary JD),5 and so the binary JD R{{SNO,SNAME},{SNO,CITY}}, holds in that projection.
It follows that the given ternary JD holds in the original relvar. By contrast, in the section immediately following, I’ll give an example of a ternary JD that’s not derived by cascading binary ones, and hence an example of a relvar that can be nonloss decomposed into three projections and not into two.
A RELVAR IN BCNF AND NOT 5NF I’ll start with a revised version─I’ll call it SPJ─of our usual shipments relvar SP. The revisions consist of (a) dropping attribute QTY and (b) introducing a new attribute JNO (“project number”). The predicate is Supplier SNO supplies part PNO to project JNO, and a sample value is shown in Fig. 9.1. Note that the relvar is “all key” and therefore certainly in BCNF.6 ┌─────┬─────┬─────┐ SPJ │ SNO │ PNO │ JNO │ ├═════┼═════┼═════┤ │ S1 │ P1 │ J2 │ │ S1 │ P2 │ J1 │ │ S2 │ P1 │ J1 │ │ S1 │ P1 │ J1 │ └─────┴─────┴─────┘ Fig.9.1: Relvar SPJ—sample value
Now suppose the following business rule is in effect:
5
I’m appealing here to an easily proved theorem: viz., that the FD X → Y holds in some projection of relvar R if and only if it holds in R itself (see Exercise 12.5 in Chapter 12).
6
As a matter of fact it’s in 4NF, too; however, it’s not in what Chapter 13 calls redundancy free normal form, RFNF, and thus not in 5NF either.
JDs and 5NF (Informal) / Chapter 9
n
101
If (a) supplier s supplies part p and (b) part p is supplied to project j and (c) project j is supplied by supplier s, then (d) supplier s supplies part p to project j.7
In slightly more concrete terms, this business rule says that if (for example) all three of the following are true propositions─ a.
Smith supplies monkey wrenches to some project.
b.
Somebody supplies monkey wrenches to the Manhattan project.
c.
Smith supplies something to the Manhattan project.
─then the following is a true proposition as well: d.
Smith supplies monkey wrenches to the Manhattan project.
In other words, if relvar SPJ contains tuples representing propositions a., b., and c., it must also contain a tuple representing proposition d.8 Note that this requirement is met in Fig. 9.1 (take S1 to be Smith, P1 to be monkey wrenches, and J1 to be the Manhattan project). Now, propositions a., b., and c. would normally not imply proposition d. To elaborate, if we know only that propositions a., b., and c. are true, then we know that Smith supplies monkey wrenches to some project j; we know that some supplier s supplies monkey wrenches to the Manhattan project; and we know that Smith supplies some part p to the Manhattan project─but we can’t validly infer that s is Smith, we can’t validly infer that p is monkey wrenches, and we can’t validly infer that j is the Manhattan project. False inferences such as these are examples of what’s sometimes called the connection trap. In the case at hand, however, the business rule tells us there is no trap; that is, we can validly infer proposition d. from propositions a., b., and c. in this particular case. Now let’s consider the example more carefully. Let me use SP, PJ, and JS, just for the moment, to denote the projections of SPJ on {SNO,PNO}, {PNO,JNO}, and {JNO,SNO}, respectively. Then we have the following: n
By the definitions of projection and join, IF THEN AND AND
( ( ( (
s s p j
, , , ,
p p j s
, j ) ) ) )
∈ ∈ ∈ ∈
JOIN { SP , PJ , JS } SP PJ JS
and therefore there exist s′ , p′, and j′ such that
7 It could be argued that, strictly speaking, “supplier s supplies part p” here should really be “supplier s supplies part p to some project” (and similarly for “part p is supplied to project j” and “project j is supplied by supplier s”). Whether such is in fact the case depends on the full semantics of the situation, which I’ve deliberately left a little underspecified in the interest of intuitive simplicity. I’ll come back to this issue in Chapter 15. 8 I’m being a little sloppy once again. For example, consider proposition a. (“Smith supplies monkey wrenches to some project”). If “some project” here means “some unspecified project”─i.e., there exists such a project, but we don’t know what it is─then the proposition isn’t an instantiation of the predicate for SPJ, and no SPJ tuple can possibly represent it. But an SPJ tuple certainly can represent the proposition “Smith supplies monkey wrenches to some specific project”; what’s more, the proposition so represented then implies the proposition “Smith supplies monkey wrenches to some project” (i.e., “there exists a project j such that Smith supplies monkey wrenches to j”). I hope that’s clear!
102
Chapter 9 / JDs and 5NF (Informal)
AND AND
( s , p , j′ ) ( s , p′ , j ) ( s′ , p , j )
∈ ∈ ∈
SPJ SPJ SPJ
Aside: I apologize for the tiny lack of symmetry in the foregoing, but it’s unavoidable if we’re to represent tuples, which are unordered by definition, by ordered commalists of symbols on the page. End of aside. n
But by the business rule, IF AND AND
( s , p , j′ ) ( s , p′ , j ) ( s′ , p , j )
∈ ∈ ∈
SPJ SPJ SPJ
∈
SPJ
then we necessarily have: ( s n
, p
, j
)
So if (s,p,j) appears in the join of SP, PJ, and JS, it also appears in SPJ. But the converse is obviously true as well─i.e., if (s,p,j) appears in SPJ, it certainly appears in the join of SP, PJ, and JS.
Thus (s,p,j) appears in SPJ if and only if it appears in the join of SP, PJ, and JS. It follows that every legal value of relvar SPJ is equal to the join of its projections on {SNO,PNO}, {PNO,JNO}, and {JNO,SNO}, and hence that the JD R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } } certainly holds in relvar SPJ. Observe now that the foregoing JD is ternary─it has three components. What’s more, it isn’t implied by FDs.9 Hence it certainly isn’t implied by keys (recall from Chapter 5 that a key constraint is just a special case of an FD). As a consequence, relvar SPJ, although it’s in BCNF (because it’s “all key”), isn’t in 5NF. In order to understand this state of affairs a little better, it’s helpful to go back to the sample SPJ value shown in Fig. 9.1. Fig. 9.2 shows (a) values of the projections SP, PJ, and JS corresponding to that sample value, (b) the effect of joining the SP and PJ projections (on {PNO}), and (c) the effect of joining that result and the JS projection (on {JNO,SNO}). As you can see, joining the first two projections produces a copy of the original SPJ relation plus one additional (“spurious”) tuple; joining in the other projection then eliminates that additional tuple, thereby getting us back to the original SPJ relation. Moreover, the net effect is the same whatever pair of projections we choose for the first join, though the intermediate result is different in each case. Exercise: Check this claim. To repeat, therefore, the JD R{SP,PJ,JS}─if now you’ll let me use the names SP, PJ, and SJ to refer not to the projections as such but to the corresponding subsets of the heading─holds in relvar SPJ; in other words, that JD captures the essence (as it were) of the original business rule. As a consequence, relvar SPJ can be nonloss decomposed accordingly. What’s more, it probably should be, because it suffers from redundancy; to be specific, in terms of the sample value of Fig. 9.1, the proposition that supplier S1 supplies part P1 to project J1 is represented
9 Proof: The only FDs that hold in relvar SPJ are trivial ones, and it’s certainly not the case that every relation satisfying those trivial FDs also satisfies the JD. For example, the relation containing the first three but not the fourth of the tuples as shown in Fig. 9.1 doesn’t.
JDs and 5NF (Informal) / Chapter 9
103
┌─────┬─────┐ ┌─────┬─────┐ ┌─────┬─────┐ │ SNO │ PNO │ │ PNO │ JNO │ │ JNO │ SNO │ ├═════┼═════┤ ├═════┼═════┤ ├═════┼═════┤ │ S1 │ P1 │ │ P1 │ J2 │ │ J2 │ S1 │ │ S1 │ P2 │ │ P2 │ J1 │ │ J1 │ S1 │ │ S2 │ P1 │ │ P1 │ J1 │ │ J1 │ S2 │ └─────┴─────┘ └─────┴─────┘ └─────┴─────┘ │ │ │ └─► join on {PNO} ◄─┘ │ │ │ ▼ │ ┌─────┬─────┬─────┐ │ │ SNO │ PNO │ JNO │────► join on ◄─────┘ ├═════┼═════┼═════┤ {JNO,SNO} │ S1 │ P1 │ J2 │ │ │ S1 │ P2 │ J1 │ └───► original value of SPJ │ S2 │ P1 │ J1 │ │ S2 │ P1 │ J2 │◄─── spurious │ S2 │ P1 │ J1 │ └─────┴─────┴─────┘ Fig. 9.2: SPJ = the join of all three of its binary projections but not of any two
both explicitly, by means of the tuple (S1,P1,J1), and implicitly as a logical consequence of the JD and the propositions represented by the other three tuples. More terminology: We say a JD like the one that applies in the SPJ example is tuple forcing, because if certain tuples appear, it forces certain additional tuples to appear as well. In Fig. 9.1, for example, the appearance of the three tuples (S1,P1,J2), (S1,P2,J1), and (S2,P1,J1) forces the appearance of the tuple (S1,P1,J1). Note carefully that not all JDs are tuple forcing; for example, the join dependency R{{SNO,SNAME,CITY},{CITY,STATUS}} holds in relvar S, but there’s no question of it forcing additional tuples to appear. Note: To jump ahead of ourselves for a moment, it’ll turn out later that a relvar that’s subject to a tuple forcing JD can’t be in 5NF (though as the SPJ example shows, it can be in BCNF).
CYCLIC RULES Observe now the cyclic nature of the business rule in the SPJ example (“if s is connected to p and p is connected to j and j is connected back to s again, then s and p and j must all be directly connected, in the sense that they must all appear together in the same tuple”). Let’s agree to say this rule is “3-way cyclic.” Then we can say in general that it’s if an n-way cyclic rule exists for some n > 2 that we might be faced with a relvar that’s (a) in BCNF and not in 5NF and therefore (b) can be nonloss decomposed into n projections and not into fewer.10 That said, I have to say too that in my experience such cyclic rules are rare in practice─which means that, in practice, most relvars, if they’re in at least BCNF, are probably in 5NF as well. Indeed, it’s quite unusual in practice to find a relvar that’s in BCNF and not in 5NF. Unusual, but not unknown!─I’ve encountered a few real world examples myself from time to time. In other words, the fact that such relvars are unusual doesn’t mean you don’t need to worry about them, or about JDs and 5NF. Au contraire: JDs and 5NF are tools in your designer’s toolkit, as
10 If the rule takes the slightly simpler form “if s is connected to p and s is connected to j, then s and p and j must all be directly connected,” then we might have a relvar that’s in BCNF but not in 4NF (and hence not in 5NF either, a fortiori). See Chapter 12.
104
Chapter 9 / JDs and 5NF (Informal)
it were, and (other things being equal) you should probably try to ensure that all of the relvars in your database are in 5NF.11
CONCLUDING REMARKS I’ll close this chapter with a few miscellaneous observations. First, note that I’m assuming throughout this part of the book (as indeed I did in the previous part as well) that the only dependencies we care about are ones that have to do with projection as the decomposition operator and join as the corresponding recomposition operator. Under that assumption, it’s immediate from the definition of join dependency that JDs are, in a sense, the “ultimate” kind of dependency; that is, there’s no “higher” kind of dependency such that JDs are just a special case of that higher kind. And it follows further that─though I haven’t really defined it properly yet!─fifth normal form is the final normal form12 with respect to projection and join (which accounts for its alternative name, projection-join normal form). Second, I’ve referred several times to relvars that are in BCNF and not 5NF; indeed, I’ve tacitly assumed that if relvar R is in 5NF, then it’s certainly in BCNF. In fact this assumption is correct. Let me also state explicitly for the record that 5NF is always achievable; that is, any relvar not in 5NF can always be decomposed into a set of 5NF projections─though not necessarily without losing dependencies, of course, since we already know from Chapter 7 that decomposition to BCNF and preserving dependencies can be conflicting objectives. Third, it follows from the definition of 5NF that a relvar R that’s in 5NF is guaranteed to be free of redundancies that can be removed by taking projections. In other words, to say R is in 5NF is to say that further nonloss decomposition of R into projections, while it might be possible, certainly won’t remove any redundancies. Note very carefully, however, that to say R is in 5NF is not to say R is free of redundancy. (A belief to the contrary is another popular misconception. See Exercise 1.11 in Chapter 1.) The fact is, there are many kinds of redundancy that projection as such is powerless to remove─which is an illustration of the point I made in Chapter 1, in the section “The Place of Design Theory,” to the effect that there are numerous issues that current design theory simply doesn’t address at all. By way of example, consider Fig. 9.3 below, which shows a sample value for a relvar, CTXD, that’s in 5NF and yet suffers from redundancy. The predicate is Teacher TNO spends DAYS days with textbook XNO on course CNO. The sole key is {CNO,TNO,XNO}. As you can see, the fact that (e.g.) teacher T1 teaches course C1 appears twice, and so does the fact that course C1 uses textbook X1.13 ┌─────┬─────┬─────┬──────┐ CTXD │ CNO │ TNO │ XNO │ DAYS │ ├═════┼═════┼═════┼──────┤ │ C1 │ T1 │ X1 │ 7 │ 8 │ │ C1 │ T1 │ X2 │ │ C1 │ T2 │ X1 │ 9 │ │ C1 │ T2 │ X2 │ 6 │ └─────┴─────┴─────┴──────┘ 9.3: The 5NF relvar CTXD─sample value
Let’s analyze this example a little more carefully:
11
Except as noted in Chapter 13.
12
Well ... except for 6NF (again, see Chapter 13).
13
One reviewer argued strongly that those repetitions didn’t really constitute redundancy. Well, I don’t want to argue the point here; I’ll just remind you that I’ll be examining the whole issue of exactly what does constitute redundancy in detail in Chapter 15.
JDs and 5NF (Informal) / Chapter 9
n
105
Since {CNO,TNO,XNO} is a key, the relvar is subject to the following functional dependency─ { CNO , TNO , XNO } → { DAYS } ─which is an “arrow out of a key.”
n
So DAYS depends on all three of CNO, TNO, and XNO, and it can’t appear in a relvar with anything less than all three.
n
Hence there’s no (nontrivial) decomposition of the relvar into projections that applies at all─the relvar is in 5NF. Note: A decomposition is trivial if and only if it’s based on dependencies (FDs or JDs) that are themselves trivial in turn, and nontrivial if and only if it isn’t trivial. Trivial FDs were discussed in Chapters 4 and 5; trivial JDs are discussed in the next chapter.
n
Hence there’s certainly no decomposition into projections that can remove the redundancies, a fortiori.
EXERCISES (Repeated from the body of the chapter.) Check that joining any pair of the binary relations shown in Fig. 9.2 9.1 yields a result containing a “spurious” tuple (i.e., a tuple not appearing in Fig. 9.1) and that joining the third binary relation to that intermediate result then eliminates that spurious tuple. 9.2 Write a Tutorial D CONSTRAINT statement to express the JD that holds in relvar SPJ as discussed in the body of the chapter. Design a database for the following. The entities to be represented are sales representatives, sales areas, and 9.3 products. Each representative is responsible for sales in one or more areas; each area has one or more responsible representatives. Each representative is responsible for sales of one or more products, and each product has one or more responsible representatives. Each product is sold in one or more areas, and each area has one or more products sold in it. Finally, if representative r is responsible for area a, and product p is sold in area a, and representative r sells product p, then r sells p in a. 9.4
Give an example from your own work environment, if possible, of a relvar in BCNF but not 5NF.
Chapter 10
JDs and 5NF (Formal) After great pain, a formal feeling comes ─Emily Dickinson
Just as Chapter 5 consisted of a more formal treatment of material introduced in Chapter 4, so this chapter consists of a more formal treatment of material introduced in Chapter 9. But there’s rather more to cover in this chapter than there was in Chapter 5, as you’ll soon see. Let me just say up front that, just as Chapter 5 had little to say about 2NF or 3NF, so this chapter has little to say about 4NF, either; like 2NF and 3NF, in fact, 4NF is─from some points of view, at least─mainly of historical interest. However, I’ll have more to say about it in a later chapter (Chapter 12).
JOIN DEPENDENCIES I begin with a precise and accurate definition of what a JD is, followed by some explanatory text that deliberately parallels the corresponding text in Chapter 5. (Similar remarks apply to the next section also.) n
Definition: Let H be a heading; then a join dependency (JD) with respect to H is an expression of the form R{X1,...,Xn}, where X1, ..., Xn (the components of the JD) are subsets of H whose union is equal to H. Note: The phrase JD with respect to H can be abbreviated to just JD, if H is understood. Here are some examples: R R R R
{ { { {
{ { { {
SNO , SNAME , CITY } , { CITY , STATUS } } CITY , SNO } , { CITY , STATUS , SNAME } } SNO , SNAME } , { SNO , STATUS } , { SNAME , CITY } } SNO , CITY } , { CITY , STATUS } }
Note carefully that JDs (like FDs) are defined with respect to some heading, not with respect to some relation or some relvar. Of the JDs just shown, for example, the first three are defined with respect to the heading {SNO,SNAME,STATUS,CITY} and the fourth is defined with respect to the heading {SNO,STATUS,CITY}. Note too that from a formal point of view (again like FDs), JDs are just expressions: expressions that, when interpreted with respect to some specific relation, become propositions that, by definition, evaluate to either TRUE or FALSE. For example, if the first two JDs shown above are interpreted with respect to the relation that’s the current value of relvar S (Fig. 1.1), then the first evaluates to TRUE and the second to FALSE. Of course, it’s common informally to define R{X1,...,Xn} to be a JD, in some specific context, only if it evaluates to TRUE in that context. However, such a definition leaves no way of saying a given relation fails to satisfy, or violates, some JD— because, by that informal definition, a JD that isn’t satisfied wouldn’t be a JD in the first place. For example, we wouldn’t be able to say the relation that’s the current value of relvar S violates the second of the JDs shown above.
108
Chapter 10 / JDs and 5NF (Formal)
Here’s another example of a JD that happens to be satisfied by the current value of relvar S (and in fact by all legitimate values of that relvar): R { { SNO , SNAME , CITY } , { CITY , STATUS } , { CITY , STATUS } } This JD corresponds to a nonloss decomposition in which one of the projections isn’t needed in the reconstruction process. In fact, it’s clearly equivalent to the first of the four shown previously1─ R { { SNO , SNAME , CITY } , { CITY , STATUS } } ─implying that one of the two identical components can be dropped without significant loss. For such reasons, I’ll feel free to refer to the components of any given JD as constituting a set, even though the commalist of components in the written form of that JD might contain repetitions (duplicates), which sets per se never do. (That’s why that commalist is enclosed in braces, of course.) To continue with the definitions: n
Definition: Let relation r have heading H and let R{X1,...,Xn} be a JD, J say, with respect to H. If r is equal to the join of its projections on X1, ..., Xn, then r satisfies J; otherwise r violates J.
Observe that it’s relations, not relvars, that satisfy or violate some given JD. For example, the relation that’s the current value of relvar S satisfies both of these JDs─ R { { SNO , SNAME , CITY } , { CITY , STATUS } } R { { SNO , SNAME } , { SNO , STATUS } , { SNAME , CITY } } ─and violates this one: R { { CITY , SNO } , { CITY , STATUS , SNAME } } Note that the question of that relation satisfying or violating the JD R{{SNO,CITY},{CITY,STATUS}}─the last of our original set of four sample JDs─doesn’t arise, because that JD isn’t defined with respect to the heading of that relation. n
Definition: Let relvar R have heading H and let R{X1,...,Xn} be a JD, J say, with respect to H. Then the JD J holds in relvar R (equivalently, relvar R is subject to the JD J) if and only if every relation that can ever be assigned to relvar R satisfies J. The JDs that hold in relvar R are the JDs of R.
Please note the terminological distinction I’m drawing here─JDs are satisfied (or are violated) by relations, but hold (or don’t hold) in relvars. I’ll adhere to this distinction throughout what follows. By way of example, the following JD holds in relvar S─ R { { SNO , SNAME , CITY } , { CITY , STATUS } } ─and these ones don’t:
1 In general, two JDs are equivalent if and only if every relation that satisfies either one also satisfies the other. I’ll have more to say on this topic (equivalence of JDs) in the next chapter.
JDs and 5NF (Formal) / Chapter 10
109
R { { SNO , SNAME } , { SNO , STATUS } , { SNAME , CITY } } R { { CITY , SNO } , { CITY , STATUS , SNAME } } (Contrast the examples following the previous definition.) So now, at last, we know precisely what it means for a given relvar to be subject to a given JD─and it’s immediate that relvar R can be nonloss decomposed into its projections on X1, ..., Xn if and only if it’s subject to the JD R{X1,...,Xn}.
FIFTH NORMAL FORM Now, when we were talking about FDs and BCNF, we got into a discussion of trivial FDs and FD irreducibility and FDs implied by keys and various related matters. As I’m sure you’d expect by now, analogous concepts arise in connection with JDs and 5NF also─but the details are a little trickier. Well, the concept of a JD being trivial is actually quite straightforward: n
Definition: Let R{X1,...,Xn} be a JD, J say, with respect to heading H. Then J is trivial if and only if it’s satisfied by every relation with heading H.
From this definition, it’s easy to prove the following result: n
Theorem: Let R{X1,...,Xn} be a JD, J say, with respect to heading H. Then J is trivial if and only if some Xi (1 ≤ i ≤ n) is equal to H (because every relation with heading H necessarily satisfies every JD with respect to H that’s of the form R{...,H,...}).
We can regard this theorem as an operational (or “syntactic”) definition, inasmuch as it provides an effective test that can easily be applied in practice. (By contrast, the formal or “semantic” definition isn’t much use in the practical problem of determining whether or not a given JD is trivial.) I’ll defer discussion of JD irreducibility to the next chapter; before then I want to explain what it means for a JD to be implied by keys. n
Definition: Let relvar R have heading H and let R{X1,...,Xn} be a JD, J say, with respect to H. Then J is implied by the keys of R if and only if every relation r that satisfies R’s key constraints also satisfies J.
This definition requires some elaboration. First of all, to say some relation satisfies some key constraint is to say it satisfies the applicable uniqueness requirement; and if it satisfies the uniqueness requirement for the attributes that constitute some key, it certainly satisfies the uniqueness requirement for every superset of that set of attributes (just so long as that superset is a subset of the pertinent heading, of course)─in other words, for every corresponding superkey. Thus, the phrase “satisfies R’s key constraints” in the definition could be replaced by the phrase “satisfies R’s superkey constraints” without making any significant difference. Likewise, the concept “implied by keys” could just as well be “implied by superkeys,” again without making any significant difference. Second, what happens if the JD J mentioned in the definition is trivial? Well, in that case, by definition, J is satisfied by every relation r with heading H, and so J is certainly satisfied by every relation r that satisfies R’s key constraints a fortiori. So trivial JDs are always “implied by keys,” trivially. Third, then, suppose J is nontrivial. How do we determine whether some nontrivial JD is implied by the keys of some relvar? This question does have a satisfactory answer, but it’s a trifle complicated, and for that reason I’ll defer it to the next section. Before then, I want to give a definition of 5NF and say a little about that definition.
110
n
Chapter 10 / JDs and 5NF (Formal)
Definition: Relvar R is in fifth normal form (5NF), also known as projection-join normal form (PJ/NF), if and only if every JD of R is implied by the keys of R.
It should be clear that if a JD is implied by the keys of R, it certainly holds in R (i.e., it’s certainly “a JD of R”). But the converse is false: A JD can hold in R without being implied by the keys of R. In other words, the whole point about the 5NF definition is that the only JDs that hold in a 5NF relvar are ones we can’t get rid of— which means ones implied by keys (including trivial ones as a special case).2 I’d like to close this section by pointing out an intuitively attractive parallelism between the BCNF and 5NF definitions: n
R is in BCNF if and only if every FD that holds in R is implied by the keys of R.
n
R is in 5NF if and only if every JD that holds in R is implied by the keys of R.
However, there’s a significant difference also. In the BCNF definition, we can simplify the phrase “implied by the keys” to “implied by some key,” meaning, loosely, that each FD that holds is an arrow out of some specific key considered in isolation (not necessarily the same key for every such FD, of course). By contrast, no such simplification applies to 5NF─the JDs that hold are JDs that are implied by the keys taken in combination, not necessarily just by some key considered in isolation. For example, suppose for the moment that relvar S had two keys, {SNO} and {SNAME}. Then the following JD (a repeat of one we’ve seen several times already)─ R { { SNO , SNAME } , { SNO , STATUS } , { SNAME , CITY } } ─would hold in that relvar. As it is, however, it doesn’t hold, because {SNAME} isn’t in fact a key. Exercise: Invent some sample data to demonstrate the truth of these claims.
JDs IMPLIED BY KEYS So how do we determine whether a given nontrivial JD is implied by keys? It turns out there’s an algorithm, the membership algorithm (due to Fagin), that does the job. It works like this. Let relvar R have heading H, and let R{X1,...,Xn} be a JD, J say, with respect to H. Then: 1.
If two distinct components of J both include the same key K of R, replace them in J by their union.
2.
Repeat the previous step until no further replacements are possible.
Then the original JD is implied by the keys of R if and only if J is now trivial─i.e., if and only if the final version of J contains H as a component.3 (Notice, incidentally, that trivial JDs in particular cause the algorithm to succeed, trivially.) Let’s look at a few examples. First of all, consider our usual suppliers relvar S. Here’s another JD─let’s call it J1─that holds in that relvar:
2
3
As usual, “getting rid of” a dependency (of any kind) really means replacing it by some multirelvar constraint.
In practice, of course, we might not need to go all the way to the bitter end and compute that final version of J—we can quit as soon as a component is produced that’s equal to H.
JDs and 5NF (Formal) / Chapter 10
111
R { { SNO , SNAME } , { SNO , STATUS } , { SNO , CITY } } We already know this JD holds by repeated application of Heath’s Theorem. However, observe now that the components {SNO,SNAME} and {SNO,STATUS} both include the key {SNO}; applying the membership algorithm, therefore, we can replace them by their union {SNO,SNAME,STATUS}. J1 now looks like this: R { { SNO , SNAME , STATUS } , { SNO , CITY } } Note that (a) this revised version of J1 is itself a JD with respect to the heading of relvar S, and also that (b) relvar S is subject to it─two facts that together should give some insight as to what’s going on with the algorithm (see further explanation later). Next, the components {SNO,SNAME,STATUS} and {SNO,CITY} of this latter JD both include the key {SNO}, and so we can replace them by their union {SNO,SNAME,STATUS,CITY}, to obtain: R { { SNO , SNAME , STATUS , CITY } } This further revision of J1 is again a JD with respect to the heading of S. However, all it says is that relvar S is equal to the “join” of its identity projection (recall from Exercise 5.1 that the join of a single relation r, JOIN {r}, is identically equal to r); in other words, that further revision of J1 simply says S can be “nonloss decomposed” into its identity projection. But this observation is trivially true: Any relvar can always be “nonloss decomposed” into its identity projection, as we saw in Chapter 6. Indeed, the JD is now formally trivial, since it contains a component that’s equal to the pertinent heading. It follows that JD J1 as originally stated is implied by the keys of relvar S. By way of a counterexample, consider now the following JD─let’s call it J2─which also holds in relvar S: R { { SNO , SNAME , CITY } , { CITY , STATUS } } Since the sole key, {SNO}, of the relvar is certainly not included in both components of this (binary) JD, the membership algorithm has no effect on it. Thus, the output from that algorithm is equal to the input (i.e., to the original JD J2, unchanged); no component of that output is equal to the entire heading, and so J2 isn’t implied by keys (and relvar S isn’t in 5NF, therefore). Finally, let’s consider some more abstract examples. Let relvar R have attributes A, B, C, D, E, and F (only); let R have keys {A}, {B}, and {C,D}, and no others; and let AB denote the set of attributes {A,B}, and similarly for other attribute name combinations (“Heath notation”─see Chapter 7). Now consider the following JDs: 1.
R { AB , ACDE , BF }
2.
R { ABC , ACD , BEF }
3.
R { AB , AC , ADEF }
4.
R { ABC , CDEF }
5.
R { ABD , ACDE , DF }
Applying the membership algorithm to these JDs, we find that Nos. 1-3 are implied by keys (and R is therefore subject to them, necessarily), while Nos. 4-5 aren’t. To elaborate briefly: Nos. 1 and 2 are both implied by the pair of keys {A} and {B} taken together, but not by any individual key; by contrast, No. 3 is implied by the
112
Chapter 10 / JDs and 5NF (Formal)
key {A} considered in isolation. No. 4 would be implied by keys─actually by an individual key─if and only if {C} were a key, but it isn’t; what’s more, that JD can’t possibly hold in R, because if it did, then {C} would have to be a key after all (think about it!). As for No. 5, it clearly isn’t implied by the keys; it might or might not hold in R, but if it does, then R can’t be in 5NF. So what exactly is going on in these examples? Let me try to explain the intuition behind what I’ve been saying (you might like to try interpreting what follows in terms of the suppliers relvar S and the JD R{{SNO,SNAME},{SNO,STATUS},{SNAME,CITY}}, under the assumption once again that {SNO} and {SNAME} are both keys for that relvar): n
Let X1, ..., Xn be subsets of the heading H of relvar R, such that the union of X1, ..., Xn is equal to H.
n
Let J be the JD R{X1,...,Xn}, and let J be implied by the keys of R.
n
Let r be the relation that’s the current value of R.
n
Choose, arbitrarily, two distinct elements (components) of the set {X1,...,Xn}, say X1 and X2.
n
Let r1 and r2 be the projections of r on X1 and X2, respectively.
Now, if X1 and X2 both include the same key K of R, then the join r12 of r1 and r2─whose heading X12 will be the union of X1 and X2─will be a strict one to one join, and so r1 and r2 can be replaced by r12 without loss of information. (At the same time, X1 and X2 can be replaced in J by X12.) Since the original version of J was implied by the keys of R, performing such replacements repeatedly will, by definition, eventually yield a relation (a) that’s equal to the original relation r, and in particular (b) will therefore have a heading equal to the entire heading H. Let me now point out that everything I’ve said so far becomes much simpler in the common special case where the pertinent relvar R has just one key K. In that case, the JD R{X1,...,Xn} is implied by keys if and only if both of the following are true: a.
Every attribute of R is included in at least one of X1, ..., Xn. (This requirement always applies, of course, in the general case as well as in this special case.)
b.
The sole key K of R is included in each of X1, ..., Xn─in other words, each of X1, ..., Xn is a superkey.
So if R has just one key K, then R is in 5NF if and only if every component of every JD that holds in R includes that key K.4 (However, please note that─important!─I’m assuming here that the only JDs under consideration are ones that are irreducible with respect to R. See Chapter 11.) By way of example, consider the parts relvar P. The only irreducible JDs R{X1,...,Xn} that hold in that relvar are such that each Xi (i = 1, ..., n) includes the sole key {PNO}. Those JDs are clearly all implied by that sole key, therefore, and relvar P is in 5NF. Here’s one of the JDs in question: R { { PNO , PNAME , COLOR } , { PNO , WEIGHT , CITY } }
4 Note that this isn’t the case with relvar S─that relvar is subject to at least one JD for which at least one component fails to include the sole key {SNO} (viz., R{{SNO,SNAME,CITY},{CITY,STATUS}}) and so isn’t in 5NF.
JDs and 5NF (Formal) / Chapter 10
113
Thus, relvar P can be nonloss decomposed into its projections on the components of this JD. Whether we would actually want to perform that decomposition is another matter, of course. We know we could if we wanted to, that’s all. Let me close this section by revisiting the SPJ example from Chapter 9. For convenience, a sample value of that relvar is shown in Fig. 10.1 (a repeat of Fig. 9.1). The predicate is Supplier SNO supplies part PNO to project JNO, and the following business rule is in effect: n
If supplier s supplies part p and part p is supplied to project j and project j is supplied by supplier s, then supplier s supplies part p to project j. ┌─────┬─────┬─────┐ SPJ │ SNO │ PNO │ JNO │ ├═════┼═════┼═════┤ │ S1 │ P1 │ J2 │ │ S1 │ P2 │ J1 │ │ S2 │ P1 │ J1 │ │ S1 │ P1 │ J1 │ └─────┴─────┴─────┘ Fig.10.1: Relvar SPJ—sample value
Now, we know from Chapter 9 that (as I put it in that chapter) the following JD captures the essence of this business rule and so holds in SPJ: R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } } Now we can see this JD isn’t implied by the sole key (viz., {SNO,PNO,JNO}) of the relvar, because the membership algorithm fails, and so SPJ isn’t in 5NF. So it can be nonloss decomposed into its three binary projections, and probably should be, if we want to reduce redundancy. Those three projections are all in 5NF (no JDs hold in them at all apart from trivial ones).
A USEFUL THEOREM I said in Chapter 9 that in practice it’s quite unusual to find a relvar that’s in BCNF and not in 5NF. In fact, there’s a theorem that addresses this issue: n
Theorem: Let R be a BCNF relvar and let R have no composite keys; then R is in 5NF. (Recall from Chapter 1 that a composite key is a key consisting of two or more attributes.)
This theorem is quite useful. What it says is, if you can get to BCNF (which is easy enough), and if there aren’t any composite keys in your BCNF relvar (which is often but not always the case), then you don’t have to worry about the complexities of JDs and 5NF in general─you know without having to think about the matter any further that the relvar simply is in 5NF. Note: Actually the theorem applies to 3NF, not BCNF; that is, it really says a 3NF relvar with no composite keys is in 5NF. But every BCNF relvar is in 3NF, and in any case BCNF is much more important than 3NF, pragmatically speaking (as well as being conceptually simpler). Caveat: I don’t know why, but people often misinterpret the foregoing theorem. To be specific, given that a BCNF relvar with no composite keys is “automatically” in 5NF, people often seem to think that simply introducing a surrogate key (noncomposite by definition) into a BCNF relvar “automatically” means the relvar is now in 5NF.
114
Chapter 10 / JDs and 5NF (Formal)
But it doesn’t mean that at all! If the relvar wasn’t in 5NF before the surrogate was introduced, it won’t be in 5NF afterward. In particular, if it had a composite key before the surrogate was introduced, it’ll still have one afterward.
FDs AREN’T JDs Statements to the effect that every FD is a JD, or that (as I put it in Chapter 9) JDs are a kind of generalized FD, are quite common in the less formal parts of the literature; indeed, I’ve said such things myself in previous books and other previous writings. But such talk is strictly incorrect. It would be better to say that every FD implies a JD (which in fact is something we already know to be the case from Heath’s Theorem). In other words, if R is subject to a certain FD, F say, then it’s certainly subject to a certain JD, J say. However, the converse is false─R can be subject to that same JD J without being subject to that same FD F, as I now show: n
Let relvar R have attributes A, B, and C (only), let F be the FD AB → C, and let R be subject to F (Heath notation once again).
n
By Heath’s Theorem, then, R is subject to the JD R{ABC,AB}. (With reference to the formulation of Heath’s Theorem given in Chapter 9, take X to be AB, Y to be C, and Z to be the empty set of attributes.) Call this JD J.
n
But this JD J is trivial─it holds in every relvar R that has heading ABC, regardless of whether that relvar is subject to the FD AB → C.
UPDATE ANOMALIES REVISITED In Chapter 3, we took a brief look at certain update anomalies that can be caused by FDs: specifically, FDs that hold in a relvar that’s not in BCNF. To be frank, however, the update anomaly concept was never very precisely defined (at least, not in that context); probably the best that could be said about it is that the update anomaly problem is just the redundancy problem looked at from another point of view. So what about JDs?─specifically, JDs that hold in a relvar that’s not in 5NF? Such JDs do cause redundancy, as we’ve seen, and so we can expect them to give rise to update anomalies as well. And indeed they do; what’s more, the concept can be (or at any rate, is) more precisely defined in that context, as we’ll see. Consider Fig. 10.2, which shows two possible values for relvar SPJ; the one on the left is a repeat of the relation from Fig. 10.1, the one on the right is obtained from the one on the left by removing two tuples. ┌─────┬─────┬─────┐ SPJ │ SNO │ PNO │ JNO │ ├═════┼═════┼═════┤ │ S1 │ P1 │ J2 │ │ S1 │ P2 │ J1 │ │ S2 │ P1 │ J1 │ │ S1 │ P1 │ J1 │ └─────┴─────┴─────┘
┌─────┬─────┬─────┐ SPJ │ SNO │ PNO │ JNO │ ├═════┼═════┼═════┤ │ S1 │ P1 │ J2 │ │ S1 │ P2 │ J1 │ └─────┴─────┴─────┘
Fig. 10.2: Two possible values for relvar SPJ
Observe now that if the current value of relvar SPJ is the relation on the left of the figure, there’s a deletion anomaly: We can’t delete just the tuple (S1,P1,J1), because what results after that deletion violates the JD and is
JDs and 5NF (Formal) / Chapter 10
115
thus not a legal value for the relvar. Likewise, if the current value of relvar SPJ is the relation on the right of the figure, there’s an insertion anomaly: We can’t insert just the tuple (S2,P1,J1), because what results after that insertion is (again, and for the same reason) not a legal value for the relvar. Now, the JD in this example is tuple forcing. (Recall from Chapter 9 that a JD is tuple forcing if it’s such that, if certain tuples appear, certain additional tuples are forced to appear as well.) And the notion of tuple forcing JDs (or the intuition behind that notion, rather) allows us to give definitions of the kinds of update anomalies that can occur in the presence of such a JD─definitions that are more precise than their FD counterparts (such as they are).5 To be specific: n
n
Definition: Let the JD J hold in relvar R. Then R suffers from a deletion anomaly with respect to J if and only if there exist a relation r and a tuple t, each with the same heading as R, such that: a.
r satisfies J, and
b.
The relation r′ whose body is obtained from that of r by removing t violates J.
Definition: Let the JD J hold in relvar R. Then R suffers from an insertion anomaly with respect to J if and only if there exist a relation r and a tuple t, each with the same heading as R, such that: a.
r satisfies J, and
b.
The relation r′ whose body is obtained from that of r by appending t satisfies R’s key constraints but violates J.
Points arising: n
Note carefully that the foregoing anomalies are specifically defined in terms of some JD J, and they can certainly occur if J is tuple forcing, as we’ve seen. In Chapter 13, however, we’ll see that a relvar can suffer from an insertion anomaly (though not a deletion anomaly) with respect to J even if J isn’t tuple forcing.
n
Although they’re more precisely defined than their FD counterparts, the foregoing anomalies can still be regarded as the redundancy problem looked at from another point of view─though here, of course, we’re referring to redundancy caused by a JD, not by an FD.
n
If relvar R is subject to update anomalies and those anomalies are caused by a JD (tuple forcing or otherwise), then replacing R by a set of 5NF projections will solve the problem. That is, such anomalies can’t occur with a 5NF relvar.
Please note carefully, however, that not all update anomalies are caused by FDs and JDs. In fact, it’s probably true to say that most integrity constraints (though not all) can give rise to an insertion anomaly, in the sense that there always exists a tuple whose insertion would cause the constraint in question to be violated. (As a simple example, suppose there’s a constraint to the effect that supplier status values must lie in the range 1 to 100, inclusive.) By contrast, comparatively few constraints can give rise to a deletion anomaly. (One that does would be a constraint to the effect that there must always be at least two distinct suppliers. Another is a foreign key
5 They might be more precise, but they’re also slightly suspect, inasmuch as they talk about inserting or deleting an individual tuple. As explained in SQL and Relational Theory, INSERT and DELETE really work on entire relations, not on individual tuples.
116
Chapter 10 / JDs and 5NF (Formal)
constraint; in the suppliers-and-parts database, for example, deleting a supplier can’t be done if it causes the pertinent foreign key constraint to be violated).
EXERCISES 10.1 The following questions are repeated from Chapter 1, but you should have a better chance of answering them now (assuming you couldn’t do so before, that is). a.
(Exercise 1.6.) Is it true that every “all key” relvar is in 5NF?
b.
(Exercise 1.7.) Is it true that every binary relvar is in 5NF?
c.
(Exercise 1.8.) Is it true that if a relvar has just one key and just one other attribute, then it’s in 5NF?
d.
(Exercise 1.9.) Is it true that if a relvar is in BCNF but not 5NF, then it must be all key?
e.
(Exercise 1.10.) Can you give a precise definition of 5NF?
f.
(Exercise 1.11.) Is it true that 5NF relvars are redundancy free?
10.2
Give as precise a definition as you can of what it means for a relvar to be subject to a join dependency.
10.3
How many JDs hold in the shipments relvar SP?
10.4
What does it mean to say a JD is implied by superkeys?
10.5
What’s a trivial JD? Is a trivial FD a special case?
10.6
Give an example of a JD that’s (a) tuple forcing, (b) not tuple forcing.
10.7 Consider relvar RAP as discussed in the answer to Exercise 9.2 in Chapter 9. Give examples of an insertion anomaly and a deletion anomaly that can occur with that relvar. 10.8 The following is a quote from a certain database textbook: “Fifth normal form concerns dependencies that are rather obscure. It has to do with relations that can be divided into subrelations, as we have been doing, but then cannot be reconstructed. The condition under which this situation arises has no clear, intuitive meaning. We do not know what the consequences of such dependencies are or even if they have any practical consequences.” Do you have any comments?
Chapter 11
Implicit Dependencies What are you implying? ─20th century catchphrase
We’ve seen several illustrations in previous chapters of the idea that certain dependencies imply others. To be specific, we saw in Chapter 7 how some FDs are implied by other FDs, and we saw in Chapters 9 and 10 how some JDs are implied by FDs. It’s time to take a closer look at such matters. (Note in particular that if we need to tell what normal form some given relvar is in, we do need to know all of the dependencies, implicit ones as well as explicit ones, that hold in that relvar.) In this chapter, therefore, I want to discuss among other things: n
Irrelevant JD components
n
Combining JD components
n
Irreducible JDs
n
Adding JD components
These discussions will pave the way for an explanation of what’s called the chase, to be described in the penultimate section of the chapter.
IRRELEVANT COMPONENTS Once again consider relvar S, with its FD {CITY} → {STATUS}. As we know from previous chapters: n
That relvar can be nonloss decomposed into its projections on {SNO,SNAME,CITY} and {CITY,STATUS}.
n
It can also clearly be nonloss decomposed into those same two projections together with the projection on (say) {SNAME,CITY}.
n
However, that third projection clearly isn’t needed in the process of reconstructing the original relvar. Let me now restate the foregoing example in terms of JDs: Relvar S is subject to the JD R { { SNO , SNAME , CITY } , { CITY , STATUS } }
and also to the JD R { { SNO , SNAME , CITY } , { CITY , STATUS } , { SNAME , CITY } }
118
Chapter 11 / Implicit Dependencies
In this latter JD, however, the {SNAME,CITY} component is irrelevant: It’s a proper subset of another component, and for that reason the corresponding projection isn’t needed in the process of reconstructing the original relvar. With the foregoing example by way of motivation, I can now give a precise definition of what it means for some component to be irrelevant in some JD: n
Definition: Let R{X1,..., Xn} be a JD, J say; then Xi is irrelevant in J if and only if (a) there exists some Xj in J such that Xi is a proper subset of Xj or (b) there exists some Xj in J (i < j) such that Xi = Xj.1
The reason for my choice of the term irrelevant here is as follows: If Xi is irrelevant in J, then every relation that satisfies J also satisfies J′, where J′ is derived from J by dropping Xi. What’s more, the converse is true too: Every relation that satisfies J′ also satisfies J. In other words, the JDs J and J′ are equivalent: Every relation that satisfies either one necessarily satisfies the other one as well. As a consequence, irrelevant components can’t just always be dropped, they can always be added too, without significant effect.
COMBINING COMPONENTS So now we’ve seen that some JDs imply other JDs (just as some FDs imply other FDs). But irrelevant components are far from being the end of the story. The next point is as follows (I’ve labeled it a theorem, but it’s very obvious and scarcely merits such a grand designation): n
Theorem: Let J be a JD and let J′ be derived from J by replacing two components by their union. Then J implies J′ (that is, every relation that satisfies J also satisfies J′).
By way of example, every legal value of relvar S satisfies the following JD (it’s the JD from the previous section, with an irrelevant component)─ R { { SNO , SNAME , CITY } , { CITY , STATUS } , { SNAME , CITY } } ─and therefore satisfies this one too: R { { SNO , SNAME , CITY } , { CITY , STATUS , SNAME } } Exercise: Check the validity of the foregoing claim for yourself─maybe even try to prove it, formally─if it isn’t immediately obvious. (Also, how many distinct JDs can be derived from the given one by combining components in this manner?) Points arising:
1
n
I made use of the foregoing theorem, tacitly, when I explained the intuition behind the membership algorithm (for testing whether a JD is implied by keys) in Chapter 10.
n
Observe that the theorem involves an implication, not an equivalence: J implies J′, but the converse isn’t true─J′ doesn’t imply J, in general, and so J and J′ aren’t equivalent (again, in general). Note: In fact this point is easy to see: If we keep on replacing components by their union, we’ll eventually obtain one that’s
If we assume the components X1, ..., Xn are all distinct, we can drop part (b) of this definition.
Implicit Dependencies / Chapter 11
119
equal to the entire heading, and the resulting JD J′ will be trivial─and it’s clearly not the case that every JD is equivalent to some trivial JD. n
Although it’s true that the second of the two JDs shown above (the binary one) holds in relvar S, nonloss decomposing that relvar on the basis of that JD would not be a good idea. Note: Exercise 11.4 asks you to explain this observation further, but you might like to take a moment now to convince yourself that it’s true. Also─to get ahead of myself for a moment─I can say the JD in question is in fact irreducible with respect to S (see the section immediately following). What the example shows, therefore, is that although irreducible JDs are important, they don’t necessarily correspond to good decompositions. Informally, in other words, we need to distinguish between “good” and “bad” JDs, where “good” and “bad” refer to the quality of the corresponding decompositions. For further discussion, see Chapter 14.
IRREDUCIBLE JDs So far the notion of one JD implying another has been more or less syntactic in nature─I haven’t really paid much attention to the question of whether the JDs we’re talking about actually hold in some given relvar. (Observe that neither the definition of irrelevant components, nor the theorem about replacing components by their union, made any mention of a relvar, nor even of a heading.) Now, however, let’s consider JDs that do actually hold in some relvar. Then we have the following theorem: n
Theorem: Let JD J hold in relvar R; then J is equivalent to some irreducible JD (not necessarily unique) that also holds in R. Note, however, that equivalence here has to be understood in the context of some particular relvar; it’s possible for two JDs both to hold in one relvar and not both to hold in another. In such a case, the two JDs might or might not be equivalent with respect to the first relvar, but they’re certainly not equivalent with respect to the second.
I’ll explain exactly what it means for a JD to be irreducible in a moment. Before I do, however, let me just remind you of a parallel with the world of FDs. Recall from Part II of this book that every FD that holds in relvar R implies some irreducible FD that also holds in relvar R. (This is easy to see: Just keep dropping attributes from the determinant until what remains is an FD that no longer holds.) Similarly, every JD that holds in relvar R implies─in fact, is equivalent to (a stronger statement)─some irreducible JD that also holds in relvar R. So what does it mean for a JD to be irreducible? Here’s a definition: n
Definition: Let R{X1,...,Xn} be a JD, J say, that holds in relvar R, and let there be no proper subset {Y1,...,Ym} of {X1,...,Xn} such that the JD R{Y1,...,Ym} also holds in R. Then J is irreducible with respect to R (or just irreducible, if R is understood). Points arising:
n
It’s easy to see that every JD that holds in relvar R implies an irreducible JD that also holds in relvar R─just keep dropping components from the given JD until what’s left is a JD that no longer holds in R, and then the last one that does hold is irreducible.
n
It’s also easy to see that the implication goes the other way, too: Start with the irreducible JD and add the dropped components back in until the original JD is reached. At each step in this process, the current version of the JD will be a JD that holds in R. Note: From this point and the previous point taken together, it follows
120
Chapter 11 / Implicit Dependencies
that (a) every JD that holds in R is equivalent to some irreducible JD that holds in R (as previously stated, in fact), and hence that (b) the irreducible JDs that hold in R in fact imply all of the JDs that hold in R. n
If some component Xi is irrelevant in J, then J is certainly reducible with respect to every relvar in which it holds (because Xi can be dropped without significant loss). However, J can still be reducible with respect to some relvar even if all components are relevant, as I now show.
Consider the suppliers relvar S once again. For simplicity, however, let’s agree to ignore attribute SNAME; what’s more, let’s agree to take the name “S” to refer to this reduced version of the relvar, until further notice. Now consider the following JD: R { { SNO , CITY } , { CITY , STATUS } , { SNO , STATUS } } This JD─let’s call it J1─has no irrelevant components. However, I’ll show that (a) it holds in relvar S but (b) it’s reducible with respect to that relvar, because the {CITY,STATUS} component can be dropped and what’s left is still a JD of S. Note: Actually the reducibility in this example is intuitively obvious, because (to state the matter precisely) the projection on {CITY,STATUS} of S is clearly equal to the projection on {CITY,STATUS} of the join of S{SNO,CITY} and S{SNO,STATUS}. As a consequence, the {CITY,STATUS} component adds nothing, as it were. To repeat, therefore: The reducibility is “obvious”─but now I want to prove it. a.
First, then, suppose the following tuples appear in S (simplified notation for tuples; s1 and s2 denote supplier numbers, c1 and c2 denote supplier cities, and t1 and t2 denote status values):2 s1 s1 s2
c1 c2 c1
t2 t1 t1
Because {SNO} is a key, the following FDs hold in S: { SNO } → { CITY } { SNO } → { STATUS } We can therefore conclude that c1 = c2 and t1 = t2, and so the tuple s1
c1
t1
appears in S, necessarily, because in fact it’s identical to the first (or, equally, the second) in the original list of tuples as shown above. But to say the original “three” tuples cause this “fourth” tuple to appear─if you see what I mean─is to say, precisely, that JD J1 holds (i.e., that’s what J1 says). So J1 does hold in S. b.
Now appealing to either of the FDs {SNO} → {CITY} and {SNO} → {STATUS} (both of which hold in S, as we know) and to Heath’s Theorem, we see that the following JD─let’s call it J2─certainly holds in relvar S: R { { SNO , CITY } , { SNO , STATUS } }
2
Note how each of these tuples corresponds to one component of the given JD (J1).
Implicit Dependencies / Chapter 11
121
But the components of J2 form a proper subset of those of J1. It follows that J1 is reducible with respect to S. To be specific, the component {CITY,STATUS} can be dropped from J1 without loss, in the sense that what remains is still a JD of S. Observe now that the foregoing proof made no use of the fact that the FD {CITY} → {STATUS} holds in S (indeed, the result would still be valid even if that FD didn’t hold). But now let’s do another example that does make use of that FD: n
First, we know now that the following JD (J1 from the previous example) holds in S: R { { SNO , CITY } , { CITY , STATUS } , { SNO , STATUS } }
n
But the FD {CITY} → {STATUS} also holds, and so by Heath’s Theorem the following JD─let’s call it J3─holds as well: R { { CITY , STATUS } , { CITY , SNO } }
n
The components of J3 form a proper subset of those of J1, and so it follows once again that J1 is reducible with respect to S. To be specific, the component {SNO,STATUS} can be dropped from J1 without loss, in the sense that what remains is still a JD of S.
Observe, therefore, that the original JD J1 is equivalent, with respect to relvar S, to two distinct JDs: namely, J2 and J3. In general, of course, the question is: Given relvar R and a JD J that holds in R, how can we find an irreducible equivalent (meaning, to be more precise about the matter, a JD that’s both equivalent to J and irreducible, where equivalent and irreducible are both understood as being with respect to R)? Well: n
If some component is irrelevant in J, that component can clearly be dropped.
n
If all components are relevant, we can only try dropping one, and then: a.
If what’s left is still a JD of R, we drop another component and repeat the process.
b.
If what’s left isn’t a JD of R, we reinstate the dropped component and try dropping another one.
Eventually, we’ll arrive at a JD that’s equivalent to the original one and is irreducible. And how do we tell whether some JD is in fact a JD of R? Well, if it’s one that’s been explicitly declared as such, there’s clearly no problem; but if not, we use the chase, which I’ll be describing in the next section but one.
SUMMARY SO FAR Let me summarize where we are. The general point is that some JDs imply others. As specific illustrations of this point, we’ve discussed:
122
Chapter 11 / Implicit Dependencies
n
Irrelevant components: Every JD J is equivalent to a JD J′ that’s obtained from J by adding or dropping irrelevant components.
n
Combining components: Every JD J implies a JD J′ that’s obtained from J by replacing two components by their union.
n
Irreducibility: Every JD J that holds in relvar R is equivalent to at least one JD J′─not necessarily distinct from J─that holds in R and is irreducible (where equivalent and irreducible must both be understood as being with respect to R). It follows that R’s irreducible JDs in fact imply all of R’s JDs. The following observations are also valid (I haven’t discussed them in detail, but they’re intuitively obvious):
n
Adding attributes: If JD J holds in relvar R, then so does every JD J′ that’s obtained from J by adding some attribute of R to some component of J.
n
Adding components: If JD J holds in relvar R, then so does every JD J′ that’s obtained from J by adding any subset of the heading of R as another component.
Observe in both of these cases, however, that we’re talking about implication, not equivalence. For example, in relvar S (but ignoring SNAME once again, for simplicity), the JD R{SNO,STATUS},{SNO,CITY}} holds, and therefore the following JD holds too: R{{SNO,STATUS},{SNO,CITY},{CITY,STATUS}}. However, the converse is false─if the latter JD holds, it doesn’t follow that the former one does.3 We can also say the following: If J is a JD that holds in relvar R and J implies another JD J′, where J′ is obtained from J by dropping attributes from components of J and/or dropping entire components from J, then J is certainly a “bad” JD (see the remarks on the topic of good vs. bad JDs at the end of the section “Combining Components”). However, not all “bad” JDs can be obtained in this simple fashion, as we’ll see. Now I’d like to generalize the discussion somewhat. First of all, from this point forward I’ll take the term dependencies to mean either FDs or JDs or both, as the context demands.4 Now, throughout this book so far, whenever I’ve considered the question of dependencies being implied by others, I’ve tacitly limited my attention to ones that are implied by an individual dependency. More generally, however, it turns out that certain sets of dependencies can imply others. Let me give an example. Consider a relvar SPT, with attributes SNO, PNO, and STATUS (only), where the attributes have their usual meanings. Suppose we’re told, not unreasonably, that the following dependencies (one FD and one JD) both hold in this relvar: { SNO , PNO } → { STATUS } R { { SNO , PNO } , { SNO , STATUS } } Now, given the semantics of the situation, it’s intuitively obvious that (a) {SNO} isn’t a key for SPT and yet (b) the FD {SNO} → {STATUS} holds in SPT implicitly (and so SPT isn’t in 2NF, incidentally). Note that I say
3 Of course, the former JD does hold in our running example, thanks to the fact that the FD {CITY} → {STATUS} also holds. But the latter JD doesn’t imply the former in general. 4 As we know, other kinds of dependencies─e.g., equality dependencies, which were mentioned in passing in Chapter 3 and elsewhere and are discussed further in Chapter 13─exist also, but I'm deliberately excluding them from consideration at this time.
Implicit Dependencies / Chapter 11
123
“implicitly” because we haven’t been told the FD holds explicitly. The question is: Can we prove (a) and (b), given only that the stated FD and JD hold? That is, can we show that (a) and (b) are valid formally, without paying any regard to semantics? (After all, that’s what the system would have to do, if we wanted it to be able to infer dependencies. The system doesn’t know anything about semantics, as I’m using that term here.)5 So let’s give it a try. First of all, suppose the following tuples appear in SPT: s1 s1
p1 p2
t2 t1
Suppose also that p1 ≠ p2. Now what we need to do, in order to show the FD {SNO} → {STATUS} holds, is to show that t1 and t2 must necessarily be equal. We begin by writing down the projections of these two tuples corresponding to the components of the given JD R{{SNO,PNO},{SNO,STATUS}}: s1 s1
p1 p2
s1 s1
t2 t1
Joining these projections together, we obtain the original two tuples plus two extra ones (shown below in bold): s1 s1 s1 s1
p1 p1 p2 p2
t2 t1 t2 t1
Since the given JD holds, the two extra tuples must in fact appear in the relvar along with the original two. But the FD {SNO,PNO} → {STATUS} holds also; it follows that t1 = t2, and hence that the FD {SNO} → {STATUS} holds (every tuple that has SNO s1 also has STATUS t1). This is part (b) of what was to be proved. At the same time, by our assumption we have p1 ≠ p2─note that nothing in the argument so far invalidates that assumption─from which it follows that the FD {SNO} → {PNO} doesn’t hold, and so {SNO} isn’t a key; and this is part (a) of what was to be proved. So we see that any given relvar is subject to both explicit dependencies (these are the ones explicitly declared) and implicit dependencies (these are the ones implied by the explicitly declared ones). For the record, let me bring these points together into an appropriate definition: n
Definition: Let R be a relvar. Associated with R are two sets of explicit dependencies: a set XFD of explicit FDs that hold in R and a set XJD of explicit JDs that hold in R. The FDs in XFD together with the JDs in XJD are the explicit dependencies of R. The FDs and JDs that aren’t in XFD or XJD but are logical consequences of the ones in XFD and XJD are the implicit dependencies of R. The explicit and implicit dependencies of R taken together are the dependencies of R. A relation r can be assigned to R only if that relation r satisfies all of the dependencies of R.
THE CHASE ALGORITHM From everything we’ve seen in this chapter so far, the obvious question presents itself:
5 I note in passing that a proof of part (b) follows immediately from what Exercise 11.3, q.v., refers to as the converse of an extended version of Heath’s theorem.
124
Chapter 11 / Implicit Dependencies
Given some set D of dependencies (FDs or JDs or a mixture), what dependencies d are implied by those in that set? A partial answer to this question is provided by the chase algorithm, which is, precisely, an algorithm for testing whether some dependency d is implied by a set of dependencies D. More specifically, given the set D and some dependency d, the chase will either: a.
Show d is implied by D, or
b.
Show it isn’t, by providing an explicit counterexample─that is, a relation that satisfies all of the dependencies in D and yet violates d.
As a matter of fact we’ve already seen some examples of the chase in action, as it were. In the previous section, I showed how a given FD and JD together implied a certain FD and not another (the latter was actually a key constraint, which is a special case of an FD, of course). And in the section before that, I gave two examples in which a given FD and JD together implied a certain JD (thereby showing the given JD was reducible, incidentally). All of these examples were in fact applications of the chase. But now let’s get more specific. In order to do that, I first need to introduce a little more terminology: n
Consider FDs. Abstractly (though of course very loosely), an FD takes the form “If certain tuples t1, ..., tn appear, then certain attributes within those tuples must have equal values.” For this reason, FDs are sometimes said to be equality generating dependencies.
n
Now consider JDs. Abstractly, but again very loosely, a JD takes the form “If certain tuples t1, ..., tn appear, then a certain tuple t must appear.” JDs are therefore sometimes said to be tuple generating dependencies.
Before going any further, I must caution you not to confuse tuple generating and tuple forcing dependencies.6 A tuple forcing dependency is a JD with the property that if tuples t1, ..., tn appear, then some tuple t is forced to appear that’s distinct from each of t1, ..., tn. By contrast, a tuple generating dependency (a) doesn’t require the “generated” tuple to be distinct from the given tuples and (b) doesn’t in fact have to be a JD, as such, at all. (However, the only tuple generating dependencies discussed in this book are indeed JDs specifically. For present purposes, therefore, you can take “tuple generating dependency” to mean a JD; thus, we can say that all tuple forcing dependencies are tuple generating, but some tuple generating dependencies aren’t tuple forcing.) Equality generating and tuple generating dependencies both involve a set of premises─viz., the tuples t1, ..., tn─and a conclusion. For a tuple generating dependency, the conclusion is the generated tuple t; for an equality generating dependency, it’s the fact that a certain equality holds. Now I can explain the chase algorithm as such. Perhaps I should say first that it’s essentially common sense; in fact, it tends to be easier to illustrate than to describe. In outline, however, it works like this. We’re trying to determine whether the dependency d follows from the dependencies in the set D. We proceed as follows: 1.
We write down tuples representing the premises of d.
2.
We apply the dependencies in D to those tuples (possibly generating additional tuples), and keep repeating this process until no further change occurs.
6 By the same token, don't confuse equality generating dependencies and equality dependencies, mentioned in an earlier footnote in this chapter and elsewhere and discussed in detail in Chapter 13.
Implicit Dependencies / Chapter 11
125
This procedure overall will eventually yield either: a.
A representation of the conclusion of d, in which case d does follow from D, or
b.
A relation that satisfies D but not d, in which case d doesn’t follow from D. Let’s do an example. Let the given set of dependencies be as follows (Heath notation once again): { A → C , B → C , C → D , CE → A , DE → C }
(Actually they’re all FDs, as you can see.) Consider also the following JD (call it J): R { AB , AD , AE , BE , CDE } I’ll now show that the given FDs do in fact imply J (a state of affairs that, I’ll think you agree, isn’t immediately obvious). The first step is to write down tuples representing the premises of the JD J. Now, let me spell out exactly what that JD says: If all of the following are the case─ n a tuple appears with A = a and B = b n a tuple appears with A = a and D = d n a tuple appears with A = a and E = e n a tuple appears with B = b and E = e a tuple appears with C = c and D = d and E = e n ─then n a tuple with A = a and B = b and C = c and D = d and E = e must appear. However, it turns out to be more convenient to use, not a, b, c, d, and e as such, but rather suffixed x’s and y’s to denote attribute values. To be specific, I’ll use x1-x5 in place of a-e, respectively, and I’ll use y’s in all other positions; e.g., I’ll use y23 to denote the “third” or C value in the “second” premise tuple. So the premise tuples look like this:7 x1 x1 x1 y41 y51
x2 y22 y32 x2 y52
y13 y23 y33 y43 x3
y14 x4 y34 y44 x4
y15 y25 x5 x5 x5
If (and only if) the JD is implied by the five FDs, then, these tuples will “generate” the following tuple: x1
x2
x3
x4
x5
7 Strictly speaking, the premise tuples aren't really tuples at all, because they contain variables instead of values. Likewise, the premise tuples taken together don't really constitute a relation, either. I propose to overlook these points from here on; however, I should at least mention in passing that─partly for such reasons─the research literature typically refers to those premise tuples as constituting not a relation but a tableau.
126
Chapter 11 / Implicit Dependencies
So let’s see if it does; i.e., let’s apply the given dependencies. n
From A → C, we have y13 = y23 = y33; likewise, from B → C, we have y13 = y43. So we can replace each of y23, y33, and y43 by y13. The premise tuples become (replacements shown in bold): x1 x1 x1 y41 y51
n
y15 y25 x5 x5 x5
x2 y22 y32 x2 y52
y13 y13 y13 y13 x3
x4 x4 x4 x4 x4
y15 y25 x5 x5 x5
x2 y22 y32 x2 y52
y13 y13 y13 y13 x3
x4 x4 x4 x4 x4
y15 y25 x5 x5 x5
From DE → C, we have y13 = x3. Make the replacements: x1 x1 x1 x1 y51
n
y14 x4 y34 y44 x4
From CE → A, we have y41 = x1. Make the replacements: x1 x1 x1 x1 y51
n
y13 y13 y13 y13 x3
From C → D, we have y14 = y34 = y44 = x4. Make the replacements: x1 x1 x1 y41 y51
n
x2 y22 y32 x2 y52
x2 y22 y32 x2 y52
x3 x3 x3 x3 x3
x4 x4 x4 x4 x4
y15 y25 x5 x5 x5
◄═
Success: all x’s !!!
The “fourth” tuple here is all x’s, and so the JD J does indeed follow from the given FDs.
Let’s look at another example. Let the given set of dependencies consist of just the JD {AB,AC}. Does this set imply the FD A → B? Note: We already know the answer is no, because what we’re talking about here is the converse of Heath’s Theorem, and we know from Exercise 5.4 that the converse of Heath’s Theorem is false. But let’s see what the chase tells us: n
Premise tuples: x1 x1
y12 y22
y13 y23
If and only if the FD is implied by the JD, then applying the JD to these tuples will have to make y12 and y22 equal. Does it do so? Well: n
The given JD “generates” tuples as follows:
Implicit Dependencies / Chapter 11
x1 x1 n
y12 y22
127
y23 y13
The four tuples taken together satisfy the JD but not the FD; in particular, they don’t require that y12 = y22. So the FD doesn’t follow from the JD.
CONCLUDING REMARKS In this chapter, we’ve seen JDs implying JDs; a JD and an FD together implying an FD; FDs implying a JD; and, in earlier chapters, FDs implying FDs. However, note carefully that all the chase lets us do is determine whether a specific dependency follows from given dependencies. What it doesn’t do is let us infer, or generate, new dependencies from the given set (that’s why I said, near the beginning of the previous section, that the chase provided only a partial answer to the question). For that, we’d need an axiomatization for FDs and JDs. And while Armstrong’s rules provide a sound and complete axiomatization for FDs by themselves, it’s unfortunately a known fact that no such axiomatization exists for FDs and JDs considered together.8
EXERCISES 11.1 Consider the parts relvar P from the suppliers-and-parts database. For simplicity, let’s rename attributes PNO, PNAME, COLOR, WEIGHT, and CITY as A, B, C, D, and E, respectively, and let’s use Heath notation once again. Then the following JDs are all defined with respect to the heading of P: a. b. c. d. e. f. g. h. i. j. k. l.
R { R { R { R { R { R { R { R { R { R { R { R {
AC , ABDE } ACD , ABDE } AE , ABCD } AB , ACD , CE } AB , ACD , AE } AB , BCD , DE } ABC , ACDE , CE } ABCD , BDE , BCE } AB , ABC , BCD , CDE , AD } AB , BC , CD , DE , AD } ABD , CDE , ABC , BE , ABE } A , AB , ABC , ABD , ACE }
Which of these JDs are trivial? Which ones involve irrelevant components? Which imply which others in the list? Which pairs are equivalent to one another? Which are satisfied by the sample value of relvar P shown in Fig. 1.1? Which hold in relvar P? Which are irreducible with respect to P? 11.2 a.
8
The dependencies in this exercise are all defined with respect to a heading consisting of attributes ABCD. Does the set of FDs {A → B, A → C} imply the JD R{AD,ABC}?
See, e.g., the book Foundations of Databases, by Serge Abiteboul, Richard Hull, and Victor Vianu (Addison-Wesley, 1995).
128
Chapter 11 / Implicit Dependencies
b.
Does the set of FDs {C → D, B → C} imply the JD R{AB,BC,CD}?
c.
Does the set of FDs {A → B, B → C} imply the JD R{AB,BC,CD}?
d.
Does the the JD R{BC,ABD} imply the JD R{AB,BC,CD}?
11.3 We know from Exercise 5.4 that the converse of Heath’s Theorem is false. However, there’s an extended version of that theorem whose converse is true. Here it is: n
Heath’s Theorem (extended version): Let relvar R have heading H and let X, Y, and Z be subsets of H such that the union of X, Y, and Z is equal to H. Let XY denote the union of X and Y, and similarly for XZ. If R is subject to the FD X → Y, then (a) R is subject to the JD R{XY,XZ}, and (b) XZ is a superkey for R.
Prove part (b) of this theorem. Prove also that (a) and (b) together imply that X → Y holds (the converse of the extended theorem). 11.4
Consider the following JDs, both of which hold in relvar S: R { { SNO , SNAME , CITY } , { CITY , STATUS } , { SNAME , CITY } } R { { SNO , SNAME , CITY } , { CITY , STATUS , SNAME } }
I pointed out in the body of the chapter (in the section “Combining Components”) that although the first of these JDs implied the second, decomposing relvar S on the basis of that second JD (even though it’s irreducible) wouldn’t be a good idea. Why not?
Chapter 12
MVDs and 4NF Who’s on first, What’s on second, I Don’t Know’s on third ─Bud Abbott and Lou Costello: Naughty Nineties
In Chapter 10, I said that 4NF, like 2NF and 3NF, is mostly of historical interest. However, that characterization is perhaps a little unfair, because: n
First of all, 4NF is the normal form with respect to what are called multivalued dependencies or MVDs. Now, MVDs are really just a special kind of JD; so if you know about JDs in general, you know about MVDs already, in a sense. Nevertheless, MVDs are still worth studying in their own right (for one thing, they’re probably more common in practice than JDs that aren’t MVDs are).
n
Second, MVDs have a more intuitive real world interpretation than JDs in general do, and therefore tend to be a little easier to understand.
n
Third, MVDs, unlike JDs in general, do have an axiomatization, as we’ll see.
So let’s take a closer look.
AN INTRODUCTORY EXAMPLE In this section and the next, I’ll examine MVDs from a comparatively informal point of view; in the section after that I’ll consider them again, but more formally, and use that more formal understanding to lead up to 4NF. I’ll begin with a definition. n
Definition: A multivalued dependency (MVD) is a join dependency with exactly two components.
It follows from this definition that a nonloss decomposition on the basis of an MVD always yields exactly two projections (recall that JDs in general can be n-way for some n > 2; by contrast, MVDs are always exactly 2-way). It follows further that the following JD (for example) is in fact an MVD: R { { SNO , SNAME , CITY } , { CITY , STATUS } } Now, we’ve seen this particular JD repeatedly in this book; it holds in relvar S. But didn’t I say in Chapter 9 that this JD was implied by a functional dependency: viz., the FD {CITY} → {STATUS}? Indeed I did; what the example shows, therefore, is that some MVDs are implied by FDs. But not all are, and as you’d probably expect it’s the ones that aren’t that are the interesting ones, in a sense. So let’s take a look at one of those “interesting ones.”
130
Chapter 12 / MVDs and 4NF
Consider Fig. 12.1, which shows a sample value for a relvar called CTX.1 The predicate is as follows: Course CNO can be taught by teacher TNO and uses textbook XNO. ┌─────┬─────┬─────┐ CTX │ CNO │ TNO │ XNO │ ├═════┼═════┼═════┤ │ C1 │ T1 │ X1 │ │ C1 │ T1 │ X2 │ │ C1 │ T2 │ X1 │ │ C1 │ T2 │ X2 │ └─────┴─────┴─────┘ Fig. 12.1: Relvar CTX─sample value
Now, relvar CTX is “all key” and is therefore certainly in BCNF. Yet it suffers from redundancy, as you can see; for example, the fact that teacher T1 can teach course C1 appears twice, and so does the fact that course C1 uses textbook X1. (It therefore suffers from certain update anomalies also. See Exercise 12.3.) And the reason for these redundancies is that I’m assuming─perhaps not very realistically─that teachers and textbooks are quite independent of one another; that is, no matter who actually teaches any particular offering of some particular course, the same textbooks are used. I also assume a given teacher or given textbook can be associated with any number of courses. Thus: n
Each course c has a set T of teachers who can teach it and a set X of textbooks that it uses.
n
And, for each such course c, there’s a tuple in CTX for every possible combination of a teacher t from T and a textbook x from X. (Loosely speaking, in other words, each CNO value appears together with the cartesian product of all of the TNO and XNO values that correspond to that CNO value.)
To state the matter more precisely, the following constraint holds in relvar CTX (recall that from Chapter 9 that the symbol “∈” means “appears in”): IF AND THEN AND
( ( ( (
c c c c
, , , ,
t1 t2 t1 t2
, , , ,
x1 x2 x2 x1
) ) ) )
∈ ∈ ∈ ∈
CTX CTX CTX CTX
But to say this constraint holds is equivalent to saying the following JD holds: R { { CNO , TNO } , { CNO , XNO } } It follows that CTX is subject to this JD, and it further follows that the relvar can, and probably should, be decomposed into its projections on {CNO,TNO} and {CNO,XNO}. Exercise: Show the values of these projections corresponding to the sample value of relvar CTX in Fig. 12.1, and check that the redundancies disappear. (But what multirelvar constraint now needs to be enforced?) As an aside, I remark that the constraint shown above could be reduced from four lines to three without loss, by simply dropping the last line. What I mean is, if tuples (c,t1,x1) and (c,t2,x2) both appear, then the tuple (c,t1,x2) must appear (that’s what the third line says); so, switching the first two tuples around, it follows that if (c,t2,x2) and
1
The example is a modified version of the CTXD example from Chapter 9.
MVDs and 4NF / Chapter 12
131
(c,t1,x1) appear, then (c,t2,x1) must appear as well. But the four-line version of the constraint is more symmetric and aesthetically satisfying, as well as perhaps being easier to understand. By the way, you might be thinking the redundancies in CTX are unnecessary; more specifically, you might be thinking the relvar doesn’t need to show all possible TNO / XNO combinations for a given CNO. For example, two tuples would clearly be enough to represent the information that course C1 has two teachers and two textbooks. The problem is, which two tuples? Any specific choice leads to a relvar having a very unobvious interpretation and very strange update behavior. (Try stating the predicate for such a relvar!─i.e., try stating the criteria for deciding whether or not some given update is logically acceptable on that relvar. If you try this exercise, I think you’ll see why the redundancies in CTX are necessary after all.)
MULTIVALUED DEPENDENCIES (INFORMAL) The existence of “problem” BCNF relvars like CTX was recognized very early on, and the way to deal with them was also recognized at that time, at least intuitively (see Exercise 12.8). However, it wasn’t until 1977 that these intuitive ideas were put on a sound theoretical footing by Fagin’s introduction of the notion of MVDs.2 Let me elaborate. Relvar CTX is subject to the JD R{{CNO,TNO},{CNO,XNO}}. However, we can equally well say it’s subject to the following pair of MVDs: { CNO } →→ { TNO } { CNO } →→ { XNO } Note: The MVD X →→ Y can be read as “X multidetermines Y” or “Y is multidependent on X,” or more simply just as “X double arrow Y.” Taken together, what the foregoing MVDs mean, intuitively, is this: Courses don’t have just one teacher or just one textbook (i.e., the FDs {CNO} → {TNO} and {CNO} → {XNO} don’t hold)─but they do have a set of teachers and a set of textbooks. What’s more, for a given course, the set of teachers and the set of textbooks are completely independent of each other. (As I put it earlier, it doesn’t matter who actually teaches some particular offering of some course, the same textbooks are used. Likewise, it doesn’t matter, with respect to some course, which textbooks are actually used─the same teachers can teach it.) So we can say the following: n
For a given course c and a given textbook x, the set of teachers t associated with that (c,x) pair depends on c alone─it makes no difference which particular x we choose.
n
Likewise, for a given course c and a given teacher t, the set of textbooks x associated with that (c,t) pair also depends on c alone─it makes no difference which particular t we choose.
Note that the sample value of relvar CTX shown in Fig. 12.1 does indeed abide by these rules. To repeat, relvar CTX is subject to a pair of MVDs. In general, in fact, it’s easy to show (see the next section) that, given relvar R with heading H and subsets X, Y, and Z of H such that the union of X, Y, and Z is equal to H, the MVD X →→ Y holds in R if and only if the MVD X →→ Z also holds in R. MVDs always go together in pairs in this way. For that reason it’s usual to write them as a “one liner,” thus: X →→ Y | Z 2 Fagin’s work on MVDs predated the widespread adoption of the concept of JDs in general, which is why MVDs were initially treated as a separate phenomenon in their own right.
132
Chapter 12 / MVDs and 4NF
(“X double arrow Y bar Z”). In the case of relvar CTX, for example, we have: { CNO } →→ { TNO } | { XNO } Now, we might say, very loosely, that an MVD is like an FD, except that instead of “For one of these, there’s one of those,” it’s “For one of these, there’s a set of those” (it’s this informal characterization that makes MVDs a little easier to understand than JDs in general). But the point about always going in pairs is important (note that nothing analogous applies to FDs). Indeed, if the MVD concept is defined too imprecisely (as I’ve just done, in fact!), one could incorrectly conclude that for every pair of subsets X and Y of the heading of the pertinent relvar, there’s an MVD from X to Y. For example, in the shipments relvar SP, there’s certainly a set of quantities for each supplier number, but the MVD {SNO} →→ {QTY} does not hold─it’s not the case that for a given supplier number s and given part number p, the set of quantities q associated with that (s,p) pair depends on s alone.
MULTIVALUED DEPENDENCIES (FORMAL) The definitions in this section parallel those given in earlier chapters for FDs and JDs and are therefore presented with little by way of further commentary. n
Definition: Let H be a heading; then a multivalued dependency (MVD) with respect to H is an expression of the form X →→ Y, where X (the determinant) and Y (the dependant) are both subsets of H. Note: The phrase MVD with respect to H can be abbreviated to just MVD, if H is understood.
Note carefully that, like FDs and JDs, MVDs are defined with respect to some heading, not with respect to some relation or some relvar. Note too that from a formal point of view (again like FDs and JDs), MVDs are just expressions: expressions that, when interpreted with respect to some specific relation, become propositions that by definition can evaluate to either TRUE or FALSE. n
Definition: Let relation r have heading H; let X →→ Y be an MVD, M say, with respect to H; and let Z be the attributes of H not contained in either X or Y. (In other words, Z is the complement with respect to H of the union of X and Y, and the union of X, Y, and Z is equal to H.) If r satisfies the JD R{XY,XZ}, then r satisfies M; otherwise r violates M.
Note that the foregoing definition is symmetric in Y and Z, whence it follows that r satisfies the MVD X →→ Y if and only if it satisfies the MVD X →→ Z (and we can therefore write them as a “one liner,” as noted in the previous section). n
Definition: The MVD M holds in relvar R (equivalently, relvar R is subject to the MVD M) if and only if every relation that can ever be assigned to relvar R satisfies M. The MVDs that hold in relvar R are the MVDs of R.
From this definition and the previous one, it follows that R is subject to the MVD X →→ Y if and only if it’s subject to the MVD X →→ Z. n
Fagin’s Theorem: Relvar R can be nonloss decomposed into its projections on XY and XZ if and only if the MVDs X →→ Y | Z hold in R.
MVDs and 4NF / Chapter 12
133
Fagin’s Theorem is the “stronger form of Heath’s Theorem” promised in Chapter 5. That is, where Heath’s Theorem gave only a sufficient condition for a relvar to be nonloss decomposable into two projections, Fagin’s Theorem gives both necessary and sufficient conditions. Of course, Fagin’s Theorem is “obvious,” given what we now know about JDs in general; with hindsight, there would never have been any formal need to define MVDs at all if JDs in general had been defined and properly investigated first. But Fagin’s Theorem was proved before JDs in general had been properly investigated, and it was a new and important result at the time; what’s more, it still has practical significance, inasmuch as MVDs do correspond to a fairly common kind of business rule, whereas the same can’t reasonably be said for “cyclic” n-way JDs for n > 2 as discussed in Chapters 9 and 10.
FOURTH NORMAL FORM You won’t be surprised to hear there’s such a thing as a trivial MVD: n
Definition: Let X →→ Y be an MVD, M say, with respect to heading H. Then M is trivial if and only if it’s satisfied by every relation with heading H.
From this definition, it’s easy to prove the following theorem (see Exercise 12.7): n
Theorem: Let X →→ Y be an MVD, M say, with respect to heading H. Then M is trivial if and only if either (a) Y is a subset of X or (b) the union of X and Y is equal to H.
You probably won’t be surprised by the next definition, either: n
Definition: Let relvar R have heading H and let X →→ Y be an MVD, M say, with respect to H. Then M is implied by the keys of R if and only if every relation r that satisfies R’s key constraints also satisfies M.
As with FDs and JDs, “implied by keys” here could just as well be “implied by superkeys” without making any significant difference. Also, if M is trivial, it’s satisfied by every relation r with heading H, and so it’s satisfied by every relation r that satisfies R’s key constraints a fortiori. Thus, trivial MVDs are always “implied by keys,” trivially. So suppose M is nontrivial. Then it’s easy to prove the following theorem: n
Theorem: Let M be a nontrivial MVD that holds in relvar R. Then M is implied by the keys of R if and only if it reduces to an FD out of a superkey of R─i.e., the double arrow reduces to a single arrow, as it were, and the determinant is a superkey.
And now I can define 4NF: n
Definition: Relvar R is in fourth normal form (4NF) if and only if every MVD of R is implied by the keys of R.
However, given the various definitions and theorems already discussed in this section, we can see that the following “operational” definition is valid too: n
Definition: Relvar R is in fourth normal form (4NF) if and only for every nontrivial MVD X →→ Y that holds in R, X is a superkey for R (in other words, every such MVD reduces to “an FD out of a superkey”).
134
Chapter 12 / MVDs and 4NF
Of course, if an MVD is implied by the keys of R, it certainly holds in R─i.e., it’s certainly “an MVD of R.” However, the converse is false: An MVD can hold in R without being implied by the keys of R (relvar CTX provides an example). Thus, the whole point about the 4NF definition is that the only MVDs that hold in a 4NF relvar are ones we can’t get rid of—which means ones implied by keys (including trivial ones as a special case).3 Recall now from Chapter 10 the parallelism between the BCNF and 5NF definitions. In fact, that parallelism extends to the 4NF definition, too. That is, we have the following: n
R is in BCNF if and only if every FD that holds in R is implied by the keys of R.
n
R is in 4NF if and only if every MVD that holds in R is implied by the keys of R.
n
R is in 5NF if and only if every JD that holds in R is implied by the keys of R.
Now, in the BCNF and 4NF definitions, we can simplify “implied by the keys” to just “implied by some key”; as noted in Chapter 10, however, the same is not true for the 5NF definition. In that sense, 4NF resembles BCNF more than it does 5NF. On the other hand, 4NF also resembles 5NF more than it does BCNF, in the sense that the 4NF and 5NF definitions both rely on context─by which I mean that the MVDs and JDs that hold in a 4NF or 5NF relvar involve, at least implicitly, all of the attributes of that relvar, whereas the same is not true for BCNF. (As I said earlier, the point about MVDs always going in pairs is important. Nothing analogous applies to FDs.) Recall now from Chapter 6 the concept of FD preservation. Essentially, the idea was as follows: If the FD X → Y holds in relvar R, then the recommendation is to decompose R─assuming that decomposition is desired at all, and assuming further that it’s done on the basis of some FD other than X → Y itself─in such a way that X and Y are kept together in the same projection. Well, the concept extends to MVDs too─that is, the recommendation still applies if we replace the FD X → Y by the MVD X →→ Y throughout. In closing this section, let me state explicitly that: a.
If relvar R is in 5NF, it’s certainly in 4NF; likewise, if relvar R is in 4NF, it’s certainly in BCNF.
b.
A relvar can be in 4NF without being in 5NF (see Exercise 12.4).
c.
4NF is always achievable. (In fact, of course, we know this already, because we know 5NF is always achievable, and now we know 5NF implies 4NF.)
AXIOMATIZATION As I mentioned near the beginning of this chapter, MVDs, unlike JDs in general, do have an axiomatization, or in other words a sound and complete set of rules for generating “new” MVDs from given ones. The rules in question are as follows:
3
1.
If Y is a subset of X, then X →→ Y (“reflexivity”).
2.
If X →→ Y and Z is a subset of W, then XW →→ YZ (“augmentation”).
As usual, “getting rid of” a dependency of any kind really means replacing it by some multirelvar constraint.
MVDs and 4NF / Chapter 12
3.
If X →→ Y and Y →→ Z, then X →→ Z - Y (“transitivity”).
4.
If (a) the union of X, Y, and Z is equal to the pertinent heading H and (b) the intersection of Y and Z is a subset of X, then (c) X →→ Y | Z (“complementation”).
135
Now, these four rules aren’t nearly as easy to understand or remember as Armstrong’s rules are for FDs (or so it seems to me, at any rate). Partly for that reason, I won’t attempt to justify them here, nor will I show them in action. However, I will at least say that further rules can be derived from the original four, the following among them: 5.
If X →→ Y and YZ →→ W, then XZ →→ W - YZ (“pseudotransitivity”).
6.
If X →→ Y and X →→ Z, then X →→ YZ (“union”).
7.
If X →→ YZ and W is the intersection of Y and Z, then X →→ Y - Z, X →→ Z - Y, and X →→ W (“decomposition”).
The following rules involve both MVDs and FDs: 8.
If X → Y, then X →→ Y (“replication”).
9.
If (a) X →→ Y, (b) Z → W, (c) W is a subset of Y, and (d) the intersection of Y and Z is empty, then (e) X → W (“coalescence”).
And the following is an additional derived rule: 10.
If X →→ Y and XY → Z, then X → Z - Y (“mixed pseudotransitivity”).
EMBEDDED DEPENDENCIES Recall relvar CTXD from Chapter 9 (a sample value, repeated from Fig. 9.3, is shown in Fig. 12.2 overleaf). That relvar can be regarded as an extended version of relvar CTX as discussed earlier in the present chapter. The predicate is Teacher TNO spends DAYS days with textbook XNO on course CNO,4 and the sole key is {CNO,TNO,XNO}. As we saw in Chapter 9, relvar CTXD suffers from redundancy;5 yet it’s in 5NF, which means no JDs (and therefore no MVDs, a fortiori) hold apart from trivial ones. In particular, therefore, the MVDs { CNO } →→ { TNO } | { XNO }
4
This is the predicate I gave in Chapter 9, but a more accurate version might be: Course CNO can be taught by teacher TNO and uses textbook XNO, and teacher TNO spends DAYS days with textbook XNO on course CNO. And we might want to add DAYS is greater than zero as well. See Chapter 15 for further discussion. 5
As noted in Chapter 9, one of my reviewers disputed this claim. Again, see Chapter 15 for further discussion.
136
Chapter 12 / MVDs and 4NF
┌─────┬─────┬─────┬──────┐ CTXD │ CNO │ TNO │ XNO │ DAYS │ ├═════┼═════┼═════┼──────┤ │ C1 │ T1 │ X1 │ 7 │ │ C1 │ T1 │ X2 │ 8 │ │ C1 │ T2 │ X1 │ 9 │ │ C1 │ T2 │ X2 │ 6 │ └─────┴─────┴─────┴──────┘ Fig. 12.2: The 5NF relvar CTXD─sample value
do not hold6─but they do hold in the projection of CTXD on {CNO,TNO,XNO}. For that reason, those MVDs are said to be embedded in the original relvar CTXD. In general, given some relvar R with heading H, an embedded dependency with respect to R is a dependency that doesn’t hold in R itself but does hold in the projection of R on some proper subset of H. As the example illustrates, therefore (and as was noted in Chapter 9, albeit in different words), embedded dependencies cause redundancy, but that redundancy can’t be eliminated by taking projections. Such redundancies thus correspond to constraints that must be separately stated and enforced (see Exercise 12.2). Observe, incidentally, that the foregoing notion of embedding applies to JDs (and therefore to MVDs)7 but not to FDs. That is, given some relvar R and a projection of R whose heading includes both X and Y, the FD X → Y holds in that projection if and only if it holds in R itself. For example, the FD {CITY} → {STATUS} holds in relvar S as such and also in every projection of that relvar that retains both of those attributes. EXERCISES 12.1 Give (a) an example of a relvar of degree at least three that’s in BCNF but not 4NF and (b) an example of a binary relvar that’s in BCNF but not 4NF. 12.2 Write Tutorial D CONSTRAINT statements to express (a) the MVDs that hold in relvar CTX and (b) the embedded MVDs that hold in relvar CTXD, where relvars CTX and CTXD are as in the body of the chapter. 12.3 Consider relvar CTX from the body of the chapter. What kinds of update anomalies can occur with that relvar? 12.4
Give an example of a relvar that’s in 4NF but not 5NF.
12.5 Prove that, given some relvar R and a projection of R whose heading includes both X and Y, the FD X → Y holds in that projection if and only if it holds in R itself. 12.6
Show that if relvar R is subject to the FD X → Y, it’s also subject to the MVD X →→ Y.
12.7 Let X →→ Y be an MVD, M say, with respect to heading H. Prove that M is trivial if and only if either (a) Y is a subset of X or (b) the union of X and Y is equal to H. Incidentally, note that it follows from this result that, given
6 I’m being a little sloppy here; by the definitions given earlier in the chapter, the MVDs {CNO} →→ {TNO}|{XNO} can’t possibly hold in relvar CTXD, since they fail to mention the DAYS attribute. But I think you see what I mean.
7
For an example of an embedded JD that’s not an embedded MVD, suppose relvar SPJ from Chapter 9 is extended to include a quantity attribute, QTY, thereby forming a new relvar SPJQ. Suppose the FD {SNO,PNO,JNO} → {QTY} holds in SPJQ (i.e., {SNO,PNO,JNO} is a key). Then R{{SNO,PNO},{PNO,JNO},{JNO,SNO}} is a JD that holds in the projection of SPJQ on {SNO,PNO,JNO} but not in SPJQ itself.
MVDs and 4NF / Chapter 12
137
the pair of MVDs X →→ Y | Z (defined with respect to heading H, where H is equal to the union of X, Y, and Z), then X →→ Y is trivial if and only if X →→ Z is trivial. 12.8
The following rule of thumb is often adopted in practice: Let relvar R have heading H and let the heading H of R be partitioned into disjoint subsets X, Y, and Z. Further, let X be the sole key and let Y and Z both be relation valued. Then, using Heath notation once again, R should be replaced by R1 and R2, where R1 = (R{XY}) UNGROUP (Y) and R2 = (R{XZ}) UNGROUP (Z), respectively. Note: UNGROUP is an operator of Tutorial D. I used it in the answer to Exercise 4.14 in Appendix D. It’s discussed in detail in SQL and Relational Theory and elsewhere.
How does this rule of thumb relate to the topics discussed in the present chapter? 12.9 (Modified version of Exercise 9.3.) Design a database for the following. The entities to be represented are sales representatives, sales areas, and products. Each representative is responsible for sales in one or more areas; each area has one or more responsible representatives. Each representative is responsible for sales of one or more products, and each product has one or more responsible representatives. Each product is sold in each area; however, no two representatives sell the same product in the same area. Each representative sells the same set of products in each area for which that representative is responsible. 12.10 The following dependencies are defined with respect to a heading consisting of attributes ABCD: B → D A →→ B | C Use the chase to show these dependencies imply the MVDs A →→ C | D. Note: I’m making use of a certain shorthand notation here, according to which A →→ B | C and A →→ C | D denote, respectively, A →→ B | CD and A →→ C | DB. See the answer to the exercise in Appendix D for further explanation.
Chapter 13
Additional Normal Forms Where’s it all going to end? ─Tom Stoppard: Rosencrantz and Guildenstern Are Dead Now, this is not the end. It is not even the beginning of the end. But it is, perhaps, the end of the beginning. ─Winston Churchill: The End of the Beginning
To paraphrase something I said in Chapter 9, I’ve assumed so far in this book that the only dependencies we care about1 are ones that have to do with projection as the decomposition operator and join as the corresponding recomposition operator. I also said that, given that assumption, it followed that 5NF was the final normal form. However, I did also say, in a footnote, that there was something called “sixth” normal form or 6NF. In fact, it turns out that we can define, not just 6NF as such, but several other normal forms also, all without departing from those same assumptions regarding available decomposition and recomposition operators. Fig. 13.1 (an extended version of Fig. 3.3 from Chapter 3) shows how some of those additional normal forms─viz., RFNF, SKNF, and 6NF, shown in boldface italics in the figure─fit into the overall scheme of things, as it were. In this chapter, I’ll be describing those three normal forms as well as (briefly) a few more, for completeness.
1NF 2NF 3NF BCNF 4NF RFNF SKNF 5NF 6NF Fig. 13.1: The normal form hierarchy (II)
EQUALITY DEPENDENCIES Before describing the various additional normal forms as such, I need to spend a little time on another preliminary matter. Recall from Chapter 3 the example in which relvar S was replaced by its projections SNC and CT on
1
Apart from equality and inclusion dependencies, that is.
140
Chapter 13 / Additional Normal Forms
{SNO,SNAME,CITY} and {CITY,STATUS}, respectively. As part of my discussion of that example, I pointed out that the following constraint─ CONSTRAINT ... SNC { CITY } = CT { CITY } ; ─holds (or at least might hold) in the result of the decomposition, and I mentioned that this constraint was in fact an equality dependency. Here’s a definition: n
Definition: Let R1 and R2 be relvars with headings H1 and H2, respectively. Also, let X1 and X2 be subsets of H1 and H2, respectively, such that there exists a possibly empty set of attribute renamings such that the result, R, of applying those renamings to the projection R1{X1} has heading X2. Then an equality dependency (EQD) between R1 and R2 is a statement to the effect that R and R2{X2} must be equal. (More generally, an EQD is any constraint that requires two relations to be equal.)
Actually, equality dependencies are an important special case of a more general phenomenon known as inclusion dependencies: n
Definition: Let R1 and R2 be relvars with headings H1 and H2, respectively. Also, let X1 and X2 be subsets of H1 and H2, respectively, such that there exists a possibly empty set of attribute renamings such that the result, R, of applying those renamings to the projection R1{X1} has heading X2. Then an inclusion dependency (IND) from R1 to R2 is a statement to the effect that R must be included in (i.e., be a subset of) R2{X2}. (More generally, an IND is any constraint that requires one relation to be included in another.) Points arising from this latter definition:
n
A foreign key constraint is a special case of an IND. In the suppliers-and-parts database, for example, {SNO} in relvar SP is a foreign key, referencing the key {SNO} in relvar S; thus, there’s an IND from SP to S─the projection of SP on {SNO} is included in the projection of S on {SNO}. But note that (to use the notation of the foregoing definition) INDs in general, unlike foreign key constraints in particular, don’t require X2 to be a key (or even a superkey) for R2.
n
As already noted, an EQD is a special case of an IND, too. To be more specific, the EQD “A = B” is equivalent to the pair of INDs “A is included in B” and “B is included in A.” In other words, an EQD is an IND that goes both ways, as it were.
Now, we’re going to be seeing lots of examples of EQDs in particular, as opposed to INDs in general, in what follows. In fact this state of affairs should be obvious: Nonloss decomposing a relvar into projections usually leads to INDs at least and often to EQDs, as we already know. However, it’s EQDs that don’t arise as a result of nonloss decomposition that are the interesting ones, in a way. The reason is that the existence of such an EQD often turns out to be a mark of redundancy─because if (as I put it in Chapter 3) some piece of information is recorded twice, an EQD might be what’s needed to keep the two representations in agreement. By the way, if you haven’t heard much about EQDs before, you might be wondering why not, given their conceptual importance. In my opinion, the most likely reason for the omission is the SQL language ... As you’ll know if you’ve ever tried the exercise, EQDs are extremely awkward to formulate in SQL, because SQL has no
Additional Normal Forms / Chapter 13
141
direct way of expressing relational comparisons.2 A striking example in support of this contention can be found in the discussion of Example 12 in the section of that name in Chapter 15.
SIXTH NORMAL FORM Having said, or at least implied, that we won’t be departing in this chapter from our usual assumptions regarding decomposition and recomposition operators, I’ll begin my discussion of sixth normal form by doing exactly that ... In our book Temporal Data and the Relational Model (Morgan Kaufmann, 2003), Hugh Darwen, Nikos Lorentzos, and I define: a.
Generalized versions of the projection and join operators, and hence
b.
A generalized form of join dependency, and hence
c.
A new normal form, which we call 6NF.
As the title of that book might suggest, these developments turn out to be particularly important in connection with temporal data, and they’re discussed in detail in that book. However, temporal data as such is beyond the scope of the book you’re reading right now; all I want to do here is give a definition of 6NF that works for “regular”─i.e., nontemporal─data (and I’ll assume from this point forward that all data is “regular” in this sense). Appealing only to projection and join as classically defined, therefore (and hence only to JDs as classically defined also),3 here’s the 6NF definition: n
Definition: Relvar R is in sixth normal form (6NF) if and only if the only JDs that hold in R are trivial ones. In other words, the only JDs that hold in R are of the form R{...,H,...}, where H is the heading.
Of course, we can never get rid of trivial dependencies; thus, a relvar in 6NF can’t be nonloss decomposed at all, other than trivially. For that reason, a 6NF relvar is sometimes said to be irreducible (yet another kind of irreducibility, observe). Our usual shipments relvar SP is in 6NF, and so is relvar CTXD from Chapter 9; by contrast, our usual parts relvar P is in 5NF but not 6NF. (By contrast, our usual suppliers relvar S isn’t even in 3NF, of course.) Now, it follows immediately from the definition that every 6NF relvar is certainly in 5NF─i.e., 6NF implies 5NF. (That’s why it’s reasonable to use the name sixth normal form, because 6NF really does represent another step along the classical road from 1NF to 2NF to ... to 5NF.) What’s more, 6NF is always achievable. It’s also intuitively attractive, for the following reason: If relvar R is replaced by its 6NF projections R1, ..., Rn, then the predicates for R1, ..., Rn are all simple, and the predicate for R overall is the conjunction of those simple predicates (i.e., it’s a conjunctive predicate). Let me immediately explain what I mean by these remarks: n
Definition: A predicate is simple if it involves no connectives and composite (or compound) if it’s not simple.
2
By SQL here, I mean SQL as defined by the SQL standard. The situation is even worse in mainstream implementations, where most EQDs can’t be formulated at all, owing to the fact that the implementations in question don’t allow subqueries in constraints.
3
So I’m not really departing from our usual assumptions after all.
142
Chapter 13 / Additional Normal Forms
n
Definition: A connective is a logical operator such as AND, OR, or NOT.
n
Definition: A conjunctive predicate is the AND of two or more other predicates. Note: This definition is a trifle loose, but it’s good enough for present purposes.
For example, suppose we replace relvar P by its projections PN, PL, PW, and PC on attributes {PNO,PNAME}, {PNO,COLOR}, {PNO,WEIGHT}, and {PNO,CITY}, respectively. Then the predicates for these projections are as follows (note that they’re all simple): n
PN:
Part PNO is named PNAME.
n
PL:
Part PNO has color COLOR.
n
PW:
Part PNO has weight WEIGHT.
n
PC:
Part PNO is stored in city CITY.
And the predicate for P itself is the AND of these four.4 As the example shows, therefore, relvars in 6NF can be thought of as breaking the meaning of the data down into pieces that can’t be broken down any further (they represent what are sometimes called “atomic facts” or, perhaps preferably, “irreducible facts”). Loosely, we might say the predicate for a 6NF relvar doesn’t involve any ANDs. Aside: In this connection, let me briefly remind you of relvars CTX and SPJ from Chapters 12 and 9, respectively. For CTX, the predicate was certainly conjunctive─Course CNO can be taught by teacher TNO and course CNO uses textbook XNO─and decomposing that relvar into its binary (and in fact 6NF) projections on {CNO,TNO} and {CNO,XNO} effectively eliminated the AND. As for SPJ, the predicate there was conjunctive too, even though it didn’t appear so in the simplified form in which I stated it. Here’s a more complete version: Supplier SNO supplies part PNO to some project JNO and part PNO is supplied to project JNO by some supplier SNO and project JNO is supplied by supplier SNO with some part PNO. Again, decomposing the relvar into its three binary (and in fact 6NF) projections eliminates the ANDs. End of aside. Here now is a nice characterization of 6NF (in fact, it’s a theorem): n
Theorem: Relvar R is in 6NF if and only if (a) it’s in 5NF, (b) it’s of degree n, and (c) it has no key of degree less than n - 1.
For example, let relvar PLUS have attributes A, B, and C (so the degree is three), and let the relvar predicate be A + B = C. Then PLUS is in 5NF, and it has three keys (viz., AB, BC, and CA, to use Heath notation once again); however, none of those keys is of degree less than two, and PLUS is thus in 6NF.5 By the way, please don’t misunderstand me─I’m not saying that relvars should always be in 6NF, or that normalization should always be carried as far as 6NF. Sometimes some lower normal form (5NF, say) is at least
4 In other words, every part has exactly one name, color, weight, and city. Indeed, it’s precisely because these things are so that we don’t actually need to decompose relvar P into its projections PN, PL, PW, and PC if we don’t want to; the single relvar P can effectively serve as shorthand for the combination of those four relvars.
5
Actually, PLUS might be a relation constant rather than a relation variable─but it still has keys.
Additional Normal Forms / Chapter 13
143
adequate. What’s more, to repeat something I said in Chapter 8, a design can be fully normalized (meaning the relvars are all in 5NF, or even 6NF) and yet still be bad. For example, the projection of the suppliers relvar S on {SNO,STATUS} is certainly in 6NF, but it’s not a good design, as we saw in Chapter 6. Another point to consider is that replacing a 5NF relvar by 6NF projections will probably lead to the need to enforce certain equality dependencies (EQDs). As we saw in the previous section, an EQD is a constraint to the effect that certain projections of certain relvars must be equal (speaking a trifle loosely). For example, if we decompose relvar P as discussed above into its projections PN, PL, PW, and PC, then the following constraints will probably apply: CONSTRAINT ... PL { PNO } = PN { PNO } ; CONSTRAINT ... PW { PNO } = PN { PNO } ; CONSTRAINT ... PC { PNO } = PN { PNO } ; On the other hand, as explained elsewhere,6 decompositions like the one under discussion can be a good basis for dealing with missing information. Suppose every part does always have a known name but doesn’t necessarily have a known color, weight, or city. Then a part with no known color will simply have no tuple in relvar PL (and similarly for weights and cities and relvars PW and PC, respectively). Of course, the equality dependencies will then become inclusion dependencies (actually foreign key constraints), from PL to PN, PW to PN, and PC to PN, respectively. The net of the foregoing discussion is as follows (I’ll express it in terms of the parts example, just for definiteness): If there are two or more properties that every part always has─say name and color─then separating those two properties into distinct projections is probably a bad idea; but if some property is “optional” (in other words, has the potential to be “missing” or unknown), then placing that property in a relvar of its own is probably a good idea.
SUPERKEY NORMAL FORM The next normal form I want to discuss, briefly, is superkey normal form, SKNF. Let me immediately say that SKNF doesn’t seem to be very important in its own right; the main reason I mention it at all is that many textbooks give what’s essentially a definition of it as an incorrect definition of fifth normal form. For example, the following is a paraphrased extract from a textbook of my own7 (warning! untruths coming up!): Relvar R is in 5NF if and only if every nontrivial JD that holds in R is implied by the keys of R, where: a.
The JD R{X1,...,Xn} is trivial if and only if at least one of X1, ..., Xn is equal to the heading of R.
b.
The JD R{X1,...,Xn} is implied by the keys of R if and only if each of X1, ..., Xn is a superkey for R.
Part a. of this definition is correct, of course, but part b. isn’t. To see why not, consider the following counterexample. Let relvar SNC be the projection of the suppliers relvar S on the attributes {SNO,SNAME,CITY}. SNC is in 5NF. Yet the following JD─
6 See either SQL and Relational Theory or the book Database Explorations: Essays on The Third Manifesto and Related Topics, by Hugh Darwen and myself (Trafford, 2010). 7
An Introduction to Database Systems (8th ed., Addison-Wesley, 2004).
144
Chapter 13 / Additional Normal Forms
R { { SNO , SNAME } , { SNO , CITY } , { SNAME , CITY } } ─holds in relvar SNC, and the {SNAME,CITY} component isn’t a superkey for that relvar. Observe now that the foregoing “definition” refers explicitly to nontrivial JDs. Thus, you might be thinking that what we need to do, in order to correct it, is to replace nontrivial by irreducible (notice that the JD just shown, the one that holds in SNC, is reducible─the {SNAME,CITY} component could be dropped without loss). However, such is not the case. Here’s a more complicated counterexample: n
Let relvar R have attributes A, B, and C (only); let AB, BC, and CA each be keys of R; and let the JD R{AB,BC,CA}─call it J─hold in R.
n
Then (a) no additional dependencies are implied by J and those keys, apart from trivial ones; (b) J is irreducible with respect to R. (These two points might not be obvious, but they are in fact correct.)
It follows that R isn’t in 5NF (the membership algorithm fails on J), and yet each component of J is a superkey. Note: If you’d prefer a slightly more concrete example, take A, B, and C to be “favorite color,” “favorite food,” and “favorite composer,” respectively, and let the predicate be There exists a person whose favorite color is A, favorite food is B, and favorite composer is C. Further, let there be business rules to the effect that: n
No two distinct persons have more than one favorite in common.
n
No three distinct persons are such that, for each favorite, two of those three have it in common.
Exercise: Invent some sample data for this relvar. If you try this exercise, I think you’ll see why the specified key constraints and JD make sense. With the foregoing by way of motivation, then, let’s define another normal form: n
Definition: Relvar R is in superkey normal form (SKNF) if and only if, for every irreducible JD R{X1,...,Xn} that holds in R, each of X1, ..., Xn is a superkey for R.
Now, I’ve said that SKNF isn’t really very interesting. That’s true─but there’s at least one theorem that concerns it: n
Theorem: 5NF implies SKNF, but the reverse is not true; also, SKNF implies 4NF, but the reverse is not true.
In other words, SKNF falls strictly between 4NF and 5NF (i.e., it’s stronger than 4NF and weaker than 5NF). That said, however, I should add that SKNF and 5NF coincide in the common special case in which the pertinent relvar R has just one key (as indeed is obvious from the definitions)─another reason, perhaps, for thinking SKNF isn’t all that interesting in its right. Nevertheless, the fact remains that there’s a logical difference between SKNF and 5NF, which is why I include it in this chapter.
REDUNDANCY FREE NORMAL FORM In Chapter 9 I discussed what I there referred to as a surprising fact: namely, the fact that there exist relvars that can’t be nonloss decomposed into two projections but can be nonloss decomposed into more than two. Well, now I have another surprise for you: namely, that 5NF, though sufficient, isn’t actually necessary in order to eliminate the
Additional Normal Forms / Chapter 13
145
kind of redundancy we’ve been talking about throughout this book so far (i.e., the kind that can be eliminated by taking projections). Now, I hope you find this state of affairs as surprising as I did when I first encountered it, in 2010! 5NF was defined by Fagin in 1979, and for the next 30 years or so it was widely believed that a relvar had to be in 5NF in order to be redundancy free (meaning 5NF was certainly necessary, though not in general sufficient, in order to eliminate the kind of redundancy we’ve been talking about). It turns out, however, that 5NF isn’t absolutely necessary to achieve that goal after all; more specifically, it turns out that a new normal form, one that’s strictly weaker than 5NF and yet stronger than fourth normal form (4NF), is precisely as effective as 5NF at eliminating redundancy. In fact, that new normal form─which we call, for obvious reasons, redundancy free normal form (RFNF)─turns out to be both necessary and sufficient for the purpose. If the goal of normalization is to reduce redundancy, therefore, RFNF, not 5NF, is the target to be aimed for. Aside: The name RFNF as used here is taken from a preliminary draft of a recent paper by Hugh Darwen, Ron Fagin, and myself (see Appendix G). As this book was going to press, however, we discovered that an earlier paper (“Redundancy Elimination and a New Normal Form for Relational Database Design,” by Millist W. Vincent, 1998) had already used that name to refer to something else (more specifically, something different from “our” normal form). For obvious reasons, therefore, we intend to choose a new name for our RFNF;8 for present purposes, however, I’ll continue to use the name RFNF to refer to our normal form, barring explicit statements to the contrary. Apologies if this causes any confusion. I’ll have more to say about Vincent’s RFNF, as well as ours, in Appendix B. End of aside. To illustrate these ideas, I’ll begin with an example: a modified form─I’ll call it SPJ′─of relvar SPJ from Chapter 9. As before, the relvar has attributes SNO (supplier number), PNO (part number), and JNO (project number), and the predicate too is the same as before: Supplier SNO supplies part PNO to project JNO. Also, the following business rule is in effect (again as before): 1.
If supplier s supplies part p and part p is supplied to project j and project j is supplied by supplier s, then supplier s supplies part p to project j.
However, suppose now that the following business rule is in effect as well: 2.
Any given supplier s supplies a given part p to at most one project j.
As we saw earlier, then, the following JD captures the essence of the first of these rules and therefore holds in SPJ′: R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } } Likewise, the following FD captures the essence of the second rule and therefore also holds in SPJ′: { SNO , PNO } → { JNO } From this FD, it follows that {SNO,PNO} is a key for SPJ′. Furthermore, it can be shown that no other FDs or JDs hold, apart from trivial ones. Thus, since the foregoing JD certainly isn’t implied by the sole key─the membership algorithm fails─SPJ′ isn’t in 5NF, though it is in BCNF (just as SPJ wasn’t in 5NF but was in BCNF, and for
8
“Our” RFNF has since been renamed ETNF (“essential tuple normal form”). For further discussion, see the “Stop Press” in Appendix C.
146
Chapter 13 / Additional Normal Forms
essentially the same reasons).9 Note: Just as an aside, I remark that the example thus gives the lie to two popular misconceptions (see Exercise 10.1): first, that a relvar with just one key and just one nonkey attribute must be in 5NF; second, that a BCNF relvar that’s not in 5NF must be all key. Now suppose the relvar contains the following three tuples: t1 t2 t3
= = =
s1 s1 s2
p1 p2 p1
j2 j1 j1
(The symbols s1 and s2 denote supplier numbers; p1 and p2 denote part numbers; j1 and j2 denote project numbers; and t1, t2, and t3 are reference labels for the three tuples.) Thanks to the JD, then, the following tuple must appear as well: t4
=
s1
p1
j1
But {SNO,PNO} is a key; it follows that tuples t1 and t4, since they have the same key value, are in fact one and the same (and hence that j1 = j2). Hence, the kind of redundancy we observed in Chapter 9 with SPJ doesn’t occur with SPJ′. (To be more specific, tuple t4 in this case isn’t an “additional” tuple. See the discussion of tuple forcing JDs in the paragraph immediately following.) In other words, SPJ′, even though it’s not in 5NF, doesn’t and in fact can’t suffer from the kind of redundancy that 5NF is intended to address. Thus, it looks as if 5NF might be, in a certain sense, too strong for the purpose. Let me now remind you of the notion of tuple forcing JDs. Basically, a JD is tuple forcing if it’s such that, if certain tuples appear, certain additional tuples are forced to appear as well. I’ve appealed to this notion several times in previous chapters, but I’ve never really defined it properly─so here now is such a definition: n
Definition: Let J be a JD with respect to heading H, and let J hold in relvar R. Then J might or might not have the consequence that if certain tuples t1, ..., tn appear in R, a certain additional tuple t is forced to appear in R as well (where additional means t is distinct from each of t1, ..., tn). If it does have that consequence, then J is tuple forcing with respect to R. Note: It’s easy to see that any such J must be (a) nontrivial, (b) not implied by any FD of R, and (c) not implied by the keys of R.10
Relvar SPJ in Chapter 9 was subject to a tuple forcing JD (indeed, that was precisely what was wrong with the design of that relvar). But the same criticism doesn’t apply to the SPJ′ example: The JD that holds in SPJ′ does not force any additional tuples to appear, thanks to the FD that also holds in that relvar. That’s why SPJ′ doesn’t suffer from the same kind of redundancy as SPJ does, even though─like SPJ─it’s not in 5NF. With the foregoing example by way of motivation, then, I can define another new normal form. However, I need to do it a step at a time. First we need a precise definition of the kind of redundancy we’re talking about: n
Definition: Relvar R is FD redundant if and only if it’s not in BCNF.
n
Definition: Relvar R is JD redundant if and only if some tuple forcing JD holds in R.
9 In fact it’s not just in BCNF, it’s actually in 4NF. Equally, it’s not just not in 5NF, it’s not even in SKNF (please excuse the deliberately clumsy wording here). 10 You might be thinking the third of these conditions is a logical consequence of the other two, but such is not the case. For example, consider a relvar R with attributes A, B, C, and D and keys A and B; let no FDs hold in R except ones implied by those keys. Then it’s easy to see the nontrivial JD R{AB,AD,BC} holds in R, because that JD is implied by those keys taken together. However, it isn’t implied by either key taken individually; in other words, it isn’t implied by any individual FD, as such, that holds in R.
Additional Normal Forms / Chapter 13
147
Note that neither kind of redundancy implies the other; that is, a relvar can be FD redundant without being JD redundant, or JD redundant without being FD redundant.11 For example: n
Relvar SPJ from Chapter 9 (with its attributes SNO, PNO, and JNO; key the combination of all three attributes; and JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}}) is in BCNF and hence not FD redundant, but it’s clearly JD redundant.
n
The suppliers relvar S (with its attributes SNO, SNAME, STATUS, and CITY; key SNO; and FD {CITY} → {STATUS}) isn’t in BCNF and is therefore FD redundant. But no tuple forcing JDs hold in that relvar, and so it isn’t JD redundant. Now to continue with the definitions:
n
Definition: Relvar R is redundancy free if and only if it’s neither FD redundant nor JD redundant.12
Note that a 5NF relvar is certainly redundancy free by the foregoing definition. So is an SKNF relvar, come to that; but a relvar doesn’t have to be in 5NF, or even SKNF, in order to be redundancy free (see below). n
Definition: Relvar R is in redundancy free normal form (RFNF) if and only if it’s redundancy free.
In other words, relvar R is in RFNF if and only if it’s neither FD redundant nor JD redundant: equivalently, if and only if it’s in BCNF and no tuple forcing JD holds. Of course, while the foregoing definition is both precise and accurate, it’s of little practical use, because it doesn’t help much with the question of determining whether a given relvar is indeed in RFNF. But there’s a theorem that does help in this regard: n
Theorem: Relvar R is in RFNF if and only if it’s in BCNF and, for every explicit JD J that holds in R, some component of J is a superkey for R.
This theorem provides both necessary and sufficient conditions for a relvar to be in RFNF. We can therefore take the theorem as a useful, usable test for RFNF: in effect, as a valid definition of RFNF. Note: The theorem refers to explicit JDs of R, but in fact we could drop that qualifier and what would be left would still be true (i.e., R is in RFNF if and only if every JD that holds in R has a superkey component). However, including that qualifier makes the theorem “tighter,” in a sense. In particular, it means there’s no need to check a relvar’s implicit JDs in order to test whether the relvar in question is in RFNF. (As a matter of fact, we could make the theorem tighter still by replacing “every explicit JD” by “every explicit irreducible JD.” In practice, however, it would be quite unlikely for some explicit JD not to be irreducible, so the point is perhaps not very important.) The next theorem shows that RFNF does indeed fall strictly between 4NF and 5NF; in fact, it falls strictly between 4NF and SKNF.13
11 This state of affairs lends weight to something I said in Chapter 9: viz., that it’s better to regard FDs and JDs as different phenomena, instead of thinking of FDs as a special case of JDs. 12
The term redundancy free here is perhaps not well chosen, giving as it does a very specialized meaning to an otherwise very general term.
13
Relvar SPJ′ is a concrete example of a relvar that’s in RFNF but (as noted in an earlier footnote) not in SKNF.
148
n
Chapter 13 / Additional Normal Forms
Theorem: 5NF implies SKNF; SKNF implies RFNF; and RFNF implies 4NF. The reverse implications do not hold.
To recap, then: RFNF is strictly weaker than 5NF, though it does just as much as 5NF to eliminate redundancy. Here now are two more theorems that provide simple, useful, and practical tests: n
Theorem: Let R be a 3NF relvar and let R have no composite key; then R is in RFNF. (Recall that a composite key is one consisting of two or more attributes.)
n
Theorem: Let R be a BCNF relvar and let R have a noncomposite key; then R is in RFNF.
Each of these theorems provides a sufficient condition, though not a necessary one, for a relvar to be in RFNF. Observe that the conditions in question have the attractive property that they refer to FDs only, not JDs. Note: As a matter of fact the first of these theorems should come as no surprise, because we already know from Chapter 10 (section “A Useful Theorem”) that a 3NF relvar with no composite keys is in 5NF. A fortiori, therefore, such a relvar is also in RFNF. As for the second theorem, it should be clear that if R is in BCNF and has a noncomposite key K, then K must necessarily be included in at least one component of every JD that holds in R, whence the stated result follows immediately. This brings us to the end of what might be called the formal part of the RFNF discussion. However, I want to take a closer look at the motivating example (relvar SPJ′), because there’s more that can usefully be said about that example. Recall that the FD {SNO,PNO} → {JNO} and the JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}} both hold in that relvar. But what do these facts mean from an intuitive point of view? Well, suppose the relvar contains these three tuples: t1 t2 t3
= = =
s1 s1 s2
p1 p2 p1
j2 j1 j1
Suppose also that s1 ≠ s2, p1 ≠ p2, and j1 ≠ j2. Because of the JD, then, the following tuple must also appear: t4
=
s1
p1
j1
But {SNO,PNO} is a key; so tuples t1 and t4 must be one and the same and j1 must be equal to j2, contradicting our original assumption. Thus, if the relvar were to contain just tuples t1 and t2, an attempt to insert tuple t3 must fail, precisely because it leads to that contradiction. Thus we see the following (somewhat bizarre) business rule must be in effect: n
If (a) supplier s1 supplies part p1 to project j2 and (b) supplier s1 also supplies part p2 to project j1 (p1 ≠ p2, j1 ≠ j2), then (c) no supplier, not even s1, can supply part p1 to project j1.14
What’s more, it should be clear that the following equally bizarre rules must be in effect as well (note the symmetry):
14 By the same token, no supplier, not even s1, can supply part p2 to project j2, either. Note: A similar remark applies also to the “equally bizarre” rules to be discussed in just a moment, of course.
Additional Normal Forms / Chapter 13
149
n
If (a) supplier s1 supplies part p1 to project j2 and (b) supplier s2 supplies part p1 to project j1 (s1 ≠ s2, j1 ≠ j2), then (c) no part, not even p1, can be supplied by supplier s1 to project j1.
n
If (a) supplier s1 supplies part p2 to project j1 and (b) supplier s2 supplies part p1 to project j1 (s1 ≠ s2, p1 ≠ p2), then (c) no project, not even j1, can be supplied by supplier s1 with part p1.
In fact, these three business rules can all be combined into one, as follows. Let’s agree, just for the moment, to say each tuple of relvar SPJ′ represents a shipment (by some supplier of some part to some project). Then there cannot exist three distinct shipments x, y, and z such that x and y involve the same supplier, y and z involve the same part, and z and x involve the same project. There’s still another point to be made in connection with the SPJ′ example. Refer again to the analysis that led to the first of the foregoing three business rules. That analysis showed that tuple t3 can’t appear together with tuples t1 and t2. It follows, therefore, that SPJ′ suffers from an insertion anomaly, despite the fact that it’s in RFNF (and the fact that no tuple forcing JD holds, therefore). By contrast, it doesn’t suffer from a deletion anomaly─assuming, that is, that the only constraints to which it’s subject are the stated FD and JD (and logical consequences thereof). So one difference between 5NF and RFNF is this: Even though both are redundancy free, 5NF guarantees “no insertion anomalies” while RFNF doesn’t─assuming, again, that FDs and JDs are the only constraints under consideration. Of course, it’s tempting to conclude from the SPJ′ example that relvars that are in RFNF and not 5NF are likely to be rare in practice. Nevertheless, there’s a clear logical difference between the two normal forms, and thus, from the point of view of reducing redundancy at least, it’s really RFNF and not 5NF that ought to be the target to be aimed for. (As a bonus, I note that RFNF is a little easier to test for, too, than 5NF is.) Note: As a matter of fact, the SPJ′ example reinforces the foregoing observation in another way also. Since the relvar is subject to the JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}}, it can be nonloss decomposed into its projections on {SNO,PNO}, {PNO,JNO}, and {JNO,SNO}, respectively. Those projections are each “all key,” and in fact in 5NF. However, that decomposition “loses” the FD {SNO,PNO} → {JNO}! As we saw in Chapter 6, losing dependencies is generally not recommended. Hence relvar SPJ′ illustrates the point that not only is 5NF sometimes too strong, but sometimes it might be positively contraindicated.
DOMAIN-KEY NORMAL FORM Domain-key normal form (DK/NF) differs from all of the normal forms discussed in this book so far in that it’s not defined in terms of FDs, MVDs, and JDs, as such, at all.15 DK/NF is really a kind of “ideal” normal form: It’s desirable because, by definition, a relvar in DK/NF is guaranteed to be free of certain update anomalies; sadly, however, it’s not always achievable, nor has the question “Exactly when can it be achieved?” been answered. Be that as it may, let’s investigate. DK/NF is defined in terms of domain constraints and key constraints. Key constraints are already familiar, of course (they were defined in Chapter 5). As for domain constraints, I remind you that domain is essentially just another word for type (see the answer to Exercise 2.4 in Appendix D). It follows that a domain constraint ought logically to be the same thing as a type constraint; in other words, it ought simply to be a specification of the set of values that constitute the type in question (see SQL and Relational Theory for further explanation of this concept). However, the term is being used in the present context in a slightly special sense. To be specific, a domain constraint, as that term is used here, is a constraint to the effect that values of a given attribute are taken from some 15 Well … it’s defined in terms of key constraints, as we’ll see, and key constraints in turn are a special case of FDs, so this remark is perhaps a little economical with the truth.
150
Chapter 13 / Additional Normal Forms
prescribed set of values: for example, a constraint on the suppliers relvar S to the effect that STATUS values (which are integers, i.e., are of type INTEGER) must be in the range one to a hundred, inclusive. Here then is a definition: n
Definition: Relvar R is in domain-key normal form (DK/NF) if and only if every relvar constraint that holds in R is implied by the domain constraints and key constraints that hold in R.16
Enforcing constraints on a DK/NF relvar is thus conceptually simple, since it is sufficient to enforce just the pertinent domain and key constraints, and all constraints─not just FDs, MVDs, and JDs, but all relvar constraints that apply to the relvar in question─on the relvar will then be enforced automatically. DK/NF was first defined by Fagin in 1981, and it was the DK/NF paper that first gave precise definitions of the terms insertion anomaly and deletion anomaly. I defined these notions in Chapter 10, but there the definitions were framed in terms of JDs specifically. Here for the record are the general definitions (note that they refer to constraints in general, not just ones that happen to be FDs or MVDs or JDs):17 n
Definition: Relvar R suffers from an insertion anomaly if and only if there exists a legal value r for R and a tuple t with the same heading as R such that the relation obtained by appending t to r satisfies R’s key constraints but is not a legal value for R (i.e., it violates some relvar constraint on R).
n
Definition: Relvar R suffers from a deletion anomaly if and only if there exists a legal value r for R and a tuple t of r such that the relation obtained by removing t from r is not a legal value for R (i.e., it violates some relvar constraint on R). Finally, we have the following theorem:
n
Theorem: So long as every pertinent attribute can take at least two distinct values, DK/NF implies 5NF.
That is (speaking a trifle loosely), every DK/NF relvar is in 5NF, and therefore in RFNF (etc.) as well─though it’s not necessarily in 6NF, of course. In fact, DK/NF and 5NF coincide in the (probably unlikely) special case where the only constraints that hold are FDs and JDs specifically.
CONCLUDING REMARKS What a long strange trip it’s been ... In previous chapters, I’ve described 1NF, 2NF, 3NF, BCNF, 4NF, and 5NF (the last three at some length), and now we’ve met four more normal forms: RFNF, SKNF, 6NF, and DK/NF (this last one being something of an odd one out). But even that’s not the end of the story. In this concluding section, just for completeness, I briefly mention a few other normal forms that have been defined in the literature at one time or another.
16 A relvar constraint is any constraint that can be tested by examining the pertinent relvar in isolation. For further discussion, see SQL and Relational Theory. 17
These definitions, like the ones in Chapter 10, are slightly suspect, inasmuch as they talk about inserting or deleting individual tuples.
Additional Normal Forms / Chapter 13
151
Elementary key normal form (EKNF) Elementary key normal form was introduced by Zaniolo in 1982.18 Here’s the definition: n
Definition: Relvar R is in elementary key normal form (EKNF) if and only if, for every nontrivial FD X → Y that holds in R, either (a) X is a superkey or (b) Y is a subkey of some elementary key─where key K is elementary if and only if there exists some attribute A of R such that the FD K → {A} is nontrivial and irreducible.
EKNF falls strictly between 3NF and BCNF; that is, BCNF implies EKNF, EKNF implies 3NF, and the reverse implications don’t hold. The stated intent of EKNF is “to capture the salient qualities of both 3NF and BCNF” while avoiding the problems of both (namely, that 3NF is “too forgiving” and BCNF is “prone to computational complexity”). That said, I should say too that EKNF isn’t much referenced in the literature. Overstrong PJ/NF Recall that 5NF was originally called PJ/NF, and PJ/NF means every JD is implied by keys (speaking rather loosely). In fact, in the paper in which he introduced PJ/NF, Fagin also introduced what he called overstrong PJ/NF, which meant (again rather loosely) that every JD is implied by some specific key considered in isolation. Note that this latter is what one might intuitively have expected the definition of regular PJ/NF (i.e., 5NF) to have been─recall the remarks in Chapters 10 and 12 concerning the parallelism between the definitions of BCNF, 4NF, and 5NF. Be that as it may, here’s the definition: n
Definition: Relvar R is in overstrong PJ/NF if and only if every JD of R is implied by some key of R.
Overstrong PJ/NF clearly implies 5NF (i.e., “regular” PJ/NF), but the reverse is not true. A single counterexample suffices to demonstrate this latter fact:19 Consider a relvar R with attributes A, B, C, and D (only) and keys {A} and {B} only. Let the only dependencies to hold in R be ones that are implied by these keys (so R is definitely in 5NF). Now consider the JD R{AB,BC,AD}. Applying the membership algorithm, we see that this JD holds in R; but it’s not a consequence of either of the keys considered in isolation, as can also be seen by checking the membership algorithm. So R is in 5NF (or PJ/NF) but not in overstrong PJ/NF. “Restriction-union” normal form Consider the parts relvar P from the suppliers-and-parts database. Normalization theory as I’ve described it prior to this point tells us relvar P is in a “good” normal form; indeed, it’s in 5NF, and it’s therefore guaranteed to be free of anomalies that can be removed by taking projections. But why keep all parts in a single relvar? What about a design in which red parts are kept in one relvar (RP, say), blue ones in another (BP, say), and so on? In other words, what about the possibility of decomposing the original parts relvar via restriction instead of projection? Would the resulting structure be a good design or a bad one? (In fact it would almost certainly be bad unless we were very careful, as we’ll see in Part IV of this book; however, the point here is that classical normalization theory as such has absolutely nothing to say about the matter.)
18
Carlo Zaniolo: “A New Normal Form for the Design of Relational Database Schemata,” ACM TODS 7, No. 3 (September 1982).
19
This same example was used in a footnote earlier in the chapter in connection with the definition of tuple forcing JDs.
152
Chapter 13 / Additional Normal Forms
Another direction for design research therefore consists of examining the implications of decomposing relvars by some operator other than projection. In the example, the decomposition operator is, as already mentioned, (disjoint) restriction; the corresponding recomposition operator is (disjoint) union. Thus, it might be possible to construct a “restriction-union” normalization theory, analogous to—but orthogonal to—the projection-join normalization theory we’ve been considering prior to this point. I don’t want to get much more specific on such matters here; suffice it to say that some initial ideas along these lines can be found (a) in Fagin’s PJ/NF paper, which additionally discusses a normal form called PJSU/NF, and (b) in a paper by Smith, which discusses a normal form called (3,3)NF.20 This latter paper, incidentally, shows that (3,3)NF implies BCNF, but that a (3,3)NF relvar need not be in 4NF, nor need a 4NF relvar be in (3,3)NF. As suggested above, therefore, reduction to (3,3)NF is orthogonal to reduction to 4NF (and 5NF).
EXERCISES 13.1
Draw the normal form hierarchy from memory. Include at least nine normal forms.
13.2
Define 6NF.
13.3 6NF relvars are sometimes said to be irreducible, and I noted in the body of the chapter that this was yet another of the many kinds of irreducibility that are relevant to design theory. How many different kinds can you identify? 13.4
Define (a) FD redundancy; (b) JD redundancy; (c) RFNF.
13.5 Take another look at the decomposition of relvar P in the body of the chapter into 6NF projections PN, PL, PW, and PC. Can you think of any improvements on that design? 13.6 You’re given a relvar R representing marriages, with attributes A, B, and C and predicate Person A married person B on date C. Assume no polygamy; assume also that no two persons marry each other more than once. What keys does R have? Does the JD R{AB,BC,CA} hold? What’s the highest normal form R is in? 13.7 In the body of the chapter, I said a relvar could be in SKNF and not 5NF, and I proposed the following as an example of such a relvar: n
Let relvar R have attributes A, B, and C (only); let AB, BC, and CA each be keys of R; and let the JD R{AB,BC,CA}─call it J─hold in R.
But you might not unreasonably be a little suspicious of this example. To be more specific, you might be wondering whether a relvar could even exist that’s subject to exactly the specified key constraints and the specified JD (even though I did go on to give a slightly more concrete version of the example). Show the example is reasonable after all by demonstrating that in fact all possible sets of dependencies (FDs and JDs) are consistent, in the sense that at least one relation can always be found that satisfies all dependencies in the set.
20
J. M. Smith, “A Normal Form for Abstract Syntax,” Proc. 4th Int. Conf. on Very Large Data Bases, Berlin, Federal German Republic (September 1978).
Additional Normal Forms / Chapter 13
153
13.8 Relvar SPJ′ from the section “Redundancy Free Normal Form” was subject to what might be called a “symmetric” JD─viz., the JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}}─and yet displayed some asymmetry also, in that just one of the three components of that JD corresponded to a key. Intuitively, you might expect the other two components to correspond to keys as well. Show this isn’t necessarily so. 13.9 Design a database for the following. The entities to be represented are soccer match fixtures for a certain team. For matches that have already been played, we wish to record “goals for” and “goals against”; however, these two properties clearly make no sense for matches that have yet to be played. What normal forms are your relvars in? 13.10 Let relvar SCP have attributes SNO, PNO, and CITY and predicate Supplier SNO and part PNO are both located in city CITY. Can SCP be derived from our usual S, P, and SP relvars? What normal form is it in? Can you think of any conventional wisdom this example might fly in the face of? 13.11 Define DK/NF. Give an example of a relvar in 6NF that’s not in DK/NF. 13.12 What’s the difference between SKNF and overstrong PJ/NF? In fact, is there a difference? 13.13 Give definitions, as precise as you can make them, of the relational operators restriction and union. 13.14 In the body of the chapter, I showed informally how reducing a relvar to 6NF projections corresponded to reducing a conjunctive predicate to simple predicates. Could there be such a thing as a disjunctive predicate? How might a relvar correspond to such a predicate? What would be involved in reducing such a predicate to simple predicates?
Part IV
ORTHOGONALITY
To repeat something I said in Chapter 1, database design is not my favorite subject. The reason is that so little of design practice is truly scientific; normalization is scientific, of course, but not much else is. However, the topic of this part of the book, orthogonality, does represent another small piece of science in what’s otherwise still (sadly) a fairly subjective field.
Chapter 14
The Principle of Orthogonal Design Orthogonal At right angles to; independent ─David Darling: The Universal Book of Mathematics
Note: Portions of this chapter originally appeared, in considerably different form, in my book Date on Database: Writings 2000-2006 (Apress, 2006). I’ll begin this chapter with a quick review of the principles of normalization and an analysis of how well normalization meets its objectives. Here’s a summary of those principles: 1.
A relvar not in RFNF should be “fully normalized”─i.e., decomposed into a set of (at least) RFNF projections.
2.
The original relvar should be reconstructable by joining those projections back together again─i.e., the decomposition should be nonloss.
3.
The decomposition process should preserve dependencies (FDs and JDs)—at least if it can do so without violating Principle No. 1.
4.
Every projection should be needed in the reconstruction process.
TWO CHEERS FOR NORMALIZATION As I’ve repeatedly said, normalization is the science (or a large part of the science, at any rate) underlying database design. But it’s far from being a panacea, as we can easily see by considering what its goals are and how well it measures up against them. Here are those goals: n
To achieve a design that’s a “good” representation of the real world (i.e., one that’s intuitively easy to understand and is a good basis for future growth)
n
To reduce redundancy
n
Thereby to avoid certain update anomalies that might otherwise occur
n
To simplify the statement and enforcement of certain integrity constraints
I’ll consider each in turn. n
Good representation of the real world: Normalization does well on this one. I have no criticisms here.
158
Chapter 14 / The Principle of Orthogonal Design
n
Reduce redundancy: Normalization is a good start on this problem too, but it’s only a start. For one thing, it’s a process of taking projections, and we’ve seen that not all redundancies can be removed by taking projections; indeed, there are many kinds of redundancy that normalization simply doesn’t address at all. (Chapter 15 discusses this issue in detail.) For another thing, taking projections, even when the decomposition is nonloss, can cause dependencies to be lost, as we saw in Chapter 6 and elsewhere.
n
Avoid update anomalies: This point is, at least in part, just the previous one by another name. It’s well known that designs that aren’t properly normalized can be subject to certain update anomalies, precisely because of the redundancies they entail. In relvar STP, for example (see Fig. 1.2 in Chapter 1), supplier S1 might be shown as having status 20 in one tuple and status 25 in another. Of course, this particular anomaly can arise only if a less than perfect job is being done on integrity constraint enforcement ... Perhaps a better way to think about the update anomaly issue is this: The constraints needed to prevent such anomalies will be easier to state, and might be easier to enforce, if the design is properly normalized than they would be if it isn’t (see the next paragraph). Yet another way to think about it is: More single tuple updates1 will be logically acceptable if the design is properly normalized than would be the case if it isn’t (because unnormalized designs imply redundancy─i.e., several tuples saying the same thing─and redundancy implies that sometimes we have to update several things at the same time).
n
Simplify statement and enforcement of constraints: As we know from earlier chapters, some dependencies imply others. (More generally, in fact, constraints of any kind can imply others. As a trivial example, if shipment quantities must be less than or equal to 5000, they must certainly be less than or equal to 6000.) Now, if constraint A implies constraint B, then stating and enforcing A will effectively state and enforce B “automatically” (indeed, B won’t need to be separately stated at all, except perhaps by way of documentation). And normalization to 5NF gives a very simple way of stating and enforcing certain important constraints; basically, all we have to do is define keys and enforce their uniqueness─which we’re going to do anyway─and then all applicable JDs (and therefore all MVDs and FDs as well) will effectively be stated and enforced automatically, because they’ll all be implied by those keys. So normalization does a pretty good job in this area too. (Of course, I’m ignoring here the various multirelvar constraints that the normalization process is likely to give rise to.)
Here on the other hand are several more reasons, over and above those already given, why normalization is no panacea:
1
n
First, JDs and MVDs and FDs aren’t the only kind of constraint, and normalization doesn’t help with any others.
n
Second, given a particular set of relvars, there’ll often be several distinct nonloss decompositions into 5NF projections, and there’s little or no formal guidance available to tell us which one to choose in such cases. (To be honest, though, I doubt whether this lack is likely to cause major problems in practice.)
n
Third, there are many design issues that normalization simply doesn’t address. For example, what is it that tells us there should be just one suppliers relvar, instead of one for London suppliers, one for Paris suppliers, and so on? It certainly isn’t normalization as classically understood.
Perhaps better, more singleton set updates.
The Principle of Orthogonal Design / Chapter 14
159
All of that being said, I must make it clear that I don’t want the foregoing comments to be seen as any kind of attack. As I said in Chapter 8, I believe anything less than a fully normalized design is strongly contraindicated. But the fact remains that normalization (“the scientific part of design”) as such really doesn’t do as much of the job as we’d like─and so it’s good to be able to say that now there’s a tiny piece of additional science available to us. That’s what the topic of orthogonality is all about. Note: The concept of orthogonality has evolved over time. As a result, portions of this chapter are at odds, somewhat, with previous writings─mostly by myself─on this same subject. What’s more, I very much doubt whether this chapter is the last word, either. I do believe the chapter is accurate as far as it goes; however, further refinements to the material might well be possible, and desirable. Caveat lector.
A MOTIVATING EXAMPLE For simplicity, suppose the FD {CITY} →{STATUS} does not hold in relvar S (please note that I’ll stay with this assumption throughout the present chapter). Consider the following decomposition of that relvar: SNC { SNO , SNAME , CITY } KEY { SNO } STC { SNO , STATUS , CITY } KEY { SNO } Sample values are shown in Fig. 14.1. As the figure shows, this decomposition is hardly very sensible (in particular, note that the fact that a given supplier is located in a given city appears twice), and yet it abides by all of the normalization principles─both projections are in 5NF; the decomposition is nonloss; dependencies are preserved; and both projections are needed in the reconstruction process. SNC ┌─────┬───────┬────────┐ │ SNO │ SNAME │ CITY │ ├═════┼───────┼────────┤ │ S1 │ Smith │ London │ │ S2 │ Jones │ Paris │ │ S3 │ Blake │ Paris │ │ S4 │ Clark │ London │ │ S5 │ Adams │ Athens │ └─────┴───────┴────────┘
STC ┌─────┬────────┬────────┐ │ SNO │ STATUS │ CITY │ ├═════┼────────┼────────┤ 20 │.London │ │ S1 │ │ S2 │ 30 │ Paris │ 30 │ Paris │ │ S3 │ │ S4 │ 20 │ London │ │ S5 │ 30 │ Athens │ └─────┴────────┴────────┘
Fig. 14.1: Relvars SNC and STC─sample values
Intuitively, the problem with the foregoing design is obvious: The tuple (s,n,c) appears in SNC if and only if the tuple (s,t,c) appears in STC; equivalently, the tuple (s,c) appears in the projection of SNC on SNO and CITY if and only if that very same tuple (s,c) appears in the projection of STC on SNO and CITY. To state the matter a trifle more formally, we can say the design is subject to the following equality dependency (EQD)─ CONSTRAINT ... SNC { SNO , CITY } = STC { SNO , CITY } ; ─and this EQD makes the redundancy explicit. To repeat, however, the foregoing design abides by all of the well established principles of normalization. It follows that those principles by themselves aren’t enough─we need something else to tell us what’s wrong with this design (something else formal, that is; we all know what’s wrong with it informally). To put the matter another
160
Chapter 14 / The Principle of Orthogonal Design
way, the normalization discipline provides a set of formal principles to guide us in our attempts to reduce redundancy, but that set of principles by itself is inadequate, as the example plainly shows. We need another principle. In other words, as I’ve said more than once in this book already, we need more science.
A SIMPLER EXAMPLE In order to see what the principle we need might look like, let’s consider a simpler example. As you know, normalization as such─in particular, normalization as used in the example of the previous section─has to do with “vertical” decomposition of relvars (meaning decomposition via projection). But “horizontal” decomposition (that is, decomposition via restriction) is clearly possible, too. Consider the design illustrated in Fig. 14.2, in which the parts relvar P has been split horizontally─in fact, partitioned─into two relvars, one (“light parts,” LP) containing parts with weight less than 17.0 pounds and the other (“heavy parts,” HP) containing parts with weight greater than or equal to 17.0 pounds. (I assume for definiteness that WEIGHT values represent weights in pounds avoirdupois.) ┌─────┬───────┬───────┬────────┬────────┐ LP │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY │ ├═════┼───────┼───────┼────────┼────────┤ │ 12.0 │ London │ │ Red │ P1 │ Nut │ 14.0 │ London │ │ P4 │ Screw │ Red │ P5 │ Cam │ Blue │ 12.0 │ Paris │ └─────┴───────┴───────┴────────┴────────┘ ┌─────┬───────┬───────┬────────┬────────┐ HP │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY │ ├═════┼───────┼───────┼────────┼────────┤ │ P2 │ Bolt │ Green │ 17.0 │ Paris │ 17.0 │ Paris │ │ P3 │ Screw │ Blue │ │ P6 │ Cog │ Red │ 19.0 │ London │ └─────┴───────┴───────┴────────┴────────┘ Fig. 14.2: Relvars LP and HP─sample values
The predicates are as follows: n
LP:
Part PNO is named PNAME, has color COLOR and weight WEIGHT (which is less than 17.0), and is stored in city CITY.
n
HP:
Part PNO is named PNAME, has color COLOR and weight WEIGHT (which is greater than or equal to 17.0), and is stored in city CITY.
Note that the original relvar P can be recovered by taking the (disjoint) union of relvars LP and HP. Why might we want to perform such a horizontal decomposition? Frankly, I’m not aware of any good logical reason for doing so, though of course that’s not to say no such reason exists. Be that as it may, observe that we can, and should, state two constraints that apply to these relvars: CONSTRAINT LPC AND ( LP , WEIGHT < 17.0 ) ; CONSTRAINT HPC AND ( HP , WEIGHT ≥ 17.0 ) ;
The Principle of Orthogonal Design / Chapter 14
161
(I remind you from Chapter 2 that the Tutorial D expression AND(rx,bx), where rx is a relational expression and bx is a boolean expression, returns TRUE if and only if bx evaluates to TRUE for every tuple in the relation denoted by rx.) So we have here a slightly unusual situation: To be specific, in the case of relvars LP and HP, part of the predicate can, and should, be captured formally in the shape of explicit constraints. Indeed, the very fact that such constraints need to be stated and enforced might be seen as militating against the design. But even if horizontal decomposition is contraindicated at the logical level, there are still plenty of pragmatic reasons (having to do with recovery, security, performance, and other such matters) for such a decomposition at the physical level; hence, given that the logical and physical levels tend to be in lockstep, pretty much, in today’s DBMSs─i.e., there’s not nearly as much data independence in those DBMSs as there ought to be─it follows that there are likely to be pragmatic reasons for performing such a decomposition at the logical level as well, at least in current products. Now, regardless of what you might think of the foregoing argument, at least there’s nothing obviously bad about the design of Fig. 14.2 (well, let’s agree as much for the sake of the example, at any rate).2 But suppose we were to define relvar LP just a little differently; to be specific, suppose we defined it to contain those parts with weight less than or equal to 17.0 pounds (adjusting the predicate and constraint LPC accordingly, of course). Fig. 14.3 below is a revised version of Fig. 14.2, showing what happens with this revised design. As you can see, now there definitely is something bad; to be specific, the tuples for parts P2 and P3 now appear in both relvars in Fig. 14.3 (in other words, there’s now some redundancy). What’s more, those tuples must appear in both relvars! For suppose, contrariwise, that (say) the tuple for part P2 appeared in HP and not in LP. Then, noting that LP contains no tuple for part P2, we could legitimately conclude from The Closed World Assumption─see Chapter 2─that it’s not the case that part P2 weighs 17.0 pounds. But then we see from HP that part P2 in fact does weigh 17.0 pounds, and the database is thus inconsistent, because it contains a contradiction. (Inconsistency in a database is highly undesirable, of course. As I show in SQL and Relational Theory, you can never trust the results you get from an inconsistent database; in fact, you can get absolutely any result whatsoever─even results asserting nonsensical things like 0 = 1─from such a database!) ┌─────┬───────┬───────┬────────┬────────┐ │ LP │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY ├═════┼───────┼───────┼────────┼────────┤ │ P1 │ Nut │ Red │ 12.0 │ London │ │ P2 │ Bolt │ Green │ 17.0 │ Paris │ │ P3 │ Screw │ Blue │ 17.0 │ Paris │ │ P4 │ Screw │ Red │ 14.0 │ London │ │ P5 │ Cam │ Blue │ 12.0 │ Paris │ └─────┴───────┴───────┴────────┴────────┘ ┌─────┬───────┬───────┬────────┬────────┐ HP │ PNO │ PNAME │ COLOR │ WEIGHT │ CITY │ ├═════┼───────┼───────┼────────┼────────┤ │ P2 │ Bolt │ Green │ 17.0 │ Paris │ │ P3 │ Screw │ Blue │ 17.0 │ Paris │ │ P6 │ Cog │ Red │ 19.0 │ London │ └─────┴───────┴───────┴────────┴────────┘ Fig. 14.3: Relvars LP (revised) and HP─sample values
Now, the problem with the design of Fig. 14.3 is easy to see: The predicates for LP and HP “overlap,” in the sense that the very same tuple t can satisfy both of them. What’s more, if t is such a tuple, and if at some given time
2
Actually there might be something bad. Consider, for example, what has to happen if the weight of part P1 is doubled.
162
Chapter 14 / The Principle of Orthogonal Design
that tuple t represents a “true fact,” then, in accordance with The Closed World Assumption, that tuple t must necessarily appear in both relvars at the time in question (whence the redundancy, of course). In fact, we have another EQD on our hands: CONSTRAINT ... ( LP WHERE WEIGHT = 17.0 ) = ( HP WHERE WEIGHT = 17.0 ) ; To say it again, the problem in the example is that we’ve allowed two relvars to have overlapping predicates. Clearly, then, the principle we’re looking for is going to say something along the lines of: Don’t do that! Let’s try and state the matter a little more precisely: n
Definition (first attempt): The Principle of Orthogonal Design says that if relvars R1 and R2 are distinct, then there must not exist a tuple with the property that if it appears in R1, then it must also appear in R2 and vice versa.3 Note: The term orthogonal here derives from the fact that what the principle effectively says is that relvars should be independent of one another─which they won’t be, if their meanings overlap in the foregoing sense.
In what follows, I’ll sometimes abbreviate the foregoing principle (or, rather, various versions of that principle) to just the orthogonality principle, or sometimes just to orthogonality. Aside: As elsewhere in this book, I might be accused of practicing a tiny deception in the foregoing. Take another look at Fig. 14.3; in particular, take a look at the tuple for part P2. That tuple appears in both LP and HP because it represents a true instantiation of the predicate for LP and a true instantiation of the predicate for HP. Or does it? The instantiations of those predicates for part P2 are actually as follows: n
LP:
Part P2 is named Bolt, has color Green and weight 17.0 (which is less than or equal to 17.0), and is stored in city Paris.
n
HP:
Part P2 is named Bolt, has color Green and weight 17.0 (which is greater than or equal to 17.0), and is stored in city Paris.
These two propositions aren’t the same! Of course, they’re certainly equivalent to one another─but in order to recognize that equivalence, we need to know that “17.0 ≤ 17.0” and “17.0 ≥ 17.0” are both true, and then we need to apply a little logical reasoning. (The point is, what’s obvious to us as human beings isn’t necessarily obvious to a machine, and for completeness I really ought to have spelled out the missing steps in my argument.) End of aside. Now, adherence to the orthogonality principle in the light vs. heavy parts example would certainly avoid the redundancies illustrated in Fig. 14.3. Note, however, that the principle as stated applies only to relvars like LP and HP that have the very same heading, because of course it’s impossible for the same tuple to appear in two different relvars if the relvars in question have different headings. Thus, you might be thinking the orthogonality principle isn’t much use, because it’s probably unusual in practice to have two relvars in the same database with the same
3 That “and vice versa” is important. Consider a revised version of the suppliers-and-parts database, in which (a) attribute QTY is dropped from relvar SP and (b) another relvar, SAP, with heading {SNO,PNO} and predicate Supplier SNO is able to supply part PNO is added. Then there might well be a constraint to the effect that a given tuple can appear in SP only if it also appears in SAP, and such a reasonable state of affairs doesn’t (and obviously shouldn’t) constitute a violation of orthogonality.
The Principle of Orthogonal Design / Chapter 14
163
heading.4 And I would probably agree with you, if that were all there was to it; I mean, in that case life would be fairly simple and this chapter could stop right here (it might not even be worth dignifying such a very obvious rule with the rather grand label “principle”). But, of course, there’s quite a lot more to be said on the matter. In order to explore the possibilities further, I first need to take a closer look at the relationship between tuples and propositions.
TUPLES vs. PROPOSITIONS As we know, every tuple appearing in some given relvar R at some given time represents a certain proposition, the proposition in question being an instantiation of the relvar predicate for that relvar R that (by convention) is understood to be true at the time in question. For example, here again is the predicate for relvar HP from Figs. 14.2 and 14.3: Part PNO is named PNAME, has color COLOR and weight WEIGHT (which is greater than or equal to 17.0), and is stored in city CITY. This relvar contains (among other things) a tuple for part P6, and that tuple represents the following instantiation of the foregoing predicate: Part P6 is named Cog, has color Red and weight 19.0 (which is greater than or equal to 17.0), and is stored in city London. Loosely speaking, then, we can say the database “contains propositions.” Now, I’ve said several times at earlier points in the book that the database involves some redundancy if and only if it says the same thing twice. Now I can make this statement a little more precise: n
Definition: The database involves redundancy if and only if it contains two distinct representations of the same proposition.
Now, given that tuples represent propositions, it’s tempting to translate the foregoing definition into the following one: The database involves some redundancy if and only if it contains two distinct appearances of the very same tuple.5 Unfortunately, this latter “definition” is, at best, considerably oversimplified. Let’s examine it more carefully. First of all, it’s at least true that we don’t want the same tuple to appear more than once in the same relvar (at the same time, that is), because such a state of affairs would certainly constitute “saying the same thing twice.” (As I once heard Codd remark: If something is true, saying it twice doesn’t make it any more true.) Of course, the relational model itself takes care of this requirement─by definition, relations never contain duplicate tuples, and the same is therefore true for relvars, and so we can ignore this possibility. Note: In other words, it might be argued that a desire to avoid redundancy is one of the motivations (perhaps a minor one) for choosing sets─which don’t
4
In this chapter, unlike previous chapters, the fact that the heading concept includes the pertinent attribute types is sometimes important; thus, the term heading must be (re)interpreted accordingly, where it makes any difference. By way of example, the headings {PNO CHAR, WEIGHT RATIONAL} and {PNO CHAR, WEIGHT INTEGER}, though they involve the same attribute names, aren’t the same heading, precisely because the two WEIGHT attributes are of different types. All of that being said, for simplicity I’ll continue to ignore attribute types as much as I can throughout the rest of the chapter. 5
One reviewer argued strongly that this “temptation” wasn’t tempting at all! Maybe not, but I still think it’s worth discussing.
164
Chapter 14 / The Principle of Orthogonal Design
contain duplicate elements, by definition─instead of “bags,” which do, as the right mathematical abstraction on which to found a solid database theory. SQL apologists please note! Aside: I observe in passing that now we have a precise characterization of the notion of “duplicate tuples.” (People use this phrase all the time, and yet I very much doubt whether many of them would be able to define it precisely if pressed.) Strictly speaking, of course, two tuples are duplicates if and only if they’re the very same tuple, just as two integers are duplicates if and only if they’re the very same integer. The phrase “duplicate tuples” thus doesn’t really make much sense from a logical point of view (to say two distinct tuples are duplicates is a contradiction in terms). What people are really talking about when they use that phrase is duplicate appearances of the same tuple. For that reason, the phrase “duplicate elimination,” which as we all know is often encountered in database contexts, would much better be duplication elimination. But I digress … Let’s get back to the main discussion. End of aside. Second, we also don’t want the same subtuple to appear more than once in the same relvar (again, at the same time).6 But classical normalization takes care of this one; e.g., it’s precisely because the FD {CITY} → {STATUS} holds in relvar S, causing the same {CITY,STATUS} pair to occur repeatedly (with the same meaning every time it appears), that we’re recommended to replace that relvar by its projections on {CITY,STATUS} and {SNO,SNAME,CITY}. My next point is that the very same tuple can represent any number of distinct propositions, as can easily be seen. As a trivial example, let SC and PC be the projection of relvar S on CITY and the projection of relvar P on CITY, respectively. Given our usual sample values, then, a tuple containing just the CITY value “London” appears in both SC and PC─but those two appearances represent distinct propositions. To be specific: The appearance in SC represents the proposition There’s at least one supplier in London, and the appearance in PC represents the proposition There’s at least one part in London (simplifying slightly in both cases for the sake of the example). What’s more─and here I have to get a little more formal on you for a moment─the same proposition can be represented by any number of distinct tuples, too. That’s because, formally, the pertinent attribute names are part of the tuple (check the definition of tuple in Chapter 5 if you need confirmation of this point). Thus, for example, we might have our usual shipments relvar SP with its attributes SNO, PNO, and QTY, and predicate: Supplier SNO supplies part PNO in quantity QTY. We might additionally have a relvar PS with attributes SNR, PNR, and AMT, with predicate: Supplier SNR supplies part PNR in quantity AMT. And then (to use Tutorial D syntax) the following tuples might appear in relvars SP and PS, respectively: TUPLE { SNO ‘S1’ , PNO ‘P1’ , QTY 300 } TUPLE { SNR ‘S1’ , PNR ‘P1’ , AMT 300 } These are clearly different tuples, but they both represent the same proposition:
6 This statement too is hugely oversimplified. A slightly better one is: We don’t want the same subtuple to appear more than once if distinct appearances represent the same proposition─but this statement isn’t perfect, either. To try to make it more precise still would take us further afield than I wish to go at this point, however. See Chapter 15 for further explanation.
The Principle of Orthogonal Design / Chapter 14
165
Supplier S1 supplies part P1 in quantity 300. In fact, either of the two relvars SP and PS can be defined in terms of the other, as the following constraints (actually EQDs once again) both show: CONSTRAINT ... PS = SP RENAME { SNO AS SNR , PNO AS PNR , QTY AS AMT } ; CONSTRAINT ... SP = PS RENAME { SNR AS SNO , PNR AS PNO , AMT AS QTY } ; A database that contained both relvars would thus clearly involve some redundancy.7 The net of the foregoing discussion is this: There’s a many to many relationship between tuples and propositions─any number of tuples can represent the same proposition, any number of propositions can be represented by the same tuple. Given this state of affairs, then, here’s an attempt at stating the orthogonality priniple a little more precisely: n
Definition (second attempt): Let relvars R and R2 be distinct, and let them have headings {A1,...,An} and {B1,...,Bn}, respectively. Let relvar R1 be defined as follows: R1 = R RENAME { A1 AS B1′
, ... , An AS Bn′ }
where B1′, ..., Bn′ is some permutation of B1, ..., Bn. (Observe that R1 and R2 thus have the same heading.) Then The Principle of Orthogonal Design says there must not exist restriction conditions c1 and c2, neither of which is identically false, such that the equality dependency (R1 WHERE c1) = (R2 WHERE c2) holds. Points arising from this second attempt: n
This version of the principle certainly solves the problem with the design of Fig. 14.3: First, take R and R2 to be LP and HP, respectively, and define R1 thus: R1 = LP RENAME { PNO AS PNO , ... , CITY AS CITY } (In other words, take R1 to be identically equal to R.) Second, take both c1 and c2 to be the restriction condition WEIGHT = 17.0. Then the equality dependency (R1 WHERE c1) = (R2 WHERE c2) holds, and the design thus violates The Principle of Orthogonal Design. Note: As this example demonstrates, so long as c1 and c2 aren’t identically false, then certain tuples exist that, if and when they represent “true facts,” must appear in both R1 and R2─and, in essence, that’s the situation we want to outlaw. (By contrast, if c1 and c2 were identically false, the restrictions R1 WHERE c1 and R2 WHERE c2 would both be empty, and there wouldn’t be any orthogonality violation.)
n
In fact, this version of the principle subsumes the previous version, because (a) we can make R1 identical to R (by effectively making the renaming a “no op,” as in the previous bullet item) and (b) we can take each of c1 and c2 to be simply TRUE. (As I pointed out earlier, the previous version of the principle did assume the
7 The example thus suggests an obvious rule of thumb: When you start the design process─which as far as I’m concerned means when you write down the predicates and other business rules─always use the same name for the same property; don’t “play games” by using, e.g., both SNO and SNR to refer to supplier numbers, both QTY and AMT to refer to quantities, and so on. Following this rule will (among other things) make it less likely that two distinct tuples will represent the same proposition.
166
Chapter 14 / The Principle of Orthogonal Design
relvars in question had the same heading. As the discussions of the present section have shown, however, we can’t limit our attention to that simple case alone.) n
Recall from Chapter 6 that, in logic, something that’s identically false (e.g., the boolean expression WEIGHT ≥ 17.0 AND WEIGHT < 17.0) is called a contradiction. Thus, the requirement that c1 and c2 not be identically false can be stated thus: Neither c1 nor c2 is a contradiction in the logical sense.
THE FIRST EXAMPLE REVISITED Now let’s return to our motivating example, in which relvar S was decomposed “vertically” into its projections SNC and STC on {SNO,SNAME,CITY} and {SNO,STATUS,CITY}, respectively. (The example of light vs. heavy parts involved horizontal decomposition, of course.) Observe now that although SNC and STC are certainly of the same degree, there’s no way any given tuple can appear in both: Tuples in SNC have an SNAME attribute, while tuples in STC have a STATUS attribute instead. What’s more, there’s no way we can simply rename (say) the SNAME attribute in SNC to STATUS and thereby produce a relvar with the same heading as STC, because SNAME in SNC is of type CHAR and STATUS in STC is of type INTEGER. (Renaming attributes changes names, not types.) It follows that our second attempt at defining the orthogonality principle is still inadequate; in the case at hand, in fact, it simply doesn’t apply. Recall now what the problem was with the foregoing design: The tuple (s,c) appears in the projection of SNC on SNO and CITY if and only if that very same tuple (s,c) appears in the projection of STC on SNO and CITY. That is, the following EQD holds: CONSTRAINT ... SNC { SNO , CITY } = STC { SNO , CITY } ; Let’s agree to ignore the question of attribute renaming for the moment, since it isn’t relevant to this example. Then the crucial point is that this EQD holds, not between distinct database relvars as such, but rather between distinct projections of the same database relvar: to be specific, projections arising from “vertical” decomposition of that database relvar. But such doesn’t have to be the case, of course─I mean, SNC and STC might have been defined independently, as two completely distinct relvars, without there ever having existed (in the designer’s mind, so to speak) a relvar equal to their join. They might even be, not relvars in their own right, but projections of two such distinct relvars. All of which leads to a third attempt at defining the orthogonality principle: n
Definition (third attempt): Let relvars R1 and R2 be distinct, and let the JD R{X1,...,Xn} be irreducible with respect to R1.8 Let there exist some Xi (1 ≤ i ≤ n) and some possibly empty set of attribute renamings on the projection, R1X say, of R1 on Xi that maps R1X into R1Y, say, where R1Y has the same heading as some subset Y of the heading of R2. Further, let the projection of R2 on Y be R2Y. Then The Principle of Orthogonal Design is violated by R1 and R2 if the equality dependency R1Y = R2Y holds.
Now, this looks a little complicated, but basically all it says is that no projection in any nonloss decomposition of R1 can be information equivalent to any projection of R2. Indeed, as you can probably see, much of the complexity in the definition (what complexity there is) arises from the need to deal with the renaming issue. For interest, here’s a slightly simpler version of the definition that ignores that complication:
8
Note that this JD certainly holds in R1, by the definition of JD irreducibility (see Chapter 11).
The Principle of Orthogonal Design / Chapter 14
n
167
Definition (third attempt, ignoring renaming): Let relvars R1 and R2 be distinct, and let the JD R{X1,...,Xn} be irreducible with respect to R1. Let some Xi (1 ≤ i ≤ n) be identical to some subset Y of the heading of R2; further, let the projections of R1 on Xi and R2 on Y be R1X and R2Y, respectively. Then The Principle of Orthogonal Design is violated by R1 and R2 if the equality dependency R1X = R2Y holds.
Observe now how adherence to this third version of the principle resolves the problem with our motivating example, in which relvar S was decomposed into its projections SNC and STC on {SNO,SNAME,CITY}) and STC {SNO,STATUS,CITY}, respectively. Suppose that decomposition is done. Then: a.
The database now contains two distinct relvars, SNC and STC.
b.
Thanks to Heath’s Theorem and the fact that the FD {SNO} → {SNAME} holds in relvar SNC, the JD R{{SNO,SNAME},{SNO,CITY}} holds in, and in fact is irreducible with respect to, that relvar SNC.
c.
Thus, the projection of relvar SNC on {SNO,CITY} is part of a valid nonloss decomposition of SNC. But an equality dependency holds between that projection and the projection of STC on those same attributes. Thus, the design violates the orthogonality principle as just articulated (the “third attempt”). Note: Points b. and c. here could be replaced by the following without changing the overall message:
b.
Thanks to Heath’s Theorem and the fact that the FD {CITY} → {STATUS} holds in relvar STC, the JD R{{CITY,STATUS},{CITY,SNO}} holds in, and in fact is irreducible with respect to, that relvar STC.
c.
Thus, the projection of relvar STC on {CITY,SNO} is part of a valid nonloss decomposition of STC. But an equality dependency holds between that projection and the projection of SNC on those same attributes. Thus, the design violates the orthogonality principle as just articulated (the “third attempt”).
I now observe that this third version of the orthogonality principle also lets me take care of a piece of unfinished business from Chapter 11. As you might recall, I pointed out in that chapter that the following JD held in relvar S, and in fact was irreducible with respect to that relvar: R { { SNO , SNAME , CITY } , { CITY , STATUS , SNAME } } I also said that decomposing relvar S on the basis of this JD wouldn’t be a good idea (and Exercise 11.4 asked why not). Well, now we can see that if that decomposition is done: a.
The database now contains two distinct relvars─I’ll call them SNC and CTN─with headings {SNO,SNAME,CITY} and {CITY,STATUS,SNAME}, respectively.
b.
Thanks to Heath’s Theorem and the fact that the FD {CITY} → {STATUS} holds in relvar CTN, the JD R{{CITY,STATUS},{CITY,SNAME}} holds in, and in fact is irreducible with respect to, that relvar CTN.
c.
Thus, the projection of relvar CTN on {CITY,SNAME} is part of a valid nonloss decomposition of CTN. But an equality dependency holds between that projection and the projection of SNC on those same attributes. In other words, the design violates the orthogonality principle once again.
The net of the example is this: Doing a decomposition on the basis of a “bad” JD is contraindicated by virtue of The Principle of Orthogonal Design. (The JD in the example is “bad” because attribute SNAME can be dropped
168
Chapter 14 / The Principle of Orthogonal Design
from the {CITY,STATUS,SNAME} component without significant loss.) What’s more, one consequence of abiding by orthogonality is that the fourth of the normalization principles as given at the beginning of the chapter─viz., that every projection should be needed in the reconstruction process─will automatically be satisfied (and so there’s a logical connection, of a kind, between orthogonality and normalization after all).
THE SECOND EXAMPLE REVISITED Unfortunately, the third version of the orthogonality principle as defined in the previous section is still missing something, and revisiting the light vs. heavy parts example shows what it is: It’s missing that business about restrictions. (In that example, the EQD wasn’t between database relvars as such, nor between projections of such relvars, but rather between certain restrictions of such relvars.) In other words, the third version of the principle failed to subsume the second version. By contrast, the following formulation takes care of both the restriction issue and the projection issue: n
Definition (fourth attempt): Let relvars R1 and R2 be distinct, and let the JD R{X1,...,Xn} be irreducible with respect to R1. Let there exist some Xi (1 ≤ i ≤ n) and some possibly empty set of attribute renamings on the projection, R1X say, of R1 on Xi that maps R1X into R1Y, say, where R1Y has the same heading as some subset Y of the heading of R2. Further, let the projection of R2 on Y be R2Y. Then The Principle of Orthogonal Design is violated by R1 and R2 if and only if there exist restriction conditions c1 and c2, neither of which is identically false, such that the equality dependency (R1Y WHERE c1) = (R2Y WHERE c2) holds.
THE FINAL VERSION Believe it or not, there’s still a small problem … Consider a version of the suppliers relvar—I’ll call it SCC—with attributes SNO, CITYA, and CITYB. Let SCC be subject to the constraint that for any given supplier, the CITYA and CITYB values are identical. Result: Redundancy! Of course, this is a crazy design, but it’s a possible one, and it would be nice to extend the orthogonality principle to take care of such designs also. And the following final (?) formulation should do the trick (I’ll leave it as an exercise for you to figure out exactly how): n
Definition (“final” version): Let R1 and R2 be relvars (not necessarily distinct), and let the JD R{X1,...,Xn} be irreducible with respect to R1. Let there exist some Xi (1 ≤ i ≤ n) and some possibly empty set of attribute renamings on the projection, R1X say, of R1 on Xi that maps R1X into R1Y, say, where R1Y has the same heading as some subset Y (distinct from Xi, if R1 and R2 are one and the same) of the heading of R2. Further, let the projection of R2 on Y be R2Y. Then The Principle of Orthogonal Design is violated by R1 and R2 if and only if there exist restriction conditions c1 and c2, neither of which is identically false, such that the equality dependency (R1Y WHERE c1) = (R2Y WHERE c2) holds.
This version of the principle subsumes all previous versions.
A CLARIFICATION I’m sorry to have to report that there’s quite a lot of confusion in the literature over orthogonality, even though the basic idea is so simple. I’m even sorrier to have to say the confusion is partly my fault─some of my previous writings on this topic have been (not to put too fine a point upon the matter) flat wrong. So let me take this
The Principle of Orthogonal Design / Chapter 14
169
opportunity to try and set the record straight. The basic point is this: Orthogonality says relvars shouldn’t have overlapping meanings; it doesn’t say relvars shouldn’t have the same heading (or, more generally, headings that “overlap”). Here’s a simple example, due to Hugh Darwen, that illustrates the difference. Consider the predicates Employee ENO is on vacation and Employee ENO is awaiting phone number allocation. The obvious design for this situation involves two relvars of degree one that look like this (in outline): ON_VACATION { ENO } KEY { ENO } NEEDS_PHONE { ENO } KEY { ENO } Clearly, the very same tuple can appear in both of these relvars at the same time. But even if it does, those two appearances represent two different propositions, and there’s no redundancy involved, and no violation of orthogonality. Observe now that there’s a difference in kind between the example just discussed and the light vs. heavy parts examples (relvars LP and HP) illustrated in Figs. 14.2 and 14.3, earlier in this chapter. In the latter case, as we saw earlier, we can write a formal constraint, to the effect that the WEIGHT value has to lie in a certain range, that a given tuple has to satisfy in order for it to be accepted into LP or HP or both. However, there’s no formal constraint we can write that a given tuple has to satisfy in order for it to be accepted into ON_VACATION or NEEDS_ PHONE or both. If the user asserts that a certain tuple is to be inserted into, say, ON_VACATION, then the system simply has to trust the user; there’s no check it can perform to ascertain that the tuple does indeed belong in ON_VACATION instead of (or as well as) NEEDS_PHONE. Here’s another example, also due to Hugh Darwen, that might also mistakenly be thought to violate orthogonality but in fact doesn’t. We’re given three relvars that look like this (in outline):9 EARNS
{ ENO , SALARY } KEY { ENO }
SALARY_UNK { ENO } KEY { ENO } UNSALARIED { ENO } KEY { ENO } Sample values are shown in Fig. 14.4. EARNS ┌─────┬────────┐ │ ENO │ SALARY │ ├═════┼────────┤ │ E1 │ 85,000 │ │ E3 │ 70,000 │ └─────┴────────┘
SALARY_UNK ┌─────┐ │ ENO │ ├═════┤ │ E2 │ └─────┘
UNSALARIED ┌─────┐ │ ENO │ ├═════┤ │ E4 │ └─────┘
Fig. 14.4: Relvars EARNS, SALARY_UNK, and UNSALARIED─sample values
9 The example illustrates a recommended approach (discussed in detail in SQL and Relational Theory) to dealing with “missing information” in relational designs.
170
Chapter 14 / The Principle of Orthogonal Design
The predicates for these three relvars are as follows: n
EARNS:
Employee ENO has salary SALARY.
n
SALARY_UNK:
Employee ENO has a salary, but we don’t know what it is.
n
UNSALARIED:
Employee ENO doesn’t have a salary.
Now, relvars SALARY_UNK and UNSALARIED do have the same heading─but even if the same tuple could simultaneously appear in both, there wouldn’t be any redundancy, because the appearances in question would represent two different propositions. In fact, of course, the semantics of the situation are such that no tuple should simultaneously appear in both, anyway (in other words, the relvars are disjoint). Here’s the necessary integrity constraint to express this fact: CONSTRAINT ... IS_EMPTY ( SALARY_UNK JOIN UNSALARIED ) ; (As explained in the answer to Exercise 6.4 in Appendix D, the Tutorial D expression IS_EMPTY ( r ) returns TRUE if relation r is empty and FALSE otherwise.)
CONCLUDING REMARKS In closing, I want to make a few further (and somewhat miscellaneous) observations on the concept of orthogonality in general. First of all, the overall objective of orthogonal design, like that of normalization, is to reduce redundancy and thereby to avoid certain update anomalies that might otherwise occur. In fact, orthogonality complements normalization, in the sense that─loosely speaking─normalization reduces redundancy within relvars, while orthogonality reduces redundancy across relvars. What’s more, orthogonality complements normalization in another way also. Consider once again the (bad) decomposition of relvar S into its projections SNC and STC, as illustrated in Fig. 14.1. As we saw earlier, that decomposition abided by all of the usual normalization principles; in other words, it was orthogonality, not normalization, that told us the design was bad. My next point is that, like the principles of normalization, The Principle of Orthogonal Design is basically just common sense─but (again like normalization) it’s formalized common sense, and the remarks I made in Chapter 1 in connection with such formalization apply here also. As I said in that chapter: What design theory does is [formalize] certain commonsense principles, thereby opening the door to the possibility of mechanizing those principles (that is, incorporating them into computerized design tools). Critics of the theory often miss this point; they claim, quite rightly, that the ideas are mostly just common sense, but they don’t seem to realize it’s a significant achievement to state what common sense means in a precise and formal way.
My final point is this: Suppose we start with the usual parts relvar P, but decide for design purposes to decompose that relvar into a set of restrictions, as in the light vs. heavy parts example. Then the orthogonality principle tells us that the restrictions in question should be pairwise disjoint (also, of course, that their union─which will in fact be a disjoint union─should take us back to the original relvar). Note: In previous writings, I’ve referred to a decomposition that meets this requirement as an orthogonal decomposition. However, I now think it would be
The Principle of Orthogonal Design / Chapter 14
171
better to generalize this term and use it to mean any decomposition that abides by the orthogonality principle. This revised definition includes the earlier one as a special case.
EXERCISES 14.1 Try stating the final version of The Principle of Orthogonal Design without looking back at the body of the chapter. 14.2 Consider the design of any database you happen to be familiar with. Does it involve any violations of The Principle of Orthogonal Design? Are there any constraints─especially “overlapping” ones─that ought to be stated declaratively but haven’t been? 14.3 Consider the second example in the section “A Clarification” (the one involving relvars EARNS, SALARY_UNK, and UNSALARIED). Do you think the design illustrated in that example is redundancy free? 14.4 Suppose we replace the suppliers relvar S by a set of relvars LS, PS, AS, ... (one for each distinct supplier city; the LS relvar, for example, contains tuples for suppliers in London only). These relvars all have the same attributes, viz., SNO, SNAME, and STATUS (there’s no need to keep the CITY attribute, because if we did its value would be constant throughout each relvar). Does this design violate orthogonality? Can you think of any other problems with it? By the way, if we did keep the CITY attribute in relvars LS, PS, AS, etc., the design would actually violate the principles of normalization! Why so, exactly?
Part V
REDUNDANCY
Throughout this book, we’ve been concerned with getting redundancy out of the design. But what is redundancy?
Chapter 15
We Need More Science What I tell you three times is true ─Lewis Carroll: The Hunting of the Snark
Note: Portions of this chapter originally appeared, in considerably different form, in my book Date on Database: Writings 2000-2006 (Apress, 2006). Redundant adj. de trop, diffuse, excessive, extra, inessential, inordinate, padded, periphrastic, pleonastical, prolix, repetitious, supererogatory, superfluous, supernumerary, surplus, tautological, unemployed, unnecessary, unneeded, unwanted, verbose, wordy I give the foregoing splendid list of synonyms here purely for whatever intrinsic interest it might have (I found it in Chambers Twentieth Century Thesaurus, which also gives the following nice list of antonyms: concise, essential, necessary). Be that as it may, we’ve seen that design theory in general can be regarded as a set of principles and techniques for reducing redundancy (and thereby reducing the potential for certain inconsistencies and update anomalies that might otherwise occur). But what exactly is redundancy? We don’t seem to have a very precise definition of the term; we just have a somewhat vague idea that it can lead to problems, at least if it isn’t managed properly.1 In order to get a slightly better handle on this question, we first need to distinguish clearly between the logical and physical levels of the system. Obviously the design goals are different at the two levels. At the physical level, redundancy will almost certainly exist in some shape or form. Here are a couple of reasons why: n
Indexes and other such “fast access path” structures necessarily entail some redundancy, because certain data values are stored both in those auxiliary structures and in the structures to which they provide that “fast access.”
n
Derived relvars (and/or derived relations) that are physically stored in some way─what are known variously as snapshots or summary tables or materialized queries or materialized views2─also obviously involve some redundancy.
The reason for redundancy at the physical level is performance, of course. But physical redundancy has (or should have!) no effect on the logical level; it’s managed by the DBMS, and it’s never directly seen by the user. I mention it here only to get it out of the way, as it were. From this point forward, I’ll be concerned only with redundancy at the logical level.
1 I remind you, though, that we do at least have a precise definition of the kind of redundancy that can be removed by taking projections (see Chapter 13). 2 This last term is strongly deprecated, by the way, because the construct in question isn’t a view. Views are virtual, not materialized (at least as far as the relational model is concerned), and materialized view is thus a contradiction in terms. The proper term is snapshot.
176
Chapter 15 / We Need More Science
At the logical level, then, it’s tempting just to say that redundancy is always bad. But of course this statement is much too simplistic, owing to the availability of the view mechanism if nothing else. Let me digress for a moment to elaborate on this latter point. It’s well known, but worth stating explicitly nevertheless, that views (like normalization, though for very different reasons) serve two rather different purposes: 1.
2.
The user who actually defines view V is, obviously, aware of the expression X in terms of which V is defined. That user can use the name V wherever the expression X is intended, but such uses are basically just shorthand (like the use of macros in a programming language). By contrast, a user who’s merely informed that view V exists and is available for use is supposed not to be aware of the expression X; to that user, in fact, V is supposed to look and feel just like a base relvar.3
As an example of Case 1, suppose the user perceives the database as containing two relvars R1 and R2 and goes on to define their join as a view; clearly, then, that view is redundant so far as that user is concerned, and it could be dropped without any loss of information. For definiteness, therefore, I’m going to assume from this point forward (barring explicit statements to the contrary) that no relvar in the database is defined in terms of any others, so that at least this particular kind of redundancy isn’t usually present. With this possibility ruled out, then, it’s tempting to set a stake in the ground and say again that redundancy at the logical level is always undesirable. In order to adopt such a position, however, we need to be able to say what we mean by redundancy─for otherwise the position can’t possibly make sense. And even if we can come up with a good definition of the term, is the position (that redundancy at the logical level is always bad, that is) really tenable? Is it possible to eliminate all redundancy? Is it even desirable? These are questions of considerable pragmatic importance, of course. Indeed, I think it’s noteworthy that Codd called his very first (1969) paper on the relational model “Derivability, Redundancy, and Consistency of Relations Stored in Large Data Banks” (boldface added; see Appendix C). And his second (1970) paper, “A Relational Model of Data for Large Shared Data Banks” (again, see Appendix C)─this is the one that’s usually regarded as the seminal paper in the field, though that characterization is a little unfair to its 1969 predecessor─was in two parts of almost equal length, the second of which was called “Redundancy and Consistency” (the first was called “Relational Model and Normal Form”). Codd thus clearly regarded his thoughts on redundancy as a major part of the contribution of his relational work: rightly so, in my opinion, since he did at least provide us with a framework in which we could begin to address the issue precisely and systematically. Now, I showed in the previous chapter that one “definition” of redundancy that doesn’t work is this: The database involves redundancy if and only if it contains two distinct appearances of the same tuple. But we can validly say the following: n
Definition: The database involves redundancy if and only if it contains, directly or indirectly, two distinct representations of the same proposition.
The trouble is, although this definition is clearly correct, it doesn’t help much with the practical problem of reducing redundancy. But it does at least imply the following, which is a little better: n
3
Definition (preliminary version): Let D be a database design; let DB be a database value (i.e., a set of values for the relvars mentioned in D) that conforms to D; and let p be a proposition. Further, let DB contain some specific appearance of some tuple, or some combination of tuples, that represents p (either explicitly or
Emphasis on supposed─I’m describing an ideal situation here. Today’s reality is rather messier, as I’m sure you know.
We Need More Science / Chapter 15
177
implicitly). If DB additionally contains some distinct appearance of some tuple, or some combination of tuples, that also represents p (either explicitly or implicitly), then DB contains, and D permits, redundancy. The principles of normalization and The Principle of Orthogonal Design are aimed precisely at reducing redundancy in the foregoing narrow sense. Observe, however, that all the definition says is if (not if and only if) certain tuples appear, then there’s redundancy; i.e., it’s not a complete definition. Indeed, we’ll see several examples later in this chapter that still involve redundancy, even though they don’t contain distinct tuples or tuple combinations that represent the same proposition. What’s more, most of the examples in question are fully normalized and fully orthogonal. In other words, the principles of normalization and orthogonality, though necessary and undoubtedly important, are far from being sufficient.
A LITTLE HISTORY Before I get into a discussion of how and why normalization and orthogonality are insufficient, I’d like to say a little more about Codd’s attempts, in his very first two papers, to address the redundancy issue. In his 1969 paper, he said this: A set of relations is strongly redundant if it contains at least one relation [that] is derivable from the rest of the [relations in the set].
And he tightened up this definition somewhat in the 1970 paper: A set of relations is strongly redundant if it contains at least one relation that possesses a projection [that] is derivable from other projections of relations in the set.
I should explain that when Codd says a relation r is derivable from a set S of relations, he means r is equal to the result of applying some sequence of relational operations (join, projection, and so forth) to relations from S. I do have a few comments on his definitions, however: n
First, the term relation should be replaced by the term relvar throughout. (Of course, this latter term wasn’t introduced until many years later, and Codd never used it at all.)
n
Second, we can ignore the qualifier strongly. Codd was distinguishing between “strong” redundancy and what he called weak redundancy, but weak redundancy is irrelevant as far as we’re concerned. The reason is that weak redundancy has to do merely with equality dependencies that don’t hold at all times but do happen to hold at particular times, given the relation values that happen to exist at the times in question. In fact, it seems to me that Codd was struggling here with the logical difference between relations and relvars!─see the previous bullet item. “Strong” redundancy applies to relvars (it’s what we usually mean by redundancy when we talk about database design). “Weak” redundancy, by contrast, applies to relations, not relvars (it’s just an artifact of the values the relvars happen to have at some particular time).
n
The 1969 definition is subsumed by the 1970 definition, of course, because (as we know from Chapter 6) every relvar R is identically equal to a certain projection of R─namely, the identity projection.
n
More to the point, the 1970 definition is still deficient as a definition of redundancy in general, for at least the following two reasons:
178
n
Chapter 15 / We Need More Science
a.
It includes certain possibilities that we normally wouldn’t regard as redundancies at all. For example, suppose the suppliers-and-parts database is subject to the constraint that every part must be supplied by at least one supplier. Then the projection of relvar SP on {PNO} will necessarily be equal to the projection of relvar P on {PNO}, and we’ll have a “strong redundancy” on our hands. Note: Perhaps a more realistic example to illustrate the same point would be a constraint on a personnel database to the effect that every department must have at least one employee.
b.
At the same time, it excludes many possibilities that we certainly would regard as redundancies─see, e.g., the example of light vs. heavy parts in Chapter 14 (second version, as illustrated in Fig. 14.3). Several further examples are given in later sections of the present chapter.
Even more to the point, the references to projections in the 1970 definition should be replaced by references to projections that correspond to components of irreducible JDs. (The first of the two objections in the previous bullet item would then go away.)
One last point on Codd’s definitions: Codd did at least say (in both papers) that “we shall associate with [the database] a collection of statements [that] define all of the redundancies” in that database. The “statements” Codd is referring to here are Tutorial D CONSTRAINT statements (or something logically equivalent to such statements, of course). In other words, Codd certainly wanted the system to be aware of the redundancies, and he wanted those redundancies to be managed accordingly. Unfortunately, however, he then went on to say: The generation of an inconsistency ... could be logged internally, so that if it were not remedied within some reasonable time ... the system could notify the security officer [sic]. Alternatively, the system could [inform the user] that such and such relations now need to be changed to restore consistency ... Ideally, [different remedial actions] should be possible ... for different subcollections of relations.
Note: “Inconsistencies” (or, as I would prefer to call them, integrity violations) can certainly be caused by redundancy─more precisely, by redundancy that’s inadequately managed─but not all integrity violations are caused by redundancy, of course. More to the point, I believe the database should never be allowed to contain any inconsistencies, at least as far as the user is concerned; as I said in the previous chapter, you can never trust the results you get from an inconsistent database. In other words, “remedying inconsistencies” needs to be done immediately, at the level of individual statements (not even at the transaction level).4 See the section “Managing Redundancy” later in this chapter.
DATABASE DESIGN IS PREDICATE DESIGN Although I’ve had a lot to say in previous chapters about both predicates and constraints, I haven’t explicitly called out the difference between these concepts. So let me remedy that deficiency now. First, the predicate─sometimes more explicitly the relvar predicate, for definiteness─for a given relvar R is the intended interpretation, or meaning, for R. Of course, every user of a given relvar R is supposed (or assumed!) to understand the corresponding predicate; note, however, that─at least in today’s implementations─predicates are stated in natural language and are therefore somewhat informal in nature, necessarily.
4 See SQL and Relational Theory for a defense of this possibly rather unorthodox opinion. Let me add, with little by the way of elaboration, that the position implies a requirement for the system to support multiple assignment, which is a form of assignment that allows several variables─in particular, several relvars─to be updated “simultaneously” (i.e., within the confines of a single statement).
We Need More Science / Chapter 15
179
So predicates are informal. By contrast, constraints are formal. In essence, a constraint is a boolean expression, expressed in some formal language like SQL or Tutorial D and usually containing references to relvars in the database, that’s required to evaluate to TRUE at all times. Let R be a relvar. Then it’s convenient to think of the logical AND of all constraints that mention R, either directly or indirectly, as the relvar constraint for R. Note, therefore, that whereas the relvar predicate for R is understood only by the user, the relvar constraint for R is “understood” by both the user and the system. In fact, the relvar constraint for R can be regarded as the system’s approximation to the relvar predicate for R. Ideally, of course, we would like R to be such that it always satisfies its predicate; the best we can hope for, however, is that it always satisfies its constraint.5 Given now that a database is supposed to be a faithful representation of the semantics of what might be called “the microworld of interest,” it follows that predicates and constraints are highly relevant to the business of database design. We could say that predicates are the informal, and constraints the formal, representation of those semantics. Thus, the database design process as I see it goes like this: 1.
First we pin down the relvar predicates (and other business rules) as carefully as possible.
2.
Then we map those predicates and rules into relvars and constraints.
As a consequence of the foregoing, we can see that another way to think about design theory─normalization and so forth─is as follows: It’s a set of principles and techniques for helping with the business of pinning down predicates (and hence constraints). This perspective underpins much of what follows in this chapter. As an aside, I note that the foregoing discussion goes a long way toward explaining why I’m not much of a fan of E/R (“entity/relationship”) modeling and similar pictorial methodologies. (You might have noticed the total absence of E/R diagrams and the like in previous chapters!) The problem with E/R modeling and suchlike schemes is that they’re less powerful─much less powerful─than formal logic. In particular, they don’t include anything like adequate support for the quantifiers (EXISTS and FORALL),6 which is a serious omission because the formulation of all but the simplest constraints requires such support, or something equivalent to such support.7 As a consequence, those schemes and those diagrams are completely incapable of representing all but a few admittedly important, but limited, constraints. Thus, while it might be acceptable to use such diagrams to explicate the overall design at a high level of abstraction, it’s misleading, and in some respects quite dangerous, to think of such diagrams as actually being the design in its entirety. Au contraire: The design is the relvars, which the diagrams do show, plus the constraints, which they don’t.8
5 As an aside, I remark that The Closed World Assumption applies to predicates, not constraints. That is, (a) if tuple t appears in relvar R at time T, then t certainly satisfies both the relvar predicate and the relvar constraint for R at time T; (b) if tuple t could plausibly appear in relvar R but doesn’t, then t certainly doesn’t satisfy the predicate for R at time T, but it still has to satisfy the constraint for R (because if it doesn’t, then it couldn’t “plausibly appear” in the first place).
6
Since the quantifiers were invented by Frege in 1879, this omission makes E/R diagrams and the like (as a friend of mine once put it) “a pre 1879 kind of logic”! Note: A tutorial on quantifiers and related matters can be found in SQL and Relational Theory and many other places. 7 Tutorial D has no explicit quantifier support either, but anything expressible in terms of the quantifiers can nevertheless be expressed in Tutorial D; that is, Tutorial D does at least have “something equivalent to” quantifier support. 8 Two qualifications here: First, the diagrams do show some constraints (basically key and foreign key constraints), as already noted. Second, they might not in fact show all of the relvars─some E/R modeling schemes don’t include in their diagrams relvars like SP in our running example that correspond to many to many relationships.
180
Chapter 15 / We Need More Science
EXAMPLE 1 It’s my claim that design theory as a field of investigation is, in general, still wide open. To bolster this claim, in this section and the next few I want to give some examples of designs that (a) are fully normalized and fully orthogonal (at least in most cases) and yet (b) still suffer from various redundancies (again, in most cases). For my first example, consider the following simple relvar, which represents a set of names and addresses (the predicate is Person NAME resides at address ADDR): NADDR { NAME , ADDR } KEY { NAME } Suppose attribute ADDR in this relvar is tuple valued, where the tuples in question have attributes STREET, CITY, STATE, and ZIP. (Yes, tuple valued attributes or TVAs are legal, just as relation valued attributes or RVAs are legal─see Chapter 4─and for much the same reasons.) A sample value for this relvar is shown in Fig. 15.1. NADDR ┌──────┬─────────────────────────────────────┐ │ NAME │ ADDR /* tuple valued */ │ ├══════┼─────────────────────────────────────┤ │ │┌────────────┬──────┬───────┬───────┐│ │ Jack ││ STREET │ CITY │ STATE │ ZIP ││ │ │├────────────┼──────┼───────┼───────┤│ │ 94100 ││ ││ 1 Main St. │ SFO │ CA │ │ │└────────────┴──────┴───────┴───────┘│ │ │┌────────────┬──────┬───────┬───────┐│ │ Jill ││ STREET │ CITY │ STATE │ ZIP ││ │ │├────────────┼──────┼───────┼───────┤│ │ ││ 2 Main St. │ SFO │ CA │ 94100 ││ │ │└────────────┴──────┴───────┴───────┘│ └──────┴─────────────────────────────────────┘ Fig. 15.1: Relvar NADDR (ADDR is tuple valued)─sample value
Assume now for the sake of the example, as we did in Exercise 6.2, that whenever two ADDR values have the same ZIP component, they also have the same CITY and STATE components. Then the foregoing design clearly involves some redundancy. Yet there’s no violation of normalization here; in particular, the functional dependency { ZIP } → { CITY , STATE } does not hold. (Why not? Answer: Because FDs are defined to hold among attributes, not among components of attributes.) That said, let me now point out that the foregoing FD does hold in the result of replacing NADDR by the result of the following expression: NADDR UNWRAP ( ADDR ) Note: The Tutorial D UNWRAP operator effectively replaces some tuple valued attribute by a set of attributes, one for each component of that TVA. Thus, the foregoing expression returns a result with attributes NAME, STREET,
We Need More Science / Chapter 15
181
CITY, STATE, and ZIP. (Of course, that result is still only in 2NF, not even BCNF, and it still suffers from redundancy.) We might conclude from this example that unwrapping TVAs is a good idea. But is it enough of a good idea to be enshrined as a principle of good design?9
EXAMPLE 2 Codd would probably have prohibited the design of Example 1 on the grounds that values of attribute ADDR aren’t “atomic” (though I’m not aware that he ever explicitly addressed the question of tuple valued attributes as such in any of his writings). Now, I don’t agree with this position myself, for reasons I’ve explained in detail in SQL and Relational Theory and elsewhere─but the point isn’t worth fighting over, because we can obviously replace that tuple valued attribute by an attribute of type CHAR as shown in Fig. 15.2. Codd would surely have allowed that revised design, and yet it suffers from redundancies precisely analogous to those in Example 1. NADDR ┌──────┬───────────────────────────┐ │ NAME │ ADDR /* type CHAR */ │ ├══════┼───────────────────────────┤ │ Jack │ 1 Main St., SFO, CA 94100 │ │ Jill │ 2 Main St., SFO, CA 94100 │ └──────┴───────────────────────────┘ Fig. 15.2: Revised relvar NADDR (ADDR is text valued)─sample value
And if you don’t like this example, consider what could happen if attribute ADDR is of some user defined type (ADDRESS, say) instead of type CHAR.
EXAMPLE 3 Redundancies similar to those in Example 2 can arise in connection with attributes of type DATE, if those attributes include the day of the week as well as a calendar date (as in, for example, “Tuesday, January 18th, 2011”).
EXAMPLE 4 My next example is an extremely simple version of the familiar employees-and-programmers example, in which all programmers are employees but some employees aren’t programmers (as in Exercise 5.7). Note that some people would say that employees and programmers in this example correspond to an entity supertype and an entity subtype, respectively. Be that as it may, here’s the conventional design: EMP
{ ENO } KEY { ENO }
9 In his book An Introduction to Relational Database Theory (Ventus, 2010), Hugh Darwen suggests that it might be, and that we might consider a wrap-unwrap normal form in this connection. He also suggests in that same book that ungrouping RVAs is a good idea, too, and that we might thus also consider a group-ungroup normal form accordingly.
182
Chapter 15 / We Need More Science
PGMR { ENO , LANG } KEY { ENO } I’m assuming for the sake of simplicity that nonprogrammers have no attributes of interest apart from ENO (if they do, it makes no significant difference to the example), and programmers have just one additional attribute, LANG (programming language skill─e.g., “Java” or “SQL” or “Tutorial D”). Now we have a choice: Record all employees in EMP, or record just the nonprogrammers in EMP. Which is better? n
If we record just the nonprogrammers in EMP, the processing involved when an employee becomes or ceases to be a programmer is slightly nontrivial─in both cases we have to delete a tuple from one relvar and insert a tuple into the other. We also need to state and enforce the following constraint: CONSTRAINT ... IS_EMPTY ( EMP JOIN PGMR ) ; Also note the implications if we want some other relvar to include a reference to employees. Normally that reference would be a simple foreign key; but if employees are split across two relvars, EMP and PGMR, it can’t be (at least, not as foreign keys are conventionally understood). The net of such considerations is that this particular design is probably not recommended.
n
But on the other hand, if we record all employees in EMP, we have some redundancy in our design: If e is a programmer, e is certainly an employee, so why say so explicitly?
EXAMPLE 5 Now I’d like to extend Example 4 slightly in order to make an additional point. Suppose relvar EMP does include at least one additional attribute, JOB; suppose further that a given employee is a programmer, and is represented in relvar PGMR, if and only if the JOB value in that employee’s tuple in EMP has the value “Programmer” (perhaps other values of JOB─“Janitor”, for example─correspond to other relvars). This kind of situation is not at all uncommon in practice, by the way. Now there’s definitely some redundancy, because the design is subject to the following equality dependency (as well as many similar ones, possibly): CONSTRAINT ... ( EMP WHERE JOB = ‘Programmer’ ) { ENO } = PGMR { ENO } ; Note, however, that there’s no violation of orthogonality in this example, even if all employees, programmers included, are represented in EMP. Suppose they are; then it’s clearly the case that the projection of PGMR on {ENO} is equal to a certain subset─it’s not a restriction as such─of the projection of EMP on {ENO}. (Exercise: Why isn’t it a restriction as such?) But neither of those projections corresponds to a component of any irreducible JD that holds in the pertinent relvar.10 (Check the final version of The Principle of Orthogonal Design in Chapter 14 if you need to refresh your memory on this point.) Thus, a database can be fully orthogonal and yet still exhibit some redundancy.
10
In fact relvars EMP and PGMR are both in 6NF, and the only irreducible JDs that hold are trivial ones.
We Need More Science / Chapter 15
183
EXAMPLE 6 In a paper he wrote in 1979 (“Extending the Database Relational Model to Capture More Meaning,” ACM TODS 4, No. 4, December 1979), Codd proposed a certain design discipline, which (simplifying slightly) can be described as follows: n
Let E be an “entity type,” and let ID be a data type such that every entity of type E has exactly one primary identifier (my term, not Codd’s), of type ID. For example, E and ID might be the entity type “suppliers” and the data type “character string,” respectively.
n
Let P1, ..., Pn be a set of “property types” such that every entity of type E has at most one property of each of the types P1, ..., Pn. For example, in the case of suppliers, P1, P2, and P3 might be the property types “name,” “status,” and “city” (so n = 3 in this example). Note: I’m assuming for the sake of the present discussion (only) that a given supplier can have any subset of the three properties, including the empty set in particular.
n
Then the database should contain: a.
Exactly one E-relvar, containing ID values for those entities of type E that exist at any given time, and
b.
Exactly one P-relvar for each Pi (i = 1, ..., n), containing (ID value, Pi value) pairs for each entity of type E that exists at any given time and has a property of type Pi at that time.
I’ll refer to this discipline as “the RM/T discipline,” since it’s part of what Codd referred to, in that 1979 paper, as “the extended relational model RM/T” (T for Tasmania, where Codd first presented his ideas for that extended model). Applying the discipline to the case of suppliers specifically, we obtain a design that looks like this (here I ignore for simplicity the fact that there’s supposed to an FD from {CITY} to {STATUS}): S
{ SNO } KEY { SNO } ;
SN { SNO , SNAME } KEY { SNO } FOREIGN KEY { SNO } REFERENCES S ST { SNO , STATUS } KEY { SNO } FOREIGN KEY { SNO } REFERENCES S SC { SNO , CITY } KEY { SNO } FOREIGN KEY { SNO } REFERENCES S Each of these relvars is irreducible; equivalently, each is in 6NF.11 Fig. 15.3 shows a set of sample values. Note: The values in question aren’t meant to be the same as our usual sample values, though they’re close. Observe
11 In the interest of historical accuracy, I note that P-relvars as described by Codd in his RM/T paper weren’t necessarily in 6NF, because he didn’t insist that each P-relvar involve just a single “property.”
184
Chapter 15 / We Need More Science
in particular that (a) supplier S3 has no status, (b) supplier S4 has no status and no city, and (c) supplier S5 has no name, no status, and no city. S ┌─────┐ │ SNO │ ├═════┤ │ S1 │ │ S2 │ │ S3 │ │ S4 │ │ S5 │ └─────┘
SN ┌─────┬───────┐ │ SNO │ SNAME │ ├═════┼───────┤ │ S1 │ Smith │ │ S2 │ Jones │ │ S3 │ Blake │ │ S4 │ Clark │ └─────┴───────┘
ST ┌─────┬────────┐ │ SNO │ STATUS │ ├═════┼────────┤ │ S1 │ 20 │ │ S2 │ 30 │ └─────┴────────┘
SC ┌─────┬────────┐ │ SNO │ CITY │ ├─────┼────────┤ │ S1 │ London │ │ S2 │ Paris │ │ S3 │ Paris │ └─────┴────────┘
Fig. 15.3: An “RM/T design” for suppliers─sample values
As I indicated in Chapter 13, this kind of design actually has quite a lot to recommend it (at least, it would do so given a well architected DBMS). For present purposes, however, all I want to do is call your attention to the following: So long as every entity of type E has at least one of the n properties, then the design certainly involves some redundancy─arguably, in fact, strong redundancy as defined by Codd himself in his 1970 paper─because, at any given time, the value of the E-relvar will be equal to the union of the projections of the P-relvars over the identifier attribute: CONSTRAINT ... S { SNO } = UNION { SN { SNO } , ST { SNO } , SC { SNO } } ; This kind of redundancy would apply to Fig. 15.3, for example, if we deleted supplier S5 (that is, if every supplier had at least one of the three properties name, status, and city). Exercise for the reader: How does the redundancy here differ from that discussed under Example 4? Does it differ? Would it make any difference if the employees in Example 4 had additional properties (for example, salaries)? Observe further that the design becomes “even more redundant,” as it were, in the (common?) special case in which every entity of type E in fact has all of the n properties. Fig. 15.4 is a revised version of Fig. 15.3 that illustrates this situation. Note in that figure that─speaking a trifle loosely─{SNO} is now a foreign key in each of the relvars that references the sole key {SNO} in each of the others; equivalently, the projection on {SNO} of any of the relvars is equal to the projection on {SNO} of any of the others. Well ... to be more precise about the matter, there’s actually an equality dependency interrelating every pair of the four relvars: CONSTRAINT ... IDENTICAL { S { SNO } , SN { SNO } , ST { SNO } , SC { SNO } } ; Note: IDENTICAL is an operator proposed by Hugh Darwen and myself12 as an addition to Tutorial D, with semantics as follows: The expression IDENTICAL { r1 , ... , rn } returns TRUE if the relations r1, ..., rn are all equal and FALSE otherwise (you can think of it as a kind of n-adic “=” operator).
12
In Database Explorations: Essays on The Third Manifesto and Related Topics (Trafford, 2010) and elsewhere.
We Need More Science / Chapter 15
S ┌─────┐ │ SNO │ ├═════┤ │ S1 │ │ S2 │ │ S3 │ │ S4 │ │ S5 │ └─────┘
SN ┌─────┬───────┐ │ SNO │ SNAME │ ├═════┼───────┤ │ S1 │ Smith │ │ S2 │ Jones │ │ S3 │ Blake │ │ S4 │ Clark │ │ S5 │ Adams │ └─────┴───────┘
ST ┌─────┬────────┐ │ SNO │ STATUS │ ├═════┼────────┤ │ S1 │ 20 │ │ S2 │ 30 │ │ S3 │ 30 │ │ S4 │ 20 │ │ S5 │ 30 │ └─────┴────────┘
185
SC ┌─────┬────────┐ │ SNO │ CITY │ ├─────┼────────┤ │ S1 │ London │ │ S2 │ Paris │ │ S3 │ Paris │ │ S4 │ London │ │ S5 │ Athens │ └─────┴────────┘
Fig. 15.4: A revised version of Fig. 15.3
Note carefully, however, that even in this extreme case, the design doesn’t violate orthogonality. What’s more, I say again that this kind of design would have quite a lot to recommend it given a well architected DBMS. In particular, the equality dependencies, and therefore the redundancies, would be “automatically” managed and maintained in such a system (see the section “Managing Redundancy,” later).
EXAMPLE 7 Consider a company in which every employee is required to be in exactly one department and every department is required to have at least one employee. Fig. 15.5 shows sample values (in outline) for an RM/T design for this situation:13 EMP ┌─────┐ │ ENO │ ├═════┤ │ E1 │ │ E2 │ │ E3 │ │ E4 │ │ E5 │ └─────┘
DEPT ┌─────┐ │ DNO │ ├═════┤ │ D1 │ │ D2 │ │ D3 │ └─────┘
EMPDEPT ┌─────┬─────┐ │ ENO │ DNO │ ├═════┼─────┤ │ E1 │ D1 │ │ E2 │ D2 │ │ E3 │ D2 │ │ E4 │ D3 │ │ E5 │ D3 │ └─────┴─────┘
Fig. 15.5: Employees and departments─sample values
With reference to those sample values, however, we see there are exactly five employees and exactly three departments. Since every employee must be in exactly one department and every department must have at least one employee, why not define one department─D3, say─to be the “default” one, and adopt a rule that says any employee mentioned in EMP and not EMPDEPT is in that default department? In terms of Fig. 15.4, this rule would allow us to omit the tuples (E4,D3) and (E5,D3) from EMPDEPT. Note that if we don’t adopt such a rule, then the design clearly involves some redundancy once again─to be specific, it’s subject to the following equality dependencies:
13 Exercise: Is EMPDEPT in that figure a P-relvar for employees, departments, or both? Justify your answer! To pursue the point a moment longer: An RM/T design might not be the best option in this example, because there’s necessarily a one to one correspondence between EMP and EMPDEPT, and there seems little reason not to collapse those two relvars into one.
186
Chapter 15 / We Need More Science
CONSTRAINT EVERY_EMP_HAS_A_DEPT
EMP { ENO }
= EMPDEPT { ENO } ;
CONSTRAINT EVERY_DEPT_HAS_AN_EMP DEPT { DNO } = EMPDEPT { DNO } ; There seem to me to be at least two factors that militate against adopting such a “default department” design, however. The first is that the choice of which department to make the default is likely to be arbitrary. The second is that now we need to be extremely careful over the meaning of relvar EMPDEPT! The obvious predicate Employee ENO is in department DNO doesn’t work. Why not? Because, under that predicate (and assuming department D3 is the default), omitting the tuple (E5,D3), say, would mean─thanks to The Closed World Assumption─that employee E5 isn’t in department D3! So the predicate has to be something like this: Employee ENO is in department DNO (which is not the default department number D3). Now, this predicate does work (I think!), but it’s pretty tricky. Suppose the tuple (E1,D1) appears in the relvar, as shown in Fig. 15.5. Then the corresponding proposition is: Employee E1 is in department D1 (which is not the default department number D3). And of course this proposition evaluates to TRUE. OK so far. However, now suppose there’s no tuple in the relvar for employee E5. The intended interpretation is, of course, that employee E5 is in department D3; but what does The Closed World Assumption actually say? Well, first of all, observe that, e.g., the specific tuple (E5,D1) doesn’t appear. By The Closed World Assumption, then, the following must be a true proposition: It’s not the case that employee E5 is in department D1 (which is not the default department number D3). Or a little more formally: NOT ( E5 is in D1 AND D1 ≠ D3 ) By De Morgan’s laws, this expression is equivalent to: E5 is not in D1 OR D1 = D3 Since D1 = D3 is false, this expression reduces to just “E5 is not in D1,” which is what we want (I mean, it’s a true proposition). A similar analysis shows that we can infer that E5 certainly isn’t in any department that’s not the default one, D3. But what about that default one? Well, the tuple (E5,D3) doesn't appear, and so the following must be a true proposition: NOT ( E5 is in D3 AND D3 ≠ D3 ) Equivalently: E5 is not in D3 OR D3 = D3 Since D3 = D3 is true, this expression reduces to just TRUE. Note, however, that this proposition doesn't actually tell us E5 is in D3! Now, perhaps we can infer this latter fact, given that E5 does exist and certainly isn’t in any
We Need More Science / Chapter 15
187
other department (?). But I seriously doubt whether users would want to have to deal with such convoluted, logicchopping arguments in practice.
EXAMPLE 8 Consider the design illustrated in Fig. 15.6 (a slightly revised, somewhat “RM/T-like” version of Fig. 14.4 from the previous chapter): EMP ┌─────┐ │ ENO │ ├═════┤ │ E1 │ │ E2 │ │ E3 │ │ E4 │ └─────┘
EARNS ┌─────┬────────┐ │ ENO │ SALARY │ ├═════┼────────┤ │ E1 │ 85,000 │ │ E3 │ 70,000 │ └─────┴────────┘
SALARY_UNK ┌─────┐ │ ENO │ ├═════┤ │ E2 │ └─────┘
UNSALARIED ┌─────┐ │ ENO │ ├═════┤ │ E4 │ └─────┘
Fig. 15.6: An “RM/T design” for employees and salaries─sample values
The predicates for these relvars are as follows: n
EMP:
Employee ENO is employed by the company.
n
EARNS:
Employee ENO has salary SALARY.
n
SALARY_UNK:
Employee ENO has a salary, but we don’t know what it is.
n
UNSALARIED:
Employee ENO doesn’t have a salary.
I observe now that either relvar SALARY_UNK or relvar UNSALARIED is redundant─any employee represented in relvar EMP and not in relvar EARNS must be represented in exactly one of the other two; thus, we could eliminate, say, relvar SALARY_UNK without any loss of information. Yet there doesn’t seem to be any good reason for choosing either of SALARY_UNK and UNSALARIED over the other as the one to be eliminated, and considerations of symmetry would argue in favor of retaining both, and living with the redundancy (?). Aside: Symmetry is usually another good design principle. To quote Polya:14 “Try to treat symmetrically what is symmetrical, and do not destroy wantonly any natural symmetry.” But Example 8 and others like it─Example 7 too, perhaps─show that symmetry and nonredundancy can sometimes be conflicting objectives. End of aside.
14
G. Polya: How To Solve It (2nd ed., Princeton University Press, 1971).
188
Chapter 15 / We Need More Science
EXAMPLE 9 This example is due to Hugh Darwen. It’s based on a real life situation that arises in connection with the Open University in the U.K. We’re given a relvar that looks like this: SCT { SNO , CNO , TNO } KEY { SNO , CNO , TNO } The predicate is: Tutor TNO tutors student SNO on course CNO. Fig. 15.7 shows a sample value for this relvar. The redundancies are obvious: For example, the fact that student S1 is enrolled in course C1, the fact that course C1 is tutored by tutor T1, and the fact that tutor T1 tutors student S1 are all represented more than once in the sample value shown in the figure.15 (Note that the JD R{{SNO,CNO},{CNO,TNO},{TNO,SNO}} does not hold in relvar SCT.) ┌─────┬─────┬─────┐ SCT │ SNO │ CNO │ TNO │ ├═════┼═════┼═════┤ │ S1 │ C1 │ T1 │ │ S1 │ C1 │ T2 │ │ S2 │ C1 │ T1 │ │ S2 │ C1 │ T2 │ │ S1 │ C2 │ T1 │ │ S2 │ C2 │ T1 │ └─────┴─────┴─────┘ 15.7: Relvar SCT─sample value
Now, one tactic we might consider for reducing redundancy in examples like this one is to make use of surrogate keys (surrogates for short).16 For example, we might introduce an attribute X, say, whose values serve as surrogates for (SNO,CNO) pairs, as illustrated in Fig. 15.8. (Observe from that figure that I’ve made {X} the primary key for relvar XSC. However, the combination {SNO,CNO} is still a key too, of course.) ┌─────┬─────┬─────┐ XSC │ X │ SNO │ CNO │ ├═════┼─────┼─────┤ │ x1 │ S1 │ C1 │ │ x2 │ S2 │ C1 │ │ x3 │ S1 │ C2 │ │ x4 │ S2 │ C2 │ └─────┴─────┴─────┘
┌─────┬─────┐ XT │ X │ TNO │ ├═════┼─────┤ │ x1 │ T1 │ │ x1 │ T2 │ │ x2 │ T1 │ │ x2 │ T2 │ │ x3 │ T1 │ │ x4 │ T1 │ └─────┴─────┘
Fig. 15.8: Using surrogates for (SNO,CNO) combinations
15
You might not agree that those repetitions constitute redundancy. If you don’t, however, I ask you to hold your objections for now─I’ll be taking a much closer look at this example later in the chapter.
16
As a matter of fact, Codd advocated the use of surrogates in his RM/T discipline in connection with all entity types. In this recommendation he was following the pioneering work of Patrick Hall, John Owlett, and Stephen Todd in their paper “Relations and Entities,” in G. M. Nijssen (ed.), Modelling in Data Base Management Systems (North-Holland/Elsevier Science, 1975).
We Need More Science / Chapter 15
189
One difficulty with this approach is as follows: On what basis do we decide to use surrogates for (SNO,CNO) combinations and not for (CNO,TNO) combinations or (TNO,SNO) combinations? Whichever choice we make is asymmetric. Moreover, surrogates are not without problems of their own. Here are some of them:17 n
Surrogates can make updating more complicated (in essence, users have to do their own foreign key checking).
n
To add insult to injury, the system’s foreign key checking─which still has to be done!─(a) will never fail and (b) will therefore be pure overhead.
n
Queries and updates become longer, more tedious to write, more error prone, harder to debug, and harder to maintain.
n
More integrity constraints become necessary.
For present purposes, however, the real question is this: Does introducing surrogates really serve to reduce redundancy? I don’t want to try to address this question here; I’ll come back to it later, in the section “Refining the Definition.”
EXAMPLE 10 Another tactic we might consider for reducing redundancy in examples like that of Fig. 15.7 is to introduce some relation valued attributes or RVAs. Fig. 15.9 below gives an example. However, one obvious problem with this approach─quite apart from all of the usual problems that always attend the use of RVAs─is again asymmetry: On what basis do we decide to use an RVA for tutors and not for students or courses? And in any case, does this tactic really reduce redundancy? Again I’ll come back to this question later, in the section “Refining the Definition.” ┌─────┬─────┬─────────┐ │ SNO │ CNO │ TNOREL │ ├═════┼─────┼─────────┤ │ │ │ ┌─────┐ │ │ S1 │ C1 │ │ TNO │ │ │ │ │ ├═════┤ │ │ │ │ │ T1 │ │ │ │ │ │ T2 │ │ │ │ │ └─────┘ │ │ │ │ ┌─────┐ │ │ S2 │ C1 │ │ TNO │ │ │ │ │ ├═════┤ │ │ │ │ │ T1 │ │ │ │ │ │ T2 │ │ │ │ │ └─────┘ │
│ │ │ ┌─────┐ │ │ S1 │ C2 │ │ TNO │ │ │ │ │ ├═════┤ │ │ │ │ │ T1 │ │ │ │ │ └─────┘ │ │ │ │ ┌─────┐ │ │ S2 │ C2 │ │ TNO │ │ │ │ │ ├═════┤ │ │ │ │ │ T1 │ │ │ │ │ └─────┘ │ └─────┴─────┴─────────┘
Fig. 15.9: Using an RVA for tutors
17
These problems are elaborated in my paper “Composite Keys” in Relational Database Writings 1989-1991 (Addison-Wesley, 1992).
190
Chapter 15 / We Need More Science
EXAMPLE 11 This one is just a placemarker. In our book Temporal Data and the Relational Model (Morgan Kaufmann, 2003), Hugh Darwen, Nikos Lorentzos, and I show that several further kinds of redundancy can arise in connection with temporal data, and we propose a number of new design principles and techniques for dealing with them. In particular, that book is the source of the new normal form 6NF (discussed in Chapter 13), though it’s important to understand that 6NF has an extended definition (and is “even more relevant”) in the temporal context.
EXAMPLE 12 My last example is typical of a common practical situation. It’s loosely based on an example in Fabian Pascal’s book Practical Issues in Database Management: A Reference for the Thinking Practitioner (Addison-Wesley, 2000). We’re given two relvars that look like this (and I assume until further notice that they’re base relvars specifically): PAYMENTS { CUSTNO , DATE , AMOUNT } KEY { CUSTNO , DATE } FOREIGN KEY { CUSTNO } REFERENCES TOTALS TOTALS { CUSTNO , TOTAL } KEY { CUSTNO } Attribute TOTAL in relvar TOTALS is an example of what’s often called derived data, since its value for any given customer is derived by summing all of the payments for the customer in question. In fact, the following equality dependency holds: CONSTRAINT C12 TOTALS = SUMMARIZE PAYMENTS BY { CUSTNO } : { TOTAL := SUM ( AMOUNT ) } ; Note: SUMMARIZE is Tutorial D’s analog of SQL’s SELECT with a GROUP BY (speaking very loosely!).18 In case you feel more comfortable with SQL than Tutorial D, let me also give an SQL version of the foregoing constraint: CREATE ASSERTION C12 CHECK ( NOT EXISTS ( SELECT * FROM TOTALS WHERE NOT EXISTS ( SELECT * FROM ( SELECT CUSTNO , SUM ( AMT ) AS TOTAL FROM PAYMENTS GROUP BY CUSTNO ) AS TEMP WHERE TOTALS.CUSTNO = TEMP.CUSTNO ) ) AND
18 Actually SUMMARIZE is likely to be dropped from the next version of Tutorial D, because expressions involving SUMMARIZE can always be formulated more “respectably” in terms of the relational EXTEND operator and what are called image relations. For example, the SUMMARIZE expression in the case at hand could be replaced by the following: EXTEND PAYMENTS{CUSTNO}:{TOTAL := SUM(‼PAYMENTS,AMOUNT). For more information regarding EXTEND in general and image relations in particular, see SQL and Relational Theory.
We Need More Science / Chapter 15
191
NOT EXISTS ( SELECT * FROM ( SELECT CUSTNO , SUM ( AMT ) AS TOTAL FROM PAYMENTS GROUP BY CUSTNO ) AS TEMP WHERE NOT EXISTS ( SELECT * FROM TOTALS WHERE TOTALS.CUSTNO = TEMP.CUSTNO ) ) ) ; For further explanation of SUMMARIZE, see SQL and Relational Theory. Now, derived data is clearly redundant─though note once again that there are no violations of either normalization or orthogonality here (in particular, relvars PAYMENTS and TOTALS are both in 6NF). I’ll analyze this example in more detail in the section immediately following.
MANAGING REDUNDANCY The fact that the design of Example 12 from the previous section is redundant is clearly shown by the fact that the specified equality dependency holds (constraint C12). And there are, at least in principle, four basic approaches to dealing with the kind of redundancy illustrated by that example: 1. 2. 3. 4.
Raw design only Declare the constraint Use a view Use a snapshot
Let’s take a closer look. 1. Raw Design Only This is perhaps the approach most likely to be encountered in practice, given the limited functionality provided by most of today’s DBMS implementations. The idea is simply that: a.
Relvars PAYMENTS and TOTALS are defined exactly as shown in the previous section.
b.
Constraint C12 is not declared to the DBMS.
c.
Maintaining the derived data is the user’s responsibility one hundred percent. (Or some user’s responsibility, at any rate; the maintenance might be done by means of a triggered procedure, but some user still has to write the code for that procedure.)19
In effect, this approach trades off (a) the extra work involved on the part of the user─or some user, at any rate─in executing certain updates (as well as the associated performance hit) against (b) the improved performance obtained when executing certain queries. But there are no guarantees; if the user makes a mistake during some update that (in effect) causes Constraint C12 to be violated, well, tough.
19 Note in particular that relvar TOTALS ought never to be updated at all, except for the updates that are needed to keep the two relvars “in synch,” as it were. (As a matter of fact, an analogous observation applies to the other three approaches as well, mutatis mutandis.)
192
Chapter 15 / We Need More Science
2. Declare the Constraint In this approach Constraint C12 is explicitly declared to the DBMS and the DBMS takes the responsibility for enforcing it. Maintaining the derived data is still the user’s responsibility, though, exactly as it was under the previous approach. What’s more, if the user carries out this task reliably and correctly, the constraint checking will never fail, and it will thus, in effect, constitute pure overhead on the user’s updates. But we can’t dispense with the constraint, precisely because we need the system to check that the user is carrying out the maintenance task reliably and correctly. 3. Use a View Clearly it would be better if, instead of simply declaring the constraint, we could actually inform the system of the rule by which the derived data is defined and have the system perform the derivation process automatically. And we can; that’s exactly what the view mechanism does. To be specific, we can replace the base relvar TOTALS by a view (or “virtual relvar”) of the same name, thus: VAR TOTALS VIRTUAL /* Tutorial D syntax for defining a view */ ( SUMMARIZE PAYMENTS BY { CUSTNO } : { TOTAL := SUM ( AMOUNT ) } ) ; Now the user no longer has to worry about maintaining the derived data; moreover, there’s now no way that Constraint C12 can possibly be violated, and there’s no need even to state it any more, except perhaps informally (as a means of telling the user the semantics of the view, perhaps). Note, however, that the user does have to be explicitly told not to try to maintain the totals! This fact doesn’t mean the user has to be told that relvar TOTALS is a view, though; it just means the user has to be told that the maintenance task will effectively be performed by the system. 4. Use a Snapshot The drawback to the view solution, however, is that the derivation process is performed every time the view is referenced (even if no updates have been done since the last time it was referenced). Thus, if the object of the exercise is in to do the derivation work at update time in order to improve subsequent query performance, the view solution is clearly inadequate. In that case, we should use a snapshot instead of a view: VAR TOTALS SNAPSHOT ( SUMMARIZE PAYMENTS BY { CUSTNO } : { TOTAL := SUM ( AMOUNT ) } ) REFRESH ON EVERY UPDATE ; The snapshot concept has its origins in a paper by Michel Adiba.20 Basically, snapshots, like views, are derived relvars; unlike views, however, they’re real, not virtual─that is, they’re represented not just by their definition in terms of other relvars, but also (at least conceptually) by their own separately materialized copy of the data. In other words, defining a snapshot is much like executing a query, except that:
20 Michel Adiba: “Derived Relations: A Unified Mechanism for Views, Snapshots, and Distributed Data,” Proc. 1981 Int. Conf. on Very Large Data Bases, Cannes, France (September 1981). See also the earlier version “Database Snapshots,” by Michel E. Adiba and Bruce G. Lindsay, IBM Research Report RJ2772 (March 7th, 1980).
We Need More Science / Chapter 15
193
a.
The result of the query is kept in the database under the specified name (TOTALS in the example) as a readonly relvar (read-only, that is, apart from the periodic refresh─see point b. immediately following).
b.
Periodically (ON EVERY UPDATE in the example) the snapshot is refreshed─that is, its current value is discarded, the query is executed again, and the result of that new execution becomes the new snapshot value. The general form of the REFRESH clause is REFRESH EVERY <now and then>
where <now and then> might be, for example, MONTH or WEEK or DAY or HOUR or n MINUTES or MONDAY or WEEKDAY (and so on). In particular, the specification REFRESH [ON] EVERY UPDATE means the snapshot is kept permanently in synch with the relvar(s) from which it is derived─which is presumably just what we want, in the case of Example 12. Now, in this section so far I’ve concentrated on Example 12 and “derived data.” However, the fact is that all forms of redundancy can be thought of as derived data: If x is redundant, then by definition x can be derived from something else in the database. (Limiting use of the term derived data to the kind of situation illustrated by Example 12 is thus misleading, and not recommended.) It follows that the foregoing analysis─in particular, the four different approaches to dealing with derived data─can be generalized to apply to all kinds of redundancy, at least in principle. Note in particular that the third and fourth of those approaches, using views and snapshots respectively, both constitute examples of what’s sometimes called controlled redundancy. Redundancy is said to be controlled if it does exist (and the user is aware of it), but the task of “propagating updates” to ensure that it never leads to any inconsistencies is managed by the system, not the user. Uncontrolled redundancy can be a problem, but controlled redundancy shouldn’t be. In fact, I want to go further─I want to say that while it’s probably impossible, and maybe not even desirable, to eliminate redundancy one hundred percent, any redundancy that isn’t eliminated ought at least to be controlled. In particular, we need support for snapshots. (Fortunately, many commercial products do now support snapshots, albeit under the deprecated name materialized views.)
REFINING THE DEFINITION I’ve deliberately left this section to the very end of the chapter (almost). Consider the shipments relvar SP, with its predicate Supplier SNO supplies part PNO in quantity QTY. Consider also the relation shown as the value of that relvar in Fig. 1.1 in Chapter 1. Observe that: a.
Two of the tuples in that relation are (S1,P5,100) and (S1,P6,100).
b.
Both of those tuples include (S1,100) as a subtuple. What do those two appearances of that subtuple mean? Well, the appearance in (S1,P5,100) means:
1.
Supplier S1 supplies some part in quantity 100.
(I’ve numbered this proposition─note that it is indeed a proposition─for purposes of future reference.) And the appearance in (S1,P6,100) means exactly the same thing! So don’t we have here a situation in which the database contains two distinct appearances of some tuple that represent the very same proposition? In other words, in accordance with the definition I gave in the introduction to this chapter, doesn’t the database contain some redundancy?
194
Chapter 15 / We Need More Science
Before I try to answer this question, I want to offer a simpler illustration of the same point. With reference again to Fig. 1.1, consider the six shipment (SP) tuples shown in that figure for supplier S1. Clearly, those tuples all contain the subtuple (S1), of degree one. And those six appearances of that subtuple all mean the same thing: 2.
Supplier S1 supplies some part in some quantity.
We could even take the argument one step further and consider the fact that every SP tuple─in fact, every possible tuple, no matter what attributes it has─always has the 0-tuple as a subtuple. Thus, the twelve “appearances” (if you see what I mean!) of that subtuple in the shipments relation of Fig. 1.1 all represent the following proposition: 3.
Some supplier supplies some part in some quantity.
So do we have redundancy on our hands here, or don’t we? Well, let me observe now that the foregoing propositions 1- 3 all involve some existential quantification. Here are slightly more formal versions of those propositions: 1.
There exists some part PNO such that supplier S1 supplies part PNO in quantity 100.
2.
There exists some part PNO such that there exists some quantity QTY such that supplier S1 supplies part PNO in quantity QTY.
3.
There exists some supplier SNO such that there exists some part PNO such that there exists some quantity QTY such that supplier SNO supplies part PNO in quantity QTY.
In these propositions, SNO in the third, QTY in the second and third, and PNO in all three aren’t parameters but what the logicians call bound variables, owing to the fact that they’re all “existentially quantified” by the phrase There exists some ... such that. Note: If you’re unfamiliar with these notions (viz., bound variables and existential quantification), you can find a tutorial treatment in SQL and Relational Theory. However, I think the present discussion should be easy enough to follow even if you don’t have any prior knowledge of such matters. In contrast to the foregoing, the propositions represented by tuples in the underlying relvar SP don’t involve any existential quantifiers. That’s because they’re all just instantiations of the relvar predicate (i.e., they’re all obtained just by substituting arguments for the parameters of that predicate), and that predicate in turn, which is as follows, involves no such quantifiers either: Supplier SNO supplies part PNO in quantity QTY. To summarize to this point, then, it looks as if the following observations apply: a.
What might be called the given propositions─the ones represented by tuples in the given relvars─are quantifier free. Aside: It might not be quite true to say the given propositions are always quantifier free; consider, e.g., a relvar with attributes WEIGHT and HEIGHT and predicate Some person has weight WEIGHT and height HEIGHT. However, we can effectively eliminate the quantifiers in such a situation by a process known as skolemization (after the logician T. A. Skolem). In the example, that process involves replacing the original predicate by a predicate of the form Person p has weight WEIGHT and height HEIGHT (where p denotes some person or persons unknown). This latter predicate is quantifier free. End of aside.
We Need More Science / Chapter 15
b.
195
By contrast, derived propositions─at least, derived propositions that correspond to tuples obtained by taking projections of tuples in the given relvars─do involve at least one existential quantifier.
Now, we surely don’t want to say our usual shipments relvar SP is intrinsically redundant (do we?). So it looks as if what we might want to say is something along the lines of: If the same proposition is represented twice, but that proposition is existentially quantified, then that repetition doesn’t count as redundancy. But wait a minute─what about the suppliers relvar S, with its FD {CITY} → {STATUS}? An argument exactly analogous to the foregoing would seem to suggest that, e.g., the tuple (London,20), which appears as a subtuple in two of the supplier tuples depicted in Fig. 1.1, represents the proposition: There exists some supplier SNO such that there exists some name SNAME such that supplier SNO is named SNAME, has status 20, and is located in city London. Clearly this proposition is existentially quantified; yet it’s represented twice, and we do want that repetition to count as redundancy. (As we know, relvar S isn’t in BCNF.) So what’s going on? As is so often the case, I believe the answer to this question can be found by taking a closer look at the predicates. First, recall from Chapter 13 that a predicate is simple if it involves no connectives, and conjunctive if it’s a set of other predicates connected by AND (and I’ll assume for present purposes that those other predicates are all simple ones). Now, the predicate for relvar SP, Supplier SNO supplies part PNO in quantity QTY, is simple in the foregoing sense. By contrast, the predicate for relvar S is conjunctive─it can be decomposed into a set of simple predicates. I can make this latter fact more immediately obvious by stating the predicate in the following slightly stilted but actually more logical form: Supplier SNO is named SNAME and Supplier SNO is located in city CITY and City CITY has status STATUS. It should be clear, then, given this version of the predicate, that: a.
Relvar S is subject to the nontrivial, irreducible JD R{SN,SC,CT}, where the names SN, SC, and CT denote the headings {SNO,SNAME}, {SNO,CITY}, and {CITY,STATUS}, respectively. (By contrast, the only JDs that hold in relvar SP are trivial ones, and SP is in 6NF. Relvar S, of course, isn’t even in BCNF.)
b.
Relvar S can therefore be nonloss decomposed in accordance with that JD. The predicates for the corresponding projections are as follows: SN:
Supplier SNO is named SNAME.
SC:
Supplier SNO is located in city CITY.
CT:
City CITY has status STATUS.
196
Chapter 15 / We Need More Science
These predicates aren’t existentially quantified, and so the corresponding propositions aren’t, either.21 c.
Relvar S certainly contains subtuples corresponding to SN, SC, and CT; however, those corresponding to SN and SC are never repeated because {SNO} is a key. By contrast, those corresponding to CT are repeated, at least potentially (as we know from Fig. 1.1), and such repetition does constitute redundancy.
With all of the foregoing by way of motivation, then, I offer the following as a putative “final” definition of what it means for a database to exhibit redundancy: n
Definition (“final” version): Let D be a database design; let DB be a database value (i.e., a set of values for the relvars mentioned in D) that conforms to D; and let p be a proposition not involving any existential quantification. If DB contains two or more distinct representations of p (either implicitly or implicitly), then DB contains, and D permits, redundancy.
Observe in particular that a database can still display redundancy by this definition, even if it fully conforms to The Principle of Orthogonal Design and all normalization principles. Note, however, that the definition still says if (not if and only if) a certain condition holds, then there’s redundancy; I’d like to replace that if by if and only if, but I don’t quite have the courage of my convictions here. Not yet. Be that as it may, let’s consider Examples 1-12 from earlier sections of this chapter and see what the implications are for those examples specifically. Please note carefully: For simplicity, I use the unqualified term proposition throughout the following analysis to mean a proposition that’s not existentially quantified. Examples 1-2 Both of these examples display redundancy because the proposition City SFO and state CA are the city and state for zip 94100 is represented twice. Example 3 Suppose two distinct tuples both contain the DATE value “Tuesday, January 18th, 2011”; then the database clearly displays redundancy because the proposition January 18th, 2011 is a Tuesday is represented twice, explicitly. In fact, there’s redundancy even if that DATE value appears just once! The reason is that even in that case, the proposition January 18th, 2011 is a Tuesday is represented both explicitly and implicitly, as a result of the fact that one part of the value, the day of the week (Tuesday, in the example), can be determined algorithmically from the rest of the value (January 18th, 2011, in the example). Example 4 Let employee E1 be represented in both relvar EMP and relvar PGMR. The corresponding propositions are E1 is an employee and E1 is a programmer. The former proposition is a logical consequence of the combination of the latter proposition together with the proposition All programmers are employees. (Note that this latter proposition is represented, in effect, by the fact that {ENO} in PGMR is a foreign key referencing {ENO} in EMP.) Thus, the proposition E1 is an employee is represented twice, once explicitly and once implicitly.
21 In connection with the lack of quantification in the predicate for CT in particular, you might want to take another look at the section “Normalization Serves Two Purposes” in Chapter 3.
We Need More Science / Chapter 15
197
Example 5 Let employee E1 be represented in relvar EMP and let the JOB value for E1 be “Programmer” (so employee E1 is represented in relvar PGMR as well). Then the proposition E1 is a programmer is clearly represented explicitly in two different ways. Example 6 For a supplier who does have at least one of the three properties (name, status, and city), this example is essentially the same as Example 4, mutatis mutandis. (For a supplier with none of those properties, there’s no redundancy.) Example 7 The proposition Employee E5 is in department D3 is represented both explicitly by a tuple in EMPDEPT and implicitly by the combination of (a) the proposition Every employee is in exactly one department (which is effectively represented by the pertinent foreign key definition) and (b) the lack of tuples in EMPDEPT representing the propositions Employee E5 is in department D1 and Employee E5 is in department D2. Example 8 The proposition Employee E4 is unsalaried is represented both explicitly by a tuple in UNSALARIED and implicitly by the combination of (a) the proposition Every employee has a known salary or an unknown salary or is unsalaried (which should again represented by a certain declared integrity constraint) and (b) the lack of a tuple for employee E4 in either EARNS or SALARY_UNK. Example 9 Now this is an interesting one. Earlier, I said the following: The redundancies ... are obvious: For example, the fact that student S1 is enrolled in course C1, the fact that course C1 is tutored by tutor T1, and the fact that tutor T1 tutors student S1 are all represented more than once in the sample value shown in [Fig. 15.7].
I also said the predicate was Tutor TNO tutors student SNO on course CNO. But if the redundancies really are as stated, the predicate can’t be quite that simple. Instead, it has to be something like this: Student SNO is enrolled in course CNO and Course CNO is tutored by tutor TNO and Tutor TNO tutors student SNO and Tutor TNO tutors student SNO on course CNO. A more complete design would thus involve relvars as follows: n
S {SNO,...}, C {CNO,...}, and T {TNO,...}, representing students, courses, and teachers, respectively
n
SC {SNO,CNO,...}, CT {CNO,TNO,...}, and TS {TNO,SNO,...}, showing which students are enrolled in which courses, which courses are tutored by which tutors, and which tutors tutor which students, respectively
198
n
Chapter 15 / We Need More Science
SCT {SNO,CNO,TNO}, as in the original version of the example Observe now that:
1.
Relvar SC is equal to some subset of the join (actually the cartesian product) of S{SNO} and C{CNO} (and similarly for CT and TS).
2.
Relvar SC is also equal to the projection of SCT on {SNO,CNO} (and, again, similarly for CT and TS). Note: To be more precise about the matter, SC is equal to SCT projected on {SNO,CNO} if and only if no student can be enrolled in a course without being assigned a tutor for that course (and, once again, similarly for CT and TS). So we’re making some semantic assumptions about the situation here, assumptions that weren’t spelled out originally and might or might not be valid.
3.
Relvar SCT is also equal to some subset of the join of SC, CT, and TS, and that join in turn is some subset of the join (actually the cartesian product) of S{SNO}, C{CNO}, and T{TNO}.
Because of point 2 in particular, SC, CT, and TS can be dropped, as indeed they were in the original version of the example. Assume for the moment, however, that they aren’t dropped. Then there’s clearly redundancy. For example, given the sample values from Fig. 15.7, the proposition Student S1 is enrolled in course C1 is represented (a) by an explicit tuple in relvar SC and also (b) as one of the conjuncts in the following proposition, which is represented by an explicit tuple in relvar SCT: Student S1 is enrolled in course C1 and Course C1 is tutored by tutor T1 and Tutor T1 tutors student S1 and Tutor T1 tutors student S1 on course C1. Even if relvar SC is dropped, however, I claim there’s still redundancy! For example, that same proposition Student S1 is enrolled in course C1 is represented as one of the conjuncts in the foregoing compound proposition and as one of the conjuncts in the following (also compound) proposition: Student S1 is enrolled in course C1 and Course C1 is tutored by tutor T2 and Tutor T2 tutors student S1 and Tutor T2 tutors student S1 on course C1. Both of these compound propositions are represented by explicit tuples in relvar SCT. Thus, although my earlier characterization of the redundancies in this example might perhaps have been slightly misleading, I claim that redundancy does nevertheless exist. What’s more, if you agree with this position, I think you also have to agree that the use of either surrogates (see the discussion of the current example, Example 9, earlier in the chapter) or relation valued attributes (see the discussion of Example 10, also earlier in the chapter) makes no difference! That is, it’s still the case, with both surrogates and RVAs, that certain propositions are represented more than once, in general. Now, I admit this latter claim on my part might be somewhat open to debate. However, if you don’t agree with it, then I think you need to justify your position rather carefully, and in particular I think you need to come up with a replacement for─in fact, an improvement on─my proposed “final” definition of redundancy. As a kind of appendix to all of the above, let me add that I believe a similar analysis applies to certain other examples from earlier in the book. For example, consider relvar CTXD from Chapters 9 and 12, with its attributes
We Need More Science / Chapter 15
199
CNO, TNO, XNO, and DAYS. When I first introduced that example, I said the predicate was Teacher TNO spends DAYS days with textbook XNO on course CNO. But it would be more accurate to say it’s as follows: Course CNO can be taught by teacher TNO and Course CNO uses textbook XNO and Teacher TNO spends DAYS days with textbook XNO on course CNO. Similarly, consider relvar SPJ from Chapters 9 and 10, with its attributes SNO, PNO, and JNO. When I first introduced that example, I said the predicate was Supplier SNO supplies part PNO to project JNO. However, I think it would be more accurate to say it’s as follows: Supplier SNO supplies part PNO and Part PNO is supplied to project JNO and Project JNO is supplied by supplier SNO and Supplier SNO supplies part PNO to project JNO. To continue with this last example just a moment longer: As we know from Chapter 10, SPJ isn’t in 5NF, and the recommendation is therefore to decompose it into its “projection” relvars SP, PJ, and JS, with headings {SNO,PNO}, {PNO,JNO}, and {JNO,SNO}, respectively. But what are the predicates for these three relvars? The answer depends on what I referred to in Chapter 9 (in a footnote) as the full semantics of the situation. Consider relvar SP, for example. If it’s possible for a tuple (s,p) to appear in SP without a tuple for supplier s appearing in JS or without a tuple for part p appearing in PJ, then the predicate for SP is simply Supplier SNO supplies part PNO. But if the appearance of tuple (s,p) in SP means there must be both a tuple for supplier s in JS and a tuple for part p in PJ, then the predicate for SP is Supplier SNO supplies part PNO to some (unspecified) project JNO. Since the second of these possibilities is more constraining than the first, it seems to me it would be prudent to assume the first interpretation. Example 10 See the discussion of Example 9 above. Example 11 No further discussion provided. Example 12 Let C1 be a customer and let the sum of payments for customer C1 be (say) $10,000. Then this very proposition─The sum of payments for customer C1 is $10,000─is represented explicitly by the appearance of a tuple for customer C1 in relvar TOTALS and implicitly by the appearance of the set of tuples for that same customer in relvar PAYMENTS.
CONCLUDING REMARKS In view of the discussions of the previous section, let’s agree for simplicity that the only propositions we’re interested in are ones that aren’t existentially quantified. I’ve claimed in this chapter, then, that a database certainly involves redundancy if it contains two distinct representations of the same proposition. In particular, we don’t want
200
Chapter 15 / We Need More Science
the same tuple to appear in two different places if those two appearances represent the same proposition. (Obviously we’d like to prohibit duplicate propositions as such; unfortunately, however, the DBMS doesn’t understand propositions as such.) But it’s all right for the same tuple to appear twice if those two appearances don’t represent the same proposition─and in any case we can have redundancy without any tuple appearing twice at all, as we’ve seen. Normalization and orthogonality seem to be all we have by way of a scientific attack on the redundancy issue at the present time. Unfortunately, we’ve seen that normalization and orthogonality don’t solve the whole problem─they can reduce redundancy, but they can’t eliminate it entirely, in general. To be specific, we’ve seen several examples of designs that fully conform to the principles of normalization and orthogonality and yet display some redundancy, and those discussions were certainly far from exhaustive. We need more science! (Now I’ve told you that at least three times, and what I tell you three times is true.) Given the foregoing state of affairs, it seems that redundancy will definitely exist in most databases. If it does: n
It should at least be controlled, in the sense that the DBMS should take responsibility for guaranteeing that it never leads to inconsistency.
n
If it can’t be controlled, then appropriate constraints should at least be declared, and enforced by the system, to ensure (again) that it never leads to inconsistency.
n
If it can’t be controlled and constraints can’t be enforced by the system (or perhaps can’t even be formally declared), then you’re on your own─and woe betide you if you make any mistakes.
Sadly, this last scenario is the one most likely to obtain in practice, given the state of today’s commercial implementations.
EXERCISES 15.1 I claimed in the body of the chapter that if proposition p involves no existential quantification and database DB contains (either explicitly or implicitly) two or more distinct representations of p, then DB contains some redundancy. Can you think of a database that doesn’t contain two or more distinct representations of any such proposition (either explicitly or implicitly) and yet in your opinion still displays some redundancy?
APPENDIXES
Appendix A
Primary Keys Are Nice but Not Essential Life is rather like a tin of sardines─ we’re all of us looking for the key ─Alan Bennett: Beyond the Fringe
Note: Portions of this appendix originally appeared in somewhat different form in my book Relational Database Writings 1991-1994 (Addison-Wesley, 1995). Recall this text from Chapter 1: I said it’s usual to choose a primary key. Indeed it is usual─but it’s not 100 percent necessary. If there’s just one candidate key, then there’s no choice and no problem; but if there are two or more, then having to choose one and make it primary smacks a little bit of arbitrariness, at least to me. (Certainly there are situations where there don’t seem to be any good reasons for making such a choice. There might even be good reasons for not doing so. Appendix A [i.e., the present appendix] elaborates on such matters.)
Now, the position articulated in this extract clearly flies in the face of conventional wisdom, somewhat; it might even be said to contravene certain widely accepted precepts of the relational model, or of relational theory in general. To be specific: n
Out of the (necessarily nonempty) set of keys possessed by a given relvar, the relational model as originally defined ascribes a primal role to an arbitrarily chosen member of that set called the primary key.
n
Relational design methodologies (though not the relational model per se) tend to suggest, again a trifle arbitrarily, that a given “entity” should be identified and referenced throughout the database by the same (primary) key value everywhere it’s represented.
As indicated, however, these recommendations─some might even call them prescriptions─both involve a certain degree of arbitrariness. The first in particular has always been the source of some slight embarrassment to relational advocates (myself included). One of the strongest arguments in favor of the relational model is and always has been its claim to a solid logical foundation. However, whereas this claim is clearly justified for the most part, the distinction between primary and alternate keys1─i.e., the idea of having to choose one member from a set of equals and make it somehow “more equal than the others”─has always seemed to rest on grounds that don’t enjoy the same degree of theoretical respectability. Certainly there doesn’t seem to be any formal justification for the distinction; it seems to smack more of dogma than logic, which is why (as I said) I find the situation embarrassing. 1 The term alternate key was defined in Chapter 1, but I repeat the definition here for convenience: Let relvar R have two or more keys and let one be chosen as primary; then the others are alternate keys. The term isn’t used much in practice, but I do need to use it in this appendix.
204
Appendix A / Primary Keys Are Nice but Not Essential
This appendix grew out of my own increasing dissatisfaction with the seeming lack of solid justification for the orthodox relational position on these matters. (As a friend of mine once put it, these are the areas where in live presentations “you talk quickly and hope no one will notice.”) What’s more, not only does there seem to be no formal justification for the primary vs. alternate key distinction, there doesn’t seem to be any formal way of making the choice, either. Indeed, Codd himself is on record as saying “The normal basis [for making the choice] is simplicity, but this aspect is outside the scope of the relational model” (my italics).2 But why should it be necessary to make the choice in the first place?─i.e., why, in those cases where a genuine choice does exist, is it necessary, or desirable, to introduce such an element of arbitrariness? Furthermore, the relational model as originally defined goes on to insist that all references via foreign keys, anywhere in the database, to (tuples in) a given relvar must always be via that relvar’s primary key specifically, never via some alternate key. Thus we see that a decision that was essentially arbitrary in the first place─the choice of which key is to be primary─can lead to arbitrary restrictions on subsequent decisions as well; that is, it might constrain the set of decisions as to what can and can’t be a legal foreign key, in ways that might not have been foreseen when that first decision (i.e., the primary key decision) was made. I claim, then, that the idea that a distinction (hereinafter referred to as the PK:AK distinction) should be made, in the relational model as such, between primary and alternate keys introduces an unpleasant note of arbitrariness, artificiality, awkwardness, and asymmetry into what is otherwise a formally defined system (i.e., the relational model itself). I claim further that it can also serve to introduce an unpleasant degree of arbitrariness, artificiality, awkwardness, and asymmetry into the database. And I claim still further that it can also lead to an undesirable and unnecessary distinction between base and derived relvars, as I’ll show. All of that being so, can the PK:AK distinction truly be justified? This appendix offers what I consider to be strong arguments in support of the position that the answer to this question must be no.
ARGUMENTS IN DEFENSE OF THE PK:AK DISTINCTION Before I consider consequences of the PK:AK distinction in detail, I should first examine the arguments in its defense. Since I’m on record as a defender of that distinction myself,3 perhaps I should begin by summarizing, and with hindsight responding to, my own arguments! The principal ones were as follows: 1.
Dropping the PK:AK distinction would imply among other things that the entity integrity rule would have to be extended to apply to all candidate keys (all candidate keys in base relvars, at any rate).
As I expect you know, the entity integrity rule is a rule to the effect that attributes participating in the primary key of a base relvar don’t allow nulls. Now, I’ve argued for a long time that this rule should be dropped anyway, partly because it has to do with nulls (a concept I categorically reject), and partly because it draws a distinction between base and other relvars and thereby violates The Principle of Interchangeability of base relvars and views. (In case you’re unfamiliar with this latter principle, it basically just says there shouldn’t be any unnecessary distinctions between base relvars and views─views should “look and feel” to the user just like base relvars.) Thus, I now find this first argument in favor of the PK:AK distinction to be irrelevant.
2
3
The quote is from Codd’s paper “Domains, Keys, and Referential Integrity in Relational Databases” (InfoDB 3, No. 1, Spring 1988).
In “Why Every Relation [sic] Should Have Exactly One Primary Key,” in Relational Database: Selected Writings (Addison-Wesley, 1986); “Referential Integrity and Foreign Keys,” in Relational Database Writings 1985-1989 (Addison-Wesley, 1990); and elsewhere.
Primary Keys Are Nice but Not Essential / Appendix A
2.
205
The discipline of using the same symbol to identify a given entity everywhere it’s referenced allows the system to recognize the fact that those references do all refer to the same thing.
This argument is clearly valid as far as it goes, but I now feel the discipline referred to should be treated as an informal guideline rather than a hard and fast requirement. See the discussions later in this appendix─in particular, the applicants and employees example─for examples of situations in which it might be desirable not to follow such a guideline in practice. In any case, the guideline in question really has to do with design (in other words, with how to apply the relational model in some specific situation), not with the relational model as such; in particular, therefore, it has nothing to do with whether the relational model as such should insist on primary keys. I must have been a little confused when I advanced this argument originally. 3.
“Metaqueries”─i.e., queries against the catalog─can be more difficult to formulate if entities are identified in different ways in different places. For example, consider what’s involved in formulating the metaquery “Which relvars refer to employees?” if employees are referred to sometimes by employee number and sometimes by social security number.
The idea here is basically that the discipline referred to under point 2 above can be beneficial for the user as well as the system. Again, however, it seems to me that we’re really talking about informal guidelines, not absolute requirements. 4.
My next point wasn’t exactly an argument for the PK:AK distinction, but rather a criticism of an argument against it. This latter argument went as follows: Suppose some user is prevented, for security reasons, from seeing some primary key; then that user needs access to the data by some alternate key instead; so why make the PK:AK distinction in the first place?
I still don’t find “this latter argument” very convincing, but of course criticizing an argument against some position doesn’t prove the contrary position is correct! 5.
My final point was an appeal to Occam’s Razor (“concepts should not be multiplied beyond necessity”). In effect, I was arguing that to treat all candidate keys as equals was to complicate the relational model’s tuple level addressing scheme unnecessarily. But it might well be argued (and now I would argue) that Occam’s Razor actually applies the other way around, and that it’s the concepts of primary key and alternate key that are unnecessary!─i.e., all we really need is candidate keys, or in other words just keys tout court.
In a nutshell, the foregoing arguments no longer seem to me very compelling; the only one that still appears to have any validity is the one summarized under points 2 and 3 above, which (as I’ve said) isn’t really an argument for making the PK:AK distinction in the relational model as such, anyway. As I’ve also said, I now feel the position supported by that particular argument should be seen more as a guideline than as an inviolable rule (again, see later for examples to justify this position). I note in passing, though, that I did hedge my bets somewhat in my original paper ... Here’s another extract (I’ve reworded it just slightly here): Note that if we can agree on retaining the PK:AK distinction for now, there’s always the possibility of eliminating that distinction if desirable at some future time. And note moreover that this argument doesn’t apply in the opposite direction: Once we’re committed to treating all candidate keys equally, a system that requires a distinguished primary key will forever be nonstandard.
206
Appendix A / Primary Keys Are Nice but Not Essential
Although I didn’t say as much at the time, this quote effectively constitutes an appeal to The Principle of Cautious Design, a principle I do still strongly believe in.4 Indeed, it seems to me the very fact that I’m able to shift my position on the PK:AK distinction now─which is indeed what I’m doing─can be regarded as a vindication of that principle. Before closing this section, I remark that Codd himself is also on record, in the same paper where he said there was no formal basis for choosing the primary key, as a defender of the PK:AK distinction (not surprisingly, since he originated it): Severe problems would arise ... if any relvar whatsoever were permitted to have more than one primary key [sic] ... The consequences of permitting more than one primary key ... for a single base relvar [would be] disastrous.
(I’ve taken the liberty of replacing the term relation by the term relvar twice in this extract.) And he goes on to give an example involving employees with “several distinct responsibilities”─project management, department management, inventory management, etc.─and then he says: Comparing for equality of identifiers ... is intended to establish that one and the same employee is involved ... This objective is dealt a severe blow if the types of identifiers used for employees can be different depending on which pair of employee-identifying [attributes] is selected for the comparison.
Well, I think you can see this argument is essentially the same as the one given under points 2 and 3 above, which (a) as I’ve already indicated, is slightly confused, and (b) as we’ll see later in this appendix, doesn’t fully stand up under close scrutiny anyway.
RELVARS WITH MORE THAN ONE KEY Now let’s consider some reasonably realistic examples of relvars with more than one key. The first concerns a relvar EXAM, with attributes S (student), J (subject), and P (position), and predicate Student S was examined in subject J and achieved position P in the class list. For the sake of the example, let’s assume there are no ties (that is, no two students obtained the same position in the same subject). Then, clearly, given a student and subject, there’s exactly one corresponding position; equally, given a subject and position, there’s exactly one corresponding student. So the FDs {S,J} → {P} and {J,P} → {S} both hold, and {S,J} and {J,P} are both keys (or candidate keys, if you prefer): EXAM { S , J , P } KEY { S , J } KEY { J , P } Here’s another example (it’s basically Exercise 13.6 from Chapter 13): We’re given a relvar representing marriages, with attributes A, B, and C and predicate Person A married person B on date C. Assuming no polygamy, and assuming also that no two persons marry each other more than once, every pair of attributes here is a key: MARRIAGE { A KEY KEY KEY 4
, { { {
B A B C
, , , ,
C B C A
} } } }
The Principle of Cautious Design says: Given a design choice between options A and B, where A is upward compatible with B and the full implications of B aren’t yet known, the cautious decision is to go with A.
Primary Keys Are Nice but Not Essential / Appendix A
207
And here’s yet another example, based on a simple airline application (the predicate is Pilot PILOT takes a flight out from gate GATE at hour HOUR on day DAY): ROSTER { DAY , HOUR , GATE , PILOT } KEY { DAY , HOUR , GATE } KEY { DAY , HOUR , PILOT } How do we choose the primary key in cases such as these? What grounds are there for choosing one key over another? Codd’s criterion of “simplicity” doesn’t seem to help. Note too that whichever we choose, we wind up with an unpleasant asymmetry; e.g., in the marriage example, we might find ourselves treating one spouse as “more equal than the other” (and thereby certainly offending someone). Why should we be forced to introduce such asymmetry? Asymmetry is usually not a good idea. Here again, repeated from Chapter 15, is that quote from Polya: “Try to treat symmetrically what is symmetrical, and do not destroy wantonly any natural symmetry.” Now, in all of the foregoing examples the keys were not only composite, they overlapped (i.e., they had an attribute in common). Lest it be thought that it’s only when keys overlap that there might be difficulty in choosing the primary key, therefore, let me give a counterexample. Suppose we have a relvar ELEMENT representing the periodic table (i.e., the table of of chemical elements).5 Then every element has a unique name (e.g., lead), a unique symbol (e.g., the symbol for lead is Pb), and a unique atomic number (e.g., the atomic number for lead is 82) . The relvar thus clearly has three distinct keys, all of which are simple (i.e., involve just one attribute), and there’s obviously no overlap at all. On what grounds do we choose one of these three keys as the primary key? It seems to me a good case could be made for any of them, depending on circumstances. Here’s another familiar (perhaps all too familiar) example of a relvar with several keys, all of which are simple: TAX_BRACKET { LOW KEY { KEY { KEY {
, HIGH , PERCENTAGE } LOW } HIGH } PERCENTAGE }
Of course, I’m assuming here that no two taxable income ranges (LOW to HIGH) are subject to the same tax rate. I could give many more examples, but by now my point is presumably clear: Not only are there no formal criteria for choosing one key over another (in those cases where there’s a choice), but sometimes there don’t appear to be any informal criteria either. Thus, it really doesn’t seem appropriate to insist that such a choice must always be made, even if it’s appropriate in some cases (perhaps even most cases). There’s another important point that needs to be mentioned, a more formal one than most of those I’ve been making so far. Over the past 40 years or so, a great deal of research has been carried out on dependency theory and further normalization, view updating, optimization (including semantic optimization in particular), usability, and many other matters. And in all of this research it’s candidate keys, not primary keys, that play the crucial role. (Indeed, it must be, precisely because the research in question is formal. The candidate key concept is formally defined. The primary key concept isn’t.) Since this is so, it really doesn’t seem appropriate to insist formally on the PK:AK distinction─though, to repeat, it might be appropriate to recommend it informally. Yet another point I want to make is that the PK:AK distinction leads to an undesirable and unnecessary differentiation between base relvars and other relvars. That’s because, according to Codd, the relational model:
5 Like the PLUS example (q.v.) in Chapter 13, ELEMENT might actually be a relation constant rather than a relation variable, but it still has keys.
208
Appendix A / Primary Keys Are Nice but Not Essential
n
Requires primary keys for base relvars;
n
Permits but does not require them for views and snapshots; and
n
Considers it “completely unnecessary for primary keys to be declared or deduced” for any other relvars (italics in the original).
These statements are paraphrased (but only slightly) from the paper in which Codd said there was no formal basis for choosing the primary key (see earlier in this appendix). As a matter of fact, that paper goes so far as to suggest that relvars other than base ones might not even possess a primary key, a suggestion that if true surely raises serious questions about the concept in the first place─remember The Principle of Interchangeability (of base relvars and views). Be that as it may, my position on these matters is rather different. To be specific, I would say: n
First, every relvar, base or derived, does have at least one key (because, of course, no relation, and a fortiori no relvar, ever permits duplicate tuples).
n
Second, every base relvar must have at least one key explicitly declared. Preferably, of course, all such keys should be explicitly declared.
n
Often a base relvar will have an explicitly declared primary key in particular, but I don’t insist on this state of affairs as a hard requirement.
n
For reasons explained in detail in SQL and Relational Theory, I believe the system should be able to deduce keys for derived relvars.
n
The previous point notwithstanding, I believe it should also be possible to declare keys for derived relvars (for views and snapshots in particular). Again, see SQL and Relational Theory for further discussion.
THE INVOICES AND SHIPMENTS EXAMPLE I now turn my attention to a more elaborate example. The example─which is based on a real world application, incidentally─concerns invoices and shipments, and there’s a one to one relationship between these two entity types: Each shipment has exactly one invoice, each invoice has exactly one shipment. Here then is the “obvious” database design (for the sake of the example, I use a hypothetical syntax that explicitly distinguishes between primary and alternate keys):6 INVOICE
{ INVNO , SHIPNO , INV_DETAILS } PRIMARY KEY { INVNO } ALTERNATE KEY { SHIPNO } FOREIGN KEY { SHIPNO } REFERENCES SHIPMENT
6 One reviewer asked why a design consisting of three relvars (one each for invoices and shipments and one for the association between them) wasn’t the “obvious” design. Well, it’s probably a better design, and it might be the obvious one. But that association relvar still has two keys (INVNO and SHIPNO), and the major conclusion of the argument that follows─viz., that those two keys need to be treated as equals─still stands.
Primary Keys Are Nice but Not Essential / Appendix A
209
SHIPMENT { SHIPNO , INVNO , SHIP_DETAILS } PRIMARY KEY { SHIPNO } ALTERNATE KEY { INVNO } FOREIGN KEY { INVNO } REFERENCES INVOICE So the database structure is as shown in Fig. A.1 (note that the arrows in that figure, in contrast to arrows in figures elsewhere in this book, represent foreign key references, not functional dependencies): ┌──────────────────────────────────────┐ ┌───▼───┬────────┬──────┐ ┌────────┬───┼───┬─────┐ │ INVNO │ SHIPNO │ ... │ │ SHIPNO │ INVNO │ ... │ └═══════┴────┼───┴──────┘ └════▲═══┴───────┴─────┘ SHIPMENT └─────────────────────┘ INVOICE Fig. A.1: The invoices-and-shipments database
Now, each relvar in this example actually has two keys, {INVNO} and {SHIPNO}. However, I assume we can agree for the sake of argument that the “natural” primary key for INVOICE is {INVNO} and the “natural” primary key for SHIPMENT is {SHIPNO}; then {SHIPNO} in INVOICE and {INVNO} in SHIPMENT are alternate keys. Furthermore, of course, each of those alternate keys is also a foreign key (as Fig. A.1 indicates), referring to the primary key of the other relvar. One problem with the foregoing design is as follows. Clearly, the database is subject to the constraint─actually it’s an equality dependency, and I’ll call it C─that if the INVOICE relvar shows invoice i as corresponding to shipment s, then the SHIPMENT relvar must show shipment s as corresponding to invoice i (and vice versa):7 CONSTRAINT C INVOICE { INVNO , SHIPNO } = SHIPMENT { INVNO , SHIPNO } ; In other words, the tuple (i,s,...) appears in INVOICE if and only if the tuple (s,i,...) appears in SHIPMENT. But the design of Fig. A.1 doesn’t capture or enforce this constraint (for example, the configuration of values shown in Fig. A.2 below is permitted by that design and yet violates the constraint). The constraint thus needs to be separately stated (as above) and separately enforced. INVOICE ┌───────┬────────┬─────┐ │ INVNO │ SHIPNO │ ... │ ├═══════┼────────┼─────┤ │ i1 │ s1 │ ... │ │ i2 │ s2 │ ... │ └───────┴────────┴─────┘
SHIPMENT ┌────────┬───────┬─────┐ │ SHIPNO │ INVNO │ ... │ ├════════┼───────┼─────┤ │ s1 │ i2 │ │ │ s2 │ i1 │ │ └────────┴───────┴─────┘
Fig. A 2: “Legal” INVOICE and SHIPMENT values that violate constraint C
Aside: It might be thought that if we pretended the primary key for each relvar was the combination {INVNO,SHIPNO}, and if we further defined each of those fake “primary keys” to be a foreign key referencing the other, then constraint C would be taken care of automatically.8 But the relational model
7
Observe, therefore, that the design violates orthogonality (see Chapter 14).
8
I’ve actually seen such a subterfuge explicitly recommended, by people who really ought to know better.
210
Appendix A / Primary Keys Are Nice but Not Essential
requires primary keys─in fact, keys in general─to be irreducible, meaning they mustn’t contain any attributes that are irrelevant for unique identification purposes (and there are good reasons for that requirement, too, as we know from Chapter 4). In other words, {INVNO,SHIPNO} just isn’t a key (and so it certainly can’t be the primary key) for either relvar, and we’d be lying if we told the system otherwise. Indeed, if {INVNO,SHIPNO} were truly a key, then the relationship between invoices and shipments would be many to many, which it isn’t. End of aside. Precisely because constraint C holds, the design of Fig. A.1 clearly involves some redundancy: Every pair of {INVNO,SHIPNO} values appearing in either relvar also necessarily appears in the other. Now, we could avoid that redundancy by combining the two relvars into one: INV_SHIP { INVNO , SHIPNO , INV_DETAILS , SHIP_DETAILS } PRIMARY KEY { INVNO } ALTERNATE KEY { SHIPNO } By eliminating the redundancy in this way, we’ve also eliminated the need to state and enforce constraint C. Furthermore, we could now define the original INVOICE and SHIPMENT relvars as views─specifically, projection views─of INV_SHIP, thus allowing the user still to regard invoices and shipments as distinct entities.9 This revised design thus does enjoy certain advantages over the “obvious” version. On the other hand, there are some disadvantages, too. Observe first that we’ve had to make an asymmetric decision once again, choosing {INVNO} over {SHIPNO}─arbitrarily─as the primary key for relvar INV_SHIP. Second, suppose further that shipments have certain subsidiary information that invoices don’t; e.g., suppose shipments are containerized, each shipment involving several containers. Then a new CONTAINER relvar is needed: CONTAINER { CONTNO , SHIPNO , ... } PRIMARY KEY { CONTNO } FOREIGN KEY { SHIPNO } REFERENCES INV_SHIP { SHIPNO } And now we have a foreign key referencing an alternate key!─which is prohibited by the relational model as originally defined, as we know. Now, can we avoid this apparent violation of the prescriptions of the original model? Well, of course, the answer is yes. There are various ways in which this might be done: 1.
We could go back to the two-relvar design (thereby reintroducing the data redundancy and the need for the additional constraint, however).
2.
We could replace SHIPNO by INVNO in the CONTAINER relvar. However, this approach seems very artificial (containers have nothing to do with invoices per se), and moreover introduces an unpleasant level of indirection into the design (the shipment for a given container would be accessible only via the corresponding invoice).
3.
We could leave the CONTAINER relvar as it is, but replace the foreign key specification by an explicit declaration to the effect that every SHIPNO value in CONTAINER must also appear in INV_SHIP (using a language like SQL or Tutorial D that permits the definition of arbitrarily complex constraints). But it does
9 There might be some difficulty over updating those views, of course, given the state of today’s commercial products. But this is a separate issue, beyond the scope of this appendix (and this book).
Primary Keys Are Nice but Not Essential / Appendix A
211
seem a pity to have to deal with a constraint that’s so similar to a “true” foreign key constraint in such a roundabout manner; indeed, it could be argued that the effect is again to introduce an undesirable asymmetry, foreign keys that reference primary keys being treated in one manner and “foreign keys” that reference alternate keys being treated in quite another. 4.
We could introduce a surrogate primary key ({ISNO}, say) for INV_SHIP, and use that as the foreign key in the CONTAINER table─which would still involve a level of indirection, as in paragraph 2 above, but would at least reintroduce the symmetry that was lost when we arbitrarily chose {INVNO} as the primary key for INV_SHIP.
To summarize: None of these four “workaround” approaches seems totally satisfactory. The example thus seems to show that─if we wish to avoid redundancy and arbitrariness and artificiality and asymmetry and indirectness─then we need to be able to treat primary and alternate keys as equals, and we need to be able to have foreign keys that reference alternate keys. In other words, we need to ignore the differences between primary and alternate keys, and simply consider them all as just keys. Please note carefully, however, that I’m not saying the apparent need in this example to violate certain precepts of the original relational model can’t be avoided; what I’m saying is I don’t see a good way to avoid it, nor a good reason for adopting a bad way. I would therefore like to suggest that the precepts in question be treated as strong (?) guidelines but not as inviolable rules.
ONE PRIMARY KEY PER ENTITY TYPE? I turn now to the second of the two issues mentioned in the introduction to this appendix: viz., that entities of a given type are supposed to be identified in exactly the same way everywhere in the database. What this means, loosely speaking, is that there’ll typically be: n
A single “anchor” relvar for the pertinent entity type, having some particular primary key, together with
n
Zero or more subsidiary relvars giving further information about entities of that type, each having a foreign key that refers back to the primary key of that anchor relvar.
(Does this state of affairs remind you of the RM/T discipline discussed in Chapter 15?) But several obvious questions arise: n
Might there not be good reasons to have more than one anchor relvar for a given entity type─perhaps corresponding to different “roles” (see the section immediately following) for that entity type?
n
If there are several such anchor relvars, might there not be good reasons to have different primary keys in different anchor relvars─thus implying that the same entity might be identified in different ways in different contexts?
n
Hence, might there not be good reasons to have different foreign keys in different relvars that, again, identify the same entity in different ways in different contexts?
212
n
Appendix A / Primary Keys Are Nice but Not Essential
Finally, might there not even be good reasons to have several distinct identifiers, all of equal weight, for the same entity in the same relvar?
We’ve already seen several examples in this appendix (in the section “Relvars with More than One Key”) in which the answer to the last of these questions is clearly yes. In order to examine the other questions, let’s consider another example.
THE APPLICANTS AND EMPLOYEES EXAMPLE This example (which, like the invoices and shipments example, is based on a real world application) concerns applicants for jobs in a certain enterprise. Relvar APPLICANT is used to keep a record of such applicants: APPLICANT { ANO , NAME , ADDR , ... } PRIMARY KEY { ANO } The applicant number (ANO) is assigned at the time the applicant applies for the job; it’s unique to the applicant, and {ANO} thus constitutes the obvious primary key (in fact, it’s the only key). Next, several further relvars are used to keep subsidiary applicant information (previous jobs held, list of references, list of dependants, etc.). I consider just one of these here, the “previous jobs held” relvar (APPLICANT_JOBS): APPLICANT_JOBS { ANO , EMPLOYER , JOB , START , END , ... } PRIMARY KEY { ANO , START } ALTERNATE KEY { ANO , END } FOREIGN KEY { ANO } REFERENCES APPLICANT Observe, incidentally, that once again we seem to be faced with an arbitrary choice of primary key, but that’s not the point I want to examine here. Now, when a job applicant is successful, he or she is assigned an employee number (ENO, unique to the employee), and information regarding the new employee─job title, department number, phone number, etc.─is recorded in an EMP relvar: EMP { ENO , JOB , DNO , PHONENO , ... } PRIMARY KEY { ENO } Now we have two distinct anchor relvars, APPLICANT and EMP, such that the very same entity (i.e., a successful applicant) is identified by an ANO value in one of the two and by an ENO value in the other. Of course, it’s true that the two relvars represent different roles─a tuple in APPLICANT represents a person in an applicant role and the corresponding tuple in EMP (if there is one) represents the same person in an employee role─but the fact remains that there’s just a single entity involved. The foregoing isn’t the end of the story. Clearly, relvar EMP needs to refer back to relvar APPLICANT somehow (I’m assuming for simplicity, though the assumption might be a little unrealistic, that every employee was once an applicant). Thus, we need to add an ANO attribute to the EMP relvar and define a foreign key accordingly: EMP { ENO , ANO , PRIMARY KEY { ALTERNATE KEY FOREIGN KEY {
JOB , DNO , PHONENO , ... } ENO } { ANO } ANO } REFERENCES APPLICANT
Primary Keys Are Nice but Not Essential / Appendix A
213
Now we have two candidate keys once again!─namely, {ENO} and {ANO}. This point will be relevant in a few moments; for now, however, I’ll ignore it. Next, of course, we’ll need additional relvars to carry subsidiary information for employees (salary history, benefit details, etc.). Here’s the salary history relvar: SAL_HIST { ENO , DATE , SALARY , ... } PRIMARY KEY { ENO , DATE } FOREIGN KEY { ENO } REFERENCES EMP Now we have the very same entity being not only identified, but also referenced, by an ENO value in one relvar (SAL_HIST) and by an ANO value in others (APPLICANT_JOBS, EMP). In other words, the database structure is as shown in Fig. A.3. ┌────────────────────────────┐ ┌──▼──┬─────┐ ┌─────┬──┼──┬─────┐ APPLICANT │ ANO │ ... │ EMP │ ENO │ ANO │ ... │ └══▲══┴─────┘ └══▲══┴─────┴─────┘ │ │ ┌──┼──┬─────┐ ┌──┼──┬─────┐ APPLICANT │ ANO │ ... │ SAL_ │ ENO │ ... │ HIST └═════┴─────┘ _JOBS └═════┴─────┘ Fig. A.3: The applicants-and-employees database
Now, we might avoid the apparent need for two different identifiers (ANO and ENO) for the same entity type by regarding EMP as a subtype of APPLICANT; after all, every employee is an applicant (loosely speaking), while the converse isn’t true. In this way we could use {ANO} as the primary key for EMP, treating {ENO} as an alternate key (or even dropping it altogether), and replace ENO by ANO in the SAL_HIST relvar. The database structure is now as shown in Fig. A.4: ┌──────────────────────┐ ┌──▼──┬─────┐ ┌──┼──┬─────┐ APPLICANT │ ANO │ ... │ EMP │ ANO │ ... │ └══▲══┴─────┘ └══▲══┴─────┘ │ │ ┌──┼──┬─────┐ ┌──┼──┬─────┐ APPLICANT │ ANO │ ... │ SAL_ │ ANO │ ... │ _JOBS └═════┴─────┘ HIST └═════┴─────┘ Fig. A.4: Using {ANO} as the primary key for EMP
However, note the implications of this state of affairs: It’s not just the database design that’s changed, it’s the way the enterprise has to operate. (For a start, it now has to identify employees by applicant number instead of employee number.) Why should the enterprise change its way of doing business, just because of a piece of relational dogma (“one primary key per entity type”)? To be specific, why shouldn’t it be allowed to identify applicants by applicant number and employees by employee number─even though applicants and employees are all persons, and indeed every employee is (or once was) also an applicant? Aside: Another possibility would be to introduce a PERSON relvar and then regard both APPLICANT and EMPLOYEE as subtypes of PERSON. I leave the details as an exercise for the reader; I simply remark that this approach basically doesn’t solve anything, even if we invent a “person number” (PNO) and make
214
Appendix A / Primary Keys Are Nice but Not Essential
{PNO} the primary key of PERSON. On the other hand, I definitely would recommend the supertype/subtype approach when “the same” primary key is involved everywhere (e.g., if we were dealing with employees and programmers and system programmers and application programmers, etc., etc., all identified by employee number). See Example 4 in Chapter 15. End of aside. To summarize: The foregoing example strongly suggests there might be occasions on which it’s indeed desirable (a) to have several different anchor relvars for the same entity type; (b) to have a different primary key in each of those anchor relvars; and (c) to have different foreign keys referring to those different primary keys in different subsidiary relvars. Again, please note that I’m not saying the apparent need here to violate the rule “one primary key per entity type” can’t be avoided; what I’m saying is I don’t see a good way to avoid it, nor do I see a good reason for adopting a bad way. Again, therefore, I would like to suggest that the “one primary key for one entity type” precept be treated as a strong (?) guideline, but not as an inviolable rule.
CONCLUDING REMARKS In this appendix I’ve presented a number of pragmatic arguments for: n
Relaxing the commonly accepted rule that every base relvar have a distinguished key called the primary key
n
Relaxing the (perhaps less commonly accepted) rule that every foreign key refer specifically to a primary key instead of to an alternate key10
n
Relaxing the commonly accepted rule that there be exactly one anchor relvar for each entity type
Of course, I’m well aware that if we do relax these rules, then we open the door to the possibility of bad designs. That’s why I recommend retaining recommendations such as “one primary key per entity type” as rules of thumb, or good design guidelines. In other words, the rules in question should be violated only if there’s some really good reason for doing so. But I’ve tried to show in this appendix that sometimes such good reasons do exist.
10
I say less commonly accepted because─to its credit─the SQL standard, at least, does allow foreign keys to reference any candidate key.
Appendix B
Redundancy Revisited Nothing is certain but the unforeseen ─19th century proverb
In Chapter 13, I discussed a normal form I called RFNF (redundancy free normal form). However, I did also mention in that chapter the fact that that very same name had been used earlier in a paper by Millist W. Vincent to mean something rather different.1 In this appendix, I present a brief introduction to Vincent’s RFNF. Consider our usual suppliers relvar S, with its FD {CITY} → {STATUS} and sample value as shown in Fig. 1.1. The tuple for supplier S1 in that relvar has city London and status 20; as a consequence, the tuple for supplier S4, which also has city London, must have status 20, for otherwise the FD {CITY} → {STATUS} would be violated. In a sense, therefore, the occurrence of that status value 20 in the tuple for supplier S4 is redundant, because there’s nothing else it could possibly be─it’s a logical consequence of, and is fully determined by, the values appearing elsewhere in the relation that’s the current value of the relvar at the time in question. Examples like the foregoing provide the motivation for the following intuitively attractive definition (due to Vincent but considerably paraphrased here): n
Definition: Let relation r be a value of relvar R, let t be a tuple in r, and let v be an attribute value within t. Then that occurrence of v within t is redundant in r, and R is subject to redundancy, if and only if replacing that occurrence of v by an occurrence of v′ (v′ ≠ v), while leaving everything else unchanged, causes some FD or JD of R to be violated.
In other words, redundancy exists if the attribute value occurrence in question must be v and nothing else. Aside: Even though I said the foregoing definition is intuitively attractive (and I think it is), I think I should also point out that in at least one respect it’s a little strange, too. Consider the motivating example again, in which the tuple in relvar S for supplier S4 had to have status value 20 because the tuple for supplier S1 had status value 20. Observe now that the reverse argument holds equally well: The tuple for supplier S1 has to have status value 20 because the tuple for supplier S4 has status value 20! Now, it surely makes no sense to say those 20’s are both redundant (does it?) ─but the fact that it appears to be arbitrary as to which of the two we regard as the redundant one does seem a little odd, at least to me. End of aside. Be that as it may, Vincent goes on to define a new normal form, as follows:2 n
Definition: Relvar R is in (Vincent’s) redundancy free normal form, RFNF, if and only if it’s not subject to redundancy as just defined.
1
Millist W. Vincent: “Redundancy Elimination and a New Normal Form for Relational Database Design,” in B. Thalheim and L.Libkin (eds.), Semantics in Databases. Berlin, FDR: Springer-Verlag (1998).
2
Note that the arbitrariness just referred to has no impact on this definition (perhaps fortunately).
216
Appendix B / Redundancy Revisited
Now, it’s obvious that a relvar that’s not in BCNF (or indeed 4NF) isn’t in Vincent’s RFNF either by the foregoing definition (once again, see relvar S for an example). But what about a relvar that’s in “our” RFNF?3 Well, recall the following example from Chapter 13. We’re given a relvar SPJ′, with attributes SNO (supplier number), PNO (part number), and JNO (project number), and predicate Supplier SNO supplies part PNO to project JNO. Also, the following dependencies hold: { SNO , PNO } → { JNO } R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } } Now, we saw in Chapter 13 that if the relvar contains the following three tuples─ t1 t2 t3
= = =
s1 s1 s2
p1 p2 p1
j2 j1 j1
─then the following tuple has to appear as well: t4
=
s1
p1
j1
But {SNO,PNO} is a key; it follows that tuples t1 and t4, since they have the same key value, are in fact one and the same (and hence that j1 = j2). As a consequence, SPJ′ suffers from neither FD redundancy nor JD redundancy (as I defined those terms in Chapter 13), and the relvar is therefore in “our” RFNF. Observe now, however, that the very fact that j2, in tuple t1, must be equal to j1 means the relvar is subject to redundancy by Vincent’s definition! It follows that the two RFNFs, ours and Vincent’s, are logically different; in fact, Vincent’s definition is strictly stronger than ours, in the sense that a relvar can be in RFNF by our definition without being in RFNF by Vincent’s, while the converse isn’t so. (It further follows that the two RFNFs really need different names, of course.) In fact, we can make the following stronger statement: n
Theorem: 5NF implies SKNF; SKNF implies Vincent’s RFNF; Vincent’s RFNF implies our RFNF; and our RFNF implies 4NF. The reverse implications do not hold. Vincent also proves the following useful result:
n
Theorem: Relvar R is in Vincent’s RFNF if and only if it’s in BCNF and, for every JD J that holds in R, the union of those components of J that are superkeys for R is equal to the heading of R.4 By way of example, consider relvar SPJ′ once again. As we know, the following JD holds in that relvar: R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } }
3 As noted in Chapter 13, “our” RFNF has since been renamed ETNF (“essential tuple normal form”). For further discussion, see the section “Stop Press” in Appendix C. 4 What Vincent actually does is this: He defines relvar R to be in yet another normal form that he calls KCNF (key complete normal form) if and only if it satisfies the stated conditions (i.e., if and only if it’s in BCNF and, for every JD J that holds in R, the union of those components of J that are superkeys for R is equal to the heading of R). Then he goes on to prove that KCNF and his RFNF are logically equivalent.
Redundancy Revisited / Appendix B
217
The only component of this JD that’s a superkey is {SNO,PNO}; the union of all superkey components is certainly not equal to the heading, therefore, and the relvar is thus not in Vincent’s RFNF. So SPJ′ is an example of a relvar that’s in our RFNF and not in Vincent’s. But can we find an example of a relvar that’s in Vincent’s RFNF and not in SKNF? Note that such relvars must exist, given that Vincent’s RFNF lies strictly between our RFNF and SKNF (that is, SKNF implies Vincent’s RFNF and Vincent’s RFNF implies our RFNF). Well, we can easily construct an example of such a relvar by taking relvar SPJ′ with its two dependencies as discussed previously─ { SNO , PNO } → { JNO } R { { SNO , PNO } , { PNO , JNO } , { JNO , SNO } } ─and adding another: { PNO , JNO } → { SNO } This additional dependency (which implies, of course, that {PNO,JNO} is another key) corresponds to an additional business rule: n
Any given part p is supplied to a given project j by at most one supplier s.
Observe now that this revised version of relvar SPJ′ satisfies the conditions of Vincent’s Theorem: To be specific, the superkey components of the JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}} are {SNO,PNO} and {PNO,JNO}; their union is equal to the entire heading; and so the relvar is in Vincent’s RFNF.5 At the same time, it isn’t in SKNF, because that same JD contains a component, {JNO,SNO}, that isn’t a superkey. So here we have an example of a relvar that’s in Vincent’s RFNF and not in SKNF. So now we’ve seen examples of relvars that are (a) in Vincent’s RFNF and not in SKNF and (b) in our RFNF and not in Vincent’s. But the “syntactic” differences between these various normal forms can be a little hard to remember, and it might be helpful to summarize them here: n
Relvar R is in our RFNF if and only if it’s in BCNF and, for every JD J that holds in R, some component of J is a superkey for R.
n
Relvar R is in Vincent’s RFNF if and only if it’s in BCNF and, for every JD J that holds in R, the union of those components of J that are superkeys for R is equal to the heading of R.
n
Relvar R is in SKNF if and only if, for every irreducible JD J that holds in R, every component of J is a superkey for R. Now let me remind you of the following definition of redundancy from Chapter 15:
n
5
Definition: Let D be a database design; let DB be a database value (i.e., a set of values for the relvars mentioned in D) that conforms to D; and let p be a proposition not involving any existential quantification. If DB contains two or more distinct representations of p, then DB contains, and D permits, redundancy.
I’m relying here on the fact that this particular JD is the only nontrivial one to hold.
218
Appendix B / Redundancy Revisited
Consider relvar SPJ′ once again (the original version, without the additional FD {PNO,JNO} → {SNO}). I now claim that the design of this relvar does permit redundancy by this definition. To be specific (and with reference to the sample tuples shown earlier), the unquantified proposition Supplier s1 supplies part p1 to project j1 is represented both explicitly, by the appearance of tuple t1 (or tuple t4), and implicitly, as a logical consequence of the JD and the following propositions: n
Supplier s1 supplies part p1 (to some project): Represented by tuple t1
n
Part p1 is supplied to project j1 (by some supplier): Represented by tuple t3
n
Project j1 is supplied by supplier s1 (with some part): Represented by tuple t2
Thus, I claim that Vincent’s specific definition of redundancy is consistent with, and can be seen as a special case of, the definition (“final version”) that I proposed for redundancy in general in Chapter 15. I’d like to close this appendix by pointing out that a relvar can be in Vincent’s RFNF (and even in 5NF) and yet still be subject to redundancy of a kind that, while not identical to that defined by Vincent, is certainly very similar to it. Recall this example (discussed briefly in a footnote in Chapter 12): We’re given a relvar SPJQ, with attributes SNO, PNO, JNO, and QTY (only) and predicate “Supplier SNO supplies part PNO to project JNO in quantity QTY.” The sole key is {SNO,PNO,JNO}, and the relvar is therefore in BCNF. Note that the JD R{{SNO,PNO},{PNO,JNO},{JNO,SNO}} does not hold in this relvar; however, it does hold in the projection of the relvar on {SNO,PNO,JNO} (in other words, it’s an embedded dependency; refer to Chapter 12 if you need to refresh your memory regarding this notion). Now suppose the relvar contains the following tuples (only): s1 s1 s2 s1
p1 p2 p1 p1
j2 j1 j1 j3
100 200 300 400
By the embedded dependency, then, we must have j3 = j1. As previously stated, therefore, relvar SPJQ is certainly subject to redundancy; what’s more, the kind of redundancy it’s subject to is very similar to the kind defined by Vincent. Nevertheless, the relvar is in Vincent’s RFNF! The point is, Vincent’s redundancy is defined with respect to the FDs and JDs (only) of the relvar in question; it has nothing to say about any other constraints, such as embedded dependencies, that might also happen to hold.
Appendix C
Historical Notes History is not what you thought. It is what you can remember. ─W. C. Sellar and R. J. Yeatman: 1066 and All That
This appendix presents a brief and not unbiased survey of some of the seminal research publications in the field of design theory. The publications in question are listed in chronological order, more or less. The relational model as such had its origins in two landmark papers by Codd: n
E. F. Codd: “Derivability, Redundancy, and Consistency of Relations Stored in Large Data Banks,” IBM Research Report RJ599 (August 19th, 1969) and elsewhere.
n
E. F. Codd: “A Relational Model of Data for Large Shared Data Banks,” CACM 13, No. 6 (June 1970); republished in Milestones of Research─Selected Papers 1958-1982 (CACM 25th Anniversary Issue), CACM 26, No. 1 (January 1983) and elsewhere.
The first of these papers has nothing to say about design per se. The second, however, includes a section with the title “Normal Form” that includes the following tantalizing remarks: “Further operations of a normalizing kind are possible. These are not discussed in this paper.” These remarks appear following an example that shows how to eliminate relation valued attributes (see the answer to Exercise 12.8 in Appendix D); that’s why Codd uses the phrase “further operations” (emphasis added). Incidentally, the second of the foregoing papers is the source of the term connection trap (see Chapter 9). Design theory as such began with Codd’s introduction of FDs, 2NF, and 3NF in: n
E.F. Codd: “Further Normalization of the Data Base Relational Model,” in Randall J. Rustin, ed., Data Base System: Courant Computer Science Symposia Series 6 (Prentice Hall, 1972).
Two brief comments here: First, the title is misleading─further normalization isn’t something that’s done to the relational model, it’s something that’s done to relvars, or rather to relvar designs. (To repeat from the answer to Exercise 1.1 in Appendix D, the relational model as such doesn’t care how the database happens to be designed, just so long as the design in question doesn’t violate any of the precepts of the relational model.) Second, a preliminary version of some of the material in this paper can be found in two earlier papers of Codd’s. The first is an IBM technical memo, “The Second and Third Normal Forms for the Relational Model,” dated October 6th, 1970. The second is “Normalized Data Base Structure: A Brief Tutorial,” Proc. 1971 ACM SIGFIDET Workshop on Data Description, Access, and Control, San Diego, Calif., (November 11th-12th, 1971).1 Heath’s Theorem actually appeared before Codd’s 1972 normalization paper, in:
1 This second paper isn’t concerned so much with 2NF and 3NF per se as it is with the idea that relations can represent anything that other data structures─hierarchies, networks, etc.─can. It does discuss 2NF and 3NF very briefly, but its coverage of those topics is essentially limited to giving a single fairly informal example in each case.
220
n
Appendix C / Historical Notes
I. J. Heath: “Unacceptable File Operations in a Relational Data Base,” Proc. 1971 ACM SIGFIDET Workshop on Data Description, Access and Control, San Diego, Calif. (November 11th-12th, 1971). BCNF was defined in the following paper (though it was there referred to as third normal form):
n
E. F. Codd: “Recent Investigations into Relational Data Base Systems,” Proc. IFIP Congress, Stockholm, Sweden (North-Holland, 1974) and elsewhere. That same IFIP meeting also saw the first presentation of Armstrong’s axioms for FDs:
n
W. W. Armstrong: “Dependency Structures of Data Base Relationships,” Proc. IFIP Congress, Stockholm, Sweden (North-Holland, 1974). MVDs and 4NF and what in Chapter 12 I referred to as Fagin’s Theorem2 were all defined in:
n
Ronald Fagin: “Multivalued Dependencies and a New Normal Form for Relational Databases,” ACM TODS 2, No. 3 (September 1977). The MVD axiomatization was reported in:
n
Catriel Beeri, Ronald Fagin, and John H. Howard: “A Complete Axiomatization for Functional and Multivalued Dependencies,” Proc. 1977 ACM SIGMOD International Conference on Management of Data, Toronto, Canada (August 1977). The theory of dependency preservation had its origins in:
n
Jorma Rissanen: “Independent Components of Relations,” ACM TODS 2, No. 4 (December 1977).
The following paper is generally credited with being the first to point out that relvars can exist that aren’t equal to the join of any two of their projections, but are equal to the join of three or more (though in fact, as mentioned in Chapter 9, Codd had effectively made the same observation in his 1969 paper). The paper is also the source of the chase algorithm; however, it considers only FDs and MVDs, not general JDs. n
A. V. Aho, C. Beeri, and J. D. Ullman: “The Theory of Joins in Relational Databases,” ACM TODS 4, No. 3 (September 1979); previously published in Proc. 19th IEEE Symposium on Foundations of Computer Science (October 1977). JDs as such were first defined in:
n
Jorma Rissanen: “Theory of Relations for Databases─A Tutorial Survey,” Proc. 7th Symposium on Mathematical Foundations of Computer Science, Springer-Verlag Lecture Notes in Computer Science 64 (Springer-Verlag, 1979).
2 Actually there are scores of theoretical results in the computing literature, not just in the field of design theory as such, that could all justifiably be referred to as “Fagin’s Theorem.”
Historical Notes / Appendix C
221
The next paper introduced the concept of projection-join normal form (PJ/NF), also called 5NF. It can be regarded as the definitive statement of what might be called “classical” normalization theory─i.e., the theory of nonloss decomposition based on projection as the decomposition operator and natural join as the corresponding recomposition operator, and the normal forms BCNF, 4NF, and 5NF. n
Ronald Fagin: “Normal Forms and Relational Database Operators,” Proc. 1979 ACM SIGMOD International Conference on Management of Data, Boston, Mass. (May/June 1979).
The next paper presents a sound and complete set of inference rules─in other words, an axiomatization─for inclusion dependencies (INDs). Note: I’m not aware of any formal treatment anywhere of equality dependencies (EQDs), which are an important, but in some ways rather trivial, special case. n
Marco A. Casanova, Ronald Fagin, and Christos H. Papadimitriou: “Inclusion Dependencies and Their Interaction with Functional Dependencies,” Proc. 1st ACM SIGACT-SIGMOD Symposium on Principles of Database Systems, Los Angeles, Calif. (March 1982). Domain-key normal form is defined in:
n
Ronald Fagin: “A Normal Form for Relational Databases That Is Based on Domains and Keys,” ACM TODS 6, No. 3 (September 1981). 6NF is defined in:
n
C. J. Date, Hugh Darwen, and Nikos A. Lorentzos: Temporal Data and the Relational Model (Morgan Kaufmann, 2003). As for orthogonality, the concept was first discussed, though not by that name, in:
n
C. J. Date and David McGoveran: “A New Database Design Principle,” in C. J. Date, Relational Database Writings 1991-1994 (Addison-Wesley, 1995); previously published in Database Programming & Design 7, No. 7 (July 1994).
Note, however, that orthogonality as described in the present book is significantly different from the version discussed in the foregoing paper. (I accept full responsibility for this state of affairs; although the concept was originally due to David McGoveran, I wrote the bulk of the referenced paper, and I realize now that I was rather confused when I did so.) Stop Press: “Our” redundancy free normal form (see Chapter 13 and Appendix B) has recently been renamed essential tuple normal form (ETNF). It’s described in: n
Hugh Darwen, C. J. Date, and Ronald Fagin: “A Normal Form for Preventing Redundant Tuples in Relational Databases,” Proc. 15th International Conference on Database Theory, Berlin, Germany (March 26th-29th, 2012).
All of the theorems, results, etc. discussed in Chapter 13 in connection with “our” RFNF (now ETNF) are proved in this paper, but the terminology has been revised somewhat. Let me relate the terminology of the paper to the terminology of Chapter 13. First of all, let R be a relvar, let r be a value of R, and let t be a tuple in r. Then t is
222
Appendix C / Historical Notes
redundant in r if and only if it’s either partly redundant or fully redundant. The paper shows that (a) such a tuple exists and is partly redundant if and only if R isn’t in BCNF (i.e., if and only if R is FD redundant─see Chapter 13); (b) such a tuple exists and is fully redundant if and only if a tuple forcing JD holds in R (i.e., if and only if R is JD redundant─again, see Chapter 13). Note, therefore, that “fully redundant” is not a special case of “partly redundant”; in fact, a tuple can be partly redundant without being fully so or the other way around. Finally, tuple t is essential in r if and only if it’s not redundant in r. If R is in ETNF, then every relation r that’s a legitimate value for R is such that every tuple is essential in r. Note: Our choice of the term essential for use in this context was influenced by Codd’s notion of essentiality, introduced in E. F. Codd and C. J. Date: "Interactive Support for Nonprogrammers: The Relational and Network Approaches," in Randall J. Rustin (ed.), Proc. ACM SIGMOD Workshop on Data Description, Access, and Control─Data Models: Data-Structure-Set versus Relational (Ann Arbor, Michigan, May 1st-3rd, 1974).3 Briefly, to say some data construct is essential in Codd’s sense is to say its loss would cause a loss of information. As already indicated, every tuple in every relation that’s a possible value for an ETNF relvar is essential in this sense.
3
Republished in C. J. Date, Relational Database: Selected Writings (Addison-Wesley, 1986).
Appendix D
Answers to Exercises Science offers the best answers ─Richard Dawkins: Break the Science Barrier
Note: All mistakes in this appendix are deliberate <joke>.
CHAPTER 1 1.1 Yes, it is. Good design benefits the user, and to some extent the DBMS as well, but the relational model as such doesn’t care how the database happens to be designed, just so long as it doesn’t violate any of the precepts of the relational model─in particular, so long as the objects it has to deal with are indeed relations and not something else (which, sadly, they often are in SQL). 1.2
See Chapter 15.
1.3
See Chapters 4 and 5.
1.4
Yes (see Chapters 4 and 5).
1.5
No. (Actually, it’s not even true that every binary relvar is in 2NF. See Exercise 4.6.)
1.6
No (see Chapters 9 and 10).
1.7
No a fortiori, given the answer to Exercise 1.5.
1.8
No (see Chapter 13).
1.9
No (see Chapter 13).
1.10
See Chapter 10.
1.11
No (see Chapters 9 and 15).
1.12
See Chapter 8.
1.13
See Chapter 5.
1.14
See Chapter 14.
1.15
See Chapter 11.
224
Appendix D / Answers to Exercises
1.16
See Chapter 7.
1.17
See Chapter 11.
1.18
See Chapter 13, also Appendix B.
CHAPTER 2 2.1 The Information Principle is a fundamental principle that underpins the entire relational model. It can be stated as follows: n
Definition: The Information Principle states that the only kind of variable allowed in a relational database is the relation variable or relvar. Equivalently, the entire information content of the database at any given time is represented in one and only one way─namely, as values in attribute positions in tuples in relations.
Note that SQL tables (at least, SQL tables in the database) that involve left to right column ordering, or contain duplicate rows or nulls, all violate The Information Principle (see the answer to the next exercise). Interestingly, however, SQL tables with anonymous columns or columns with nonunique names apparently don’t violate the principle. The reason is that the principle as stated applies explicitly to relvars or relations in the database. And while SQL tables in general can have anonymous columns or columns with nonunique names, such tables can’t be part of the database as such. This state of affairs suggests rather strongly that The Information Principle could do with a little tightening up. 2.2 a. True. b. True. c. True. d. True. e. True. f. True. g. True. h. False. (However, it’s “almost” true; there are two small exceptions, both of which I’ll simplify just slightly for present purposes. The first is that if relation r is of type T, then no attribute of r can itself be of type T. The second is that no relation in the database can have an attribute of any pointer type.) i. True. Subsidiary exercise: Would any of these answers change if the original statements are were framed in terms of SQL tables instead of relations and relvars? (Answer: Yes, they would all change except for a. and h. In the case of h., moreover, the answer ought really to change too, from “False” to “False, but even more so.” One reason for this state of affairs─not the only one─is that SQL has no proper notion of table type, and SQL columns thus can’t possibly be of such a type a fortiori.) 2.3 a. True. b. True. c. True. Note: Perhaps I should state for the record here that throughout this book, in accordance with normal practice, I take expressions of the form “B is a subset of A” to include the possibility that B and A might be equal. Thus, e.g., every heading is a subset of itself, and so is every body, and so is every tuple. When I want to exclude such a possibility, I’ll talk explicitly in terms of proper subsets. For example, the body of our usual suppliers relation is certainly a subset of itself, but not a proper subset of itself (no set is a proper subset of itself). What’s more, the foregoing remarks apply equally to supersets, mutatis mutandis; for example, the body of our usual suppliers relation is a superset of itself, but not a proper superset of itself. More terminology: A set is said to include its subsets. Incidentally, don’t confuse inclusion with containment─a set includes its subsets but contains its elements. 2.4 The reason the term isn’t mentioned in the body of the chapter is that it’s just a synonym for type. (Early relational writings, my own included, tended to use it, but more recent ones use type instead, since it’s shorter and has a more extensive pedigree anyway, at least in the computing world.) Thus, a domain is a named, finite set of values─all possible values of some specific kind: for example, all possible integers, or all possible character strings, or all possible triangles, or all possible XML documents, or all possible relations with a specific heading (etc., etc.).
Answers to Exercises / Appendix D
225
By the way, don’t confuse domains as understood in the relational world with the construct of the same name in SQL, which (as explained in SQL and Relational Theory) can be regarded at best as a very weak kind of type. 2.5
See the body of the chapter.
2.6 Relvar S: Supplier SNO is named SNAME and is located in city CITY, which has status STATUS. Relvar P: Part PNO is named PNAME, has color COLOR and weight WEIGHT, and is stored in city CITY. Relvar SP: Supplier SNO supplies part PNO in quantity QTY. 2.7
No answer provided.
The Closed World Assumption says, loosely, that everything stated or implied by the database is true and 2.8 everything else is false.1 And The Open World Assumption─yes, there is such a thing─says that everything stated or implied by the database is true and everything else is unknown. What are the implications? Well, first let’s agree to abbreviate Closed World Assumption and Open World Assumption to CWA and OWA, respectively. Now consider the query “Is supplier S6 in Rome?” (meaning, more precisely, “Is there a tuple for supplier S6 in relvar S with CITY value equal to Rome?”). Tutorial D formulation: ( S WHERE SNO = ‘S6’ AND CITY = ‘Rome’ ) { } As explained in SQL and Relational Theory, this expression evaluates to either TABLE_DEE or TABLE_DUM (where TABLE_DEE and TABLE_DUM are the only relations of degree zero; TABLE_DEE contains just one tuple, and TABLE_DUM contains no tuples at all). Under the CWA, moreover, if the result is TABLE_DEE, it means the answer is yes, supplier S6 does exist and is in Rome; if the result is TABLE_DUM, it means the answer is no, it’s not the case that supplier S6 exists and is in Rome. Under the OWA, by contrast, TABLE_DEE still means yes, but TABLE_DUM means it’s unknown whether supplier S6 exists and is in Rome. Now consider the query “If supplier S6 exists, is that supplier in Rome?” (note the logical difference between this query and the one discussed above). Observe that the answer to this query has to be no if relvar S shows supplier S6 as existing but in some city other than Rome, regardless of whether we’re talking about the CWA or the OWA.2 So here’s the Tutorial D formulation: TABLE_DEE MINUS ( ( S WHERE SNO = ‘S6’ AND CITY ≠ ‘Rome’ ) { } ) Note carefully, therefore, that if this expression evaluates to TABLE_DUM, that TABLE_DUM has to mean no, even under the OWA. Thus, the OWA suffers from an inherent ambiguity: Sometimes TABLE_DUM has to mean unknown and sometimes it has to mean no─and of course we can’t say (in general) which interpretation applies when. Just to beat the point to death: TABLE_DEE and TABLE_DUM simply do mean yes and no, respectively, in the relational world, and there’s no “third relation” of degree zero available to represent the “third truth value” that the OWA fundamentally requires. Thus, the OWA and the relational model are fundamentally incompatible with each other.
1 To illustrate what I mean by “stated or implied” here, consider the shipment tuple (S1,P1,300) shown in Fig. 1.1. That tuple states the proposition “Supplier S1 supplies part P1 in quantity 300.” However, it also implies several other propositions─for example, the proposition “Supplier S1 supplies at least one part in quantity 300.” 2 By contrast, the answer has to be yes if relvar S has no tuple for supplier S6 (in logic, “if p then q” is true if p is false—again, regardless of whether we’re talking about the CWA or the OWA).
226
2.9
Appendix D / Answers to Exercises
Precise definitions are given in Chapter 5.
2.10 Two values of any kind are equal if and only if they’re the very same value (meaning they must be of the same type, a fortiori). In particular, (a) two tuples t and t′ are equal if and only if they have the same attributes A1, ..., An and for all i (i = 1, ..., n), the value of Ai in t is equal to the value of Ai in t′; (b) two relations r and r′ are equal if and only if they have the same heading and the same body (i.e., their headings are equal and their bodies are equal). Note in particular, therefore, that two “empty relations” (i.e., relations without any tuples) are equal if and only if their headings are equal. 2.11 Yes! However, we would of course want such operators always to produce a valid tuple as a result (i.e., we would want closure for such operations, just as we have closure for relational operations─see the answer to Exercise 2.16 below). For tuple union, for example, we would want the input tuples to be such that attributes with the same name have the same value (and are therefore of the same type, a fortiori). By way of example, let t1 and t2 be a supplier tuple and a shipment tuple, respectively, and let t1 and t2 have the same SNO value. Then the union of t1 and t2, UNION{t1,t2}, is─to use Tutorial D syntax─a tuple of type TUPLE {SNO CHAR, SNAME CHAR, STATUS INTEGER, CITY CHAR, PNO CHAR, QTY INTEGER}, with attribute values as in t1 or t2 or both (as applicable). E.g., if t1 is (S1,Smith, 20,London) and t2 is (S1,P1,300)─to use the shorthand notation for tuples introduced in the body of the chapter─then their union is the tuple (S1,Smith,20,London,P1,300). Note: This operation might reasonably be called tuple join instead of tuple union. By the way, it’s not just the usual set operators that might be adapted to apply to tuples─the same goes for certain of the well known relational operators, too (as in fact I’ve just suggested). One important example is the tuple projection operator, which is a straightforward adaptation of the relational projection operator. For example, let t be a supplier tuple; then the projection t{SNO,CITY} of t on attributes {SNO,CITY} is that subtuple of t that contains just the SNO and CITY components from t. (Of course, a subtuple is itself a tuple in its own right.) Likewise, t{CITY} is that subtuple of t that contains just the CITY component from t, and t{} is that subtuple of t that contains no components at all (in other words, it’s the 0-tuple─see the next exercise). In fact, it’s worth noting explicitly that every tuple has a projection on the empty set of attributes whose value is, precisely, the 0-tuple. 2.12 The empty tuple (note that there’s exactly one such; equivalently, all empty tuples are equal to one another) is the same thing as the 0-tuple, mentioned in the answer to the previous exercise. As for uses for such a tuple, I’ll just say that, conceptually at least, the fact that such a tuple does exist is crucially important in numerous ways. In particular, the empty tuple is the only tuple in the special relation TABLE_DEE, already mentioned in the answer to Exercise 2.8. 2.13 To say relvar R has an empty key is to say R can never contain more than one tuple. Why? Because every tuple has the same value for the empty set of attributes─namely, the empty tuple (see the answers to the previous two exercises); thus, if R had an empty key, and if R were to contain two or more tuples, we would have a key uniqueness violation on our hands. And, yes, constraining R never to contain more than one tuple could certainly be useful. I’ll leave finding an example of such a situation as a subsidiary exercise. 2.14 A predicate with an empty set of parameters is a proposition. (In other words, a proposition is a degenerate predicate; all propositions are predicates, but “most” predicates aren’t propositions.) 2.15 n
Definitions of projection and join are given in Chapter 5, but here’s a definition of RENAME: Definition: Let r1 be a relation, let A be an attribute of r1, and let r1 not have an attribute named B. Then the renaming r1 RENAME {A AS B} is a relation r2 with (a) heading identical to that of r1 except that
Answers to Exercises / Appendix D
227
attribute A in that heading is renamed B and (b) body identical to that of r1 except that all references to A in that body (more precisely, in tuples in that body) are replaced by references to B. Note: Tutorial D additionally supports a form of RENAME that allows two or more separate renamings to be carried out in parallel (“multiple RENAME”). Examples are given in Chapter 14. 2.16 The relational algebra consists of operators that (speaking very loosely) allow us to derive “new” relations from “old” ones. Each such operator takes one or more relations as input and produces another relation as output (for example, the difference operator takes two relations as input and “subtracts” one from the other to derive another relation as output)─and that’s the closure property. Note that it’s that property that (among other things) lets us write nested relational expressions; since the output from every operation is the same kind of thing as the input, the output from one operation can become the input to another. For example, we can take the difference between relations r1 and r2 (in that order), feed the result as input to a union with some relation r3, feed that result as input to a projection or restriction, and so on.
CHAPTER 3 With reference to the sample value shown for relvar STP in Chapter 1 (Fig. 1.2), we can’t insert the fact that 3.1 supplier S5 has status 30 until supplier S5 supplies some part; we can’t delete the shipment for supplier S3 without losing the fact that supplier S3 has status 30; and we can’t change the status in one tuple for a given supplier, say supplier S1, without changing it in all of them. The obvious decomposition is into relvars with headings {SNO,STATUS} and {SNO,PNO,QTY}; it’s also obvious that this decomposition avoids the anomalies. Note: It’s worth pointing out in passing that the insertion and deletion anomalies are caused by the fact that the design is logically incorrect, whereas the modification anomaly is caused by the fact that it’s redundant (see Exercise 3.3). Let the heading of r be partitioned into sets of attributes X, Y, and Z, and let the projections r1 and r2 be on 3.2 {X,Y} and {Y,Z}, respectively. (X, Y, and Z are disjoint by definition.) Now let (x,y,z) be a tuple of r; then (x,y) and (y,z) are tuples of r1 and r2, respectively, and so (x,y,z) is a tuple in the join of r1 and r2. Subsidiary exercise: What happens to the foregoing proof if the set Y is empty? 3.3 The two purposes (correcting an incorrect design and reducing redundancy) are explained in the body of the chapter. As for whether you think the point is widely understood: Well, only you can answer this question, but speaking for myself I have to say I don’t think it is.
CHAPTER 4 4.1 The complete set of FDs─what’s known, formally, as the closure, though it has nothing to do with the closure property of the relational algebra─for relvar SP contains a total of 31 FDs. Here they are: { { { { { { { {
SNO SNO SNO SNO SNO SNO SNO SNO
, , , , , , , ,
PNO PNO PNO PNO PNO PNO PNO PNO
, , , , , , , ,
QTY QTY QTY QTY QTY QTY QTY QTY
} } } } } } } }
→ → → → → → → →
{ { { { { { { {
SNO SNO SNO PNO SNO PNO QTY }
, , , , } } }
PNO PNO QTY QTY
, QTY } } } }
228
Appendix D / Answers to Exercises
{ { { { { { { {
SNO SNO SNO SNO SNO SNO SNO SNO
, , , , , , , ,
PNO PNO PNO PNO PNO PNO PNO PNO
} } } } } } } }
→ → → → → → → →
{ { { { { { { {
SNO SNO SNO PNO SNO PNO QTY }
, , , , } } }
{ { { {
SNO SNO SNO SNO
, , , ,
QTY QTY QTY QTY
} } } }
→ → → →
{ { { {
SNO , QTY } SNO } QTY } }
{ { { {
PNO PNO PNO PNO
, , , ,
QTY QTY QTY QTY
} } } }
→ → → →
{ { { {
PNO , QTY } PNO } QTY } }
{ SNO } { SNO }
→ { SNO } → { }
{ PNO } { PNO }
→ { PNO } → { }
{ QTY } { QTY }
→ { QTY } → { }
{ }
→ { }
PNO PNO QTY QTY
, QTY } } } }
The only ones that aren’t trivial are the following four: { { { {
SNO SNO SNO SNO
, , , ,
PNO PNO PNO PNO
} } } }
→ → → →
{ { { {
SNO SNO PNO QTY
, PNO , QTY } , QTY } , QTY } }
The only irreducible ones are the following eleven: { { { { {
SNO SNO SNO SNO SNO
, , , , ,
PNO PNO PNO PNO PNO
} } } } }
→ → → → →
{ { { { {
SNO SNO SNO PNO QTY
, , , , }
PNO PNO QTY QTY
, QTY } } } }
{ SNO , QTY } → { SNO , QTY } { PNO , QTY } → { PNO , QTY } { SNO }
→ { SNO }
{ PNO }
→ { PNO }
Answers to Exercises / Appendix D
{ QTY }
→ { QTY }
{ }
→ { }
229
4.2 Yes, it is (“whenever two tuples agree on X, they also agree on Y” implies a comparison between the projections of the tuples in question on the attributes of X and Y). 4.3
No answer provided.
4.4
First of all, here are the two definitions, numbered for purposes of subsequent reference: 1.
Relvar R is in 2NF if and only if, for every key K of R and every nonkey attribute A of R, the FD K → {A} is irreducible.
2.
Relvar R is in 2NF if and only if, for every nontrivial FD X → Y that holds in R, at least one of the following is true: (a) X is a superkey; (b) Y is a subkey; (c) X is not a subkey.
Now, Definition 2 says R isn’t in 2NF if and only if there exists a nontrivial FD X → Y that holds in R such that X isn’t a superkey and Y isn’t a subkey and X is a subkey. But if X is a subkey and not a superkey, it must be a proper subkey; thus, Definition 2 effectively says R isn’t in 2NF if and only if there exists a nontrivial FD X → Y that holds in R such that X is a proper subkey and Y isn’t a subkey. So let K be a key that includes X as a proper subkey. Then the FD K → Y holds in R and is reducible, whence it follows that the FD K → {A} holds in R and is reducible for every attribute A contained in Y. So Definition 2 implies Definition 1. Following this argument in the reverse direction will likewise show that Definition 1 implies Definition 2. 4.5
Consider the following argument. Let relvar R not be in 2NF. Then there must be some key K of R and some nonkey attribute A of R such that the FD K → {A} (which holds in R, necessarily) is reducible─meaning some attribute can be dropped from K, yielding K′ say, such that the FD K′ → {A} still holds. Hence K must be composite.
This argument appears to show that the answer to the exercise must be yes─i.e., if a relvar isn’t in 2NF, it must have a composite key. But the argument is incorrect! Here’s a counterexample. Let USA be a binary relvar with attributes COUNTRY and STATE; the predicate is STATE is part of COUNTRY, but COUNTRY is the United States in every tuple. Now, {STATE} is the sole key for this relvar, and the FD {STATE} → {COUNTRY} thus certainly holds. However, the FD {} → {COUNTRY} clearly holds as well (see the answer to Exercise 4.10 below); the FD {STATE} → {COUNTRY} is thus reducible, and so the relvar isn’t in 2NF, and yet the key {STATE} isn’t composite. 4.6 No! By way of a counterexample, consider relvar USA from the answer to the previous exercise. That relvar is subject to the FD {} → {COUNTRY}, which is neither trivial nor an arrow out of a superkey, and so the relvar isn’t in BCNF. (In fact, of course, it isn’t even in 2NF, as we saw in the answer to the previous exercise.) It follows that the relvar can be nonloss decomposed into its two unary projections on {COUNTRY} and {STATE}, respectively. (Note that the corresponding join, needed to reconstruct the original relvar, is in fact a cartesian product.)
230
Appendix D / Answers to Exercises
4.7 Yes. If no nontrivial FDs hold at all─which is certainly the case for an “all key” relvar─then there’s no nontrivial FD that holds for which the determinant isn’t a superkey, and so the relvar is in BCNF. 4.8
CONSTRAINT ... COUNT ( SNP { SNO , SNAME } ) = COUNT ( SNP { SNO } ) ; CONSTRAINT ... COUNT ( SNP { SNO , SNAME } ) = COUNT ( SNP { SNAME } ) ;
By the way, this trick for specifying that an FD holds─i.e., by stating that two projections have the same cardinality─certainly does the job; as noted in Chapter 2, however, it’s hardly very elegant, and for that reason I showed a different approach, using AND, RENAME, and JOIN, in that chapter. Alternatively, Hugh Darwen and I have proposed3 that Tutorial D should support another form of CONSTRAINT statement in which the usual boolean expression is replaced by the combination of a relational expression and one or more key specifications. Using this syntax, the foregoing constraints could be stated thus: CONSTRAINT ... SNP { SNO , SNAME } KEY { SNO } KEY { SNAME }; Explanation: Think of the relational expression─SNP{SNO,SNAME}, in the example─as defining some temporary relvar (perhaps a view); then the key specifications─KEY {SNO} and KEY{SNAME}, in the example above─indicates that the specified attributes constitute keys for that relvar. As an aside, I note that Darwen and I have also proposed allowing foreign key constraints to be specified for expressions in the same kind of way. 4.9 Let the FD X → Y hold in R. By definition, X and Y are subsets of the heading of R. Given that a set of n elements has 2ⁿ possible subsets, it follows that each of X and Y has 2ⁿ possible values, and hence an upper limit on the number of possible FDs that might hold in R is 2²ⁿ. For example, if R is of degree five, the maximum number of FDs that might hold is 1,024 (of which 243 are trivial). Subsidiary exercises: (a) Where did that figure of 243 come from? (b) Suppose those 1,024 FDs do all in fact hold. What can we conclude about R in that case? (Answer: It must have cardinality less than two. The reason is that one FD that holds in such a case is {} → H, where H is the heading; it follows that {} is a key, and so R is constrained to contain at most one tuple, as explained in the answer to the next exercise.) As for how many keys R can have: Let m be the smallest integer greater than or equal to n/2. R will have the maximum possible number of keys if either (a) every distinct set of m attributes is a key or (b) m is odd and every distinct set of (m-1) attributes is a key. Either way, it follows that the maximum number of keys is n! / (m! * (n-m)!).4 For example, a relvar of degree five can have at most ten distinct keys. 4.10 Let the specified FD X → Y hold in relvar R. Now, every tuple (regardless of whether it’s a tuple of R) has the same value─namely, the 0-tuple─for the projection of that tuple over the empty set of attributes. If Y is empty, therefore, the FD X → Y holds for all possible sets X of attributes of R; in fact, it’s a trivial FD (and so it isn’t very interesting), because the empty set is a subset of every set and so Y is definitely a subset of X in this case. On the other hand, if X is empty, the FD X → Y means that, at any given time, all tuples of R have the same value for Y (since they certainly all have the same value for X). What’s more, if Y in turn is the heading of R─in other words, if X is a superkey─then R is constrained to contain at most one tuple. Note: In this latter case, X isn’t just a superkey
3
In our book Database Explorations: Essays on The Third Manifesto and Related Topics (Trafford, 2010) and elsewhere.
4
The symbol r! is read as “r factorial” and denotes the product r * (r-1) * … * 2 * 1.
Answers to Exercises / Appendix D
231
but a key, since it’s certainly irreducible. What’s more, it’s the only key, because every other subset of the heading includes it as a proper subset. 4.11 Consider a relvar in the database catalog whose purpose is to record the FDs that hold in various relvars in the database. Given that an FD is an expression of the form X → Y where X and Y are sets of attribute names (see Chapter 5), a reasonable design for that catalog relvar is one with attributes R (relvar name), X (determinant), and Y (dependant), and predicate X → Y holds in R. For any given value of R, then, the values of X and Y are relations of degree one, whose tuples contain names of attributes of the relvar named R. For another example, involving a “user relvar” instead of a relvar in the catalog, you might like to think about the following problem: I decided to throw a party, so I drew up a list of people I wanted to invite and made some preliminary soundings. The response was good, but several people made their acceptance conditional on the acceptance of certain other invitees. For example, Bob and Cal both said they would come if Amy came; Fay said she would come if Don and Eve both came; Guy said he would come anyway; Hal said he would come if Bob and Amy both came; and so on. Design a database to show whose acceptance is based on whose. (With acknowledgments to Hugh Darwen.)
It seems to me that a reasonable design here would involve a relvar with two attributes X and Y, both relation valued, and predicate The set of people X will attend if and only if the set of people Y will attend. Subsidiary exercise: Can you think of any refinements you might want to make to this design? (Hint: Is it true that Bob will attend if and only if Bob will attend?) 4.12 Well, I don’t know what you conclude, but I know what I do. One thing I conclude is that we should always be on our guard against getting seduced by the latest fad. I could say quite a lot more on this subject, but I don’t think this appendix is the appropriate place to do so. 4.13 There are two cases to consider: (a) The relation depicted is a sample value for some relvar R; (b) the relation depicted is a sample value for some relational expression rx, where rx is something other than a simple relvar reference (where a relvar reference is basically just the pertinent relvar name). In Case (a), double underlining simply indicates that a primary key PK has been declared for R and the pertinent attribute is part of PK. In Case (b), you can think of rx as the defining expression for some temporary relvar R (think of it as a view defining expression and R as the corresponding view, if you like); then double underlining indicates that a primary key PK could in principle be declared for R and the pertinent attribute is part of PK. 4.14 I assume for the sake of this exercise and the next that the relation shown in Fig. 4.1 is a sample value for a relvar SPQ. Here then are Tutorial D formulations (not the only ones possible) of the two queries: a.
( ( SPQ WHERE SNO = ‘S2’ ) UNGROUP ( PQ ) ) { PNO }
b.
( ( SPQ UNGROUP ( PQ ) ) WHERE PNO = ‘P2’ ) { SNO }
Observe that the first of these expressions involves a restriction followed by an ungrouping, while the second involves an ungrouping followed by a restriction (there’s the asymmetry). Note: The UNGROUP operator hasn’t been discussed prior to this point, but its semantics should be obvious from the foregoing examples. Basically, it’s used to map a relation with an RVA to one without such an attribute. (There’s a GROUP operator too, for “going the other way”─that is, mapping a relation without an RVA to one with one.) For further discussion, see SQL and Relational Theory.
232
Appendix D / Answers to Exercises
4.15 Here I think it might be helpful to give part of the Tutorial D grammar for , which is the fundamental relational update operator in Tutorial D. (The names of the syntactic categories are meant to be intuitively self-explanatory.) ::= := | | <delete> | ::= <delete> ::= ::=
INSERT DELETE | DELETE [ WHERE ] UPDATE [ WHERE ] : { }
And an , if the attribute in question is relation valued, is basically just a (except that the pertinent appears in place of the target in that ), and that’s where we came in. Here then are Tutorial D statements for the required updates: a.
INSERT SP RELATION { TUPLE { ‘S2’ , ‘P5’ , 500 } } ;
b.
UPDATE SPQ WHERE SNO = ‘S2’ : { INSERT PQ RELATION { TUPLE { PNO ‘P5’ , QTY 500 } } } ;
4.16 No answer provided—except to note that I was just as confused as everybody else, back in 1995! (But at least I corrected my error in subsequent editions of the subject book.) CHAPTER 5 5.1 The join of a single relation, JOIN{r}, is just r; the join of no relations at all, JOIN{}, is TABLE_DEE (the only relation of degree zero and cardinality one). For further explanation, see SQL and Relational Theory. 5.2
See the body of the chapter.
5.3 FDs c. and d. (only) are trivial. All eight FDs a.- h. are satisfied by the current value of relvar S. All but h. hold in relvar S. FDs a., c., e., and g. are irreducible with respect to relvar S; FDs b., d., and f. are reducible. (As for h., the question of irreducibility doesn’t arise, since that FD doesn’t hold in the relvar. Check the definition of FD irreducibility if you don’t immediately grasp this point.) 5.4 Heath’s Theorem (original version) says that if (a) relation r has heading H, (b) X, Y, and Z are subsets of H whose union is equal to H, and (c) r satisfies the FD X → Y, then (d) r is equal to the join of its projections on XY and XZ (where XY denotes the union of X and Y, and similarly for XZ). In what follows, I show the proof of this theorem in exhaustive detail. Note: The expression “t ∈ r” can be read as “tuple t appears in relation r.” First of all, consider the simplest possible case, in which X, Y, and Z are singleton sets (i.e., contain just one attribute each). Let the attributes in question be A, B, and C, respectively. Now, we know from the answer to Exercise 3.2 that no tuple of r is lost by taking the projections r1 over XY (= {A,B}) and r2 over XZ (= {A,C}),
Answers to Exercises / Appendix D
233
respectively, and then joining r1 and r2 back together again. I now show that, conversely, every tuple of the join is indeed a tuple of r (in other words, the join doesn’t generate any “spurious” tuples). Let (a,b,c) ∈ JOIN {r1,r2}. In order to generate such a tuple in the join, we must have (a,b) ∈ r1 and (a,c) ∈ r2. Hence there must exist tuples (a,b,c′) ∈ r and (a,b′,c) ∈ r for some b′ and some c′. But r satisfies {A} → {B}; hence b = b′, and so (a,b,c) ∈ r. The next simplest case is the one in which X, Y, and Z aren’t necessarily singleton sets but are pairwise disjoint. In this case, we can regard the attributes constituting X as a single composite attribute (and similarly for Y and Z), and the argument of the previous paragraph then applies directly. We now need to consider what happens if X, Y, and Z aren’t pairwise disjoint. There are three cases to consider: X and Y not disjoint, X and Z not disjoint, and Y and Z not disjoint. First, then, let X and Y not be disjoint, but let X and Z be disjoint and let Y and Z be disjoint (hence Z = + H - XY). Recall now that if X → Y is satisfied, then so is X → Y for all subsets Y of Y. It follows that the FD X → Y - X is satisfied. But X and Y - X are disjoint; by the previous result, therefore, r is equal to the join of its projections on (a) the union of X and Y - X and (b) XZ. But (again) X and Y - X are disjoint, so their union is equal to XY. So the theorem applies in this case also, and we can (and I will) assume without loss of generality in the remainder of the proof that X and Y are disjoint. Now let X and Z not be disjoint, but let Y and Z be disjoint. By the previous result, then, r is equal to the join of its projections on (a) XY and (b) the union of X and Z - X. But the union of X and Z - X is equal to XZ. So the theorem applies in this case also, and we can (and I will) assume without loss of generality in the remainder of the proof that X and Z are disjoint. Now let Y and Z not be disjoint. Let W = Z - Y. Since r satisfies the FD X → Y, then, it also satisfies the FD X → Y - W, and Y - W and Z are disjoint. By the previous result, therefore, r is equal to the join of its projections on (a) the union of X and Y - W and (b) XZ. I now appeal to a lemma, easily proved (see below), to the effect that if (a) r1 and r2 are projections of r such that JOIN{r1,r2} = r, (b) H′ is a subset of H but a superset of the heading of r1, and (c) r′ is the projection of r on H′, then (d) JOIN{r′,r2} = r; in other words, loosely, r1 can be extended with arbitrary attributes of r2 without altering the result of the join. From this lemma, it follows immediately that r is equal to the join of its projections on XY and XZ; so the theorem applies in this case also. Conclusion: Heath’s Theorem is valid in all possible cases. Lemma: Let r have heading H and let H be partitioned into A, B, C, and D, and assume for simplicity that none of these four subsets is empty. (Extending the proof to cover the case where that assumption fails to hold is left as a subsidiary exercise.) Without loss of generality, we can treat A, B, C, and D as if they were individual attributes. So let r1 = R{A,B} and r2 = r{B,C,D}, and let (a,b) ∈ r1 and (b,c,d) ∈ r2. Since r = JOIN{r1,r2}, it follows that (a,b,c,d) ∈ r; hence (a,b,c) ∈ r{A,B,C} and (b,c,d) ∈ r{B,C,D}; hence (a,b,c,d) ∈ JOIN{r{A,B,C},r{B,C,D}}. The desired result follows─r{B,C,D} is r2, and r{A,B,C} can be taken as r′, with H′ = {A,B,C}. End of lemma. The converse of Heath’s Theorem would say that if relation r is equal to the join of its projections on XY and XZ, then r satisfies the FD X → Y. This converse is false. To show this is so, it’s sufficient to exhibit a counterexample. So consider a relvar CTX, with attributes CNO (course), TNO (teacher), and XNO (textbook), and predicate Course CNO can be taught by teacher TNO and uses textbook XNO. Here’s a sample value for this relvar:
234
Appendix D / Answers to Exercises
┌─────┬─────┬─────┐ │ CNO │ TNO │ XNO │ ├═════┼═════┼═════┤ │ C1 │ T1 │ X1 │ │ C1 │ T1 │ X2 │ │ C1 │ T2 │ X1 │ │ C1 │ T2 │ X2 │ └─────┴─────┴─────┘ This sample value is equal to the join of its projections on {CNO,TNO} and {CNO,XNO}, but it clearly fails to satisfy the FD {CNO} → {TNO} (or the FD {CNO} → {XNO}, come to that). Note: I’ll have more to say about this particular example in Chapter 12. 5.5
See the body of the chapter.
5.6 Suppose we start with a relvar with attributes D, P, S, L, T, and C corresponding to parameters of the predicate in the obvious way. Then the following nontrivial FDs hold in that relvar: { { { {
L D D D
} → { , P , C } → { , P , T } → { , P , S } → {
D L L L
, , , ,
P T C C
, C , T } } } , T }
A possible set of BCNF relvars is:5 SCHEDULE { L KEY KEY KEY
, { { {
D L D D
, P , C , T } } , P , C } , P , T }
STUDYING { S , L } KEY { S , L } Note that the FD {D,P,S} → {L,C,T} is “lost” in this decomposition (see Chapter 6). 5.7
The simplest design is: EMP
{ ENO , ENAME , SALARY } KEY { ENO }
PGMR { ENO , LANG } KEY { ENO } FOREIGN KEY { ENO } REFERENCES EMP Every employee has a tuple in EMP (and EMP has no other tuples). Employees who happen to be programmers additionally have a tuple in PGMR (and PGMR has no other tuples). Note that the join of EMP and PGMR gives full information─employee number, name, salary, and language skill─for programmers (only).
5
Subsidiary exercise: What are the predicates for these relvars?
Answers to Exercises / Appendix D
235
The only significant difference if programmers could have an arbitrary number of language skills is that relvar PGMR would be “all key” (i.e., its sole key would be {ENO,LANG}). 5.8
Yes, they are (of course!).
CHAPTER 6 6.1
CONSTRAINT ... COUNT ( JOIN { TJ , TS } ) = COUNT ( ( JOIN { TJ , TS } ) { S , J } ) ;
Or, using the alternative style for constraints described in the answer to Exercise 4.8: CONSTRAINT ... JOIN { TJ , TS } KEY { S , J } ; 6.2 Let LT and CT be the projections of RX2A′ on {CLASS,STATUS} and {CITY,STATUS}, respectively. Then (a) {CLASS} and {CITY} will be foreign keys in RX2B′, referencing LT and CT, respectively, and (b) the following multirelvar constraint will also hold: CONSTRAINT ... WITH ( LTX := LT RENAME { STATUS AS X } , CTY := CT RENAME { STATUS AS Y } ) : AND ( JOIN { RX2B′ , LTX , CTY } , X = Y ) ; 6.3 The first of the given FDs means {STREET,CITY,STATE} is a key; the second means the relvar isn’t in BCNF. However, if we use Heath’s Theorem to decompose it (on the basis of the FD {ZIP} → {CITY,STATE}) into BCNF projections as follows─ ZCT { ZIP , CITY , STATE } KEY { ZIP } ZR
{ ZIP , STREET } KEY { ZIP , STREET }
─then we lose the FD {STREET,CITY,STATE} → {ZIP}. As a result, relvars ZCT and ZR can’t be independently updated. (Subsidiary exercise: Develop some sample values for ZCT and ZR to illustrate this point.) Of course, if we don’t perform this decomposition, there’ll be some redundancy; to be specific, the fact that a given zip code corresponds to a particular city and state will appear several times. But does that redundancy cause problems? Given that the zip code for a given city and state doesn’t change very often, the answer is “possibly, but not very often.” (On the other hand, it’s not true to say zip codes never change.) 6.4
Here’s an irreducible cover for RX1: { SNO , PNO } → { QTY } { SNO } → { CITY } { CITY } → { STATUS}
The 3NF procedure yields {SNO,PNO,QTY}, {SNO,CITY}, and {CITY,STATUS}. Next, RX3. An irreducible cover:
236
Appendix D / Answers to Exercises
{ SNO } → { CLASS } { CLASS } → { CITY } { CITY } → { STATUS } The 3NF procedure yields {SNO,CLASS}, {CLASS,CITY}, and {CITY,STATUS}. Finally RX2. Irreducible cover: { { { {
SNO } SNO } CLASS } CITY }
→ → → →
{ { { {
CLASS } CITY } STATUS } STATUS }
The 3NF procedure yields {SNO,CLASS,CITY}, {CLASS,STATUS}, and {CITY,STATUS}. The interesting thing about this example is that (as was shown in the body of the chapter) if we decompose on the basis of the FD {SNO} → {CLASS,CITY}, we obtain {SNO,CLASS,CITY} and {CLASS,CITY,STATUS} as the 3NF projection headings, and that’s not what we get from the 3NF procedure. In fact, the result of the 3NF procedure requires the following rather complicated multirelvar constraint to be maintained: CONSTRAINT ... JOIN { SLC , LT } = JOIN { SLC , CT } ; (“for a given supplier, class status = city status”; SLC, LT, and CT here denote the projections of RX2 on {SNO,CLASS,CITY}, {CLASS,STATUS}, and {CITY,STATUS}, respectively). The example thus illustrates the point that although the 3NF procedure is certainly guaranteed to yield 3NF projections and not to lose any FDs, it probably shouldn’t be followed too blindly. Note: Suppose we were to name the status attributes in relvars LT and CT differently, thus: LT { CLASS , CLASS_STATUS } CT { CITY , CITY_STATUS } Then the constraint that the two status values must be equal for any given supplier might be stated thus: CONSTRAINT ... IS_EMPTY ( ( JOIN { SLC , LT , CT } ) WHERE CLASS_STATUS ≠ CITY_STATUS ) ; (The Tutorial D expression IS_EMPTY (r) returns TRUE if relation r is empty and FALSE otherwise.) Alternatively: CONSTRAINT ... AND ( JOIN { SLC , LT , CT } , CLASS_STATUS = CITY_STATUS ) ; The overall message of this example might be put this way: This whole business of losing or preserving FDs in particular is really just a special case of a more general phenomenon. In fact, it should be obvious that, in general, if we start with some design DBD1 and map it into some logically equivalent design DBD2, then that process will necessarily involve some restructuring of constraints as well as of relvars. 6.5 Assumptions: No star plays more than one role in any given movie; no movie has more than one director. (Are these assumptions reasonable?) FDs:
Answers to Exercises / Appendix D
{ { { { {
S M S B Z
, M } } } } , C }
→ → → → →
{ { { { {
R D B Z H
237
} , Y } } , C } }
{S,M} is a key. The BCNF procedure yields {S,M,R}, {M,D,Y}, {S,B}, {B,Z,C}, and {Z,C,H}. No FDs are lost.
CHAPTER 7 7.1
See the body of the chapter.
7.2 The closure F+ of a set F of FDs is the set of all FDs implied by those in F. The closure of the set of FDs that hold in the shipments relvar SP is given in the answer to Exercise 4.1. 7.3 The FD X → Y is satisfied if and only if whenever two tuples agree on X, they also agree on Y (I’m deliberately giving this definition in a pretty loose form). So: n
If two tuples agree on X, they certainly agree on every subset Y of X, so the reflexivity rule is reasonable.
n
If two tuples agree on XZ, they certainly agree on Z. They also certainly agree on X and hence, if X → Y is satisfied, on Y as well; hence they agree on YZ, and so the augmentation rule is reasonable.
n
If two tuples agree on X and X → Y is satisfied, they agree on Y. If they agree on Y and Y → Z is satisfied, they agree on Z. So the transitivity rule is reasonable.
7.4
See the body of the chapter.
7.5 Let U denote the intersection of Z and Y and let V denote the difference Z – Y between Z and Y (in that order). Then: 1. 2. 3. 4. 5. 6. 7.
X Z X XV XV XV XV
→ → → → → → →
Y W U UV Z W YW
(given) (given) (1, decomposition) (3, augmentation) (simplifying 4) (5, 2, transitivity) (1, 6, composition; this completes the proof)
The rules used in this proof are indicated in the comments. The following rules are all special cases of Darwen’s theorem: the union, transitivity, and augmentation rules. So too is the following useful rule: n
If X → Y and XY → Z, then X → Z.
Note: This latter is a special case of what’s sometimes called the pseudotransitivity rule, which in its general form looks like this:
238
n
Appendix D / Answers to Exercises
If X → Y and YW → Z, then XW → Z.
7.6
The first step is to rewrite the given set of FDs such that every FD has a singleton right side:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
AB C BC ACD BE CE CE CF CF D D
→ → → → → → → → → → →
C A D B C A F B D E F
Now: n
2 implies 6, so we can drop 6.
n
8 implies CF → BC by augmentation, which with 3 implies CF → D by transitivity, so we can drop 9.
n
8 implies ACF → AB by augmentation, and 11 implies ACD → ACF by augmentation, and so ACD → AB by transitivity, and so ACD → B by decomposition, so we can drop 4.
No further reductions are possible, and so we’re left with the following irreducible cover: AB C BC BE CE CF D D
→ → → → → → → →
C A D C F B E F
Alternatively: n
2 implies 6, so we can drop 6 (as before).
n
2 implies CD → AD by augmentation, which implies CD → ACD by augmentation again, which with 4 implies CD → B by transitivity, so we can replace 4 by CD → B.
n
2 and 9 imply CF → AD by composition, which implies CF → ADC by augmentation, which with (the original) 4 implies CF → B by transitivity, so we can drop 8.
No further reductions are possible, and so we’re left with the following irreducible cover:
Answers to Exercises / Appendix D
AB C BC CD BE CE CF D D
→ → → → → → → → →
239
C A D B C F D E F
Observe, therefore, that there are (at least) two distinct irreducible covers for the original set of FDs. Note too that those two covers have different cardinalities. 7.7 Yes, it is. The easiest way to prove this result is to compute the closure ACF+ of the set ACF, which turns out to be the entire set ABCDEFG. Alternatively, we can apply Armstrong’s axioms and the other rules discussed in the body of the chapter, as follows: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
A ACF BC BCF ACF ACF AEF ACF BC BC BCF BCF ACF ACF
7.8
Let’s number the FDs of the first set as follows:
1. 2. 3. 4.
A AB D D
→ → → → → → → → → → → → → →
→ → → →
B BCF E EF EF AEF G G DE D DF D D DG
(given) (1, augmentation) (given) (3, augmentation) (2, 4, transitivity) (5, augmentation) (given) (6, 7, transitivity) (given) (9, decomposition) (10, augmentation) (11, decomposition) (2, 12, transitivity) (7, 13, composition)
B C AC E
Now, 3 can be replaced by: 3.
D → A
and
D → C
Next, 1 and 2 together imply (see the “useful rule” mentioned near the end of the answer to Exercise 7.5) that 2 can be replaced by: 2.
A → C But now we have D → A and A → C, so D → C is implied by transitivity and can be dropped, leaving:
3.
D → A
240
Appendix D / Answers to Exercises
The first set of FDs is thus equivalent to the following irreducible cover: A A D D
→ → → →
B C A E
The second given set of FDs A → BC D → AE is clearly also equivalent to this same irreducible cover. The two given sets are thus equivalent. 7.9 The set is clearly reducible, since C → J and CJ → I together imply C → I. As for keys: An obvious superkey is ABCDGJ (the combination of all attributes mentioned on the left sides of the given FDs). We can drop J from this set because C → J, and we can drop G because AB → G. Since none of A, B, C, D appears on the right side of any of the given FDs, it follows that ABCD is a key.
CHAPTER 8 8.1 This exercise is (deliberately) a repeat in different words of Exercise 4.6. The claim is incorrect, as was shown in the answer to that earlier exercise. 8.2
Here are some of my own responses to the views expressed:
n
“Many queries are much easier to understand if the data is denormalized”: I suspect that understand here ought really to be formulate (for instance, understanding the query “Get all supplier details” has nothing to do with how the database is designed). If I’m right, then the claim might be valid. But the opposite claim is valid too!─many queries are easier to formulate if the data isn’t denormalized, as I showed in the body of the chapter.
n
The interviewer suggests that denormalization can cause integrity problems and can reduce flexibility in supporting unanticipated queries. I agree with these suggestions.
n
“Normalization, and its emphasis on elimination of redundant storage, is purely a transaction processing issue”: Normalization is about reducing redundancy, not reducing redundant storage─though I suppose the consultant might be forgiven for conflating the two, given the implementations most widely available today. But it’s certainly not “a transaction processing issue”! As I put it in Chapter 1, when we do database design in general, and when we do normalization in particular, we’re concerned primarily with what the data is, not with how it’s going to be used.
n
“When users view data, they see it in a redundant form”: Sometimes they do, sometimes they don’t. But even if they do, that’s not an argument for a denormalized design; for example, the user could be presented with a denormalized perception of the data by means of the conventional view mechanism, while the underlying database remains properly normalized.
Answers to Exercises / Appendix D
241
n
“In order to transform data into a form that is useful to users ...”: This is simply a tendentious remark.
n
“[Join] is essentially a way of dynamically denormalizing data for greater ease of use”: The user might think of joins being done dynamically, but there’s no reason in general why they can’t be done statically (i.e., ahead of time)─and I believe they often would be, given a well architected DBMS.6 It’s also untrue to suggest that the result of a join must always be denormalized. “Greater ease of use” is another tendentious remark.
n
“[Users] can’t tolerate the time and cost of joins”: Joins aren’t necessarily time consuming or expensive. Again, it depends on the implementation.
n
“To address the problem, companies replicate data in an ever increasing number of decision support databases, which represent denormalized views of the data”: This might be true, but if it is, it’s an indictment of current implementations, not an argument for denormalization as such.
8.3 First of all, surrogate keys are not the same thing as tuple IDs. For one thing (to state the obvious), surrogates identify entities and tuple IDs identify tuples, and there’s certainly nothing like a one to one correspondence between entities and tuples. (Think of derived tuples in particular─for example, tuples in the result of some query. In fact, it’s not at all clear that derived tuples will have tuple IDs anyway.) Furthermore, tuple IDs usually have performance connotations, but surrogates don’t (access to a tuple via its tuple ID is usually assumed to be fast, but no such observation applies to surrogates). Also, tuple IDs are usually concealed from the user, but surrogates mustn’t be, thanks to The Information Principle (see Exercise 2.1); in other words, it’s probably (and desirably!) not possible to store a tuple ID in a database relvar, while it certainly (and desirably) is possible to store a surrogate in a database relvar. In a nutshell: Surrogate keys have to do with logical design, tuple IDs have to do with physical design. Are surrogate keys a good idea? Well, observe first that the relational model has nothing to say on this question; like the business of design in general, in fact, whether or not to use surrogate keys has to do with how to apply the relational model, not with the relational model as such. That said, I have to say too that the question of whether surrogate keys are good or bad is far from straightforward. There are strong arguments on both sides: so many such, in fact, that I can’t possibly do justice to them here (though some of them are summarized in Chapter 15). For further details, see the paper “Composite Keys,” in my book Relational Database Writings 1989-1991 (Addison-Wesley, 1992). Note: The paper is called “Composite Keys” because surrogate keys are most likely to be useful in practice in situations in which existing keys, and corresponding foreign keys, are composite keys specifically. 8.4
I show solutions in SQL, just for a change. Defining the first in terms of the second (in outline): SELECT DISTINCT EX.ENO , ( SELECT PAY FROM EMP AS EY WHERE EY.ENO = EX.ENO AND MONTH = ‘Jan’ ) AS JAN_PAY , ...
6 I have in mind here, primarily, a DBMS implemented using the facilities of The TransRelationaltm Model (and a similar remark applies to all of my uses of that phrase “well architected” throughout the present book). You can find a preliminary (and very incomplete) description of that model in my book An Introduction to Database Systems (8th edition, Addison-Wesley, 2004), and a much more comprehensive account in my book Go Faster! The TransRelationaltm Approach to DBMS Implementation (Ventus, 2002,2011).
242
Appendix D / Answers to Exercises
( SELECT FROM WHERE AND FROM EMP AS
PAY EMP AS EY EY.ENO = EX.ENO MONTH = ‘Dec’ ) AS DEC_PAY EX
Defining the second in terms of the first (again in outline): SELECT ENO , ‘Jan’ AS MONTH , JAN_PAY AS PAY FROM EMP UNION ... UNION SELECT ENO , ‘Dec’ AS MONTH , DEC_PAY AS PAY FROM EMP CHAPTER 9 9.1 Joining SP and PJ is discussed in the body of the chapter. Joining PJ and JS yields the spurious tuple (S2,P2,J1), which is then eliminated because there’s no (S2,P2) tuple in SP. Joining JS and SP yields the spurious tuple (S1,P2,J2), which is then eliminated because there’s no (P2,J2) tuple in PJ. 9.2
CONSTRAINT ... SPJ = JOIN { SPJ { SNO , PNO } , SPJ { PNO , JNO } , SPJ { JNO , SNO } } ;
9.3
First of all, we’ll presumably need three relvars for representatives, areas, and products, respectively: R { RNO , ... } KEY { RNO } A { ANO , ... } KEY { ANO } P { PNO , ... } KEY { PNO }
Now, if representative r is responsible for area a, and product p is sold in area a, and representative r sells product p, then r sells p in a. This is a 3-way cyclic rule. So if we were to have a relvar RAP looking like this─ RAP { RNO , ANO , PNO } KEY { RNO , ANO , PNO } (with the obvious predicate)─then the following JD would hold in that relvar: R { { RNO , ANO } , { ANO , PNO } , { PNO , RNO } } The relvar would thus be subject to redundancy. So let’s replace it by its three binary projections: RA { RNO , ANO } KEY { RNO , ANO } AP { ANO , PNO } KEY { ANO , PNO } PR { PNO , RNO } KEY { PNO , RNO } (Now there are several equality dependencies that need to be stated and enforced─e.g., the projections R{RNO}, RA{RNO}, and PR{RNO} must always be equal─but the details are straightforward and I omit them here.) Next, each representative is responsible for sales in one or more areas, and each area has one or more responsible representatives. But this information is already contained in relvar RA, and nothing more is necessary. Similarly, relvar AP takes care of the facts that each area has one or more products sold in it and each product is sold
Answers to Exercises / Appendix D
243
in one or more areas, and relvar PR takes care of the facts that each product has one or more responsible representatives and each representative is responsible for sales of one or more products. Note, however, that the user does need to be told that the join of RA, AP, and PR does not involve any “connection trap” (i.e., that the 3-way cyclic rule holds). Let’s explore this point. First of all, the predicates for RA, AP, and PR are as follows: n
RA:
Representative RNO is responsible for area ANO.
n
AP:
Product PNO is sold in area ANO.
n
PR:
Product PNO is sold by representative RNO.
Note, incidentally, that a well architected DBMS─sadly, not one that’s on the market today, so far as I know─would allow the designer to tell it about these predicates. Note: Telling the DBMS about the predicates would serve to tell the user too, of course. The difference is that this latter can be done informally (in fact, it has to be done informally, in today’s systems), but the former, if it could be done at all, would have to be done formally (see Chapter 15). Back to the 3-way rule. Clearly the designer can’t just tell the user that the join of relvars RA, AP, and PR is equal to relvar RAP, because after the decomposition relvar RAP no longer exists. However, we might define that join as a view (or “virtual relvar”): VAR RAP VIRTUAL ( JOIN { RA , AP , PR } ) KEY { RNO , ANO , PNO } ; And that same well architected DBMS would then be able to infer the following as a predicate for view RAP: Representative RNO is responsible for area ANO and product PNO is sold in area ANO and product PNO is sold by representative RNO. But this predicate is less than the truth (it doesn’t capture the 3-way cyclic rule). Ideally, therefore, there ought to be a way for the designer to tell the DBMS (as well as the user) that the predicate is actually as follows:7 Representative RNO is responsible for area ANO and product PNO is sold in area ANO and product PNO is sold by representative RNO and representative RNO sells product PNO in area ANO. Note that this latter predicate is stronger than the former, in that if a certain (RNO,PNO,ANO) triple satisfies the latter, it certainly satisfies the former. 9.4
7
No answer provided.
This is thus one of those situations where the user (or in this case the designer) definitely knows more than the system does.
244
Appendix D / Answers to Exercises
CHAPTER 10 10.1 a. No (see the discussion of relvar SPJ in the body of the chapter for a counterexample). b. No (in fact, as was shown in the answer to Exercise 4.6, a binary relvar isn’t necessarily even in BCNF, or even in 2NF). c. No (see Chapter 13). d. No (again, see Chapter 13). e. See the body of the chapter. f. No (see relvar CTXD in Chapter 9 for a counterexample; see also Chapter 15). 10.2
See the body of the chapter.
10.3 First, I assume no JD has any repeated components, for otherwise the number of JDs would literally be infinite. Second, relvar SP is in 5NF, and in fact in 6NF; we haven’t discussed 6NF yet (see Chapter 13), but I can at least say that if a relvar is in 6NF, then all of the JDs that hold in that relvar will be trivial ones. So the question becomes: How many trivial JDs hold in relvar SP? Well, all such JDs take the form R{H,X1,...,Xn}, where H denotes the entire heading and {X1,...,Xn} is a set─possibly empty─of proper subsets of H. Since H is of degree three, it has eight subsets, of which all but one are proper. How many distinct sets are there whose elements are some subset of a prescribed set of seven elements? Well, there’s one such set with no elements at all; there are seven such sets with just one element; and, more generally, there are “7 pick i” such sets with i elements (i = 0, 1, ..., 7).8 So the total number of sets of proper subsets of H = (7 pick 0) + (7 pick 1) + (7 pick 2) + ... + (7 pick 7) = 1 + 7 + 21 + 35 + 35 + 21 + 7 + 1 = 128. So there are 128 trivial JDs that hold in relvar SP. Note: Of those 128, 64 involve an empty component, which might reasonably be ignored─for example, the JDs R{H,{}} and R{H} are clearly equivalent9─thereby reducing the total count to 64. 10.4
See the body of the chapter.
10.5 For the definition, see the body of the chapter. Since an FD isn’t a JD but merely implies one, a trivial FD isn’t a special case. However, the JD implied by a trivial FD is indeed itself trivial in turn. For example, the trivial FD {CITY,STATUS} → {STATUS} holds in the suppliers relvar S. Applying Heath’s Theorem, therefore, we see the trivial JD R{AB,AC} holds in S, where A is {CITY,STATUS}, B is {STATUS}, and C is {SNO,SNAME} (and hence AC is the entire heading). 10.6 For an example of a tuple forcing JD, see the SPJ example in the body of the chapter. As for one that’s not tuple forcing, consider, e.g., the JD R{{SNO,SNAME,CITY},{CITY,STATUS}} that holds in relvar S (which fails to be tuple forcing, observe, precisely because it has a component that’s a superkey for the pertinent relvar). 10.7 Examples can be obtained from the examples given in the body of the chapter in connection with relvar SPJ by systematically replacing supplier numbers by RNO values, part numbers by ANO values, and project numbers by PNO values. No further answer provided. 10.8 Well, obviously I don’t know whether you have any comments, but I certainly do. However, I don’t think it would be polite to air them here, so I won’t.
8
In general, the expression “n pick r” denotes the number of ways of picking r elements from a set of n elements.
9
Proof: For all relations r, JOIN{r{H},r{}} = JOIN{r} = r.
Answers to Exercises / Appendix D
245
CHAPTER 11 11.1 Which JDs are trivial? None. Which ones involve irrelevant components? i., k., and l. Which imply others? a. implies b.; d. implies g. and h.; e. implies g.; f. implies h. and i.; j. implies k. Which pairs are equivalent? None. Which are satisfied by the sample value in Fig. 1.1? a., b., c., d., e., g., and l. Which hold in relvar P? a., b., c., e., and l. Which are irreducible? a., b., c., and e. 11.2 a.
By Heath’s Theorem, the answer is obviously yes (take X as A, Y as BC, and Z as D). But let’s see if we can prove this result using the chase. Premise tuples: x1 x1
y12 x2
y13 x3
x4 y24
From the FD A → B, we have y12 = x2; from the FD A → C, we have y13 = x3. Make the replacements: x1 x1
x2 x2
x3 x3
x4 y24
Now we have a tuple of all x’s, and the desired result follows. The given JD does follow from the given JDs. b.
Premise tuples: x1 y21 y31
x2 x2 y32
y13 x3 x3
y14 y24 x4
The FDs imply y24 = x4 and y13 = x3. Make the replacements: x1 y21 y31
x2 x2 y32
x3 x3 x3
y14 x4 x4
The FD C → D now implies y14 = x4; making the replacement gives us a tuple of all x’s, and so the result follows: The given JD does follow from the given FDs. Note that we had to use one of the FDs twice in the chase in this example. Note too that we could have obtained the same result by applying Heath’s Theorem twice: The FD C → D implies the JD R{CD,CAB}, which in turn implies the JD R{CD,BC,BA}, thanks to the FD B → C. c.
I leave it to you to show the answer here is no.
d.
Premise tuples: x1 y21 y31
x2 x2 y32
y13 x3 x3
y14 y24 x4
Applying the JD R{BC,ABD} to the tuples with a common B value (viz., x2) generates the following tuples:
246
Appendix D / Answers to Exercises
x1 y21
x2 x2
x3 y13
y24 y14
We don’t obtain a tuple of all x’s, and so the “target” JD doesn’t follow from the given one; in fact, we now have a sample relation (of five tuples) that satisfies the latter and not the former. 11.3 1. 2. 3. 4.
Here first is a proof of part (b) of the extended theorem: X XZ XZ XZ
→ → → →
Y YZ XZ XYZ
(given) (augmentation) (self determination) (2 and 3, union)
Hence XZ is a superkey for R. As for the converse, suppose relvar R contains the following tuples: x x
y1 y2
z1 z2
Thanks to the JD R{XY,XZ}, the following tuples must then also appear: x x
y1 y2
z2 z1
But XZ is a superkey and so XZ → Y holds, so y1 = y2; hence X → Y holds. 11.4 This exercise is discussed further in Chapter 14, but I give a preliminary discussion here. First of all, suppose such a decomposition (i.e., on the basis of the second JD) were done. Let the projections so obtained be labeled SNC and CTN in the obvious way. Then the projections of SNC and CTN on {SNAME,CITY} are clearly equal; that is, the following equality dependency holds (see Chapter 13)─ CONSTRAINT ... SNC { SNAME , CITY } = CTN { SNAME , CITY } ; ─and relvars SNC and CTN thus suffer from redundancy. Observe further that the FD {CITY} → {STATUS} holds in CTN. By Heath’s Theorem, therefore, we can decompose CTN into its projections CT and CN on {CITY,STATUS} and {CITY,SNAME}, respectively. It follows that the JD R { { SNO , SNAME , CITY } , { CITY , STATUS , SNAME } } implies the JD R { { SNO , SNAME , CITY } , { CITY , STATUS } , { CITY , SNAME } } In this latter JD, however, the {CITY,SNAME} component is clearly irrelevant, since it’s a proper subset of the {SNO,SNAME,CITY} component; it can therefore be dropped without significant loss. (In fact, of course, this latter JD is identical to the first of the two JDs as given in the original exercise.)
Answers to Exercises / Appendix D
247
CHAPTER 12 12.1 (a) Relvar CTX in the body of the chapter is an example, of course, but it would be better if you could come up with an example from your own work environment. (b) Let C be a certain club, and let relvar R{A,B} be such that the tuple (a,b) appears in R if and only if a and b are both members of C. Then R is equal to the cartesian product of its projections R{A} and R{B}; thus, it’s subject to the JD R{A,B} and, equivalently, to the following MVDs: { } →→ A | B These MVDs aren’t trivial, since they certainly don’t hold in all binary relvars, and they’re not implied by a superkey either (the only key in R is the entire heading). It follows that R isn’t in 4NF. However, it’s certainly in BCNF, because it’s “all key.” 12.2
Possible formulations:
a.
CONSTRAINT ... CTX = JOIN { CTX { CNO , TNO } , CTX { CNO , XNO } } ;
b.
CONSTRAINT ... CTXD { CNO , TNO , XNO } = JOIN { CTXD { CNO , TNO } , CTXD { CNO , XNO } } ;
12.3 (a) Suppose the current value of CTX is as given in Fig. 12.1. Then none of the four tuples shown can be deleted in isolation: a deletion anomaly. (b) Suppose the current value of CTX contains just “the first two” of the tuples shown in Fig. 12.1. Then neither “the third” nor “the fourth” tuple shown can be inserted in isolation: an insertion anomaly. 12.4 Relvar SPJ from Chapter 9 is an example (no MVDs hold in that relvar at all, apart from trivial ones, and so the relvar is certainly in 4NF). 12.5 The following proof might be thought to make very heavy weather of such an obvious point: Let the projection in question be R′. The FD X → Y holds in R′ if and only if, whenever tuples t1′ and t2′ of R′ have the same X value, they also have the same Y value. Let T1 and T2 be, respectively, the set of tuples in R from which t1′ is derived and the set of tuples in R from which t2′ is derived. By the definition of projection, every tuple t1 in T1 has the same X and Y values as t1′; likewise, every tuple t2 in T2 has the same X and Y values as t2′. It follows that whenever tuples t1 and t2 of R have the same X value, they also have the same Y value; thus the FD X → Y holds in R. And it further follows that X → Y holds in R′ if and only if it holds in R. 12.6 This result is immediate from Heath’s Theorem: If R is subject to the FD X → Y, it’s also subject to the JD R{XY,XZ}, where Z is “the other” attributes of R, and therefore it’s subject to the MVDs X →→ Y | Z. 12.7 The JD R{XY,XZ} is trivial if and only if XY = H or XZ = H. If XY = H, we have Case (b). If XZ = H, then Z = H - X; but Z = H – X - Y by definition, so Y is a subset of X, and we have Case (a). 12.8 The rule amounts to saying: If we start with a relvar with two or more independent relation valued attributes (RVAs) and we want to eliminate them─which we usually but not invariably do want to do (see the answer to Exercise 4.11)─then the first thing we should do is separate those RVAs. Using the notation of the exercise, this step will give us relvars with headings XY and XZ, respectively. The next thing we should do is ungroup the RVA in
248
Appendix D / Answers to Exercises
each of those relvars. Suppose the relations in Y and Z have headings A and B, respectively; then the relvars that result from those ungroupings will have headings XA and XB, respectively.10 Now normalize those relvars in the usual way, replacing them by BCNF projections. Then those BCNF projections will “automatically” be in 4NF. In other words, MVDs that cause a relvar not to be in 4NF shouldn’t arise in practice, if the foregoing procedure is followed. It’s interesting to note, incidentally, that in his famous 1970 paper (see Appendix C), Codd gave an example in which he actually followed the foregoing procedure, and he touched on it again, briefly, in another paper the following year (“Normalized Data Base Structure: A Brief Tutorial,” Proc. 1971 ACM SIGFIDET Workshop on Data Description, Access, and Control, San Diego, Calif., November 11th-12th, 1971; again, see Appendix C). But I don’t think he ever mentioned it again, at least not in writing (because it was so intuitively obvious, perhaps). Note: In case you find the foregoing discussion too abstract, take R to be a relvar with heading {CNO,T,X}, where T and X are relation valued and contain relations with headings {TNO} and {XNO}, respectively. Separating the RVAs gives us relvars with headings {CNO,T} and {CNO,X}, respectively. Ungrouping then gives us relvars with headings {CNO,TNO} and {CNO,XNO}, respectively─which is precisely what we want, of course, in the CTX example. 12.9
First of all, we’ll presumably need three relvars for representatives, areas, and products, respectively: R { RNO , ... } KEY { RNO } A { ANO , ... } KEY { ANO } P { PNO , ... } KEY { PNO }
Next, we can represent the relationships (a) between sales representatives and sales areas and (b) between sales representatives and products by relvars like this: RA { RNO , ANO } KEY { RNO , ANO } RP { RNO , PNO } KEY { RNO , PNO } Every product is sold in every area. So if we introduce a relvar AP { ANO , PNO } KEY { ANO , PNO } to represent the relationship between areas and products, then we have the following constraint: CONSTRAINT C1 AP = JOIN { A { ANO } , P { PNO } } ; (The join here is actually a cartesian product.) Note that this constraint implies that AP isn’t in 4NF. In fact, AP doesn’t give us any information we can’t obtain from the other relvars. To be precise, the following EQDs hold: AP { ANO } = A { ANO } AP { PNO } = P { PNO } But let’s assume for the moment that relvar AP is included in our design anyway. No two representatives sell the same product in the same area. In other words, given an {ANO,PNO} combination, there’s exactly one responsible sales representative, RNO, and so we can introduce a relvar
10
We might have to do some attribute renaming first, if any attribute in either A or B has the same name as some attribute in X.
Answers to Exercises / Appendix D
249
APR { ANO , PNO , RNO } KEY { ANO , PNO } in which (to state the FD explicitly) { ANO , PNO } → { RNO } (Specification of {ANO,PNO} as a key is sufficient to express this FD.) However, relvars RA, RP, and AP are now all redundant, since they’re all projections of APR; they can therefore all be dropped. In place of constraint C1 we now need constraint C2: CONSTRAINT C2 APR { ANO , PNO } = JOIN { A { ANO } , P { PNO } } ; This constraint must be separately and explicitly stated, since it isn’t “implied by keys.” Also, since every representative sells all of that representative’s products in all of that representative’s areas, we have the additional constraint C3 on relvar APR: { RNO } →→ { ANO } | { PNO } (These MVDs are nontrivial and not implied by keys, and relvar APR is thus not in 4NF.)11 Again the constraint must be separately and explicitly stated. Thus the final design consists of the relvars R, A, P, and APR, together with the constraints C2 and C3 (both of which are in fact equality dependencies once again): CONSTRAINT C2 APR { ANO , PNO } = JOIN { A { ANO } , P { PNO } } ; CONSTRAINT C3 APR = JOIN { APR { RNO , ANO } , APR { RNO , PNO } } ; (There are also some foreign key constraints from APR to the other three relvars, but the details are straightforward and I omit them here.) This exercise illustrates very nicely the point that, in general, normalization might be adequate to represent some of the semantic aspects of a given problem (basically, FDs, MVDs, and JDs that are implied by keys), but explicit statement of additional constraints might be needed for other aspects. It also illustrates the point that it might not always be desirable to normalize “all the way” (relvar APR is in BCNF but not in 4NF). As a subsidiary exercise, you might like to consider whether a design involving RVAs might be appropriate for the problem under consideration. Might such a design mean that some of the comments in the previous paragraph no longer apply? 12.10 The first point to note here is that the MVDs A →→ B | C and A →→ C | D make no mention of attributes D and B, respectively. But didn’t I say the union of X, Y, and Z, given the generic pair of MVDs X →→ Y | Z, had to be equal to the heading? Well, yes, I did─but I must now explain that we allow a certain shorthand notation as well, illustrated in this exercise. For definiteness, let’s focus on the expression A →→ B | C. By definition, this expression means A →→ B and A →→ C; and A →→ B implies A →→ CD, and A →→ C implies A →→ BD. Moreover, since A, B, C, and D are single attributes and hence mutually disjoint, the decomposition rule for MVDs
11 Note, therefore, that relvar APR gives the lie to another popular misconception: viz., that a relvar consisting of a single key and a single nonkey attribute is necessarily in 4NF. See also the answer to Exercise 13.10, later in this appendix.
250
Appendix D / Answers to Exercises
allows us to infer A →→ D from either A →→ CD or A →→ BD. Putting this all together, we see that A →→ B | C is shorthand for either or both of A →→ B | CD and A →→ BD | C. Given this state of affairs, moreover, we adopt a shorthand according to which A →→ B | CD and A →→ BD | C can both be written thus: A →→ B | C | D─and this latter expression in turn can also be thought of as shorthand for the following three MVDs in combination: A →→ B, A →→ C, and A →→ D. Now let’s try the chase. Here are premise tuples for A →→ C | D, which as we’ve just seen is equivalent to A →→ BC | D: x1 x1
x2 y22
x3 y23
y14 x4
Applying A →→ B | CD generates: x1 x1
x2 y22
y23 x3
x4 y14
Applying B → D gives y14 = x4. Replacing: x1 x1 x1 x1
x2 y22 x2 y22
x3 y23 y23 x3
x4 x4 x4 x4
And now we have a tuple of all x’s, so the given dependencies do imply the target JD.
CHAPTER 13 13.1
See Fig. 13.1.
13.2
See the body of the chapter.
13.3 Irreducibility of keys and FDs, and the relevance of FD irreducibility to 2NF, are all discussed in Chapter 4; FD irreducibility is discussed further in Chapter 5. Irreducible covers are discussed in Chapter 6. Irreducible JDs are discussed in Chapter 11. Irreducible (i.e., 6NF) relvars and the associated notion of “irreducible facts” are discussed in the body of the present chapter (i.e., Chapter 13). 13.4
See the body of the chapter.
13.5 The main point that occurs to me is that it might be nice to have some kind of “master” relvar whose primary purpose is just to record the part numbers for all parts currently represented in the database. If we call that relvar P, there’ll be EQDs between that relvar P and the projection on {PNO} of each of the relvars PN, PL, PW, and PC (instead of EQDs between, arbitrarily, the projection of PN on {PNO} and the projection on {PNO} of PL, PW, and PC; indeed, one nice thing about having the master relvar is precisely that it avoids that slight arbitrariness). Moreover, suppose every part always has a known name and weight but doesn’t necessarily have a known color or city. Then we can combine relvars P, PN, and PW, making that combination─which I’ll still call P─the master relvar, and replace the EQDs previously required by foreign key constraints from PL and PC to that master relvar. (A part with no known color will be represented in P but not PL; likewise, a part with no known city will be represented in P but not PC.)
Answers to Exercises / Appendix D
251
Incidentally, another argument in favor of including that master relvar P has to do with the shipments relvar SP: Given that master relvar, we can retain the conventional foreign key constraint from SP to P; without it, life becomes rather messier. 13.6 Every pair of attributes is a key. The specified JD doesn’t hold, because the following is certainly a legitimate value for the relvar: a1 b1 a1 b2 a2 b1
b1 a1 b2 a1 b1 a2
c2 c2 c1 c1 c1 c1
(a1 ≠ a2, b1 ≠ b2, c1 ≠ c2); that is, the tuples (a1,b1,c2), (a1,b2,c1), and (a2,b1,c1) most certainly don’t force the tuple (a1,b1,c1) to appear (!). The relvar is in 6NF. Note, however, that it’s subject to a certain symmetry constraint; to be specific, the tuple (a,b,c) appears if and only if the tuple (b,a,c) appears (see the sample value above for an illustration of this point).12 As a consequence, the relvar is also subject to certain insertion and deletion anomalies, and it isn’t in DK/NF. 13.7 Let relation r have heading H. Then r will certainly satisfy all possible FDs and JDs that can be defined with respect to H if r has cardinality either one or zero. Thus, all possible sets of dependencies (FDs and JDs) are consistent (though some such sets might have the implication that any relation that satisfies them can have cardinality at most one). 13.8
The following is certainly a legitimate value for relvar SPJ′─ s1 s2
p1 p1
j1 j1
(s1 ≠ s2)─so {PNO,JNO} isn’t a key. Likewise, the following is also a legitimate value for SPJ′─ s1 s1
p1 p2
j1 j1
(p1 ≠ p2)─so {JNO,SNO} isn’t a key either. 13.9
The thing to do here is to separate matches that have already been played from those that haven’t: PAST_MATCHES { DATE , OPPONENT , GOALS_FOR , GOALS_AGAINST , ... } KEY { DATE } FUTURE_MATCHES { DATE , OPPONENT , ... } KEY { DATE }
These relvars are both in 5NF. PAST_MATCHES in particular probably shouldn’t be replaced by 6NF projections. 13.10 Yes, we can define it as a view: 12
So do you think this relvar is subject to redundancy? Justify your answer!
252
Appendix D / Answers to Exercises
VAR SCP VIRTUAL ( ( JOIN { S , SP , P } ) { SNO , PNO , CITY } ) ; The following FD holds in this view: { SNO , PNO } → { CITY } (in fact, {SNO,PNO} is a key). The following (nontrivial) MVDs also hold: { CITY } →→ { SNO } | { PNO } Because of these MVDs, relvar SCP isn’t in 4NF, though it is in BCNF. As for “conventional wisdom,” this example gives the lie to another popular misconception: viz., that a relvar consisting of a single key and a single nonkey attribute is necessarily in 6NF, or at least 5NF (see Exercise 1.8). 13.11 For the definition, see the body of the chapter. As for an example, suppose relvar SP is subject to a constraint to the effect that odd numbered parts can be supplied only by odd numbered suppliers and even numbered parts only by even numbered suppliers (the example is very contrived, of course, but it suffices for the purpose at hand). Then this constraint is clearly not implied by the domain and key constraints that hold in relvar SP, and so the relvar isn’t in DK/NF; yet it’s certainly in 6NF. 13.12 There certainly is a difference, since overstrong PJ/NF implies 5NF and 5NF implies SKNF and the reverse implications don’t hold. But it’s easy to confuse the two, because the following superficially similar observations are both true (note the boldface): n
Relvar R is in SKNF if and only if, for every irreducible JD R{X1,...,Xn} that holds in R, each Xi (i = 1, ..., n) includes some key K of R.
n
Relvar R is in overstrong PJ/NF if and only if, for every irreducible JD R{X1,...,Xn} that holds in R, each Xi (i = 1, ..., n) includes the same key K of R.
13.13 Apologies if you think these definitions a little late in coming: n
Definition: Let r be the relation and let c be a boolean expression in which every attribute reference identifies some attribute of r and there aren’t any relvar references. Then c is a restriction condition, and the restriction of r according to c, r WHERE c, is the relation , where x is the set of all tuples of r for which c evaluates to TRUE.
n
Definition: Let relations r1, ..., rn (n ≥ 0) all have the same heading H. Then the union of r1, ..., rn, UNION {r1,...,rn}, is a relation with heading H and body the set of all tuples t such that t appears in at least one of r1, r2, ..., rn. (If n = 0, some syntactic mechanism, not shown here, is needed to specify the pertinent heading H, and the result is the unique empty relation having that heading.) Observe that union as here defined is an n-adic operator, not a dyadic operator merely.
13.14 Loosely speaking, a disjunction of predicates is the OR of two or more other predicates. If some relvar R had a disjunctive relvar predicate, then each of the individual predicates that are OR’d together would have to have the same parameters (because the tuples that satisfy them would all have to be of the same type). Reducing such a predicate to simple predicates would involve decomposition of the relvar via restriction instead of projection (and
Answers to Exercises / Appendix D
253
recomposition via union instead of join). Indeed, that’s exactly what the final subsection in the body of the chapter was all about. More specifics are given in Part IV of this book.
CHAPTER 14 14.1
See the body of the chapter.
14.2
No answer provided.
14.3
No, it isn’t. See the further remarks on examples of this kind in Chapter 15.
14.4 The design doesn’t violate orthogonality, but there are several other things wrong with it. For example, how would you express the query “Get the city for supplier S1”? (There are two cases to consider: one where you do at least know what supplier cities exist, and one where you don’t. In the latter case, you might want to think about this query too: “Is supplier S1 represented in the database?”) Also, what’s happened to the FD {CITY} → {STATUS}? And what about the {SNO} foreign key in relvar SP? (Again there are two cases to consider─the same two cases as before, in fact.) Next, if we did keep the CITY attribute in relvars LS, PS, etc., then the FD {} → {CITY} would hold in each of those relvars. Since this FD isn’t “an arrow out of a key,” the relvars wouldn’t be in BCNF. (See the answer to Exercise 4.6, where an essentially similar example is discussed.) What’s more, given that the FD {CITY} → {STATUS} holds in the original suppliers relvar S, it certainly still holds in relvars LS, PS, etc.─assuming, that is, that we keep the CITY attribute in those relvars─and so again those relvars aren’t in BCNF. Finally, regardless of whether we keep the CITY attribute or not, the FD {} → {STATUS} also holds in each of those relvars, and so yet again the relvars wouldn’t be in BCNF. Note, therefore, that the FD {CITY} → {STATUS}, if it holds at all (which it does only if the CITY attribute is retained), is in fact reducible, under the suggested horizontal decomposition.
CHAPTER 15 15.1 If you have a good answer to this exercise, please communicate it to me at PO Box 1000, Healdsburg, CA 95448, USA (regular mail only, please).
Index For alphabetization purposes, (a) differences in fonts and case are ignored; (b) quotation marks are ignored; (c) other punctuation symbols─hyphens, underscores, parentheses, etc.─are treated as blanks; (d) numerals precede letters; (e) blanks precede everything else.
→ (FD arrow), 21 →→ (MVD double arrow), 131 R (JD star), 98 ∈ (set membership), 99,130,232 0-tuple, 226,230 1NF, see first normal form 2NF, see second normal form 3NF, see third normal form 3NF procedure, 67 (3,3)NF, 152 4NF, see fourth normal form 5NF, see fifth normal form 6NF, see sixth normal form Abbey, Edward, 19 Abbot, Bud, 129 Abiteboul, Serge, 127 Adamson, Chris, xiii,88 Adiba, Michel, 192 Aho, A.V., 220 ALL BUT, 28 all key, 42 alternate key, 8,203 AND (aggregate operator), 21-22,161 Armstrong, Louis, 3 Armstrong, W.W., 75,220 Armstrong’s axioms, 75 “arrow out of X,” 41 “atomic fact,” 142 attribute, 50 attribute-name / type-name pair, 17 multivalued, see multivalued attribute relation valued, see relation valued attribute tuple valued, see tuple valued attribute axiomatization FDs, 76 MVDs, 134 not for JDs, 127
Bacon, Francis, 75 base relvar, 16 BCNF, see Boyce/Codd normal form BCNF procedure, 70 Beeri, Catriel, 220 Bennett, Alan, 203 body relation, 17,50 relvar, 50 bound variable, 194 Boyce, Raymond F., 46,47 Boyce/Codd normal form, 45,52ff explanation of name, 46-47 Brown, Robert R., 10 business rule, 60 candidate key, 7,42 canonical form, 35 cardinality, 17 Carroll, Lewis, 175 Casanova, Marco A., 221 chase algorithm, 123ff Churchill, Winston, 139 Closed World Assumption, The, 19,179,186,225 closure relational algebra, 23,227 set of attributes, 79 set of FDs, 76,227 Codd, E. F., passim commalist, 7 common sense, 10 completeness, 76 component (JD), 98,107 composite key, 8 connection trap, 101 connective, 142 CONSTRAINT, 21,230 name, 21,30
256
Index
contain vs. include, 224 contradiction, 72 Costello, Lou, 129 cover (FDs), 68 CWA, see Closed World Assumption, The cyclic rules, 103 D, 20 da Vinci, Leonardo, 10 Darling, David, 157 Darwen, Hugh, passim data model first sense, 5 second sense, 6 database professional, 15 Date, C. J., passim Dawkins, Richard, 223 DBMS, xii decomposition, see nonloss decomposition DEE, see TABLE_DEE degree, 17 deletion anomaly, 150,227 and BCNF, 32 and 5NF, 115 denormalization, 83ff considered harmful, 90ff increasing redundancy, 85 dependency, 33 implicit, see implicit dependencies dependency preservation, 59ff,134 dependant FD, 41,50 MVD, 132 determinant FD, 41,50 MVD, 132 Dickinson, Emily, 107 Dijkstra, Edsger W., iii dimension table, 88 DK/NF, see domain-key normal form domain, 149,224-225 domain constraint (DK/NF), 149 domain-key normal form, 149-150 double underlining, 8,231 DUM, see TABLE_DUM duplicate tuples, 164 see also tuple equality
E-relvar, 183 E/R modeling, xii,179 EKNF, see elementary key normal form elementary key, 151 elementary key normal form, 151 Elmasri, Ramez, 48 embedded dependencies, 135 empty key, 23,226 empty restriction, 72 empty tuple, 23,226 entity integrity, 204 entity/relationship modeling, see E/R modeling entity supertype/subtype, 181,214 EQD, see equality dependency equality, 226 relation, see relation equality tuple, see tuple equality equality dependency, 30,140 equality generating dependency, 124 equivalence JDs, 119 sets of FDs, 81 essential, 222 essential tuple normal form, 145,216,221-222 ETNF, see essential tuple normal form existential quantifier, 194 EXISTS, 99,179 explicit dependencies, 123 EXTEND, 190 fact table, 88 factorial, 230 Fagin, Ronald, passim Fagin’s Theorem, 132,220 Fallacy of False Conversion, The, 86 FD, 21,40ff,50ff axiomatization, 76 of a relvar, 51 not a JD, 114 trivial, 41,52 FD graph, 72 FD redundant, 146,221 fifth normal form, 110 not necessarily redundancy free, 104 first normal form, 37ff relation, 38 relvar, 38 table, 39
Index
FORALL, 179 foreign key, 8 fourth normal form, 133 Boyce, 47 Frege, Gottlob, 179 fully redundant, 221 functional dependency, see FD see also Boyce/Codd normal form further normalization, 27 Garcia-Molina, Hector, 48 Gehrke, Johannes, 48 “getting rid of” (constraints), 53-54 GROUP, 231 group/ungroup normal form, 181 Hall, Patrick, 188 Hamdan, Sam, 84 heading, 49 relation, 17,50 Heath, Ian, 55,220 Heath notation, 75 Heath’s Theorem, 54ff,99,219,232-234 extended version, 128 Hesiod, iii hold (in a relvar) FD, 51 JD, 108 horizontal decomposition, 160 Howard, John H., 220 Hull, Richard, 127 IDENTICAL, 184 identity decomposition, 71 identity restriction, 71 identity projection, 71 image relation, 190 implicit dependencies, 117ff ,123 implied by keys FD, 53 JD, 109 MVD, 133 implied by superkeys, see implied by keys IMS, 38 include vs. contain, 224 inclusion dependency, 140 IND, see inclusion dependency independent projections, 73
information equivalence, 28 Information Principle, The, 224,241 insertion anomaly, 150,227 and BCNF, 32 and 5NF, 115 instance, see relation schema instantiation, 18 integrity constraint, see constraint irreducibility cover, 68,77 “fact,” 142 FD, 43,52 JD, 119 key, 42 relvar, 141 irrelevant component (JD), 118 IS_EMPTY, 170,236 JD, 98,107 implied by superkeys, 109,110ff of a relvar, 108 trivial, 109 see also fifth normal form; sixth normal form JD redundant, 146,221-222 join, 50 of no relations, 57 of one relation, 57,111,232 join dependency, see JD joinable, 50 KCNF, see key complete normal form key, 7,42ff,53 key attribute, 42 key constraint, 21,53,149 key complete normal form, 216 Kimball, Ralph, 89 Korth, Henry F., 48 Lindsay, Bruce G., 192 logical vs. physical design, xii,8,175,241 Lorentzos, Nikos A., x,190,221 losing dependencies see dependency preservation lossless decomposition see nonloss decomposition lossy decomposition, 54 lossy join, 29,54-55
257
258
Index
“materialized view,” 175 McGoveran, David, xiii,221 Melzak, Z.A., 37 membership algorithm, 110 missing information, 143,169 modification anomaly, 32,227 multiple assignment, 178 multirelvar constraint, 34,54,73,110,130,134 multivalued attribute, 40 multivalued dependency, see MVD MVD, 129,131ff implied by superkey, 133 shorthand notation, 137,249 trivial, 133 see also fourth normal form n pick r, 244 natural join, see join Navathe, Shamkant B., 48 Nixon, Richard M., 36 nonkey attribute, 42 nonloss decomposition, 28 nonprime attribute, 42 normal form, 36 hierarchy, 32,139 normalization, 27,36 and constraints, 34 conventional procedure, 63ff decreasing redundancy, 85 goals, 157 principles, 157 two purposes, 29ff,227 normalized, 38 null, 40,224 Open World Assumption, The, 225 orthogonal decomposition, 159 orthogonality, 159 overstrong PJ/NF, 151 OWA, see Open World Assumption, The Owlett, John, 188 P-relvar, 183 Papadimitriou, Christos H., 221 partly redundant, 221 Pascal, Fabian, 190 physical design, see logical design
PJ/NF, see fifth normal form PJSU/NF, 152 PK:AK distinction, 204 plausible tuple see Closed World Assumption, The Polya, George, 187 predicate, 18 composite / compound, 141 conjunctive, 142 empty set of parameters, 23,226 overlapping, 161 relvar, see relvar predicate simple, 141 preserving dependencies, see dependency preservation primary key, 8,203ff prime attribute, 42 Principle of Cautious Design, The, 206 Principle of Interchangeability, The, 16,204,208 Principle of Orthogonal Design, The, 159ff “final” definition, 168 principles of normalization, see normalization projection, 21,28,50 projection-join normal form, 104,110 proper subset, see subset proper superset, see superset proposition, 19 quantifier, 179 see also EXISTS; FORALL Ramakrishnan, Raghu, 48 redundancy, 163,175ff controlled, 193 “final” definition, 196 managing, 191-193 revisited, 215ff Vincent’s definition, 215 redundancy free, 147 redundancy free normal form Darwen, Date, and Fagin, 100,144ff Vincent, 215 refresh, see snapshot regular column, 40 relation, 50 vs. relvar, 16ff see also relvar relation constant, 142,207
Index
relation equality, 225 relation schema, 20 relation value, see relation relation valued attribute, 37,189 relation variable, see relvar relational assignment, 232 relvar, 50 constraint, see relvar constraint predicate, see relvar predicate virtual, see view vs. relation, 159ff see also relation relvar constraint, 150 the (total) relvar constraint, 179 relvar predicate, 178 RENAME, 21,226 repeating group, 40 restriction, 252 “restriction-union” normal form, 151 RFNF, see redundancy free normal form Rissanen, Jorma, 73,220 Rissanen’s Theorem, 73 RM/T, 183 Russell, Bertrand, 12 RVA, see relation valued attribute satisfy (by a relation) FD, 51 JD, 108 MVD, 132 second normal form, 43 two definitions, 44,229 Sellar, W.C., 219 semantic vs. syntactic definition, 52 Shakespeare, William, 19 Silberschatz, Abraham, 48 simple key, 8 sixth normal form, 141 SKNF, see superkey normal form Skolem, T.A., 194 skolemization, 194 Smith, J.M., 152 snapshot, 192 soundness, 76 SQL and Relational Theory, xi star schemas, 88 Steele, Richard, iii Stoppard, Tom, 139
subject to, see hold subkey, 43 proper, 43 subset, 35,224 proper, 35,224 Sudarshan, S., 48 SUMMARIZE, 190 superkey, 43,52 proper, 43 superkey constraint, 52 superkey normal form, 144 superset, 224 proper, 224 surrogate, 113,188,241 symmetry, 187,207,251 table, 39 TABLE_DEE, 71,225 TABLE_DUM, 71,225 tableau, 125 tautology, 72 temporal data, 190 Third Manifesto, The, 20 third normal form, 45 Todd, Stephen, 188 TransRelational Model, 241 trivial dependency, see FD; JD; MVD tuple, 49 vs. entity, 241 vs. proposition, 163-164 tuple equality, 225 tuple forcing JD, 103,146 tuple generating dependency, 124 tuple ID, 241 tuple projection, 49,226 tuple valued attribute, 180 Tutorial D, 20 TVA, see tuple valued attribute Ullman, J.D., 48,220 UNGROUP, 137,231 union, 252 uniqueness (key), 42 UNWRAP, 180 update anomaly, 31,227 and BCNF, 32,61-62 and 5NF, 115 update propagation, 193
259
260
Index
vertical decomposition, 160 Vianu, Victor, 127 view, 16 “materialized,” see snapshot Vincent, Millist W., 145,215 violate (by a relation) FD, 51 JD, 108 MVD, 132 virtual relvar, see view “well architected,” 241 Widom, Jennifer, 48 WITH, 21 Wittgenstein, Ludwig, 15 wrap/unwrap normal form, 181 XML, 38 Yeatman, R.J., 219 Zaniolo, Carlo, 150