Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
190,43 KB
Nội dung
exception: weensy_plus := 'Lots of room for me to type now'; When you create a subtype based on an existing variable or database column, that subtype inherits the length (or precision and scale, in the case of a NUMBER datatype) from the original datatype. This constraint takes effect when you declare variables based on the subtype, but only as a default. You can always override that constraint. You will have to wait for a future version of PL/SQL, however, to actually enforce the constraint in a programmer-defined subtype. Finally, an anchored subtype does not carry over the NOT NULL constraint to the variables it defines. Nor does it transfer a default value that was included in the original declaration of a variable or column specification. Previous: 4.5 Anchored Declarations OraclePL/SQL Programming, 2nd Edition Next: 4.7 Tips for Creating and Using Variables 4.5 Anchored Declarations Book Index 4.7 Tips for Creating and Using Variables The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates. All rights reserved. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Previous: 4.4 Variable Declarations Chapter 4 Variables and Program Data Next: 4.6 Programmer- Defined Subtypes 4.5 Anchored Declarations This section describes the use of the %TYPE declaration attribute to anchor the datatype of one variable to another data structure, such as a PL/SQL variable or a column in a table. When you anchor a datatype, you tell PL/SQL to set the datatype of one variable from the datatype of another element. The syntax for an anchored datatype is: <variable name> <type attribute>%TYPE [optional default value assignment]; where <variable name> is the name of the variable you are declaring and <type attribute> is any of the following: ● Previously declared PL/SQL variable name ● Table column in format "table.column" Figure 4.2 shows how the datatype is drawn both from a database table and PL/SQL variable. Figure 4.2: Anchored declarations with %TYPE Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Here are some examples of %TYPE used in declarations: ● Anchor the datatype of monthly_sales to the datatype of total_sales: total_sales NUMBER (20,2); monthly_sales total_sales%TYPE; ● Anchor the datatype of the company ID variable to the database column: company_id# company.company_id%TYPE; Anchored declarations provide an excellent illustration of the fact that PL/SQL is not just a procedural-style programming language but was designed specifically as an extension to the Oracle SQL language. A very thorough effort was made by Oracle Corporation to tightly integrate the programming constructs of PL/SQL to the underlying database (accessed through SQL). NOTE: PL/SQL also offers the %ROWTYPE declaration attribute, which allows you to create anchored datatypes for PL/SQL record structures. %ROWTYPE is described in Chapter 9. 4.5.1 Benefits of Anchored Declarations All the declarations you have so far seen -- character, numeric, date, Boolean -- specify explicitly the type of data for that variable. In each of these cases, the declaration contains a direct reference to a datatype and, in most cases, a constraint on that datatype. You can think of this as a kind of hardcoding in your program. While this approach to declarations is certainly valid, it can cause problems in the following situations: ● Synchronization with database columns. The PL/SQL variable "represents" database information in the program. If I declare explicitly and then change the structure of the underlying table, my program may not work properly. ● Normalization of local variables. The PL/SQL variable stores calculated values used throughout the application. What are the consequences of repeating (hardcoding) the same datatype and constraint for each declaration in all of my programs? Let's take a look at each of these scenarios in more detail. 4.5.1.1 Synchronization with database columns Databases hold information that needs to be stored and manipulated. Both SQL and PL/SQL perform these manipulations. Your PL/SQL programs often read data from a database into local program variables, and then write information from those variables back into the database. Suppose I have a company table with a column called NAME and a datatype of VARCHAR2(60). I Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. can therefore create a local variable to hold this data as follows: DECLARE cname VARCHAR2(60); and then use this variable to represent this database information in my program. Now, consider an application which uses the company entity. There may be a dozen different screens, procedures, and reports which contain this same PL/SQL declaration, VARCHAR2(60), over and over again. And everything works just fine .until the business requirements change or the DBA has a change of heart. With a very small effort, the definition of the name column in the company table changes to VARCHAR2(100), in order to accommodate longer company names. Suddenly the database can store names which will raise VALUE_ERROR exceptions when FETCHed into the company_name variable. My programs have become incompatible with the underlying data structures. All declarations of cname (and all the variations programmers employed for this data throughout the system) must be modified. Otherwise, my application is simply a ticking time bomb, just waiting to fail. My variable, which is a local representation of database information, is no longer synchronized with that database column. 4.5.1.2 Normalization of local variables Another drawback to explicit declarations arises when working with PL/SQL variables which store and manipulate calculated values not found in the database. Suppose my programmers built an application to manage my company's finances. I am very bottom-line oriented, so many different programs make use of a total_revenue variable, declared as follows: total_revenue NUMBER (10,2); Yes, I like to track my total revenue down to the last penny. Now, in 1992, when specifications for the application were first written, the maximum total revenue I ever thought I could possibly obtain from any single customer was $99 million, so we used the NUMBER (10,2) declaration, which seemed like plenty. Then in 1995, my proposal to convert B-2 bombers to emergency transport systems to deliver Midwestern wheat to famine regions was accepted: a $2 billion contract! I was just about ready to pop the corks on the champagne when my lead programmer told me the bad news: I wouldn't be able to generate reports on this newest project and customer: those darn total_revenue variables were too small! What a bummer .I had to fire the guy. Just kidding. Instead, we quickly searched out any and all instances of the revenue variables so that we could change the declarations. This was a time-consuming job because we had spread equivalent declarations throughout the entire application. I had, in effect, denormalized my local data structures, with the usual consequences on maintenance. If only I had a way to define each of local total revenue variables in relation to a single datatype. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. If only they had used %TYPE! 4.5.2 Anchoring at Compile Time The %TYPE declaration attribute anchors the datatype of one variable to that of another data structure at the time a PL/SQL block is compiled. If a change is made to the "source" datatype, then any program which contains a declaration anchored to this datatype must be recompiled before it will be able to use this new state of the datatype. The consequences of this rule differ for PL/SQL modules stored in the database and those defined in client-side tools, such as Oracle Forms. Consider the following declaration of company_name in the procedure display_company: PROCEDURE display_company (company_id_in IN INTEGER) IS company_name company.name%TYPE; BEGIN . END; When PL/SQL compiles this module, it looks up the structure of the company table in the data dictionary, finds the column NAME, and obtains its datatype. It then uses this data dictionary-based datatype to define the new variable. What, then, is the impact on the compiled display_company procedure if the datatype for the name column of the company table changes? There are two possibilities: ● If display_company is a stored procedure, then the compiled code will be marked as "invalid." The next time a program tries to run display_company, it will be recompiled automatically before it is used. ● If display_company is a client-side procedure, then the Oracle Server cannot mark the program as invalid. The compiled client source code remains compiled using the old datatype. The next time you execute this module, it could cause a VALUE_ERROR exception to be raised. Whether stored or in client-side code, you should make sure that all affected modules are recompiled after data structure changes. 4.5.3 Nesting Usages of the %TYPE Attribute You can nest usages of %TYPE in your declarations as well: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. DECLARE /* The "base" variable */ unlimited_revenue NUMBER; /* Anchored to unlimited revenue */ total_revenue unlimited_revenue%TYPE; /* Anchored to total revenue */ total_rev_94 total_revenue%TYPE; total_rev_95 total_revenue%TYPE; BEGIN In this case total_revenue is based on unlimited_revenue and both variables for 1994 and 1995 are based on the total_revenue variable. There is no practical limit on the number of layers of nested usages of %TYPE. 4.5.4 Anchoring to Variables in Other PL/SQL Blocks The declaration of the source variable for your %TYPE declarations does not need to be in the same declaration section as the variables which use it. That variable must simply be visible in that section. The variable could be a global PL/SQL variable (defined in a package) or be defined in an PL/SQL block which contains the current block, as in the following example: PROCEDURE calc_revenue IS unlimited_revenue NUMBER; total_revenue unlimited_revenue%TYPE; BEGIN IF TO_CHAR (SYSDATE, 'YYYY') = '1994' THEN DECLARE total_rev_94 total_revenue%TYPE; BEGIN . END; END IF; END calc_revenue; 4.5.5 Anchoring to NOT NULL Datatypes When you declare a variable, you can also specify the need for the variable to be NOT NULL This NOT NULL declaration constraint is transferred to variables declared with the %TYPE attribute. If I include a NOT NULL in my declaration of a source variable (one that is referenced afterwards in a % TYPE declaration), I must also make sure to specify a default value for the variables which make use of that source variable. Suppose I declare max_available_date NOT NULL in the following example: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. DECLARE max_available_date DATE NOT NULL := LAST_DAY (ADD_MONTHS (SYSDATE, 3)); last_ship_date max_available_date%TYPE; The declaration of last_ship_date will then fail to compile, with the following message: a variable declared NOT NULL must have an initialization assignment. If you use a NOT NULL variable in a %TYPE declaration, the new variable must have a default value provided. The same is not true, however, for variables declared with %TYPE where the source is a database column. The NOT NULL column constraint does not apply to variables declared with the %TYPE attribute. The following code will compile successfully: DECLARE -- Company name is a NOT NULL column in the company table. comp_name company.name%TYPE; BEGIN comp_name := NULL; You will be able to declare the comp_name variable without specifying a default, and you will be able to NULL out the contents of that variable. Previous: 4.4 Variable Declarations OraclePL/SQL Programming, 2nd Edition Next: 4.6 Programmer- Defined Subtypes 4.4 Variable Declarations Book Index 4.6 Programmer-Defined Subtypes The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates. All rights reserved. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Previous: 4.3 NULLs in PL/ SQL Chapter 4 Variables and Program Data Next: 4.5 Anchored Declarations 4.4 Variable Declarations Before you can make a reference to a variable, you must declare it. (The only exception to this rule is for the index variables of FOR loops.) All declarations must be made in the declaration section of your anonymous block, procedure, function, or package (see Chapter 15, Procedures and Functions, for more details on the structure of the declaration section). When you declare a variable, PL/SQL allocates memory for the variable's value and names the storage location so that the value can be retrieved and changed. The declaration also specifies the datatype of the variable; this datatype is then used to validate values assigned to the variable. The basic syntax for a declaration is: <variable_name> <datatype> [optional default assignment]; where <variable_name> is the name of the variable to be declared and <datatype> is the datatype or subtype which determines the type of data which can be assigned to the variable. The [optional default assignment] clause allows you to initialize the variable with a value, a topic covered in the next section. 4.4.1 Constrained Declarations The datatype in a declaration can either be constrained or unconstrained. A datatype is constrained when you specify a number which constrains or restricts the magnitude of the value which can be assigned to that variable. A datatype is unconstrained when there are no such restrictions. Consider the datatype NUMBER. It supports up to 38 digits of precision -- and uses up the memory needed for all those digits. If your variable does not require this much memory, you could declare a number with a constraint, such as the following: itty_bitty_# NUMBER(1); large_but_constrained_# NUMBER(20,5); Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Constrained variables require less memory than unconstrained number declarations like this: no_limits_here NUMBER; 4.4.2 Declaration Examples Here are some examples of variable declarations: ● Declaration of date variable: hire_date DATE; ● This variable can only have one of three values: TRUE, FALSE, NULL: enough_data BOOLEAN; ● This number rounds to the nearest hundredth (cent): total_revenue NUMBER (15,2); ● This variable-length string will fit in a VARCHAR2 database column: long_paragraph VARCHAR2 (2000); ● This constant date is unlikely to change: next_tax_filing_date CONSTANT DATE := '15-APR-96'; 4.4.3 Default Values You can assign default values to a variable when it is declared. When declaring a constant, you must include a default value in order for the declaration to compile successfully. The default value is assigned to the variable with one of the following two formats: <variable_name> <datatype> := <default_value>; <variable_name> <datatype> DEFAULT <default_value>; The <default_value> can be a literal, previously declared variable, or expression, as the following examples demonstrate: ● Set variable to 3: term_limit NUMBER DEFAULT 3; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. ● Default value taken from Oracle Forms bind variable: call_topic VARCHAR2 (100) DEFAULT :call.description; ● Default value is the result of a function call: national_debt FLOAT DEFAULT POWER (10,10); ● Default value is the result of the expression: order_overdue CONSTANT BOOLEAN := ship_date > ADD_MONTHS (order_date, 3) OR priority_level (company_id) = 'HIGH'; I like to use the assignment operator (:=) to set default values for constants, and the DEFAULT syntax for variables. In the case of the constant, the assigned value is not really a default, but an initial (and unchanging) value, so the DEFAULT syntax feels misleading to me. 4.4.4 NOT NULL Clause If you do assign a default value, you can also specify that the variable must be NOT NULL. For example, the following declaration initializes the company_name variable to PCS R US and makes sure that the name can never be set to NULL: company_name VARCHAR2(60) NOT NULL DEFAULT 'PCS R US'; If your code includes a line like this: company_name := NULL; then PL/SQL will raise the VALUE_ERROR exception. You will, in addition, receive a compilation error with this next declaration: company_name VARCHAR2(60) NOT NULL; Why? Because your NOT NULL constraint conflicts instantly with the indeterminate or NULL value of the company_name variable when it is instantiated. Previous: 4.3 NULLs in PL/ SQL OraclePL/SQL Programming, 2nd Edition Next: 4.5 Anchored Declarations 4.3 NULLs in PL/SQL Book Index 4.5 Anchored Declarations Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... Oracle and non -Oracle data sources, you should avoid any references to the rowid pseudo-column and the ROWID datatype 4.2.4 The Boolean Datatype The Oracle RDBMS/SQL language offers features not found in PL/SQL, such as the Oracle SQL DECODE construct PL/SQL, on the other hand, has a few tricks up its sleeve which are unavailable in native SQL One particularly pleasant example of this is the BOOLEAN... fixed-length, PL/SQL will right-pad any value assigned to a CHAR variable with spaces to the maximum length specified in the declaration Prior to Oracle7 , the CHAR datatype was variable-length; Oracle did not, in fact, support a fixed-length character string datatype and prided itself on that fact To improve compatibility with IBM relational databases and to comply with ANSI standards, Oracle7 reintroduced... Version 1.1 of PL/SQL, which you use in Oracle Developer/2000 tools like Oracle Forms, the compiler does not insist that you include a maximum length for a VARCHAR2 declaration As a result, you could mistakenly leave off the length in the declaration and end up with a variable with a maximum length of a single character As discussed in the section on the fixed-length CHAR datatype, this can cause PL/SQL to... character variable declarations The maximum length allowed for PL/SQL VARCHAR2 variables is a much higher maximum than that for the VARCHAR2 datatype in the Oracle RDBMS, which is only 2000 As a result, if you plan to store a PL/SQL VARCHAR2 value into a VARCHAR2 database column, you must remember that only the first 2000 can be inserted Neither PL/SQL nor SQL automatically resolves this inconsistency,... LONG datatype for PL/SQL variables is quite different from the LONG datatype for columns in the Oracle Server The LONG datatype in Oracle7 can store character strings of up to two gigabytes or 231-1 bytes; this large size makes the LONG column a possible repository of multimedia information, such as graphics images As a result of these maximum length differences, you can always insert a PL/SQL LONG variable... is declared The difference between RAW and VARCHAR2 is that PL/SQL will not try to interpret raw data Within the Oracle RDBMS this means that Oracle will not perform character set conversions on RAW data when it is moved from one system (based, for example, on 7-bit ASCII) to another system Once again, there is an inconsistency between the PL/SQL maximum length for a RAW variable (32767) and the RDBMS... a LONG RAW variable is not interpreted by PL/SQL Given the fact that a RAW variable actually has a higher maximum length than the LONG RAW and has no restrictions attached to it, I recommend that you always use the RAW datatype in PL/SQL programs LONG RAWs have a place in the RDBMS, but that role is not duplicated in PL/SQL 4.2.3.6 The ROWID datatype In the Oracle RDBMS, ROWID is a pseudocolumn that... the database in your pl/sql program You can SELECT or FETCH the rowid for a row into a ROWID variable To manipulate rowids in Oracle8 , you will want to use the built-in package, dbms_rowid (see Appendix A, What's on the Companion Disk?) In Oracle7 , you will use the rowidtochar function to convert the rowid to a fixed-length string and then perform operations against that string In Oracle7 , the format... placed in that variable PL/SQL offers a comprehensive set of predefined scalar and composite datatypes A scalar datatype is an atomic; it is not made up of other variable components A composite datatype has internal structure or components The two composite types currently supported by PL/SQL are the record and table (described in Chapter 9, Records in PL/SQL, and Chapter 10, PL/SQL Tables, respectively)... represent each character Oracle offers National Language Support (NLS) to process single-byte and multibyte character data NLS features also allow you to convert between character sets PL/SQL8 supports two character sets which allow for the storage and manipulation of strings in either single-byte or multibyte formats The two character sets are: q q Database character set: used for PL/SQL identifiers and . the fact that PL/SQL is not just a procedural-style programming language but was designed specifically as an extension to the Oracle SQL language. A very. made by Oracle Corporation to tightly integrate the programming constructs of PL/SQL to the underlying database (accessed through SQL). NOTE: PL/SQL also