美文网首页
PL/SQL programing 第六版学习笔记-3

PL/SQL programing 第六版学习笔记-3

作者: e652d1fb12eb | 来源:发表于2020-11-26 15:59 被阅读0次

    Working with Program Data

    1. Naming Your Program Data

    2. Overview of PL/SQL Datatypes

    Character Data

    CHAR and NCHAR are fixed-length datatypes; VARCHAR2
    and NVARCHAR2 are variable-length datatypes.

    PL/SQL has the CLOB (character large object) and NCLOB (National Language Support CLOB) datatypes. For backward compatibility,PL/SQL also supports the LONG datatype. These datatypes allow you to store and manipulate very large amounts of data; in Oracle Database 11g, a LOB can hold up to 128 terabytes of information.

    Numbers
    /* File on web: numbers.sql */
    DECLARE
      salary NUMBER(9,2); -- fixed-point, seven to the left, two to the right
      raise_factor NUMBER; -- decimal floating-point
      weeks_to_pay NUMBER(2); -- integer
    BEGIN
      salary := 1234567.89;
      raise_factor := 0.05;
      weeks_to_pay := 52;
    END;
    
    Dates, Timestamps, and Intervals
    Booleans
    Binary Data

    including RAW, BLOB, and BFILE.
    for example, you try to fetch a LONG RAW from the database into your PL/SQL variable that exceeds the 32,760 byte limit, you will encounter an ORA-06502: PL/SQL: numeric or value error exception. To work with LONG RAWs longer than PL/SQL’s limit, you need an OCI program; this is a good reason to migrate your legacy code from LONG RAWs to BLOBs, which have no such limit.

    ROWIDs

    Oracle provides two proprietary datatypes, ROWID and UROWID, used to represent
    the address of a row in a table. ROWID represents the unique physical address of a row
    in its table; UROWID represents the logical position of a row in an index-organized
    table (IOT). ROWID is also a SQL pseudocolumn that can be included in SQL statements.

    REF CURSORs

    The REF CURSOR datatype allows developers to declare cursor variables. A cursor
    variable can then be used with static or dynamic SQL statements to implement more
    flexible programs. There are two forms of REF CURSORs: the strong REF CURSOR
    and the weak REF CURSOR. PL/SQL is a statically typed language, and the weak REF
    CURSOR is one of the few dynamically typed constructs supported.
    Here is an example of a strong REF CURSOR declaration. I associate the cursor variable with a specific record structure (using a %ROWTYPE attribute):

    DECLARE
      TYPE book_data_t IS REF CURSOR RETURN book%ROWTYPE;
      book_curs_var book_data_t;
    

    And here are two weak REF CURSOR declarations in which I do not associate any
    particular structure with the resulting variable. The second declaration (the last line)
    showcases SYS_REFCURSOR, a predefined weak REF CURSOR type:

    DECLARE
      TYPE book_data_t IS REF CURSOR;
      book_curs_var book_data_t;
      book_curs_var_b SYS_REFCURSOR;
    
    Internet Datatypes

    XML (Extensible Markup Language) and URIs (universal resource identifiers).

    “Any” Datatypes
    User-Defined Datatypes

    3. Declaring a Variable

    The basic syntax for a declaration is:
    name datatype [NOT NULL] [ := | DEFAULT default_assignment];

    Declaring Constants

    the syntax for the declaration of a constant is:
    name CONSTANT datatype [NOT NULL] := | DEFAULT default_value;

    Anchored Declarations

    PL/SQL offers two kinds of anchoring:

    • Scalar anchoring Use the %TYPE attribute to define your variable based on a table’s column or some other PL/SQL scalar variable.

    • Record anchoring
      Use the %ROWTYPE attribute to define your record structure based on a table or a predefined PL/SQL explicit cursor.

    • The syntax for an anchored datatype is:
      variable_name type_attribute%TYPE [optional_default_value_assignment];
      variable_name table_name | cursor_name%ROWTYPE [optional_default_value_assignment];

    Anchoring to Cursors and Tables

    Suppose that I want to query a single row of information from the book table. Rather
    than declare individual variables for each column in the table (which, of course, I should
    do with %TYPE), I can simply rely on %ROWTYPE:

    DECLARE
      l_book book%ROWTYPE;
    BEGIN
      SELECT * INTO l_book FROM book WHERE isbn = '1-56592-335-9';
      process_book (l_book);
    END;
    

    Suppose now that I only want to retrieve the author and title from the book table. In

    this case, I build an explicit cursor and then %ROWTYPE against that cursor:

    DECLARE
      CURSOR book_cur IS
      SELECT author, title FROM book WHERE isbn = '1-56592-335-9';
      l_book book_cur%ROWTYPE;
    BEGIN
      OPEN book_cur;
      FETCH book_cur INTO l_book; END;
    

    Finally, here is an example of an implicit use of the %ROWTYPE declaration: the cursor FOR loop.

    BEGIN
      FOR book_rec IN (SELECT * FROM book)
    LOOP
      process_book (book_rec);
    END LOOP;
    END;
    
    Benefits of Anchored Declarations
    • Synchronization with database columns
    • Normalization of local variables

    Programmer-Defined Subtypes

    • Constrained subtype

    SUBTYPE POSITIVE IS BINARY_INTEGER RANGE 1 .. 2147483647;

    • Unconstrained subtype

    SUBTYPE FLOAT IS NUMBER;

    Conversion Between Datatypes

    • Implicit Data Conversion
    • Explicit Datatype Conversion
      1. The CHARTOROWID function

      The CHARTOROWID function converts a string of either type CHAR or type VARCHAR2 to a value of type ROWID.

      1. The CAST function

      It converts from one (and almost any) built-in datatype or collection-typed value to another builtin datatype or collection-typed value.

      1. The CONVERT function

      The CONVERT function converts strings from one character set to another character
      set.
      4.The HEXTORAW function
      The HEXTORAW function converts a hexadecimal string from type CHAR or VARCHAR2 to type RAW.

      1. The RAWTOHEX function
      2. The ROWIDTOCHAR function

    3. STRINGS

    • The VARCHAR2 Datatype

    If you omit the CHAR or BYTE qualifier when declaring a VARCHAR2 variable, then
    whether the size is in characters or bytes depends on the NLS_LENGTH_SEMANTICS
    initialization parameter. You can determine your current setting by querying NLS_SESSION_PARAMETERS.

    • The CHAR Datatype

    Prior to 12c, the maximum length of the CHAR datatype in SQL was 2,000; in 12c, this
    is now increased to match the PL/SQL maximum: 32,767 bytes. Note, however, that SQL supports these maximum sizes only if the MAX_SQL_STRING_SIZE initialization parameter is set to EXTENDED.

    • String Subtypes

    It’s unlikely that you’ll ever need to use these—I never do—but you should be aware that they exist.


    图片.png
    Specifying String Constants

    If you want to embed a single quote within a string constant, you can do so by typing
    the single quote twice:

    'Aren''t you glad you''re learning PL/SQL with O''Reilly?'
    

    If your program will be dealing with strings that contain embedded single-quote characters,a more elegant approach is to specify your own string delimiters. Do this using the q prefix (uppercase Q may also be specified). For example:

    q'!Aren't you glad you're learning PL/SQL with O'Reilly?!'
    or:
    q'{Aren't you glad you're learning PL/SQL with O'Reilly?}'
    

    Occasionally, however, you may need to explicitly specify a string constant to be represented in the national character set. You can do so using the n prefix:

    n'Pils vom faß: 1₠'
    

    If you need a string in the national character set, and you also want to specify some
    characters by their Unicode code point, you can use the u prefix:

    u'Pils vom fa\00DF: 1\20AC'
    

    00DF is the code point for the German letter ß, while 20AC is the code point for the
    Euro symbol. The resulting string constant is the same as for the preceding n-prefixed
    example.
    When they encounter an ampersand,these tools “see” the next word as a variable and prompt you to supply a value:

    SET SERVEROUT ON;
    SET DEFINE OFF;
    begin
        DBMS_OUTPUT.PUT_LINE ('Generating & saving test data.');
    END;
    /
    

    There are several solutions to this problem. One that works well with SQL*Plus and
    SQL Developer is to issue the command SET DEFINE OFF to disable the variable substitution feature.

    • Using Nonprintable Characters

    You can do that by concatenating all the address lines together into one long text value
    and using CHR to insert linefeeds where desired. The location in the standard ASCII
    collating sequence for the linefeed character is 10, so you can code:

    SELECT name || CHR(10) || address1 || CHR(10) || address2 || CHR(10) || city || ', ' || state || ' ' || zipcode AS company_address FROM company;
    

    You say your boss doesn’t want to see any blank lines? No problem. You can
    eliminate those with a bit of cleverness involving the NVL2 function:

    SELECT name  || NVL2(address1, CHR(10) || address1, '') || NVL2(address2, CHR(10) || address2, '') || CHR(10) || city || ', ' || state || ' ' || zipcode AS company_address
    FROM company;
    

    Now the query returns a single formatted column per company. The NVL2 function
    returns the third argument when the first is NULL, and otherwise returns the second
    argument. In this example, when address1 is NULL, the empty string (‘’) is returned,
    and likewise for the other address columns.
    The ASCII function, in essence, does the reverse of CHR: it returns the decimal representation of a given character in the database character set. For example, execute the following code to display the decimal code for the letter J:

    BEGIN
      DBMS_OUTPUT.PUT_LINE(ASCII('J'));
    END;
    

    and you’ll find that, in UTF-8 at least, the underlying representation of J is the value 74.

    • Concatenating Strings

    There are two mechanisms for concatenating strings: the CONCAT function and the
    concatenation operator, represented by two vertical bar characters (||).
    use the CONCAT function, which takes two arguments as follows:

    CONCAT (string1, string2)
    
    CONCAT ('abc', 'defg') --> 'abcdefg'
    CONCAT (NULL, 'def') --> 'def'
    CONCAT ('ab', NULL) --> 'ab'
    CONCAT (NULL, NULL) --> NULL
    

    To perform the identical concatenation using CONCAT, you would need to nest one
    call to CONCAT inside another:

    x := CONCAT(CONCAT('abc','def'),'ghi');
    
    • Forcing a string to all upper- or lowercase

    One way to deal with case issues is to use the built-in UPPER and LOWER functions.
    These functions let you force case conversion on a string for a single operation. For
    example:

    DECLARE
      name1 VARCHAR2(30) := 'Andrew Sears';
      name2 VARCHAR2(30) := 'ANDREW SEARS';
    BEGIN
      IF LOWER(name1) = LOWER(name2) THEN
      DBMS_OUTPUT.PUT_LINE('The names are the same.');
    END IF;
    END;
    
    • Making comparisons case insensitive P208
    • Case insensitivity and indexes

    Initially the code is using the emp_name_ix index, but when I set NLS_COMP=LINGUISTIC
    and NLS_SORT=BINARY_CI to enable case insensitivity I stop using the
    index and start doing full table scans instead—oops! One solution is to create a functionbased,case-insensitive index, like this:

    CREATE INDEX last_name_ci ON EMPLOYEES (NLSSORT(last_name, 'NLS_SORT=BINARY_CI'))
    

    Now when I do my case-insensitive query, I use the case-insensitive index and keep my
    good performance.

    • Capitalizing each word in a string

    A third case-related function, after UPPER and LOWER, is INITCAP. This function forces the initial letter of each word in a string to uppercase, and all remaining letters to lowercase.

    • Traditional Searching, Extracting, and Replacing

    The INSTR function returns the character position of a substring within a larger string. The following code finds the locations of all the commas in a list of names:

    DECLARE
      names VARCHAR2(60) := 'Anna,Matt,Joe,Nathan,Andrew,Aaron,Jeff';
      comma_location NUMBER := 0;
    BEGIN
    LOOP
      comma_location := INSTR(names,',',comma_location+1);
      EXIT WHEN comma_location = 0;
      DBMS_OUTPUT.PUT_LINE(comma_location);
    END LOOP;
    END;
    
    The output is:
    5
    10
    14
    21
    28
    34
    

    例如:INSTR('CORPORATE FLOOR','OR', 3, 2)中,源字符串为'CORPORATE FLOOR',在字符串中查找'OR',从第三个字符位置开始查找"OR",取第三个字后第2个匹配项的位置。

    • Padding

    You can use LPAD and RPAD
    to add spaces (or some other character) to either end of a string in order to make the
    string a specific length.

    DECLARE
      a VARCHAR2(30) := 'Jeff';
      b VARCHAR2(30) := 'Eric';
      c VARCHAR2(30) := 'Andrew';
      d VARCHAR2(30) := 'Aaron';
      e VARCHAR2(30) := 'Matt';
      f  VARCHAR2(30) := 'Joe';
    BEGIN
      DBMS_OUTPUT.PUT_LINE( RPAD(a,10) || LPAD(b,10) );
      DBMS_OUTPUT.PUT_LINE( RPAD(c,10) || LPAD(d,10) );
      DBMS_OUTPUT.PUT_LINE( RPAD(e,10) || LPAD(f,10) );
    END;
    
    The output is:
    Jeff Eric
    Andrew Aaron
    Matt Joe
    

    The default padding character is the space. If you like, you can specify a fill character
    as the third argument. Change the lines of code to read:

    DBMS_OUTPUT.PUT_LINE( RPAD(a,10,'.') || LPAD(b,10,'.') );
    DBMS_OUTPUT.PUT_LINE( RPAD(c,10,'.') || LPAD(d,10,'.') );
    DBMS_OUTPUT.PUT_LINE( RPAD(e,10,'.') || LPAD(f,10,'.') );
    And the output changes to:
    Jeff............Eric
    Andrew.........Aaron
    Matt.............Joe
    

    Your fill “character” can even be a string of characters:

    DBMS_OUTPUT.PUT_LINE( RPAD(a,10,'-~-') || LPAD(b,10,'-~-') );
    DBMS_OUTPUT.PUT_LINE( RPAD(c,10,'-~-') || LPAD(d,10,'-~-') );
    DBMS_OUTPUT.PUT_LINE( RPAD(e,10,'-~-') || LPAD(f,10,'-~-') );
    
    Now the output looks like:
    Jeff-~--~--~--~-Eric
    Andrew-~---~--~Aaron
    Matt-~--~--~--~--Joe
    
    • Trimming

    What LPAD and RPAD giveth, TRIM, LTRIM, and RTRIM taketh away. For example:

    DECLARE
      a VARCHAR2(40) := 'This sentence has too many periods......';
      b VARCHAR2(40) := 'The number 1';
    BEGIN
      DBMS_OUTPUT.PUT_LINE( RTRIM(a,'.') );
      DBMS_OUTPUT.PUT_LINE(
        LTRIM(b, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
      );
    END;
    The output is:
    This sentence has too many periods
    1
    

    The other trimming function is just plain TRIM. Oracle added TRIM when Oracle8i
    Database was released in order to make the database more compliant with the ISO SQL standard. TRIM works a bit differently from LTRIM and RTRIM, as you can see:

    DECLARE
      x VARCHAR2(30) := '.....Hi there!.....';
    BEGIN
      DBMS_OUTPUT.PUT_LINE( TRIM(LEADING '.' FROM x) );
      DBMS_OUTPUT.PUT_LINE( TRIM(TRAILING '.' FROM x) );
      DBMS_OUTPUT.PUT_LINE( TRIM(BOTH '.' FROM x) );
      -- The default is to trim from both sides
      DBMS_OUTPUT.PUT_LINE( TRIM('.' FROM x) );
      -- The default trim character is the space:
      DBMS_OUTPUT.PUT_LINE( TRIM(x) );
    END;
    
    The output is:
    Hi there!.....
    .....Hi there!
    Hi there!
    Hi there!
    .....Hi there!.....
    
    • Regular Expression Searching, Extracting, and Replacing

    Detecting a pattern
    The general syntax for the REGEXP_LIKE function is:
    REGEXP_LIKE (source_string, pattern [,match_modifier])

    Locating a pattern
    You can use REGEXP_INSTR to locate occurrences of a pattern within a string. The
    general syntax for REGEXP_INSTR is:
    REGEXP_INSTR (source_string, pattern [,beginning_position [,occurrence
    [,return_option [,match_modifier [,subexpression]]]]])

    Extracting text matching a pattern
    I’ll use REGEXP_SUBSTR to extract a phone number from a string containing
    contact information:

    DECLARE
      contact_info VARCHAR2(200) := 'address:1060 W. Addison St.Chicago, IL 60613
        home 773-555-5253';
      phone_pattern VARCHAR2(90) :=
        '\(?\d{3}\)?[[:space:]\.\-]?\d{3}[[:space:]\.\-]?\d{4}';
    BEGIN
      DBMS_OUTPUT.PUT_LINE('The phone number is: '||
      REGEXP_SUBSTR(contact_info,phone_pattern,1,1));
    END;
    
    This code shows me the phone number:
    The phone number is: 773-555-5253
    
    • Working with empty strings

    Oracle database treats empty strings as NULLs. This is contrary to the ISO SQL standard, which recognizes the difference between an empty string and a string variable that is NULL.

    DECLARE
        empty_varchar2 VARCHAR2(10) := '';
        empty_char CHAR(10) := '';
    BEGIN
        IF empty_varchar2 is null then
            DBMS_OUTPUT.PUT_LINE('empty_varchar2 is Null');
        end if;
        IF '' IS NULL THEN
            DBMS_OUTPUT.PUT_LINE(''''' is NULL');
        END IF;
        
        IF empty_char IS NULL THEN
            DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
        ELSIF empty_char IS NOT NULL THEN
            DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
        END IF;
    END;
    

    You’ll notice in this example that the CHAR variable is not considered NULL. That’s
    because CHAR variables, as fixed-length character strings, are never truly empty.
    a NULL is never not equal, or equal,to any other value.

    • Mixing CHAR and VARCHAR2 Values

    Database-to-variable conversion When you SELECT or FETCH data from a CHAR database column into a VARCHAR2 variable, the trailing spaces are retained. If you SELECT or FETCH from a VARCHAR2 database column into a CHAR variable, PL/SQL automatically pads the value with spaces out to the maximum length. In other words, the type of the variable, not the column, determines the variable’s resulting value.

    • String comparisons

    • String Function Quick Reference

    ASCII(single_character)

    Returns the NUMBER code that represents the specified character in the database
    character set.

    ASCIISTR(string1)

    Takes a string in any character set and converts it into a string of ASCII characters.
    Any non-ASCII characters are represented using the form \XXXX, where
    XXXX represents the Unicode value for the character.

    CHR(code_location)

    Returns a VARCHAR2 character (length 1) that corresponds to the location in the
    collating sequence provided as a parameter. This is the reverse of ASCII.

    COMPOSE(string1)

    Takes a Unicode string as input and returns that string in its fully normalized
    form.

    CONCAT(string1, string2)

    Appends string2 to the end of string1. You’ll get the same results as from the expression string1 || string2. I find the || operator so much more convenient
    that I almost never invoke the CONCAT function.

    CONVERT(string1, target_char_set)

    Converts a string from the database character set to the specified target character
    set. You may optionally specify a source character set:
    CONVERT(string1, target_char_set, source_character_set)

    DECOMPOSE(string1)

    Takes a Unicode string as input and returns that string with any precomposed
    characters decomposed into their separate elements. This is the opposite of COMPOSE.
    For example, DECOMPOSE(‘ã’) yields ‘a˜’. (See COMPOSE.)

    GREATEST(string1, string2, ...)

    Takes one or more strings as input, and returns the string that would come last (i.e.,
    that is the greatest) if the inputs were sorted in ascending order. Also see the LEAST
    function, which is the opposite of GREATEST.

    INITCAP(string1)

    Reformats the case of the string argument, setting the first letter of each word to
    uppercase and the remainder of the letters to lowercase. This is sometimes called
    title case. A word is a set of characters separated by a space or nonalphanumeric
    character (such as # or _). For example, INITCAP(‘this is lower’) gives ‘This Is
    Lower’.

    INSTR(string1, string2)

    Returns the position at which string2 is found within string1; if it is not found,
    returns 0.

    Several variations are available:
    INSTR(string1, string2, start_position)
    Begins searching for string2 at the column in string1 indicated by start_position.
    The default start position is 1, so INSTR(string1, string2, 1) is equivalent
    to INSTR(string1, string2).
    INSTR(string1, string2, negative_start_position)
    Begins searching from the end of string1 rather than from the beginning.
    INSTR(string1, string2, start_position, nth)
    Finds the nth occurrence of string2 after the start_position.
    INSTR(string1, string2, negative_start_position, nth)
    Finds the nth occurrence of string2, counting from the end of string1.

    LEAST(string1, string2, ...)

    Takes one or more strings as input and returns the string that would come first (i.e.,
    that is the least) if the inputs were sorted in ascending order.

    LENGTH(string1)

    LOWER(string1)

    LPAD(string1, padded_length)

    LTRIM(string1)

    NCHR(code_location)

    NLS_INITCAP(string1)

    NLS_LOWER(string1) and NLS_LOWER(string1, ‘NLS_SORT=sort_se
    quence_name’)

    NLS_UPPER(string1) and NLS_UPPER(string1, ‘NLS_SORT=sort_se
    quence_name’)

    SUBSTR(string1, start, length)

    • Page236 of the book

    相关文章

      网友评论

          本文标题:PL/SQL programing 第六版学习笔记-3

          本文链接:https://www.haomeiwen.com/subject/bsivbktx.html