SCALAR vs. NONSCALAR TYPES

It’s usual to think of types as being either scalar or nonscalar. Loosely, a type is scalar if it has no user visible components and nonscalar otherwise—and values, variables, attributes, operators, parameters, and expressions of some type T are scalar or nonscalar according as type T itself is scalar or nonscalar. For example:

  • Type INTEGER is a scalar type; hence, values, variables, and so on of type INTEGER are also all scalar, meaning they have no user visible components.

  • Tuple and relation types are nonscalar—the pertinent user visible components being the corresponding attributes—and hence tuple and relation values, variables, and so on are also all nonscalar.

That said, I must now emphasize that these notions are quite informal. Indeed, we’ve already seen that the concept of data value atomicity has no absolute meaning, and “scalarness” is just that same concept by another name. Thus, the relational model certainly doesn’t rely on the scalar vs. nonscalar distinction in any formal sense. In this book, however, I do rely on it informally; I mean, I do find it intuitively useful. To be specific, I use the term scalar in connection with types that are neither tuple nor relation types, and the term nonscalar in connection with types that are either tuple or relation types.[29]

Aside: Another term you’ll sometimes hear used to mean “scalarness” is encapsulation. Be aware, however, that this term is also used—especially in object contexts—to refer to the physical bundling, or packaging, of code and data (or operator definitions and data representation definitions, to be more precise). But to use the term in this latter sense is to mix model and implementation considerations; clearly the user shouldn’t care, and shouldn’t need to care, whether code and data are physically bundled together or are kept separate. End of aside.

Let’s look at an example. Here’s a Tutorial D definition for the base relvar S (“suppliers”)—and note that, for simplicity, I now define the attributes all to be of some system defined type:

  1. VAR S BASE
  2.     RELATION { SNO CHAR , SNAME CHAR , STATUS INTEGER , CITY CHAR }
  3.     KEY { SNO } ;

Explanation:

  • The keyword VAR in line 1 means this is a variable definition; S is the name of that variable, and the keyword BASE means the variable is a base relvar specifically.

  • Line 2 specifies the type of this variable. The keyword RELATION shows it’s a relation type; the rest of the line specifies the set of attributes that make up the corresponding heading (where, as you’ll recall from Chapter 1, an attribute is defined to be an attribute-name/type-name pair, and no two attributes in the same heading have the same attribute name). The type is, of course, a nonscalar type. No significance attaches to the order in which the attributes are specified.

  • Line 3 defines {SNO} to be a (candidate) key for this relvar.

    In fact, the example also illustrates another point—namely, that the type

    RELATION { SNO CHAR , SNAME CHAR , STATUS INTEGER , CITY CHAR }

is an example of a generated type. A generated type is a type that’s obtained by invoking some type generator (in the example, the type generator is, specifically, RELATION). You can think of a type generator as a special kind of operator; it’s special because (a) it returns a type instead of a value, and (b) it’s invoked at compile time instead of run time. For instance, most programming languages support a type generator called ARRAY, which lets users define a variety of specific array types. For present purposes, however, the only type generators we’re interested in are TUPLE and RELATION. Here’s an example involving the TUPLE type generator:

     VAR STV /* tuple variable */
         TUPLE { STATUS INTEGER , SNO CHAR , CITY CHAR , SNAME CHAR } ;

The value of variable STV at any given time is a tuple with the same heading as that of relvar S (I’ve deliberately specified the attributes in a different order, just to show the order doesn’t matter).[30] Thus, we might imagine a code fragment that (a) extracts a one-tuple relation (perhaps the relation containing just the tuple for supplier S1) from the current value of relvar S, then (b) extracts the single tuple from that one-tuple relation, and finally (c) assigns that tuple to the variable STV. In Tutorial D:

     STV := TUPLE FROM ( S WHERE SNO = 'S1' ) ;

Important: I don’t want you to misunderstand me here. While a variable like STV might certainly be needed in some application program that accesses the suppliers-and-parts database, I’m not saying such a variable can appear inside the database itself. A relational database contains variables of exactly one kind—namely, relation variables (relvars); in other words, relvars are the only kind of variable allowed in a relational database. (This latter fact—i.e., that relvars are the only kind of variable allowed in a relational database—constitutes what’s called The Information Principle. I’ll have more to say about it in Appendix A.)

By the way, note carefully that (as the foregoing example suggests) there’s a logical difference between a tuple t and the relation r that contains just that tuple t. In particular, they’re of different types—t is of some tuple type and r is of some relation type (though the types do at least have the same heading, or in other words the same attributes).

Finally, a few miscellaneous points to close this section:

  • Even though tuple and relation types do have user visible components (namely, their attributes), there’s no suggestion that those components have to be physically stored as such. In fact, the physical representation of tuples and relations should be hidden from the user, just as it is for scalar values. (Recall the discussion of physical data independence in Chapter 1.)

  • Like scalar types, tuple and relation types certainly need associated selector operators (and literals as a special case). I’ll defer the details to the next chapter. They don’t need THE_ operators, however; instead, they have operators that provide access to the corresponding attributes, and those operators play a role somewhat analogous to that played by THE_ operators in connection with scalar types.

  • Tuple and relation types also need assignment and equality comparison operators. I gave an example of tuple assignment earlier in the present section; I’ll defer details of the other operators to the next chapter.



[29] This sentence is only an approximation to the truth. A more accurate statement would be: Nongenerated types—see later in the present section—are scalar; generated types (e.g., relation types) are typically nonscalar, but don’t have to be. An example of a scalar generated type is the SQL type CHAR(25) (see the next section)

[30] Note that it does make sense to talk about the heading of a tuple—tuples have headings just as relations do (as will be explained in more detail in the next chapter).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.164.164