ORACLE编程规范
更新时间:2024-04-11 07:11:01 阅读量: 综合文库 文档下载
目 录
第1章 范围和简介 ....................................................................................................... 4 1.1 简介 ........................................................................................................................ 4 1.2 范围 ........................................................................................................................ 4 1.3 关键词 ..................................................................................................................... 4 1.4 术语和定义 ............................................................................................................. 4 第2章 文件格式及命名 ................................................................................................ 5 2.1 文件格式 ................................................................................................................. 5 2.2 文件命名 ................................................................................................................. 5 第3章 书写规范 ........................................................................................................... 6 3.1 大小写风格 ............................................................................................................. 6 3.2 缩进风格 ................................................................................................................. 7 3.3 空格及换行 ........................................................................................................... 11 3.4 创建表 ................................................................................................................... 14 3.5 创建过程/函数/包 .................................................................................................. 15 第4章 命名规范 ......................................................................................................... 16 第5章 注释规范 ......................................................................................................... 21 第6章 常用语法 ......................................................................................................... 25 6.1 变量声明 ............................................................................................................... 25 6.2 返回值 ................................................................................................................... 25 6.3 符号* ..................................................................................................................... 25 6.4 包的使用 ............................................................................................................... 26 6.5 绑定变量 ............................................................................................................... 26 6.6 异常处理 ............................................................................................................... 28 6.7 事务控制 ............................................................................................................... 29 6.8 游标使用 ............................................................................................................... 29 6.9 代码规模 ............................................................................................................... 31 第7章 SQL建议与约束 ............................................................................................. 32 7.1 建议 ...................................................................................................................... 32 7.2 禁止 ...................................................................................................................... 35 第8章 应用设计及性能调整 ....................................................................................... 40 8.1 日志表设计 ........................................................................................................... 40 8.1.1 特点描述 ......................................................................................................... 40 8.1.2 数据分析 ......................................................................................................... 41 8.1.3 设计方案 ......................................................................................................... 41 8.1.4 注意事项 ......................................................................................................... 44 8.2 并发事务表设计 .................................................................................................... 45 8.2.1 特点描述 ......................................................................................................... 45 8.2.2 数据分析 ......................................................................................................... 45 8.2.3 设计方案 ......................................................................................................... 45 8.2.4 注意事项 ......................................................................................................... 49 8.3 分区的设计 ........................................................................................................... 50
8.3.1 分区的优点 ..................................................................................................... 51 8.3.2 RANGE分区的应用场景 ................................................................................ 52 8.3.3 HASH分区的应用场景 ................................................................................... 53 8.3.4 分区注意事项 .................................................................................................. 54 8.4 索引设计 ............................................................................................................... 54 8.5 性能参数 ............................................................................................................... 60 8.5.1 序列对性能的影响 .......................................................................................... 60 8.5.2 EXTENT对数据插入性能的影响 .................................................................... 61 8.5.3 INITRANS对性能的影响 ................................................................................ 62 8.6 常见等待事件 ........................................................................................................ 63 第9章 开发工具 ......................................................................................................... 64 9.1 UltraEdit-32 .......................................................................................................... 64 9.2 PL/SQL Developer ............................................................................................... 64 9.3 TOAD ................................................................................................................... 64 9.4 PowerDesigner ..................................................................................................... 65 第10章 数据库代码走读CheckList ............................................................................. 66 第11章 附录 ................................................................................................................ 69 11.1 常见模块缩写表 .............................................................................................. 69 11.2 常用词缩写表 .................................................................................................. 69
2013-07-15 第2页,共70页
表目录
表1 表2 表3 表4 表5 表6
大小写规范表 .......................................................................................................... 6 对象前缀表 ........................................................................................................... 16 ORACLE系统对象使用前缀表 ............................................................................. 17 参数、变量、常量、异常等前缀表 ....................................................................... 18 常见模块缩写表 .................................................................................................... 69 常用词缩写表 ........................................................................................................ 69
2013-07-15 第3页,共70页
第1章 范围和简介
1.1 简介
本规范是针对关系型数据库ORACLE的相关特性,拟定的用于指导和规范相关开发过程的规范,其旨在通过该规范的约束和建议,使开发人员可以在他们所编写的代码中保持统一正确的风格,提供代码的可读性以及减少出现错误的几率。
1.2 范围
本规范仅适用于关系型数据库系统ORACLE以及其对应的PL/SQL脚本语言。
1.3 关键词
编程规范、数据库、ORACLE、PL/SQL
1.4 术语和定义
本规范采用以下的术语描述:
★ 规则:编程时强制必须遵守的原则。 ★ 建议:编程时必须加以考虑的原则。 ★ 说明:对此规则或建议进行必要的解释。 ★ 示例:对此规则或建议从正、反两个方面给出。
2013-07-15 第4页,共70页
第2章 文件格式及命名
2.1 文件格式
规则:数据库脚本文件的文件格式必须为纯文本,不允许使用包含格式文本的文件格式。
2.2 文件命名
规则:每个数据库脚本文件命名请参照下列描述:
1.表:TableName.tab 2.函数:FunctionName.fnc 3.存储过程:ProcedureName.prc 4.包规范:PackageName.spc 5.包体:PackageName.bdy
2013-07-15 第5页,共70页
第3章 书写规范
3.1 大小写风格
规则:数据库脚本中涉及到的各种保留字、关键字、操作符、数据类型、标识符、对象、字段、变量、常量等的大小写风格必须遵循以下规范:
表1
文字类型 ORACLE保留字(Reserved Word) 大小写规范表 大小写 大写 示例 IDENTIFIED、INITIAL、LONG、MAXEXTENTS、RENAME、ROWNUM、SYSDATE、VARCHAR2 ANALYZE、AUTOEXTEND、COMPILE、DBA、EXTENT、INSTANCE、MAXTRANS、SAVEPOINT、TABLESPACE ADD、BETWEEN、CREATE、DISTINCT、DROP、FROM、SESSION、SELECT、TABLE、UPDATE、VARCHAR BEGIN、COMMIT、CONSTRAINT、COUNT、CURSOR、DECLARE、EXECUTE、PRIMARY、SUM、TRANSACTION ARRAY、BOOLEAN、DATABASE、DO、EXIT、RAISE、SAVEPOINT、RUN、WHILE、XOR ALL、AND、ANY、ESCAPE、EXISTS、OR、UNION INT、NUMBER、DATE USER$、DBA_JOBS、DECODE、SUBSTR、DBMS_OUTPUT、PUT_LINE、NO_DATA_FOUND
第6页,共70页
ORACLE关键字(Keywords) 大写 ANSI SQL保留字(Reserved Word) 大写 ANSI SQL关键字(Keywords) 大写 PL/SQL保留字(Reserved Word) 大写 操作符(Operators) 大写 数据类型(Data Types) 系统数据库对象(System Tables、Views、Functions、Packages、Package Methods、Exceptions) 2013-07-15
大写 大写
自定义数据库对象(User Objects) 逻辑首字母大写 T_Table_Name、F_Function_Name、P_Procedure_Name User_Name、Acct_Item_ID c_BeginDate、c_EndDate v_BeginDate、v_FaxNumber、v_StaffAuth 字段名(Field) 常量(Constants) 变量(Variable) 逻辑首字母大写 逻辑首字母大写 逻辑首字母大写 说明:
? ORACLE的关键字和保留字请参见视图V$RESERVED_WORDS;
? 上表中需要大写的关键字/保留字,可以录入UltraEdit的wordfile.txt,在使用
UltraEdit开发时输入这些关键字保留字后会自动变为大写。
3.2 缩进风格
规则:脚本代码块采用缩进风格书写,保证代码清晰易读,风格一致。缩进格数统一为4个空格,但需要关键字右对齐或者参数/字段向上对齐的时候例外。 示例1:
CREATE SEQUENCE SQ_CSP_TABLENAME MINVALUE 1 START WITH 1 INCREMENT BY 1;
示例2:
IF c_CursorName%ISOPEN THEN CLOSE c_CursorName; END IF;
规则:缩进必须使用空格键,不允许使用TAB键。
规则:同一条语句占用多于一行时,每行的第一个关键字应当右对齐,但INSERT...SELECT语句例外。 示例1:
FETCH c_Cursor
INTO v_Field1, v_Field2, ... 2013-07-15
第7页,共70页
↑ 关键字右对齐
示例2:
SELECT FIELD1, FIELD2, ... FROM T_CSP_TABLENAME WHERE FIELD1 > 1
AND (FIELD2 < SYSDATE OR FIELD2 > SYSDATE + 3) AND FIELD3 LIKE 'HUAWEI%' GROUP BY FIELD1, FIELD2 ORDER BY FIELD1, FIELD2; ↑ 关键字右对齐
规则:在INSERT...SELECT语句中,如果需要换行时,应使INSERT INTO部分的字段与SELECT部分的字段一一对应,以增强可读性。 示例:
错误的写法:
BEGIN
INSERT INTO T_DEST_TABLENAME (DESTFIELDNAME1, DESTFIELDNAME2, DESTFIELDNAME3, DESTFIELDNAME4, DESTFIELDNAME5, DESTFIELDNAME6, DESTFIELDNAME7)
SELECT SRCFIELDNAME1, SRCFIELDNAME2, SRCFIELDNAME3, SRCFIELDNAME4, SRCFIELDNAME5, SRCFIELDNAME6, SRCFIELDNAME7 FROM T_SRC_TABLENAME; END;
正确的写法A:
BEGIN
INSERT INTO T_DEST_TABLE_NAME (DESTFIELDNAME1, DESTFIELDNAME2, DESTFIELDNAME3, DESTFIELDNAME4, DESTFIELDNAME5, DESTFIELDNAME6, DESTFIELDNAME7) SELECT SRCFIELDNAME1, SRCFIELDNAME2,
SRCFIELDNAME3, SRCFIELDNAME4, SRCFIELDNAME5, SRCFIELDNAME6, SRCFIELDNAME7 FROM T_SRC_TABLE_NAME; END;
正确的写法B:
BEGIN
INSERT INTO T_DEST_TABLE_NAME (DESTFIELDNAME1, -- 注释 2013-07-15
第8页,共70页
DESTFIELDNAME2, -- 注释 DESTFIELDNAME3, -- 注释 DESTFIELDNAME4, -- 注释 DESTFIELDNAME5, -- 注释 DESTFIELDNAME6, -- 注释 DESTFIELDNAME7) -- 注释 SELECT SRCFIELDNAME1, -- 注释 SRCFIELDNAME2, -- 注释 SRCFIELDNAME3, -- 注释 SRCFIELDNAME4, -- 注释 SRCFIELDNAME5, -- 注释 SRCFIELDNAME6, -- 注释 SRCFIELDNAME7 -- 注释 FROM T_SRC_TABLE_NAME; END;
正确的写法C:
BEGIN
INSERT INTO T_DEST_TABLE_NAME ( DESTFIELDNAME1, -- 注释 DESTFIELDNAME2, -- 注释 DESTFIELDNAME3, -- 注释 DESTFIELDNAME4, -- 注释 DESTFIELDNAME5, -- 注释 DESTFIELDNAME6, -- 注释 DESTFIELDNAME7) -- 注释 SELECT SRCFIELDNAME1, -- 注释 SRCFIELDNAME2, -- 注释 SRCFIELDNAME3, -- 注释 SRCFIELDNAME4, -- 注释 SRCFIELDNAME5, -- 注释 SRCFIELDNAME6, -- 注释 SRCFIELDNAME7 -- 注释 FROM T_SRC_TABLE_NAME; END;
正确的写法D:
BEGIN
INSERT INTO T_DEST_TABLE_NAME ( DESTFIELDNAME1, -- 注释 DESTFIELDNAME2, -- 注释 DESTFIELDNAME3, -- 注释 DESTFIELDNAME4, -- 注释 2013-07-15
第9页,共70页
DESTFIELDNAME5, -- 注释 DESTFIELDNAME6, -- 注释 DESTFIELDNAME7) -- 注释 SELECT SRCFIELDNAME1, -- 注释 SRCFIELDNAME2, -- 注释 SRCFIELDNAME3, -- 注释 SRCFIELDNAME4, -- 注释 SRCFIELDNAME5, -- 注释 SRCFIELDNAME6, -- 注释 SRCFIELDNAME7 -- 注释 FROM T_SRC_TABLE_NAME; END;
↑ 关键字右对齐
说明:
1、 在错误的写法中,虽然SELECT语句部分的SRCFIELDNAME1, SRCFIELDNAME2,
SRCFIELDNAME3可以写在一行中,但由于INSERT INTO语句部分中DESTFIELDNAME1, DESTFIELDNAME2写在一行中,而DESTFIELDNAME3在下一行,因此SELECT语句中每行的字段应与INSERT INTO语句中的字段一一对应(如正确的写法A);
2、 INSERT INTO语句中的各个字段折行后,应缩进并与上一字段左对齐(如正确的写法
B),或者与INTO关键字左对齐(如正确的写法C);
3、 SELECT语句中折行后的第一个字段名应缩进并与上一行的第一个字段名左对齐。
规则:INSERT INTO语句中,如果需要对每个字段增加注释,应将每个字段单独列为一行,并在行尾增加注释。 示例1:
INSERT INTO T_DEST_TABLE_NAME (DESTFIELDNAME1, -- 注释1 DESTFIELDNAME2, -- 注释2 DESTFIELDNAME3) -- 注释3 VALUES (FieldValue1, FieldValue2, FieldValue3);
或者
2013-07-15
第10页,共70页
INSERT INTO T_DEST_TABLE_NAME ( DESTFIELDNAME1, -- 注释1 DESTFIELDNAME2, -- 注释2 DESTFIELDNAME3) -- 注释3 VALUES (
FieldValue1, FieldValue2, FieldValue3);
或者
INSERT INTO T_DEST_TABLE_NAME (
DESTFIELDNAME1, -- 注释1 DESTFIELDNAME2, -- 注释2 DESTFIELDNAME3 -- 注释3 ) VALUES (
FieldValue1, FieldValue2, FieldValue3 );
其他说明:
1、 在规范的代码模板中详细给出了各种情况下的范例写法,请编码过程参考; 2、 在数据库脚本的编码过程中,请严格按照代码模板进行书写;
3、 对于模板中未涉及的情况,应在保证符合上述规范原则,同时和代码模板中的风格保
持一致的前提下,根据实际情况灵活处理。
3.3 空格及换行
规则:不允许把多个短语句写在一行中,即一行只写一条语句。 示例:
v_Variable1 := 1; v_Variable2 := 'abc';
应写成:
v_Variable1 := 1; v_Variable2 := 'abc';
2013-07-15 第11页,共70页
说明:两个赋值语句不能写在一行中,必须分两行写。
规则:相对独立的程序块之间、变量说明之后必须加空行。 示例:
v_Variable1 := 1;
IF v_BeginDate IS NULL THEN v_BeginDate := SYSDATE - 15; END IF;
应写成:
-- 初始化局部变量 v_Variable1 := 1;
-- 判断开始时间
IF v_BeginDate IS NULL THEN v_BeginDate := SYSDATE - 15; END IF;
说明:两个程序块在逻辑上相对独立,应用空行加以分隔,同时增加注释。
建议:建议对超过120字符的语句要分行书写,长表达式应在低优先级操作符处换行,操作符或关键字放在新行之首。划分出的新行应适当地缩进,使排版整齐、语句可读。是否分行应根据实际情况而定,原则是保证代码整齐、语句可读。 分行示例:
120字符 ↓
?? (a * b * c * d) + (e * f) + ??
应写成:
?? (a * b * c * d) + (e * f) + ??
说明:
1、 加法的优先级低于乘法,因此应在加号处换行;
2、 两组乘法虽然在逻辑上会先于加法执行,但显式加上括号使可读性更强。
规则:调用函数或过程时,如果参数列表超过120字符,应根据逻辑内容进行换行,或者每个参数占用一行。
2013-07-15
第12页,共70页
示例:
错误的写法:
120字符 ↓
P_PROCEDURE(i_Param1, i_Param2, i_Param3, o_Param1, oParam2, ...);
正确的写法A:
P_PROCEDURE(i_Param1, i_Param2, i_Param3, o_Param1, o_Param2, ...);
正确的写法B:
P_PROCEDURE(i_Param1, -- 注释 i_Param2, -- 注释 i_Param3, -- 注释 o_Param1, -- 注释 o_Param2, -- 注释 ...) -- 注释
说明:
1、 因为前三个为输入参数,后两个为输出参数,因此在第3、4参数之间换行比较清晰
(如正确的写法A);
2、 有时为了增加注释,可以使每个参数皆占用一行(如正确的写法B); 3、 参数换行以后与上一行的第一个参数对齐。
规则:双目运算符、操作符前后应以空格分隔,间隔符之后应以空格分隔。 示例:
v_DateVar:=TO_DATE('2001-01-01 01:30:00','YYYY-MM-DD HH24:MI:SS');
v_IntegerVar1:=v_IntegerVar2+v_IntegerVar3;
IF v_Number>0 THEN
应写成:
v_DateVar := TO_DATE('2001-01-01 01:30:00', 'YYYY-MM-DD HH24:MI:SS'); ↑ ↑ 赋值符前后加空格 逗号后面加空格
v_IntegerVar1 := v_IntegerVar2 + v_IntegerVar3; ↑ ↑ 赋值符前后加空格 加号前后加空格 2013-07-15
第13页,共70页
IF v_Number > 0 THEN ↑ 比较符号前后加空格
建议:不同优先级的操作符混合使用时,建议使用括号进行隔离。 示例:
?? a * b + c ??
应写成:
?? (a * b) + c ??
说明:使用括号使代码的优先级更加清晰,而且可以避免犯错。
建议:SQL语句中存在不同优先级的关系运算符时,建议使用括号。 示例:
WHERE FIELD1 > 1 AND FIELD2 < SYSDATE OR FIELD3 > SYSDATE + 3
应写成:
WHERE (FIELD1 > 1 AND FIELD2 < SYSDATE) OR (FIELD3 > SYSDATE + 3)
说明:如果SQL语句的条件复杂,很容易出现问题,因此增加括号可以提高可阅读性。
3.4 创建表
规则:脚本中的字段名缩进为4个空格。
规则:脚本中字段名称、字段类型、DEFAULT关键字应左对齐,NULL/NOT NULL应右对齐(也可以认为就是NULL关键字左对齐)。 示例:
CREATE TABLE T_WF_TABLE_NAME (
INTFIELD DATEFIELD )
TABLESPACE SERVICE_MAIN_DAT;
INT
NOT NULL, NOT NULL, NULL, NULL
FLOATFIELD NUMBER(4, 2)
DATE
VARCHAR2FIELD
DEFAULT 1.23
DEFAULT SYSDATE
VARCHAR2(200)
说明:至于每行中的每个项目之间使用多少个空格没有明确要求,只要求从纵向上各个字
2013-07-15
第14页,共70页
段的名称、数据类型、缺省值、是否为空等对齐美观即可。
3.5 创建过程/函数/包
规则:脚本中的参数缩进为4个空格。
规则:脚本中的参数名称、数据类型、注释信息应左对齐,IN/OUT/IN OUT关键字左对齐右对齐皆可。 示例:
CREATE OR REPLACE PROCEDURE P_CSP_PROCEDURENAME (
i_DateParam o_IntParam o_RetCode )
DATE,
-- 注释 -- 注释 -- 注释
IN OUT INT, OUT INT
o_VarcharParam OUT VARCHAR2, -- 注释
或者
CREATE OR REPLACE PROCEDURE P_CSP_PROCEDURENAME (
i_DateParam o_IntParam o_RetCode )
DATE, INT, INT
-- 注释 -- 注释 -- 注释
IN OUT
OUT OUT
o_VarcharParam VARCHAR2, -- 注释
说明:至于每行中的每个项目之间使用多少个空格没有明确要求,只要求从纵向上各个参数的名称、数据类型、IN/OUT关键字等对齐美观即可。
2013-07-15 第15页,共70页
第4章 命名规范
规则:所有用户自定义的数据库对象名称统一使用形如“对象前缀+下划线+模块名缩写+下划线+对象名称”的格式。 说明:
? 对象名称中可以根据需要使用下划线进行分隔;
? 创建对象时,禁止通过双引号指定对象名称,ORACLE在数据字典中统一存放为
大写;
? 对象类型前缀建议不要超过三个字符,可参考以下对象前缀表;
? 编码时禁止以ORACLE系统对象的前缀作为对象类型前缀,具体请参考
ORACLE系统对象使用前缀表;
? 模块名缩写建议不要超过三个字符,可参考附录中的常见模块名缩写表; ? 数据表字段名称没有前缀; ? 对象名称长度不宜超过18个字符。 ? 计费相关模块名:Comm,Cash,Owe,Acct
表2
对象类型 前缀 对象前缀表
示例 TBS_ACCT_INDEX TBS_COMM_INDEX T_OWE_TABLENAME T_CASH_BEGINDATE 备注 TBS 表空间命名(TableSpace) 表(Table) T 遵循现有规则,以A开头,例如:A_OWE_ITEM 建议采用 STATE_DATE的方式来命名 视图(View) 字段(Field) V 无 V_OWE_VIEWNAME FIELDNAME STATE_DATE 序列(Sequence) SEQ SEQ_TABLENAME_FIELDNAME 2013-07-15 第16页,共70页
索引(Index) IDX IDX_OWE_INDEXNAME IDX_CASH_INDEXNAME 如果表名或字段名过长,则用表名和字段名的缩写表示 如果表名或字段名过长,则用表名和字段名的缩写表示 如果表名过长,则用表名的缩写表示 T1为外键所在的表,T2为外键所参照的表 如果表名过长,则用表名的缩写表示 唯一索引 UK UK_OWE_INDEXNAME UK_CASH_INDEXNAME 主键(Primary Key) 外键(Foreign Key) PK PK_OWE_KEYNAME PK_CASH_KEYNAME FK_OWE_T1_T2 FK_CASH_T1_T2 FK 簇(Cluster) CLS CLS_OWE_TABLENAME CLS_CASH_TABLENAME 触发器(Trigger) 过程(Stored Procedure) 函数(Function) 包(Package) TRG TRG_OWE_TRIGGERNAME TRG_CASH_TRIGGERNAME P_OWE_PROCEDURENAME P_CASH_PROCEDURENAME P_OWE_FUNCTIONNAME P_CASH_FUNCTIONNAME PKG_OWE_PKGNAME PKG_CASH_PKGNAME SYN_OWE_TABLENAME P F PKG 同义词(Synonyms) 保存点(SavePoint) 类型(Type)
SYN SPT TYP SPT_OWE_SPTNAME SPT_CASH_SPTNAME TYP_OWE_TYPENAME 表3
对象类型 簇(Cluster) 索引(Index) ORACLE系统对象使用前缀表
前缀 C_ AQ$_ HS$_
示例 C_USER# AQ$_MSGTYPE_PRIMARY HS$_GRANTUSER_PK 第17页,共70页
2013-07-15
I_ SYS_ 包(Package) DBMS_ UTL_ AQ$_ EVT_ HS$_ ORA_ REPCAT$_ SMP_ SYSTEM_ DEF$_ SMP_ AQ$_ HS$_ DEF$_ EVT_ REPCAT$_ SMP_ AQ$_ SMP_ I_AUDIT SYS_C00512 DBMS_OUTPUT UTL_FILE AQ$_QIDSEQ EVT_NOTIFY_SEQ HS$_CLASS_CAPS_S ORA_TQ_BASE# REPCAT$_REPPROP_KEY SMP_LONG_ID SYSTEM_GRANT DEF$_ERROR SMP_JOB_ID AQ$_MESSAGE_TYPES HS$_PRIVILEGES DEF$_LOB EVT_OPERATORS REPCAT$_DDL SMP_JOB AQ$_DEF$_AQCALL SMP_BLOB 序列(Sequence) 同义词(Synonyms) 表(Table) 视图(View)
规则:所有用户定义的存储过程或函数中使用的参数、变量、异常等统一采用“小写前缀+下划线+逻辑首字母大写”的格式,其中的小写前缀代表参数、变量、类型或异常等的类型,而常量则统一使用全部大写(可根据情况使用下划线进行分隔)。小写前缀请参考下表:
表4
变量类型 函数、过程输入参数 函数、过程输出、输入输出参数 函数、过程局部变量 游标变量 i o v _Cursor 参数、变量、常量、异常等前缀表
示例 i_BeginDate i_EndDate o_Result o_Info v_WorkerNo CursorName_Cursor 备注 首字母 2013-07-15 第18页,共70页
自定义常量 自定义异常 自定义表类型 自定义表变量 自定义记录类型 自定义记录变量
c e _Table_Type _Table c_BeginTime e_UserException Emp_Table_Type Emp_Table _Record_Type Emp_Record_Type _Record Emp_Record 规则:标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
建议:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写,请参考附录中的常用词缩写表。
规则:命名中若使用特殊约定或缩写,则要有注释说明。
说明:应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。
规则:所有的命名不允许使用拼音,必须使用英文命名。
规则:使用有意义、易于记忆、描述性强、简短及具有唯一性的英文单词。使用下划线要有一致性,要么不用。自己特有的命名风格,要自始至终保持一致,不可来回变化。 说明:个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。
规则:对于变量命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还能表明其变量类型、数据类型等。形如i、j、k的变量只允许作为局部循环变量。
说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。
2013-07-15
第19页,共70页
规则:除非必要,不允许使用数字或较奇怪的字符来定义标识符。 示例:
如下命名,使人产生疑惑。
DECLARE temp_0_TEST VARCHAR2(10);
规则:用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。 示例:
Start <-> Finish First <-> Last Prior <-> Next Add <-> Remove Get <-> Set
启动 <-> 完成 第一个 <-> 最后一个 前一个 <-> 后一个 增加 <-> 删除 创建 <-> 析构 获取 <-> 设置 增量 <-> 减量 加锁 <-> 解锁 打开 <-> 关闭
Create <-> Destroy
Increment <-> Decrement Lock <-> UnLock Open <-> Close
2013-07-15 第20页,共70页
第5章 注释规范
建议:存储过程/函数脚本代码有效注释量应该在20%以上。
说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。
规则:在数据库脚本文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数或过程功能简要说明。 示例:
------------------------------------------------------------------------- -- File Name -- Author -- Version -- Date -- Copyright -- Usage -- Comments -- History -- 1. Date -- Author -- 2. ......
-------------------------------------------------------------------------
: 该脚本文件的文件名 : 该脚本文件的作者姓名与工号 : 该脚本文件的版本号 : 该脚本文件的最后更新日期 : 该脚本文件的版权信息
: 简要描述该脚本的使用/加载方法 : 该脚本文件的注释信息 : 该脚本文件的维护历史信息
: 修改日期,格式为YYYY-MM-DD : 修改人姓名与工号
-- Description : 该脚本文件的描述信息
-- Function List : 该脚本文件提供对象、函数、过程的列表
-- Modification : 修改说明
说明:格式内容请参见代码模板文件头。
规则:函数/存储过程头部应进行注释,列出:功能说明、设计人、编码人、创建日期、修改记录、调用关系(可选)等,输入参数/输出参数/返回值的说明直接添加到参数后面。 示例:
CREATE OR REPLACE FUNCTION F_CSP_FUNCTIONNAME /*
Description : 该函数的功能说明 Author 2013-07-15
: 姓名 工号
第21页,共70页
Date Version Caller Callee Comments History 1. Date */ (
i_DateParam o_IntParam ) RETURN INT AS
DATE,
-- 输入参数注释。包括含义、值域等。 -- 输出参数描述。 -- 返回值。
Author
: YYYY-MM-DD : 版本 : 调用者 : 被调用者
: 注释信息(包括产生异常的说明) :
: 修改日期,格式为YYYY-MM-DD : 修改人姓名与工号
Modification : 修改说明
2. ......
IN OUT VARCHAR2, -- 输入输出参数注释。
o_FloatParam OUT INT
规则:边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
规则:注释的内容要清楚、明了,含义准确,防止注释二义性。 说明:错误的注释不但无益反而有害。
规则:避免在注释中使用缩写,特别是非常用缩写。 说明:在使用缩写时或之前,应对缩写进行必要的说明。
规则:单行注释符“--”后必须加上一个空格。
规则:注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。 示例:
BEGIN ??
-- i_DateParam必须早于当前时间 2013-07-15
第22页,共70页
IF i_DateParam >= SYSDATE THEN RETURN 1; END IF; ?? END;
规则:注释与所描述内容进行同样的缩进。
说明:可使程序排版整齐,并方便注释的阅读与理解。
规则:注释与其上的代码用空行隔开。
建议:对变量的定义和分支语句(条件分支、循环语句等)建议给出注释。
说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。
规则:不允许在一行代码或表达式的中间插入注释。
说明:不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
规则:通过对函数或过程、变量、结构等合适的命名以及合理地组织代码的结构,使代码成为自注释的。
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。
规则:在代码的功能、意图层次上进行注释,提供有用、额外的信息。
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。 示例:
如下注释意义不大
-- i_RetCode = 0 IF i_RetCode = 0 THEN
2013-07-15 第23页,共70页
而如下的注释则给出了额外有用的信息。
-- 流程传入的标志为发送成功 IF i_RetCode = 0 THEN
2013-07-15
第24页,共70页
第6章 常用语法
6.1 变量声明
规则:代码中声明与表的字段相对应的变量时,应保证变量名和字段名相同。 说明:这样要求的目的是增强可读性。 示例:
DECLARE
v_DateField T_TABLENAME.DATEFIELD%TYPE; BEGIN
SELECT DATEFIELD INTO v_DateField FROM T_TABLENAME WHERE ROWNUM = 1; END;
规则:代码中声明与表的字段相对应的变量时,对类型的定义需要使用%TYPE方式。 说明:这样表结构的变动不会影响存储过程,避免表结构变更后出现变量长度或类型不一致的问题。
6.2 返回值
规则:函数的返回值定义应遵从下列规范:成功出口返回0,失败出口返回大于0整数。过程中定义的用于返回错误码的OUTPUT参数,其定义应遵从下列规范:成功出口返回0,失败出口返回非0整数。
6.3 符号*
规则:脚本中不允许出现“*”的用法,必须用实际的字段名代替,INSERT语句必须指定要插入的字段名。 示例:
1、游标定义
2013-07-15
第25页,共70页
错误用法:
CURSOR c_CursorName IS SELECT * FROM TABLENAME ...
正确用法:
CURSOR c_CursorName IS
SELECT FIELD1, FIELD2, ... FROM TABLENAME ...
2、INSERT 语句 错误用法:
INSERT INTO TABLENAME VALUES ...
正确用法:
INSERT INTO TABLENAME (FIELD1, FIELD2, ...) VALUES ...
6.4 包的使用
建议:ORACLE的包类似C++中的Class,有包头和包体两部分组成;包能够把相关的功能封装性在一个包中,包里面里可以有函数和过程。PACKAGE与PROCEDURE和FUNCTION的优点是封装性比较好;在开发过程中,可以把功能点紧密相关的PROCEDURE、FUNCTION封装在一个包里面。在对包体进行编译时,调用该包的存储过程不会失效。
6.5 绑定变量
规则:使用绑定变量的SQL语句,能使用绑定变量方式的业务逻辑下不允许使用绑定常量实现。
说明:在存储过程拼SQL语句作为动态SQL执行时,尤其需要注意。 示例:
错误用法:
v_SQL := 'DELETE FROM TABLENAME WHERE FIELD1 > SYSDATE AND FIELD2 = 102'; EXECUTE IMMEDIATE v_SQL;
正确用法:
v_ID := 102; 2013-07-15
第26页,共70页
v_SQL := 'DELETE FROM TABLENAME WHERE FIELD1 > :1 AND FIELD2 = :2'; EXECUTE IMMEDIATE v_SQL USING SYSDATE, v_ID;
规则:为提升性能,减少循环的开销,可以使用批量绑定。
说明:下面示例中的UPDATE语句可以一次将多条记录进行更新,而避免了通过使用循环同一条SQL执行多次。 示例:
CREATE OR REPLACE PROCEDURE P_CSP_TEST /*
Description : 根据输入的多个工单流水号,更新对应的SERVICECLASSID值 Author Date Version Caller Callee Comments History 1. Date */ (
i_SerialNos VARCHAR2, -- 一次输入多个工单流水号以'~'分隔' i_ServiceClassID VARCHAR2,
o_Ret OUT VARCHAR2 -- 成功返回0,失败返回1 ) AS
TYPE typ_StrArray IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER; v_ArrSerial typ_StrArray; BEGIN
FOR i IN 1..9999 LOOP
-- 把输入参数的值取出存放在数组v_ArrSerial中
EXIT WHEN GetParamStr(i_SerialNos, '~', i, v_ArrSerial(i)) <> 0;
END LOOP;
-- 根据数组中的工单流水号批量更新 FORALL i IN 1..v_ArrSerial.COUNT 2013-07-15
第27页,共70页
Author
: 姓名 工号 : YYYY-MM-DD : 版本 : 调用者 : 被调用者 : 注释信息 :
: 修改日期,格式为YYYY-MM-DD : 修改人姓名与工号
Modification : 修改说明
2. ......
UPDATE T_WF_SERVICEINFO t
SET t.SERVICECLASSID = i_ServiceClassID WHERE SerialNo = v_ArrSerial(i);
COMMIT;
o_Ret := 0;
EXCEPTION
WHEN OTHERS THEN ROLLBACK; o_Ret := 1; END;
6.6 异常处理
规则:函数/过程中应该有异常处理的代码,除非需要将任何可能的异常都向上抛出。 说明:不论代码逻辑是否简单,只要有可能会抛出异常,函数/过程块就应该包括异常处理代码。详见代码模板。
规则:如果需要的话,可以在异常处理部分将异常继续向上抛出给调用者。
说明:如果有些异常是预料可能产生,而且脚本需要根据是否有异常来做不同的逻辑处理,这种情况可以在异常处理部分将该异常进行处理,但可能有些意料之外的异常,需要继续向上抛出,便于调用者了解脚本执行是否成功,以便于调用者作下一步的处理如写错误日志等操作。
规则:如果需要自定义异常,必须在异常处理块中对其进行处理。
说明:如果自定义了异常,却没有相应的代码进行处理,那么就应该去掉该异常的定义。
规则:在对容错性要求比较高的情况下,对异常块中的代码还需要判断是否可能触发异常,必要的时候应使用嵌套的异常。
说明:在异常处理部分中的写日志之前,如果有事务,一定要先ROLLBACK;异常块中写日志、向表中插入一条初始化记录等语句也可能失败,对这些代码必要时也应该增加异
2013-07-15
第28页,共70页
常保护,即使用嵌套的异常处理。
6.7 事务控制
规则:在任何出口之前,只要存在事务未结束,必须提交或者回滚,除非有特殊设计考虑。
说明:存储过程在每个出口前,如果启动了事务必须结束所有事务,以提交(COMMIT)或回滚(ROLLBACK)来结束事务,否则可能会导致表锁等严重问题;如果在存储过程中,没有启动事务,就不必执行COMMIT或ROLLBACK,否则多余的ROLLBACK或COMMIT操作将增加数据库的额外开销。
规则:ORACLE的事务是串行的,嵌套调用中内层存储过程的提交会导致外层的存储过程事务被一并提交;诸如生成流水号这类存储过程应使用独立事务,否则在产生流水号时就将之前的业务逻辑操作提交,而后续的操作不能保证在一个事务中。例如现有系统中一个工单循环派给多个部门时,循环体内产生流水号,如最后一个派单失败时回滚操作根本就不能回撤所有操作,导致事务一致性被破坏。
建议:尽量分解大事务,事务的大小应视系统的性能和应用的具体情况而定,过多过小的事务造成重做日志同步的等待,比如要往一个表插入100万条记录,如果每条记录提交一次,则事务太小,可以做一个计数器,设置1万或事务5万条作一次提交。
6.8 游标使用
规则:原则上避免使用游标,尤其是动态游标。 说明:
1. 游标的效率较低,如果在代码中可以通过不同的条件分支实现的逻辑,尽量不要使用
游标。
2. 动态游标通常都可以转化为若干个静态游标,因此除非必要,尽量使用静态游标代替
动态游标。
2013-07-15
第29页,共70页
建议:推荐使用CURSOR FOR LOOP语句,可以隐式打开关闭游标;否则,显式打开游标,就必须在任何出口之前显式关闭游标。下面的示例通过 FOR IN LOOP取数据,不需要显示打开和关闭游标。 示例:
DECALRE
CURSOR c_Dept IS SELECT DEPTNO, DNAME FROM DEPT ORDER BY DEPTNO; v_Tot_Salary EMP.SALARY%TYPE; BEGIN
FOR r_Dept IN c_Dept LOOP
DBMS_OUTPUT.PUT_LINE('Department:' || r_Dept.DEPTNO); v_Tot_Salary := 0; END LOOP; END;
规则:如果存储过程返回游标类型参数,必须在任何出口前打开游标。
说明:如果存储过程有游标类型的输出参数,而在某个分支中未打开,其调用者使用该游标获取数据时会报错。 示例:
CREATE OR REPLACE PROCEDURE P_TMP_TESTSYSCURSOR( o_Cur OUT SYS_REFCURSOR -- 注释 ) AS BEGIN
IF v_Flag > 0 THEN
OPEN o_Cur FOR SELECT FIELD1 FROM T_WF_TABLE; RETURN; ELSE RETURN; END IF; END;
应写成:
CREATE OR REPLACE PROCEDURE P_TMP_TESTSYSCURSOR( o_Cur OUT SYS_REFCURSOR -- 注释 ) AS BEGIN
IF v_Flag > 0 THEN 2013-07-15
第30页,共70页
OPEN o_Cur FOR SELECT 0 AS RET, FIELD1 AS MSG FROM T_WF_TABLE; RETURN; ELSE
OPEN o_Cur FOR SELECT -1 AS RET, ’ErrorMsg’ AS MSG FROM DUAL; RETURN; END IF; END;
6.9 代码规模
建议:建议每个存储过程和函数的规模不宜超过500行。
说明:存储过程和函数的逻辑不宜太过复杂,应当注意对于同样的计算,存储过程执行效率远低于其他应用程序,所以要避免将大量业务逻辑都放到存储过程实现。
2013-07-15 第31页,共70页
第7章 SQL建议与约束
7.1 建议
建议:在开发过程中,在SQL语句中,尽量不要指定索引。
说明:指定索引后,在以后的优化过程中,无法通过创建和优化索引,使对应的SQL语句用到其他更好的索引,对指定的索引删除、重建改名后,可能导致该SQL语句用不到索引。
建议:在不使用DISTINCT、UNION、ORDER BY、GROUP BY情况下,也能实现业务功能的情况,一定不要使用这些功能。使用这些功能会导致对应的SQL语句排序,增加系统的开销。 示例:
错误的用法:
SELECT COUNT(*) FROM (
SELECT SERIALNO
FROM T_PUB_COMMONINFO WHERE A.PARTID >= '0127' AND A.PARTID <= '1227'
ORDER BY ACCEPTBEGINTIME DESC -- 没有用的ORDER BY )
建议:创建组合索引时,要注意组合索引的顺序和字段的选择性,把经常出现在WHERE条件中同时选择性比较好的字段放在复合索引的第一个位置。
说明:SQL语句在使用复合索引时,与该复合索引字段的组合顺序有关,当索引的第一个字段出现在WHERE条件中,这时候对该表的查询能够用到该索引,当该索引的第一个字段没有出现在SQL语句的查询条件中,但该索引的其他的字段出现在WHERE条件中时,在基于规则的优化模式中,SQL引擎会用全表扫描方式查询,在基于成本的优化模式中的(First Rows)方式查询,SQL引擎会对该索引全索引扫描方式查询。 示例:
2013-07-15 第32页,共70页
错误的用法:
ALTER TABLE T_WF_SERVICEINFOHIS
ADD CONSTRAINT PK_WF_SERVICEINFOHIS PRIMARY KEY (MONTHDAY, SERIALNO, SERVICECLASSID);
说明:在业务逻辑的查询中,许多时候之间按SERIALNO, SERVICECLASSID查时,在基于规则的优化模式中,用不到索引。
正确的用法:
ALTER TABLE T_WF_SERVICEINFOHIS
ADD CONSTRAINT PK_WF_SERVICEINFOHIS PRIMARY KEY (SERIALNO, SERVICECLASSID, MONTHDAY);
建议:创建表时数据和索引建议在不同的表空间。
建议:在WHERE条件表达式中,尽可能避免在要使用到索引的字段上使用函数,如果要使用函数建议创建相应的函数索引。 示例:
错误用法:
SELECT FIELD FROM TABLENAME
WHERE SUBSTRB(FIELD, 1, 4) = '5378'
正确用法:
SELECT FIELD FROM TABLENAME
WHERE FIELD LIKE '5378%'
建议:当查询条件选择性很低时使用索引反而降低效率,这种情况下,应该用特殊的方法屏蔽该索引,如果字段为数值型的就在表达式的字段名后+ 0,为字符型的就并上空串。 示例:
SELECT NUM_FIELD FROM TABLENAME
WHERE NUM_FIELD + 0 > 30
SELECT STRING_FIELD FROM TABLENAME
WHERE STRING_FIELD || '' = 'EXAMPLE' 2013-07-15
第33页,共70页
建议:在SQL语句中,尽可能使用变量绑定,少用常量绑定。
建议:如果业务逻辑允许的情况下,尽量用UNION ALL代替UNION,用UNION ALL代替OR。 示例:
错误的用法:
SELECT SERIALNO
FROM T_WF_DISPOSALSTATUSHIS
WHERE (ACCEPTPHONE = :B4 OR CALLERNO = :B3 OR USERPHONE1 = :B2) AND ACCEPTTIME > SYSDATE - :B1
正确的用法:
SELECT SERIALNO
FROM T_WF_DISPOSALSTATUSHIS WHERE (ACCEPTPHONE = :B4)
AND ACCEPTTIME > SYSDATE - :B1 UNION ALL SELECT SERIALNO
FROM T_WF_DISPOSALSTATUSHIS WHERE (CALLERNO = :B3)
AND ACCEPTTIME > SYSDATE - :B1 UNION ALL SELECT SERIALNO
FROM T_WF_DISPOSALSTATUSHIS A WHERE (USERPHONE1 = :B2)
AND ACCEPTTIME > SYSDATE - :B1
建议:如果要对整个表或分区的数据删除,建议使用TRUNCATE替代DELETE。
建议:为了提高系统的并发性,尽可能的使事务的时间缩短。
建议:创建分区表的索引时,必须创建本地(LOCAL)索引。
说明:如果创建的是全局索引,在对分区表的某个分区TRUNCATE时,导致该索引失效;需要对该全局索引进行重新编译。
2013-07-15
第34页,共70页
建议:避免通过DUAL表赋值。
说明:过多的对DUAL表的访问,导致调用该表的等待时间事件比较长。比如取系统时间之类的操作,往一个表插入记录等。 示例:
错误的用法:
SELECT SYSDATE INTO v_Date FROM DUAL
正确的用法:
v_Date := SYSDATE
错误的用法:
INSERT INTO TABLENAME(FIELD1, FIELD2, FIELD3) SELECT '2', SYSDATE, SUSBTR(v_Name, 1, 30) FROM DUAL;
正确的用法:
INSERT INTO TABLENAME(FIELD1, FIELD2, FIELD3) VALUES('2', SYSDATE, SUSBTR(v_Name, 1, 30));
7.2 禁止
规则:严禁用系统表空间作为用户默认表空间;严禁在系统表空间上创建用户数据库对象;严禁在SYSTEM/SYS等系统用户下,创建用户数据库对象。
规则:SQL语句的WHERE子句中应尽可能将字段放在等式左边,将计算操作放在等式的右边,除非是要屏蔽该字段的的索引,否则禁止字段参与表达式运算。
说明:任何对字段的操作都将造成此字段上的索引被屏蔽,导致全表扫描,这里所谓的操作包括数据库函数、计算表达式等等。 示例:
错误的用法:
SELECT SOME_FIELD FROM TABLENAME
WHERE NUM_FIELD / 30 < 1000
正确的用法:
2013-07-15
第35页,共70页
SELECT SOME_FIELD FROM TABLENAME
WHERE NUM_FIELD < 1000 * 30
错误的用法:
SELECT SOME_FIELD FROM TABLENAME
WHERE TO_CHAR(LOGDATE, 'YYYYMMDD') = '19991201'
正确的用法:
SELECT SOME_FIELD FROM TABLENAME
WHERE LOGDATE >= TO_DATE('19991201', 'YYYYMMDD') AND LOGDATE < TO_DATE('19991202', 'YYYYMMDD')
规则:SQL语句的WHERE子句中每个条件的操作符两边类型应相同,禁止潜在的数据类型转换。
说明:潜在的字段数据类型转换将造成索引被屏蔽,导致全表扫描。例如将字符型数据与数值型数据比较,ORACLE会自动将字符类型字段用TO_NUMBER函数进行转换。 示例:
错误的用法:
表TABLENAME中的列STRING_FIELD是字符型(VARCHAR),则以下语句存在类型转换:
SELECT SOMEFIELD FROM TABLENAME
WHERE STRING_FIELD > 10
正确的用法:
SELECT SOMEFIELD FROM TABLENAME
WHERE STRING_FIELD > '10'
规则:SQL语句的WHERE子句中避免使用IN操作,严禁使用NOT IN操作。
说明:在SQL语句中,能用表连接尽量使用表连接,不能使用表连接则使用EXISTS,严禁使用IN。 示例:
2013-07-15
第36页,共70页
错误的用法:
SELECT SOME_FIELD FROM TABLE1 WHERE FIELD1 IN (
SELECT FIELD2 FROM TABLE2 )
正确的用法:
SELECT T1.SOME_FIELD FROM TABLE1 T1, TABLE2 T2 WHERE T1.FIELD1 = T2.FIELD2
错误的用法:
SELECT SOME_FIELD FROM TABLE1
WHERE FIELD1 NOT IN (
SELECT FIELD2 FROM TABLE2 )
正确的用法:
SELECT SOME_FIELD FROM TABLE1 T1 WHERE NOT EXISTS (
SELECT 1
FROM TABLE2 T2
WHERE T2.FIELD2 = T1.FIELD1 )
规则:禁止对VARCHAR(2000)之类的大字段值进行ORDER BY、DISTINCT、GROUP BY、UNION之类的操作。
说明:此类操作将消耗大量的CPU和内存资源。
规则:禁止在没有事务的存储过程和代码中,随意使用COMMIT和ROLLBACK。 说明:过多多余的ROLLBACK和COMMIT容易引起数据库的同步日志等待事件,对系统的性能有影响,下面语句中的COMMIT和ROLLBACK就是多余的。 示例:
2013-07-15
第37页,共70页
错误的用法:
CREATE OR REPLACE PROCEDURE P_MS_QUERYBYSERIALNO (
i_SerialNo VARCHAR2, -- 工单流水号 rCursor OUT PACK_SERVICE.t_RetDataSet -- 返回结果集 ) AS BEGIN
OPEN rCursor
FOR SELECT b.STAFFNO AS STAFFNO, DECODE(b.COMMITRESULT, 0, '成功', '失败') AS COMMITRESULT FROM T_MS_SENDLOGHIS a, T_MS_INTERFACECALLED b WHERE b.SERIALNO = i_SerialNo;
COMMIT;
EXCEPTION
WHEN OTHERS THEN ROLLBACK; END;
正确的用法:
CREATE OR REPLACE PROCEDURE P_MS_QUERYBYSERIALNO (
i_SerialNo VARCHAR2, -- 工单流水号 rCursor OUT PACK_SERVICE.t_RetDataSet -- 返回结果集 ) IS BEGIN
OPEN rCursor
FOR SELECT b.STAFFNO AS STAFFNO, DECODE(b.COMMITRESULT, 0, '成功', '失败') AS COMMITRESULT FROM T_MS_INTERFACECALLED b WHERE b.SERIALNO = i_SerialNo;
EXCEPTION
WHEN OTHERS THEN OPEN rCursor
FOR SELECT '成功' AS STAFFNO, '成功' AS COMMITRESULT FROM DUAL WHERE 1 = 2; END; 2013-07-15
第38页,共70页
规则:禁止利用SQL语句做一些业务逻辑的判断或操作。 示例:
错误的用法:
SELECT STAFFNO, STAFFNAME FROM T_PUB_STAFF
WHERE (i_StaffNo IS NULL OR STAFFNO = i_StaffNo)
AND (i_StaffName IS NULL OR STAFFNAME LIKE '%' || i_StaffName || '%')
错误分析:上面的SQL语句中,利用SQL引擎对变量的值进行判断,导致在使用过程中,对该表进行全表扫描。
正确的用法:通过代码中对变量的值进行判断然后决定执行对应的SQL语句。
规则:禁止在生产系统,直接用PL/SQL Developer或TOAD之类的工具中直接调试存储过程。
规则:禁止在PL/SQL Developer中执行SELECT * FROM TABLE_NAME FOR UPDATE,然后点击锁图标方式,再编辑数据的方式进行更新数据库中的数据。
2013-07-15 第39页,共70页
第8章 应用设计及性能调整
应用中的表、索引设计,直接影响到事务处理以及查询操作的性能。通过对数据模型的合理的设计,可以极大的优化处理性能以及数据的维护工作。
表和索引的分类不具有唯一性,例如A_REAL_TIME_SERVICE表,属于并发事务类的范围,但是A_REAL_TIME_SERVICE_LOG属于较典型的日志表。因此分类的整理,不做具体限定。
8.1 日志表设计 8.1.1 特点描述
系统中日志表是用来存放业务以及应用系统轨迹的数据。其特点就是数据量巨大,并且不与核心业务相关联,后期不存在回退以及其它操作。
针对此类数据的特点,采用对表进行时间范围分区,对归档时间范围外的分区记录,通过分区交换的技术,予以摘除,减少在线查询的数据量,提供在线数据的稳定性和相关查询的稳定性。
表名 描述 备注 登录日志表 A_STAFF_LOGON_LOG A_STAFF_QUERY_LOG 综合查询日志表 待续
2013-07-15 第40页,共70页
8.1.2 数据分析
销帐登录日志表分为A_STAFF_LOGON,A_STAFF_LOGON_LOG,其中A_STAFF_LOGON表为在线事务表,A_STAFF_LOGON_LOG表为历史日志数据。并且LOG表,只会查询历史记录的查询操作,不会有回退等业务操作。
对生产系统中的日志表记录进行分析,数据量分布如下:
1 2 3 4 5 6 7 8 9 10
日期 记录数 时间点 记录数 2010-8-3 25337 1 2010-8-10 8:31 41 2010-7-6 23587 2 2010-8-10 8:32 36 2010-1-11 21186 3 2010-8-18 9:41 36 2010-1-26 19733 4 2010-7-6 15:30 34 2010-1-6 18639 5 2010-7-6 15:30 34 2010-9-3 17642 6 2010-8-10 8:31 33 2010-2-8 17545 7 2010-8-10 8:32 32 2010-9-6 16739 8 2010-9-15 15:06 28 2010-1-25 15693 9 2010-9-15 15:07 28 2010-7-27 15662 10 2010-9-15 15:07 27 日峰值记录 秒峰值记录
通过日峰值记录可以评估单月最大的数据量 25337*30=760110 单月记录数100w。
秒峰值记录可以评估表的并发操作数据,此记录数只是单纯的并发INSERT,不包括UPDATE/DELETE等操作,实际并发会更大一些。
8.1.3 设计方案
表类型 表名 在线事务表 A_STAFF_LOGON 历史日志表 A_STAFF_LOGON_LOG 归档日志表 A_STAFF_LOGON_201001
1、在线事务表,通过HASH分区的方式提高并发处理效率,减少资源争用
对在线数据表A_STAFF_LOGON,如果在V$SEGMENT_STATISTICS中查询,发
2013-07-15 第41页,共70页
现buffer busy waits,ITL waits统计结果较大,可以采取对在线数据表进行HASH分区的方式,减少资源的争用以及等待。
2、历史日志表,通过时间范围分区,改善查询性能,方便数据归档 通过登录时间对日志表进行时间范围分区
--建立时间分区日志表
CREATE TABLE A_STAFF_LOGON_LOG (
STAFF_LOGON_ID NUMBER(10) NOT NULL, STAFF_ID NUMBER(9) NOT NULL, IP_ADDR VARCHAR2(100) NOT NULL, APP_ID NUMBER(3) NOT NULL, LOGIN_DATE DATE NOT NULL, LOGOUT_DATE DATE,
JSESSION_ID VARCHAR2(250) )
PARTITION BY RANGE (LOGIN_DATE) (
PARTITION LOGIN_DATE_BEFORE201001 VALUES LESS THAN (TO_DATE('2010-01-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA01_TBS,
PARTITION LOGIN_DATE_BEFORE201002 VALUES LESS THAN (TO_DATE('2010-02-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA02_TBS,
PARTITION LOGIN_DATE_BEFORE201003 VALUES LESS THAN (TO_DATE('2010-03-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA03_TBS,
PARTITION LOGIN_DATE_BEFORE201004 VALUES LESS THAN (TO_DATE('2010-04-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA04_TBS,
PARTITION LOGIN_DATE_BEFORE201005 VALUES LESS THAN (TO_DATE('2010-05-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA05_TBS,
PARTITION LOGIN_DATE_BEFORE201006 VALUES LESS THAN (TO_DATE('2010-06-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA06_TBS,
PARTITION LOGIN_DATE_BEFORE201007 VALUES LESS THAN (TO_DATE('2010-07-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA07_TBS,
PARTITION LOGIN_DATE_BEFORE201008 VALUES LESS THAN (TO_DATE('2010-08-01', 'YYYY-MM-DD')) 2013-07-15
第42页,共70页
TABLESPACE ACCT_DATA08_TBS,
PARTITION LOGIN_DATE_BEFORE201009 VALUES LESS THAN (TO_DATE('2010-09-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA01_TBS,
PARTITION LOGIN_DATE_BEFORE201010 VALUES LESS THAN (TO_DATE('2010-10-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA02_TBS,
PARTITION LOGIN_DATE_BEFORE201011 VALUES LESS THAN (TO_DATE('2010-11-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA03_TBS,
PARTITION LOGIN_DATE_BEFORE201012 VALUES LESS THAN (TO_DATE('2010-12-01', 'YYYY-MM-DD'))
TABLESPACE ACCT_DATA04_TBS );
--建立时间分区索引
CREATE INDEX IDX_STAFF_LOGON_CREATE_DATE ON A_STAFF_LOGON_LOG(LOGIN_DATE) LOCAL
(PARTITION LOGIN_DATE_BEFORE201001 TABLESPACE ACCT_IDX01_TBS, PARTITION LOGIN_DATE_BEFORE201002 TABLESPACE ACCT_IDX02_TBS, PARTITION LOGIN_DATE_BEFORE201003 TABLESPACE ACCT_IDX03_TBS, PARTITION LOGIN_DATE_BEFORE201004 TABLESPACE ACCT_IDX04_TBS, PARTITION LOGIN_DATE_BEFORE201005 TABLESPACE ACCT_IDX01_TBS, PARTITION LOGIN_DATE_BEFORE201006 TABLESPACE ACCT_IDX02_TBS, PARTITION LOGIN_DATE_BEFORE201007 TABLESPACE ACCT_IDX03_TBS, PARTITION LOGIN_DATE_BEFORE201008 TABLESPACE ACCT_IDX04_TBS, PARTITION LOGIN_DATE_BEFORE201009 TABLESPACE ACCT_IDX01_TBS, PARTITION LOGIN_DATE_BEFORE201010 TABLESPACE ACCT_IDX02_TBS, PARTITION LOGIN_DATE_BEFORE201011 TABLESPACE ACCT_IDX03_TBS, PARTITION LOGIN_DATE_BEFORE201012 TABLESPACE ACCT_IDX04_TBS);
--建立查询索引
CREATE INDEX IDX_STAFF_LOGON_LOG_STAFF_ID ON A_STAFF_LOGON_LOG(STAFF_ID);
3、添加维护计划,对过期的日志表,进行分区摘除的操作,归档为独立的日志表,用于进行归档数据查询
--生成日志表脚本
SELECT CTAS || ' TABLESPACE ' || B.TABLESPACE_NAME || ' AS SELECT * FROM A_STAFF_LOGON WHERE 1=0;'
FROM (SELECT 'CREATE TABLE A_STAFF_LOGON_' ||
TO_CHAR(TRUNC(ADD_MONTHS(TO_DATE('200911', 'YYYYMM'), ROWNUM)), 'YYYYMMDD') CTAS, 2013-07-15
第43页,共70页
ROWNUM RN
FROM USER_TABLES A) A,
(SELECT T.TABLESPACE_NAME, ROWNUM RN FROM DBA_TABLESPACES T WHERE T.TABLESPACE_NAME LIKE 'ACCT_DATA%') B WHERE A.RN = B.RN AND ROWNUM <= 12;
--为分区表建立时间索引
CREATE INDEX IDX_STAFF_LOGON_20091201 ON A_STAFF_LOGON_20091201(LOGIN_DATE);
--进行分区交换操作
ALTER TABLE A_STAFF_LOGON_LOG EXCHANGE PARTITION LOGIN_DATE_BEFORE201001 WITH TABLE A_STAFF_LOGON_20091201 INCLUDING INDEXES UPDATE GLOBAL INDEXES;
--检查分区交换后索引的有效状态,防止查询异常
SELECT T.TABLE_NAME, T.INDEX_NAME, T.STATUS FROM USER_INDEXES T WHERE T.TABLE_NAME = 'A_STAFF_LOGON_LOG';
SELECT T.INDEX_NAME, T.PARTITION_NAME, T.STATUS FROM USER_IND_PARTITIONS T
WHERE T.INDEX_NAME = 'IDX_STAFF_LOGON_CREATE_DATE';
8.1.4 注意事项
A. 分区条件应该选择记录生成的时间标识,不会出现出现变更,避免分区记录的迁
移现象。
B. 历史归档数据需要在表上根据分区键建立时间条件索引,在进行分区交换时,通
过INCLUDING INDEXES操作进行交换。 C. 对于局部索引,通过使用
索引的失效。
D. 对于日志表和归档表,PCTFREE参数可以设置为0,因为不存在表上面的
UPDATE/DELETE操作,并且可以考虑采用压缩计数,降低存储空间的占用。 E. 对于归档日志表的跨范围查询,通过视图、时间分区表的方式进行查询。
UPDATE GLOBAL INDEXES
的方式,避免在分区交换时造成
2013-07-15 第44页,共70页
8.2 并发事务表设计 8.2.1 特点描述
系统中的停复机记录、短信记录表都存在短时间内大并发的操作。主要表现在DML操作频繁,并且对数据进行均匀分段时,较频繁的采用全表扫描方式访问。并且对处理效率要求较高,处理速度较慢时会出现大量数据挤压,对系统影响较大。
表名 描述 备注 A_REAL_TIME_SERVICE 销帐实时停复机请求表 A_SMS_SEND 短信记录表 待续
8.2.2 数据分析
以苏州数据库记录为例,目前A_REAL_TIME_SERVICE_LOG表的记录占用空间为
6G。
A_REAL_TIME_SERVICE表上会有大量的INSERT/UPDATE/DELETE操作,同时由于处理失败,会有部分状态为失败的记录遗留在表中,需要进行人工维护。如果有大帐户出现,短时间内无法处理完成时,后续记录不停的插入,会造成表所占用的空间逐步增大,现场出现过超过上G空间占用的情况。
8.2.3 设计方案
表类型 在线事务表 历史日志表 归档日志表 错误日志表
1、在线事务表,通过增大表和索引的INITRANS提高并发性能,将表放置在EXTEN较大的表空间上,避免频繁的空间分配操作,对表进行HASH分区提高并发处理效率,减
2013-07-15
第45页,共70页
表名 A_REAL_TIME_SERVICE A_REAL_TIME_SERVICE_LOG A_REAL_TIME_SERVICE_201001 A_REAL_TIME_SERVICE_ERR
少资源争用。
--创建HASH分区表
CREATE TABLE A_REAL_TIME_SERVICE (
ORDER_ID NUMBER(10) not null, PAYMENT_ID NUMBER(12) not null, ACCT_ID NUMBER(12) not null, SERV_ID NUMBER(12) not null, ACTION NUMBER(2) not null, STATE VARCHAR2(3) not null, CREATED_DATE DATE not null, STATE_DATE DATE not null, PROCESS_RESULT VARCHAR2(1000), SERVICE_TYPE VARCHAR2(3) not null, PROCESS_TYPE NUMBER(5) default 1, STAFF_ID NUMBER(9) )
PCTFREE 20 INITRANS 20 STORAGE (INITIAL 8M)
PARTITION BY HASH (PAYMENT_ID) PARTITIONS 8 STORE IN (
ACCT_DATA01_TBS, ACCT_DATA02_TBS, ACCT_DATA03_TBS, ACCT_DATA03_TBS );
--创建HASH分区索引
CREATE INDEX IDX_REAL_TIME_PAYMENT_ID ON A_REAL_TIME_SERVICE (PAYMENT_ID) INITRANS 20 LOCAL STORE IN (
ACCT_IDX01_TBS, ACCT_IDX02_TBS, ACCT_IDX03_TBS, ACCT_IDX04_TBS );
2、历史日志表,通过时间范围分区,改善查询性能,方便数据归档 通过记录生成时间对日志表进行时间范围分区
create table A_REAL_TIME_SERVICE_LOG (
ORDER_ID NUMBER(10) not null, PAYMENT_ID NUMBER(12) not null, ACCT_ID NUMBER(12) not null, SERV_ID NUMBER(12) not null, ACTION NUMBER(2) not null, 2013-07-15
第46页,共70页
STATE VARCHAR2(3) not null, CREATED_DATE DATE not null, STATE_DATE DATE not null, PROCESS_RESULT VARCHAR2(1000), SERVICE_TYPE VARCHAR2(3) not null, PROCESS_TYPE NUMBER(5) default 1, STAFF_ID NUMBER(9) )
PARTITION BY RANGE (CREATED_DATE) (
PARTITION REAL_TIME_LOG_AFT01 VALUES LESS THAN (TO_DATE('2010-02-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA01_TBS,
PARTITION REAL_TIME_LOG_AFT02 VALUES LESS THAN (TO_DATE('2010-03-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA02_TBS,
PARTITION REAL_TIME_LOG_AFT03 VALUES LESS THAN (TO_DATE('2010-04-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA03_TBS,
PARTITION REAL_TIME_LOG_AFT04 VALUES LESS THAN (TO_DATE('2010-05-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA04_TBS,
PARTITION REAL_TIME_LOG_AFT05 VALUES LESS THAN (TO_DATE('2010-06-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA01_TBS,
PARTITION REAL_TIME_LOG_AFT06 VALUES LESS THAN (TO_DATE('2010-07-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA02_TBS,
PARTITION REAL_TIME_LOG_AFT07 VALUES LESS THAN (TO_DATE('2010-08-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA03_TBS,
PARTITION REAL_TIME_LOG_AFT08 VALUES LESS THAN (TO_DATE('2010-09-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA04_TBS,
PARTITION REAL_TIME_LOG_AFT09 VALUES LESS THAN (TO_DATE('2010-10-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA01_TBS,
PARTITION REAL_TIME_LOG_AFT10 VALUES LESS THAN (TO_DATE('2010-11-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA02_TBS,
PARTITION REAL_TIME_LOG_AFT11 VALUES LESS THAN (TO_DATE('2010-12-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA03_TBS,
PARTITION REAL_TIME_LOG_AFT12 VALUES LESS THAN (TO_DATE('2011-01-01','YYYY-MM-DD')) TABLESPACE ACCT_DATA04_TBS )
3、添加维护计划,对过期的日志记录进行归档,对错误日志记录进行记录转储,对在线表的空间占用进行定期回收。
分区日志表的切换参考8.1中日志表的处理方式。
2013-07-15 第47页,共70页
--日志转储和空间回收测试脚本
CREATE OR REPLACE PROCEDURE ACCT_ONLINE_MIGRATE_PRC IS CURSOR ONLINE_MIGRATE_CUR IS
SELECT JOB_ID FROM ACCT_ONLINE_MIGRATE_LIST; MIGRATE_JOB_ID NUMBER; BEGIN
FOR ONLINE_MIGRATE_REC IN ONLINE_MIGRATE_CUR LOOP
DBMS_OUTPUT.put_line('JOB_ID = '||ONLINE_MIGRATE_REC.JOB_ID); --启动多个JOB执行数据迁移 DBMS_JOB.SUBMIT(MIGRATE_JOB_ID,
'TABLE_ONLIE_MIGRATE_PRC('||ONLINE_MIGRATE_REC.JOB_ID||');'); END LOOP; COMMIT; END; /
CREATE OR REPLACE PROCEDURE TABLE_ONLIE_MIGRATE_PRC(V_JOB_ID NUMBER) IS ONLINE_TYPE_INFO ACCT_ONLINE_MIGRATE_LIST%ROWTYPE; HIS_MIGRATE_SQL VARCHAR2(1000); ERR_MIGRATE_SQL VARCHAR2(1000); SHRINK_TABLE_SQL VARCHAR2(100); BEGIN
SELECT * INTO ONLINE_TYPE_INFO FROM ACCT_ONLINE_MIGRATE_LIST T WHERE T.JOB_ID = V_JOB_ID;
DBMS_OUTPUT.put_line('JOB_ID = '||ONLINE_TYPE_INFO.JOB_ID); DBMS_OUTPUT.put_line('ONLINE_TABLE = '||ONLINE_TYPE_INFO.ONLINE_TABLE);
DBMS_OUTPUT.put_line('HIS_TABLE = '||ONLINE_TYPE_INFO.HIS_TABLE); DBMS_OUTPUT.put_line('ERR_TABLE = '||ONLINE_TYPE_INFO.ERR_TABLE); DBMS_OUTPUT.put_line('HIS_TYPE = '||ONLINE_TYPE_INFO.HIS_TYPE); DBMS_OUTPUT.put_line('ERR_TYPE = '||ONLINE_TYPE_INFO.ERR_TYPE);
--历史数据迁移脚本
HIS_MIGRATE_SQL := 'INSERT INTO '||ONLINE_TYPE_INFO.HIS_TABLE||' SELECT * FROM '||ONLINE_TYPE_INFO.ONLINE_TABLE||
' WHERE STATE = '''||ONLINE_TYPE_INFO.HIS_TYPE||''''; --删除历史数据
EXECUTE IMMEDIATE HIS_MIGRATE_SQL; COMMIT; 2013-07-15
第48页,共70页
--不存在错误迁移的数据,不需要执行该操作 --错误数据迁移脚本
ERR_MIGRATE_SQL := 'INSERT INTO '||ONLINE_TYPE_INFO.ERR_TABLE||' SELECT * FROM '||ONLINE_TYPE_INFO.ONLINE_TABLE||
' WHERE STATE = '''||ONLINE_TYPE_INFO.ERR_TYPE||''''; --删除错误数据
EXECUTE IMMEDIATE ERR_MIGRATE_SQL; COMMIT;
--启动表数据行迁移 --表数据空间回收
SHRINK_TABLE_SQL := 'ALTER TABLE '||ONLINE_TYPE_INFO.ONLINE_TABLE||' SHRINK SPACE CASCADE';
EXECUTE IMMEDIATE SHRINK_TABLE_SQL; END; /
8.2.4 注意事项
A. 日志表的注意事项参考 8.1。
B. 调整在线事务表的建表、索引参数,对可以使用批量条件的业务,使用批量提交
的方式,提高性能。
C. 定期监控表的空间占用,防止出现空间占用过大的情况,对空间进行收缩后,统
计信息的更新。
D. 对需要进程全扫描划分进程段的表,可以考虑放入keep池中,提高全表扫描的
性能,优化数据分段SQL。(主要测试验证,已经空的块,是否会在keep中进行空间占用)
E. 维护脚本的后台运行时间是否会造成性能问题。
F. 维护列表中的表太多时,需要注意数据支持的最大JOB数是否符合。
G. 将DELETE操作改到夜间进行统一处理,但是会造成逻辑代码的大量修改,暂时
不考虑对业务代码进程此类操作。只对错误记录进行统一备份删除工作。 H. 加大序列的缓存值,提高处理性能。
2013-07-15 第49页,共70页
8.3 分区的设计
ORACLE的分区,用于解决海量数据存储、管理和性能的问题。目前系统中,对用户资料,余额信息,缴费信息,发票信息,欠费信息等数据进行了分区处理。主要采用到HASH、RANGE两类分区。
数据类型 ACCT AGREEMENT CUST CUST_IDENTIFICATION 表名 分区字段 ACCT_ID 未分区 CUST_ID CUST_ID SERV_ID ACCT_ID SERV_ID SERV_ID SERV_ID ACCT_ID OPER_PAYOUT_ID ACCT_BALANCE_ID ACCT_BALANCE_ID ACCT_BALANCE_ID ACCT_ID ACCT_ID ACCT_ID ACCT_ID ACCT_ID PRINT_ID PAYMENT_ID ACCT_ID 分区方式 RANGE RANGE RANGE RANGE RANGE RANGE RANGE RANGE RANGE HASH HASH HASH HASH RANGE RANGE RANGE RANGE RANGE HASH HASH RANGE 用户资料 SERV SERV_ACCT SERV_ATTR SERV_LOCATION SERV_SUBSRIBER ACCT_BALANCE BALANCE_ACCT_ITEM_PAYED 余额信息 BALANCE_PAYOUT BALANCE_SOURCE BALANCE_SOURCE_PAYOUT_RELA A_VIREMENT_BATCH_BILL A_VIREMENT_BATCH_PAYED 销帐数据 BILL PAYMENT ACCT_ITEM_OWE A_INVOICE_DETAIL 发票数据 A_INVOICE_EXTEND INVOICE 2013-07-15 第50页,共70页
正在阅读:
ORACLE编程规范04-11
《磁生电》02-12
现代诗歌:栗子03-21
护理技术操作手册2012年01-26
实行党政领导干部任期制的难点及对策12-05
数学建模习题集06-02
ASTM A系列(黑色金属)标准目录(中英文) - 图文11-12
安全教育活动方案通用版(精彩6篇)03-22
先进人物通讯稿范文02-20
老司机的开车经验01-05
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 规范
- 编程
- ORACLE
- 如果你看完你将收获100万
- 专题03 正确使用词语(包括熟语)-2014年高考语文考纲解读及热点
- 考场规则
- 《多元统计分析》第三版例题习题数据文件
- 中小学信息课程标准(完整版)
- 2011年下半年客户经理岗位资格考试模拟试卷(福州分行)
- 持续改进控制程序(正文)
- 银联POS终端系统参数设置说明
- 东北大学材料加工复试题背诵版
- 《用业绩证明你的能力》读后感
- 论现代博物馆陈列布展设计
- 我的硕士路(2)
- 教育叙事之教育实习日记100篇
- 2012年“金钥匙”科技竞赛(初三学生CESL活动)决赛试题 有答案
- 第十三章 光单元检测
- 公务员面试技巧:你真的懂考官想听什么
- 2017届高考物理一轮复习 专题汇编 5 带电粒子在电场中运动的综合
- 湘雅医学院08上口腔内科学 考试评分标准
- 中国充气婴儿水池行业发展研究报告 - 图文
- 浙江省台州市2018年中考科学(化学部分)真题试题(含解析)