Previous | Table of Contents | Next

Page 46

Table 3.2. Subtypes of the NUMBER datatype.

Subtype Usage
DECIMAL Same as NUMBER.
DEC Same as DECIMAL.
DOUBLE PRECISION Same as NUMBER.
NUMERIC Same as NUMBER.
REAL Same as NUMBER.
INTEGER Equivalent to NUMBER(38).
INT Same as INTEGER.
SMALLINT Same as NUMBER(38).
FLOAT Same as NUMBER.
FLOAT(prec) Same as NUMBER(prec), but the precision is expressed in terms of binary bits, not decimal digits. Binary precision can range from 1 through 126.

Subtypes of NUMBER are not considered to be constraining. The same underlying datatype is used, and subject to the precision and scale you specify, all the subtypes can store the same range of values. Strange as it may seem, even an integer can be defined to hold noninteger, decimal values. Take a look at Listing 3.2, which shows all the NUMBER subtypes being used to declare identical variables.

INPUT/OUTPUT
Listing 3.2. Identical declarations using NUMBER subtypes.

 1: --Remember to execute: SET SERVEROUTPUT ON
 2: DECLARE
 3:   --all these declarations are identical.
 4:   num_dec     DECIMAL(5,2);
 5:   num_int     INTEGER(5,2);
 6:   num_dbl     DOUBLE PRECISION(5,2);
 7:   num_num     NUMERIC(5,2);
 8:   num_real    REAL(5,2);
 9:   num_sint    SMALLINT(5,2);
10: 
11:   --decimal precision / 0.30103 = binary precision,
12:   --so 5/.30103 = 16.6. Round it up to 17.
13:   num_flt     FLOAT(17);
14:
15:  BEGIN
16:   --Assign the same value to each variable, and make it one
17:   --that needs to be rounded.
18:   num_dec := 123.456;
19:   num_int := 123.456;
20:   num_dbl := 123.456;

Page 47

21:   num_num := 123.456;
22:   num_real := 123.456;
23:   num_sint := 123.456;
24:   num_flt := 123.456;
25:
26:   --Now display each value to demonstrate that they are all the same.
27:   DBMS_OUTPUT.PUT_LINE(num_dec);
28:   DBMS_OUTPUT.PUT_LINE(num_int);
29:   DBMS_OUTPUT.PUT_LINE(num_dbl);
30:   DBMS_OUTPUT.PUT_LINE(num_num);
31:   DBMS_OUTPUT.PUT_LINE(num_real);
32:   DBMS_OUTPUT.PUT_LINE(num_sint);
33:   DBMS_OUTPUT.PUT_LINE(num_flt);
34: END;
35: /
36: 123.46
37: 123.46
38: 123.46
39: 123.46
40: 123.46
41: 123.46
42: 123.456
43:
44: PL/SQL procedure successfully completed.

ANALYSIS
Notice that even the variables defined as INTEGER and SMALLINT still can hold noninteger values. The underlying datatype allows it, and the use of INTEGER(5,2) in the declaration overrides the integer subtype definition of NUMBER(38).

Notice also that the last value printed was 123.456. Why was this not rounded? Because that value came from the variable declared as FLOAT(17). Variables of subtype FLOAT store floating-point values, so rounding might not occur. There is no exact correspondence between binary and decimal precision either. Seventeen bits is slightly more than enough to hold any value that a NUMBER(5,2) variable could hold.

TIP
Please don't take advantage of the fact that you can declare an INTEGER variable with a precision and scale, for example INTEGER(5,2), and assign a value to it. Knowing that this can be done is interesting, but actually doing it will be confusing to other programmers.

BINARY_INTEGER

The BINARY_INTEGER datatype is used for declaring signed integer variables. Compared to the NUMBER datatype, BINARY_INTEGER variables are stored in binary format, which takes less space. Calculations on binary integers can also run slightly faster because the values are already in a binary format.

Page 48

The Syntax for the BINARY_INTEGER Datatype

variable_name BINARY_INTEGER;

In this syntax, variable_name is whatever you want to name the variable.

Here is a sample declaration:

my_integer BINARY_INTEGER;

A BINARY_INTEGER variable can store any integer value in the range _2,147,483,647 through 2,147,483,647.

TIP
If you are running PL/SQL version 2.3 or later, you have access to the new PLS_INTEGER datatype, which is optimized for fast calculations. For new applications I recommend using it instead of BINARY_INTEGER.

BINARY_INTEGER Subtypes
Oracle has defined five subtypes for the BINARY_INTEGER datatype, as explained in Table 3.3.

Table 3.3. Subtypes of BINARY_INTEGER.

Subtype Usage
POSITIVE Allows only positive integers to be stored, up to the maximum of 2,147,483,647. Zero is not considered a positive number, and so is not an allowed value.
NATURAL Allows only natural numbers to be stored, which includes zero. Allowed values are 0, 1, 2, 3, and so on up to the maximum of 2,147,483,647.
POSITIVEn Like POSITIVE but cannot be null.
NATURALn Like NATURAL but cannot be null.
SIGNTYPE Restricts a variable to only the values -1, 0, and 1. Oracle's built-in sign() function returns values in this range depending on whether its argument is negative, zero, or positive. (New for Oracle8.)

Unlike the subtypes defined for NUMBER, these subtypes are constraining. There is no way, for example, to define a POSITIVE in such a way as to still allow negative values.

Why would you want to use these subtypes? One reason might be for purposes of documentation. A subtype might be more descriptive of the type of data you intend to store

Page 49

in a variable, which can help prevent mistakes by other programmers who later work on the code. Another reason might be for error detection. If the code is later modified to assign the wrong type of value to a variable, a VALUE_ERROR exception will be generated, alerting the programmer to the mistake. Listing 3.3 shows an example of this.

INPUT/OUTPUT
Listing 3.3. An attempt to assign a negative value to a POSITIVE variable.

 1: --Remember to execute: SET SERVEROUTPUT ON
 2: DECLARE
 3:   age   POSITIVE;
 4:
 5:   current_year  NATURAL;    --a year of 00 is valid.
 6:   current_month POSITIVE;
 7:   current_day   POSITIVE;
 8:
 9:   birth_year    NATURAL;    --a year of 00 is valid.
10:   birth_month   POSITIVE;
11:   birth_day     POSITIVE;
12:
13:   birth_date    DATE := TO_DATE('11-15-1961','mm-dd-yyyy');
14:   current_date  DATE;
15: BEGIN
16:   --Set the current date.  Normally we would do "current_date := sysdate",
17:   --but LET'S pretend it's the year 2000.
18:   current_date := TO_DATE ('12-1-2000','mm-dd-yyyy');
19:
20:   --Show the effect of trying to set a negative age.
21:   --Pretend it's the year 2000 and we forgot to convert this code.
22:   --Note that only the two digit year is retrieved.
23:   current_year := TO_NUMBER(TO_CHAR(current_date,'yy'));
24:   current_month := TO_NUMBER(TO_CHAR(current_date,'mm'));
25:   current_day := TO_NUMBER(TO_CHAR(current_date,'dd'));
26:
27:   --Oops! Only two digits allowed for birth year.
28:   birth_year := TO_NUMBER(TO_CHAR(birth_date,'yy'));
29:   birth_month := TO_NUMBER(TO_CHAR(birth_date,'mm'));
30:   birth_day := TO_NUMBER(TO_CHAR(birth_date,'dd'));
31:
32:   --Now make the actual computation.
33:   IF current_month > birth_month THEN
34:     age := current_year - birth_year;
35:   ELSIF (current_month = birth_month) and (current_day >= birth_day) THEN
36:     age := current_year - birth_year;
37:   ELSE
38:     age := current_year - birth_year - 1;
39:   END IF;
40: END;
41: /
42: DECLARE
43: *
44: ERROR at line 1:
45: ORA-06502: PL/SQL: numeric or value error
46: ORA-06512: at line 25

Previous | Table of Contents | Next

Используются технологии uCoz