Xpert 基础

Xpert 基础
----------------------- 01 -------------------------------

declare

    cursor emp_cur is

        select empname 

          from company

          where name = 'asdf';

    emp_rec emp_cur%rowtype;

begin

    open emp_cur;

    loop

        fetch emp_cur into emp_rec

        exit when emp_cur%notfound;

        give_raise(emp_rec.empno);

    end loop;

    close emp_cur;

end;



-- for style, 不用open 和 close 游标

declare

    cursor emp_cur is

        select empname 

          from company

          where name = 'asdf';

begin

    for emp_rec in emp_cur

    loop

        give_raise(emp_rec.empno);

    end loop;

end;

------------------------ 02 ---------------------------------

-- cursor parameter

-- cursor parameters use the same structure as the parameter list for procedures and function.

-- 只能使用 in 模式, 不是使用OUT, IN OUT 模式

cursor company_cur(id_in company.company_id%type,

                    status_in in company.cstatus%type := 'O')

        is 

        select * from company

         where company_id = id_in

           and status = status_in;



----------------------- 03 --------------------------------------

-- cursor in package, 有两种方法, 第一种是定义cursor同时制定select, 这种跟普通的pl/sql块一样

-- 另外一种是, 在package中只定义一个header, 并指定 return, 在 packagebody 中完整定义cursor

create or replace package book_info

is

    cursor byauthor_cur( author_in IN books.author%type) 

    is

        select * from books where author = author_in;

    

    -- return type 直接使用 %rowtype

    cursor bytitle_cur( title_filter_in in books.title%type)

        return books%rowtype;

    

    -- 自己定义的行记录

    type author_summary_rt is record(

        author books.author%type,

        total_page_count pls_integer,

        total_book_count pls_integer);

    

    -- 返回自己定义的行记录类型

    cursor summary_cur( author_in in books.author%type)

        return author_summary_rt;

end book_info;
cursor
Xpert 基础
-- 01 变量名--

cursor company_cur    -- cursor

c_constant_data     -- constants

v_varibale_value    -- variable

company_id_in        -- parameter

company_rec            -- record



-- 02 尽量使用间接

-- 使用 %rowtype, %type

-- 使用 常量等, 不要直接使用数字等, 比如

min_diff constant number := 1;

max_diff constant number := 100;

if footing between min_diff and max_diff then    --



if footing between 1 and 100 then -- 不好
变量
Xpert 基础
/*

 If the loop executes for a fixed number of times (by number or number of records), use the FOR loop.

 If you want to make sure the loop executes at least once, use the simple loop.

 If you want the termination condition evaluated before the body executes, use the WHILE loop.

 */



-- If the code used to initialize is similar to the body, then switch to a simple loop. For example, 

-- the following WHILE loop relies on two fetch statements:

OPEN emp_cur;

FETCH emp_cur INTO emp_rec;        -- FETCH 第一次

WHILE emp_cur%FOUND AND

      emp_rec.sal < avg_sal

LOOP

   

   FETCH emp_cur INTO emp_rec;    -- FETCH 第二次

END LOOP;



-- 所以, 以上应该使用 简单循环, 这样就只 FETCH 了一次

LOOP

   FETCH emp_cur INTO emp_rec;

   EXIT WHEN emp_cur%NOTFOUND OR

        emp_rec.sal >= avg_sal;

END LOOP;
loop
Xpert 基础
/*

 Do not use PL/SQL where you can use a SQL statement instead. 

 The SQL statement will often be much faster. You should replace PL/SQL loops 

 with single SQL statements when possible.

 */



-- lower PL/SQL Version:



FOR year_count IN 1 .. 20

LOOP

   INSERT INTO v1table1 

      SELECT * FROM v1table2

       WHERE yr_nu = year_count; 

END LOOP;



-- Faster, Simpler SQL Version:

INSERT INTO v1table1

   SELECT * FROM v1table2

    WHERE yr_nu BETWEEN 1 AND 20;
SQL FASTER THAN PL/SQL
Xpert 基础
-- Never Use a RETURN Statement Inside a Loop



-- 错误的方法

BEGIN

   the_rowcount := Get_Group_Row_Count( rg_id );

   

   FOR j IN 1..the_rowcount 

   LOOP

   

      col_val := Get_Group_Char_Cell( gc_id, j );

   

      IF UPPER(col_val) = UPPER(the_value) 

      THEN

         RETURN j;

      END IF;

   

   END LOOP;

END;



/*

 Once again, if the loop should be conditionally terminated, do not use a FOR loop. 

 Instead, use a WHILE or infinite loop and then issue the RETURN after the loop is completed. 

 The following code replaces the unstructured IF statement shown above:

 */



BEGIN

/* Initialize the loop boundary variables. */

   row_index := 0;

   the_rowcount := Get_Group_Row_Count (rg_id);

   

   /* Use a WHILE loop. */

   WHILE row_index <= the_rowcount AND 

          match_not_found 

   LOOP

         row_index := row_index + 1;

         col_val := Get_Group_Char_Cell (gc_id, row_index);

         match_not_found := UPPER (col_val) != UPPER (the_value) 

   END LOOP;

   

   /* Now issue the RETURN statement. */

   RETURN row_index;

END;
Return Vs Loop
Xpert 基础
FUNCTION func_name (...) RETURN datatype 

 IS

    /* Variable for RETURN */

    return_value datatype;

 BEGIN

    <executable statements>

   

    /* Last line always: */

    RETURN return_value;

 EXCEPTION

  

 END func_name;
Function templete
Xpert 基础
PROCEDURE calc_sales

   (company_id_in   IN     company.company_id%TYPE,

    rank_inout      IN OUT NUMBER,

    total_sales_out OUT    NUMBER);
parameter name
Xpert 基础
-- package 果然跟 objective c 很像

-- By placing data inside the package body, 

-- it is protected from direct access by any programs outside of the package.

-- recommendation:

-- Never put your variables and other data structures in the package specification.

/*

Always put them in the body.

Then build programs to change values in the data structures and retrieve the current values.

Make these “get and set” programs available in the package specification. 

The benefits include: 

Tighter control over data structures.

Flexibility to change implementation of data structure. 

 */

/*

it's recommended that you set standards for elements and their names in your "get and set"

programs. For example, if the data structure is “maximum length,” then create the following elements:



A public procedure named “set_max_length”

A public function named “max_length”

A private variable named “v_max_length”. 

 */
package
Xpert 基础
/*

     shared pool 可以重复利用 SQL 的条件:

    ~ 字母的大小写要一致.

    ~ 空格要一致(只用一个空格).

    ~ 要在同一个 schema 下的对象.

    ~ 如果table使用了别名, 并且别名不一样, 比如一个C, 另一个E, 那么也不能被重复利用.

    总之要想被重复利用, 必须完完全全一样. 一个字, 一个空格都不能差, 单纯重字面上. 

 */



/*

 Put all SQL verbs in one case. 例子中, SQL verbs 全部大写, 表,列等等全部小写

 Begin all SQL verbs on a new line. SQL 关键字重启一行

 Right- or left-align verbs with the initial SQL verb. 貌似右对齐的人比较多

 Separate all statement "words" by a single space. 一个空格分隔

*/

-- 例如, 左对齐

SELECT emp_no, emp_name, emp_salary

FROM   emp

WHERE  sal_grade > 10

AND    ( emp_salary >= 10000

OR     tot_staff > 100 )



-- 右对齐

SELECT emp_no, emp_name, emp_salary

  FROM emp

 WHERE sal_grade > 10

   AND ( emp_salary >= 10000

    OR tot_staff > 100 )



-- 这里也可以全部使用小写, 避免一些问题, 因为你要知道, 如果要想SQL被重复利用, 字符大小写是有关系的

-- 所以, 全部用小写就不会有什么问题. 这样, 有些懒程序员就可以全部使用小写.

select emp_no, emp_name, emp_salary

  from emp

 where sal_grade > 10

   and (emp_salary >= 10000 or tot_staff > 100)

-- 当然, 你使用大小写区分的好处是, 很容易分辨关键字等信息.



/*

 好的方式

Use UPPER and lower case to distinguish between reserved words and application-specific identifiers.

Use white space to improve readability.

Use a consistent commenting style that is low in maintenance and high in readability.

Comment only to add value.

Use consistent formats for different constructs of the language, including SQL statements.

    Distinguish between the SQL syntax and your application constructs. Put all keywords to the left, 

        application elements to the right.

    Separate the distinct clauses with white space.(行与行之间的空格)

    Use meaningful aliases, especially for tables.

 */

-- <wait picture 1-1.jpg>##########################################

-- 另外, 要多使用间接, 甚至连 业务逻辑都可以写到间接变量里, 例如:

DECLARE

   /* I hide my business rule behind this variable. */

   order_overdue CONSTANT BOOLEAN

  DEFAULT (shipdate < ADD_MONTHS (SYSDATE, +3) OR

       order_date >= ADD_MONTHS (SYSDATE, -2)) AND

    order_status = 'O';

   high_priority CONSTANT BOOLEAN 

  DEFAULT cust_priority_type = 'HIGH';



BEGIN

   IF order_overdue AND high_priority    -- 业务逻辑已经隐藏在上边的定义中

   THEN

      ship_order ('EXPRESS');

   ELSE

      ship_order ('GROUND'); 

   END IF;

END;



-- 行内的空格

-- Always include a space between every identifier and separator in a statement.

WHILE (total_sales < maximum_sales AND company_type = 'NEW')

LOOP

-- Use spaces to make module calls and their parameter lists more understandable.

calc_totals (company_id, LAST_DAY (end_of_year_date), total_type);

-- procedure 等名字后面要有个空格再接括号, 括号与字符之间不需要有空格.



-- 如果有大量的声明, 那么声明最好有一定顺序, 例如: by datatye, by logical relationship

-- by datatype

DECLARE

 min_value NUMBER;

 company_id NUMBER;

 company_name VARCHAR2(30);

 employee_name VARCHAR2(60);

 hire_date DATE;

 termination_date DATE;

-- by logical relationship

DECLARE

 company_name VARCHAR2(30);

 company_id INTEGER;

 employee_name VARCHAR2(60);

 hire_date DATE;

 termination_date DATE;

 min_value NUMBER;



-- 如果有多行参数时, 美观的写法是, 参数另起一行, 例如: 并且缩进

generate_company_statistics 

   (company_id, last_year_date, rollup_type, 

   total, average, variance, budgeted, next_year_plan);

FOR month_index IN

   first_month .. last_month    -- 区间另起一行, 可能区间很长, 在一行不美观

LOOP



q1_sales := 

   month1_sales + 

   month2_sales +

   month3_sales;        -- 在一行, 太长, 不美观, 也不直观.



-- 美观的 SQL 语句, 例子

-- <wait picture 1-2.jpg>#############################

-- Here are some examples of this format in use:



SELECT last_name, first_name

  FROM employee

 WHERE department_id = 15

   AND hire_date < SYSDATE;



SELECT department_id, SUM (salary) AS total_salary

  FROM employee

 GROUP BY department_id

 ORDER BY total_salary DESC;



INSERT INTO employee 

   (employee_id, ... )

VALUES (105 ... );



DELETE FROM employee

      WHERE department_id = 15;



UPDATE employee

   SET hire_date = SYSDATE

 WHERE hire_date IS NULL

   AND termination_date IS NULL;



-- we recommand

-- Placing each expression of the WHERE clause on its own line

-- Using a separate line for each expression in the select list of a SELECT statement.

-- Placing each table in the FROM clause on its own line.

-- Placing each separate assignment in a SET clause of the UPDATE statement on its own line.

-- 例如

SELECT last_name,

       C.name,

       MAX (SH.salary) best_salary_ever

  FROM employee E,

       company C,

       salary_history SH

 WHERE E.company_id = C.company_id

   AND E.employee_id = SH.employee_id

   AND E.hire_date > ADD_MONTHS (SYSDATE, -60);



UPDATE employee

   SET hire_date = SYSDATE,

       termination_date = NULL

 WHERE department_id = 105;



-- pl/sql 格式, 跟SQL类似, 只是每个块要有空格区分

FUNCTION company_name (company_id_in IN company.company_id%TYPE)  -- 参数多时可另起一行, 并缩进

   RETURN VARCHAR2

IS

   cname company.company_id%TYPE;



BEGIN        -- 前面有一行空格

   SELECT name INTO cname FROM company

    WHERE company_id = company_id_in;

   RETURN cname;



EXCEPTION    -- 前面有一行空格

   WHEN NO_DATA_FOUND 

   THEN

      RETURN NULL;

END;
SQL 好的结构

1-1.jpg

1-2.jpg

Xpert 基础
-- 如果注释另起一行, 要注意缩进要同注释的语句在同一个缩进级别

-- 多行注释, 推荐使用

/*

|| this is a multipule comments.

|| another line

*/



-- 注释接上一行时, 可以使用缩进

/*

|| Variables used to keep track of string scan:

||    atomic_count - running count of atomics scanned.

||    still_scanning - Boolean variable controls WHILE loop.

*/
注释
Xpert 基础
-- if 格式

-- <wait picture 1-3.jpg>#############



-- exception 格式

EXCEPTION

   WHEN exception1

   THEN

      executable_statements1;

 

   WHEN exception 2

   THEN

      executable_statements1;

 

   ...

   WHEN OTHERS

   THEN

      otherwise_code;

END;



/*

|| Indent each WHEN clause in from the EXCEPTION keyword that indicates the start of the exception section.

|| Place the THEN directly below the WHEN.

|| Indent all the executable statements for that handler in from the THEN keyword.

|| Place a blank line before each WHEN (except for the first)

*/



-- 在 package 中声明的内容

/*

|| 全局变量

|| Complex datatypes, such as records and tables

|| Database-related declarations, such as cursors

|| Named exceptions

|| Modules (procedures and functions)

 */
Format statement

1-3.jpg

 

你可能感兴趣的:(XP)