Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 12 ■ DATATYPES 503 ops$tkyte@ORA10GR1> create table t ( raw_data raw(16) ); Table created. The RAW type is much like the VARCHAR2 type in terms of storage on disk. The RAW type is a variable-length binary string, meaning that the table T just created, for example, may store anywhere from 0 to 16 bytes of binary data. It is not padded out like the CHAR type. When dealing with RAW data, you will likely find it being implicitly converted to a VARCHAR2 type—that is, many tools such as SQL*Plus will not display the RAW data directly, but will convert it to a hexadecimal format for display. In the following example, we create some binary data in our table using SYS_GUID(), a built-in function that returns a 16-byte RAW string that is globally unique (GUID stands for globally unique identifier): ops$tkyte@ORA10GR1> insert into t values ( sys_guid() ); 1 row created. ops$tkyte@ORA10GR1> select * from t; RAW_DATA -------------------------------- FD1EB03D3718077BE030007F01002FF5 You can immediately note two things here. First, the RAW data looks like a character string. That is just how SQL*Plus retrieved and printed it, and that is not how it is stored on disk. SQL*Plus cannot print arbitrary binary data on your screen, as that could have serious side effects on the display. Remember that binary data may include control characters such as a carriage return or linefeed, or maybe a Ctrl+G character that would cause your terminal to “beep.” Second, the RAW data looks much larger than 16 bytes—in fact, in this example, you can see 32 characters. This is due to the fact that every binary byte takes two hexadecimal characters to display. The stored RAW data is really 16 bytes in length, and you can see this using the Oracle DUMP function. Here, I am “dumping” the value of the binary string and using the optional parameter to specify the base that should be used when displaying the value of each byte. I am using base 16, so we can compare the results of dump with the previous string: ops$tkyte@ORA10GR1> select dump(raw_data,16) from t; DUMP(RAW_DATA,16) ------------------------------------------------------------------------------- Typ=23 Len=16: fd,1e,b0,3d,37,18,7,7b,e0,30,0,7f,1,0,2f,f5 So, DUMP shows us this binary string is in fact 16 bytes long (LEN=16) and displays the binary data byte by byte. As we can see, this dump display matches up with the implicit conversion performed when SQL*Plus fetched the RAW data into a string. This implicit conversion goes the other direction as well: ops$tkyte@ORA10GR1> insert into t values ( 'abcdef' ); 1 row created. That did not insert the string abcdef, but rather a 3-byte RAW with the bytes AB, CD, EF, or in decimal with the bytes 171, 205, 239. If you attempt to use a string that does not consist of valid hex characters, you will receive an error message:

504 CHAPTER 12 ■ DATATYPES ops$tkyte@ORA10GR1> insert into t values ( 'abcdefgh' ); insert into t values ( 'abcdefgh' ) * ERROR at line 1: ORA-01465: invalid hex number The RAW type may be indexed and used in predicates—it is as functional as any other datatype. However, you must take care to avoid unwanted implicit conversions, and you must be aware that they will occur. I prefer and recommend using explicit conversions in all cases, which can be performed using the following built-in functions: • HEXTORAW: To convert strings of hexadecimal characters to the RAW type • RAWTOHEX: To convert RAW strings to hexadecimal strings The RAWTOHEX function is invoked implicitly by SQL*Plus when it fetches a RAW type into a string, and the HEXTORAW function is invoked implicitly when inserting the string. It is a good practice to avoid implicit conversions and to always be explicit when coding. So the previous examples could have been written as follows: ops$tkyte@ORA10GR1> select rawtohex(raw_data) from t; RAWTOHEX(RAW_DATA) -------------------------------- FD1EB03D3718077BE030007F01002FF5 ops$tkyte@ORA10GR1> insert into t values ( hextoraw('abcdef') ); 1 row created. Number Types Oracle 10g supports three native datatypes suitable for storing numbers. Oracle9i Release 2 and earlier support exactly one native datatype suitable for storing numeric data. In this list, the NUMBER type is supported by all releases, and the subsequent two types are new datatypes supported only in Oracle 10g and later: • NUMBER: The Oracle NUMBER type is capable of storing numbers with an extremely large degree of precision—38 digits of precision, in fact. The underlying data format is similar to a “packed decimal” representation. The Oracle NUMBER type is a variable-length format from 0 to 22 bytes in length. It is appropriate for storing any number as small as 10e -130 and numbers up to but not including 10e 126 . This is by far the most common NUMBER type in use today. • BINARY_FLOAT: This is an IEEE native single-precision floating-point number. On disk it will consume 5 bytes of storage: 4 fixed bytes for the floating-point number and 1 length byte. It is capable of storing numbers in the range of ~ ± 10 38.53 with 6 digits of precision.

CHAPTER 12 ■ DATATYPES 503<br />

ops$tkyte@ORA10GR1> create table t ( raw_data raw(16) );<br />

Table created.<br />

The RAW type is much like the VARCHAR2 type in terms of storage on disk. The RAW type is a<br />

variable-length binary string, meaning that the table T just created, for example, may store<br />

anywhere from 0 to 16 bytes of binary data. It is not padded out like the CHAR type.<br />

When dealing with RAW data, you will likely find it being implicitly converted to a VARCHAR2<br />

type—that is, many tools such as SQL*Plus will not display the RAW data directly, but will convert<br />

it to a hexadecimal format for display. In the following example, we create some binary<br />

data in our table using SYS_GUID(), a built-in function that returns a 16-byte RAW string that is<br />

globally unique (GUID st<strong>and</strong>s for globally unique identifier):<br />

ops$tkyte@ORA10GR1> insert into t values ( sys_guid() );<br />

1 row created.<br />

ops$tkyte@ORA10GR1> select * from t;<br />

RAW_DATA<br />

--------------------------------<br />

FD1EB03D3718077BE030007F01002FF5<br />

You can immediately note two things here. First, the RAW data looks like a character string.<br />

That is just how SQL*Plus retrieved <strong>and</strong> printed it, <strong>and</strong> that is not how it is stored on disk.<br />

SQL*Plus cannot print arbitrary binary data on your screen, as that could have serious side<br />

effects on the display. Remember that binary data may include control characters such as a<br />

carriage return or linefeed, or maybe a Ctrl+G character that would cause your terminal to<br />

“beep.”<br />

Second, the RAW data looks much larger than 16 bytes—in fact, in this example, you can<br />

see 32 characters. This is due to the fact that every binary byte takes two hexadecimal characters<br />

to display. The stored RAW data is really 16 bytes in length, <strong>and</strong> you can see this using the<br />

<strong>Oracle</strong> DUMP function. Here, I am “dumping” the value of the binary string <strong>and</strong> using the<br />

optional parameter to specify the base that should be used when displaying the value of each<br />

byte. I am using base 16, so we can compare the results of dump with the previous string:<br />

ops$tkyte@ORA10GR1> select dump(raw_data,16) from t;<br />

DUMP(RAW_DATA,16)<br />

-------------------------------------------------------------------------------<br />

Typ=23 Len=16: fd,1e,b0,3d,37,18,7,7b,e0,30,0,7f,1,0,2f,f5<br />

So, DUMP shows us this binary string is in fact 16 bytes long (LEN=16) <strong>and</strong> displays the<br />

binary data byte by byte. As we can see, this dump display matches up with the implicit conversion<br />

performed when SQL*Plus fetched the RAW data into a string. This implicit conversion<br />

goes the other direction as well:<br />

ops$tkyte@ORA10GR1> insert into t values ( 'abcdef' );<br />

1 row created.<br />

That did not insert the string abcdef, but rather a 3-byte RAW with the bytes AB, CD, EF, or<br />

in decimal with the bytes 171, 205, 239. If you attempt to use a string that does not consist of<br />

valid hex characters, you will receive an error message:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!