数据库开发规范
以下是偶参照各方资料写的一点数据库开发规范。
写的不是很全,而且一直在完善中,杯具的是发现和word写出来的格式上稍微有一点不一样的,嘿嘿,那就凑合看了。
欢迎讨论这个文档的内容,如果转载,请写明出处。
本规范采用以下术语描述:
★规则:也称为强规范是编程时必须强制遵守的原则
★建议:编程时必须加以考虑的原则
★说明:对此规则或建议进行必要的解释
★示例:对此规则或建议从正、反两个方面给出
规则1: 数据库代码中,关键字大写,其他内容小写(在PL/SQL中可设置关键字自动转换为大写,以降低编码时的大小写切换)
示例:
如下代码不符合规范:(关键字未大写)
select last_name ,job_id
from hr.employees;
如下代码符合规范:
SELECT last_name ,job_id
FROM hr.employees;
规则1:程序块应采用缩进风格书写,保证代码可读,风格一致,缩进格数统一为2格;
规则2:代码中需要空位时,统一采用空格键输入,不允许用TAB键产生空位;
说明:不同的编辑器对TAB的空位格数设置不一致,会导致使用TAB键产生空位的代码格式混乱;
规则3:同一条语句占用多行时,每一行的开始应是关键字,且关键字应和第一行左对齐,如确实不能从关键字分行,则分行处应对其上一行被分行的同类代码的最左边;
示例:
如下代码不符合规范(分行书写时,其余行未和第一行左对齐)
SELECT last_name , job_id
FROM hr.employees;
如下代码也不符合规范(分行时,不是从关键字分行)
SELECT last_name,
job_id FROM hr.employees;
如下代码符合规范
SELECT last_name , job_id
FROM hr.employees;
如下代码符合规范
SELECT last_name,
first_name,
job_id
FROM hr.employees;
建议1:对于INSERT… VALUES和UPDATE语句,一行写一个字段,每个字段相对于INSERT语句空两格,这段后面紧跟注释(注释语句左对齐),VALUES和INSERT左对齐,左括号和右括号与INSERT、VALUES左对齐。
示例:
如下代码不符合建议(字段未和INSERT语句空两格)
INSERT INTO hr.sm_user
(
user_id, -user’s id ,primary key
user_name, -username
login_name -login name
)
VALUES
(
p_user_id,
p_user_name,
p_login_name
)
如下代码符合建议
INSERT INTO hr.sm_user
(
user_id, -用户ID,主键
user_name, -用户名
login_name -登录名
)
VALUES
(
p_user_id,
p_user_name,
p_login_name
)
建议2:INSERT…SELECT 语句时,应使每行的字段顺序对应,以每行最多不超过4 个字段,以方便代码阅读,括号的内容另起一行缩进2 格开始书写,关键字单词左对齐,左括号、右括号另起一行与左对齐。
示例
如下代码不符合建议(字段未和括号分行)
INSERT INTO hr.sm_duty_bak(duty_id,duty_ name, created_by, creation_date,
last_updated_by, last_update_date, disable_date)
SELECT duty_id, duty_name, created_by, creation_date,
last_updated_by, last_update_date, disable_date
FROM hr.sm_duty
WHERE duty_id=:duty_id
如下代码符合建议
INSERT INTO hr.sm_duty_bak
(
duty_id, duty_name, created_by, creation_date,
last_updated_by, last_update_date, disable_date
)
SELECT duty_id, duty_name, created_by, creation_date,
last_updated_by, last_update_date, disable_date
FROM hr.sm_duty
WHERE duty_id=:duty_id
说明:
1.SELECT 语句中每行的字段应与INSERT 语句对应。
2.INSERT 语中中折行的字段名应缩进并与上一行的第一个字段名对齐。
3.SELECT 语句中折行的字段名应缩进并与上一行的第一个字段名对齐。
规则1:不允许将多行语句书写在同一行
示例
如下代码不符合规范(将两行定义书写在同一行)
v_count := 1; v_creation_date := sysdate;
如下代码符合规范
v_count := 1;
v_creation_date := sysdate;
规则2:不允许将SQL语句写成一行,再短的SQL也应该在谓词处分行
示例
如下代码不符合规范(未在谓词部分进行分行)
SELECT last_name , job_id FROM hr.employees WHERE job_id = 1;
如下代码符合规范
SELECT last_name , job_id
FROM hr.employees;
WHERE job_id = 1;
规则3:相对独立的程序块之间应加空行
示例
如下代码不符合规范(变量定义和程序段之间无空行)
v_duty_id := 1;
IF TRUNC(NVL(disabled_date, sysdate + 1)) > TRUNC(sysdate) THEN
SELECT duty_name
FROM hr.sm_duty
WHERE duty_id = :duty_id;
…
END IF;
如下代码符合规范
v_duty_id := 1;
IF TRUNC(NVL(disabled_date, sysdate + 1)) > TRUNC(sysdate) THEN
SELECT duty_name
FROM hr.sm_duty
WHERE duty_id = :duty_id;
…
END IF;
规则4:不同类型的操作符混合使用时,应使用括号明确的表达运算的先后关系
示例
如下代码不符合规范(运算优先级关系易混淆)
SELECT a*b/c+d*e
FROM dual;
如下代码符合规范
SELECT ((a*b)/c)+(d*e)
FROM dual;
规则5:BEGIN和END应独立成行
示例
如下代码不符合规范(BEGIN和END未独立成行)
BEGIN null; EXCEPTION WHEN others TEN null; END;
如下代码符合规范
BEGIN
null;
EXCEPTION
WHEN others TEN
null;
END;
规则6:SQL语句中的逗号后面应增加一个空格,以使得代码清晰
示例
如下代码不符合规范(逗号后面没有空格)
SELECT last_name , job_id
FROM hr.employees;
如下代码符合规则
SELECT last_name , job_id
FROM hr.employees;
建议1:减少控制语句的判断次数,比如在ELSE(IF…ELSE)语句中,尽量将尽快能检测到结果的判断提前
示例
如下语句不符合规范(假定v_count=1的条件大多数情况会满足)
IF (v_count = 0) THEN
null;
ELSEIF (v_count = 1) THEN
null;
END IF;
如下语句符合规范(假定v_count=1的条件大多数情况会满足)
IF (v_count =1) THEN
null;
ELSEIF (v_count = 0) THEN
null;
END IF;
建议2:尽量避免使用嵌套的IF语句,在这种情况应使用多个IF语句来判断其可能性。
示例
如下语句不符合规范(使用了嵌套的IF语句来进行判定)
IF v_count = 0 THEN
IF v_flag = 0 THEN
null;
ELSE
null;
END IF;
ELSE v_count = 1 THEN
IF v_flag = 0 THEN
null;
ELSE
null;
END IF;
END IF;
如下语句符合规范
IF (v_count = 0) AND (v_flag = 0) THEN
null;
ELSEIF (v_count = 0 ) AND (v_flag = 1) THEN
null;
ELSEIF (v_count = 1) AND (v_flag = 0) THEN
null;
ELSEIF (v_count = 1) AND (v_flag = 1) THEN
null;
END IF;
建议3:存储过程、函数、触发器、程序块中定义的变量和输入、输出参数在命名上有所区分。
说明:
一般用’v_’开头代表程序块中定义的变量
一般用’p_’开头代表输入参数变量
一般用’x_’开头代表输入输出或输出参数变量
规则1:查询数据时,尽量不使用SELECT *,而是给出明确的字段,但该规则不包括SELECT COUNT(*)语句
示例
如下语句不符合规范(SELECT操作未给出字段)
SELECT *
FROM hr.employees;
如下语句符合规范
SELECT last_name , first_name
FROM hr.employees;
规则2:INSERT语句应该出字段列表
示例
如下语句不符合规范(INSERT操作未给出字段名称)
INSERT INTO hr.employees
VALUES
(
‘GUO’,
’DAVID’,
100
);
如下语句符合规范
INSERT INTO hr.employees
(
last_name,
first_name,
job_id
)
VALUES
(
‘GUO’,
‘DAVID’,
100
);
规则3:从表中同一笔记录中获取记录的字段值,须使用一SQL 语句得到,不允许分多条SQL 语句。
示例
如下语句不符合规范(从同一个表中取出记录,分成两条语句分别扫描)
UPDATE hr.employees_new
SET last_name=
(SELECT last_name
FROM hr.employees
WHERE job_id = 100
)
WHERE job_id = 100;
UPDATE hr.employees_new
SET first_name =
(SELECT first_name
FROM hr.employees
WHERE job_id = 100
)
WHERE job_id = 100;
如下语句符合规范
UPDATE hr.employees_new
SET first_name =
(SELECT last_name
FROM hr.employees
WHERE job_id = 100
),
last_name =
(SELECT first_name
FROM hr.employees
WHERE job_id = 100
)
WHERE job_id = 100;
规则4:当一个PL/SQL 或SQL 语句中涉及到多个表时,始终使用别名来限定字段名,这使其它人阅读起来更方便,避免了含议模糊的引用,其中能够别名中清晰地判断出表名。
说明 : 别名命名时,尽量避逸使用无意义的代号a、b 、c… , 而应该有意义( 如表mtl_system_items_b 对应别名为msi,po_headers_all 别名对应为pha)。
示例
如下语句不符合规范(未使用有明确含义的表别名)
SELECT a.wip_entity_name, a.wip_entity_id, a.date_released
FROM wip.wip_entities b,
wip.wip_discrete_jobs a
WHERE b.wip_entity_id = a.wip_entity_id
AND a.status_type = 3
AND a.date_released > TRUNC(sysdate);
如下语句符合规范
SELECT wdj.we_entity_name, wdj.wip_entity_id, wdj.date_released
FROM wip.wip_entities we,
wip.wip_discrete_jobs wdj
WHERE we.wip_entity_id = wdj.wip_entity_id
AND we.status_type = 3
AND we.date_released > TRUNC(sysdate);
规则5:确保变量和参数在类型和长度与表数据列类型和长度相匹配。
说明:如果与表数据列宽度不匹配,则当较宽或较大的数据传进来时会产生运行异常。
示例
如下代码不符合规范(假定表wap_user的字段user_name的定义为varchar2(10))
DECLARE
v_user_name varchar2(15);
BEGIN
UPDATE wap.wap_user
SET user_name = :v_user_name;
WHERE sky_id = 100;
END;
如下代码符合规范
DECLARE
v_user_name varchar2(10);
BEGIN
UPDATE wap.wap_user
SET user_name = :v_user_name;
WHERE sky_id = 100;
END;
规则6:一句SQL如果只访问了单表,禁止使用表别名
示例
如下代码不符合规范(单表使用了表别名)
SELECT emp.last_name , emp.job_id
FROM hr.employees emp;
如下代码符合规范
SELECT last_name , job_id
FROM hr.employees;
规则7:运算符以及比较符左边或者右边只要不是链接的括弧,则空一格
示例
如下代码不符合规范(运算符没有空格)
SELECT sysdate + 1
FROM dual;
如下代码符合规范
SLEECT sysdate + 1
FROM dual;
规则8:任何SQL书写单行不得超过80字符(含左边的缩进)
规则9:无特殊情况,代码注释尽量使用英文;
所有命名规则中,必须优先遵守通用规则,列入通用规范中的规则必须强制遵守
规则1:任何数据库对象的命名,不得使用汉字;
示例
如下语句不符合规范(表明和字段名使用了汉字)
CREATE TABLE hr.用户
(
用户名 varchar2(100),
pass_word varchar2(16)
);
如下语句符合规范
CREATE TABLE hr.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则2:任何命名长度不得超过30
说明:在部分数据库中(例如ORACLE),表名长度是不可以超过30的,如果命名超过30,则可能给以后的迁移带来麻烦
示例
如下语句不符合规范(表命名达到31位长度)
CREATE TABLE wap.wap_user_telphone_number_region
(
user_name varchar2(100),
pass_word varchar2(16)
);
如下语句符合规范
CREATE TABLE wap.wap_user_tel_number_region
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则3:用户对象命名应全部为小写,且不允许使用控制符号强制转换对象为小写字符
说明:部分数据库(如oracle中,系统表会记录对象为大写,如果使用了强制转换为小写,则每次访问均要使用强制字符访问)
示例
如下语句不符合规范(使用控制引号将表名强制为小写)
CREATE TABLE “WAP”.“wap_user_tel_number_region”
(
user_name varchar2(100),
pass_word varchar2(16)
);
如下语句符合规范
CREATE TABLE wap.wap_user_tel_number_region
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则4:命名应使用富有意义的英文,禁止使用拼音首字母,一般情况下不建议使用拼音命名;
示例
如下语句不符合规范(表名使用了中文且字段使用了拼音首字母简写)
CREATE TABLE wap.wap_yonghu
(
yhm varchar2(100),
pass_word varchar2(16)
);
如下语句符合规范
CREATE TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
规范5:命名不得使用数据库保留字
说明:使用了数据库保留字,会导致需要访问该对象时,需要代码做特别的转换才能访问
示例
如下代码不符合规范(假定user为数据库保留字)
CREATE TABLE wap.wap_user
(
user varchar2(100),
pass_word varchar2(16)
);
如下代码符合规范
CREATE TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则1:同类业务的表,以相同的表示该类业务的英文开头
说明:同类业务的表以相同的英文开头,在逻辑上清晰,且可避免维护过程中对该类表的误操作
示例
如下语句不符合规范(假定表wap_user和表user_login_log都属于wap类业务)
CREATA TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
CREATE TABLE wap.user_login_log
(
user_name varchar2(100),
login_date date
);
如下语句符合规范
CREATA TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
CREATE TABLE wap.wap_user_login_log
(
user_name varchar2(100),
login_date date
);
规则2:同类表,如果按照时间不同建立的表,后缀格式一般情况下应为’_YYYY[MM[DD]]’格式
示例
如下语句不符合规范(将年份2010简写为10,导致含义模糊)
CREATE TABLE wap.wap_user_login_1004
(
user_name varchar2(100),
login_date date
);
CREATE TABLE wap.wap_user_login_1005
(
user_name varchar2(100),
login_date date
);
如下语句符合规范
CREATE TABLE wap.wap_user_login_201004
(
user_name varchar2(100),
login_date date
);
CREATE TABLE wap.wap_user_login_201005
(
user_name varchar2(100),
login_date date
);
规则1:字段命名应具有含义,能反映该字段存储的内容,如确实无法使用富有含义的字段名,则应增加字段备注。
示例
如下语句不符合规范(假定存储的字段为用户名和密码,如下的字段名毫无意义)
CREATE TABLE wap.wap_user
(
col1 varchar2(100),
col2 varchar2(16)
);
如下语句符合规范
CREATE TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
-如下语句是使用了无意义字段名,但增加了字段说明,不作为推荐方法,但确实字段名无法表述含义时,必须使用该方法;
CREATE TABLE wap.wap_user
(
col1 varchar2(100),
pass_word varchar2(16)
);
COMMENT ON COLUMN wap.wap_user.a IS ‘username’;
规则2:同种用途的字段,在同一个业务中的所有表中,应保持有同样的字段类型和字段长度,并尽量保持一致的字段命名
示例
如下语句不符合规范(字段user_name在两个有业务关系的表中字段长度不一致,易导致业务接口冲突)
CREATA TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
CREATE TABLE wap.wap_user_login_log
(
user_name varchar2(80),
login_date date
);
如下语句符合规范
CREATA TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
CREATE TABLE wap.wap_user_login_log
(
user_name varchar2(100),
login_date date
);
建议1:字符类型尽量定义为varchar类型而非char类型
说明:在数据库存储中,varchar类型采用变长存储,而char类型为定长存储,在大多数情况下,定长更浪费空间,但是定长字符的性能略高于变长字符
示例
如下语句不符合建议
CREATA TABLE wap.wap_user
(
user_name char(100),
pass_word varchar2(16)
);
如下语句符合建议
CREATA TABLE wap.wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则1:主键名称应以”pk_”开头,后接表名
示例
如下语句不符合规则(主键名未以pk_开头)
ALTER TABLE wap.wap_user
ADD CONSTRAINT wap_user_p PRIMARY KEY (user_name) ;
如下语句符合规则
ALTER TABLE wap.wap_user
ADD CONSTRAINT pk_wap_user PRIMARY KEY (user_name) ;
规则1:外键名应以”fk_”开头,后接表名
示例
如下语句不符合规范(外键名未以fk_开头)
ALTER TABLE wap.wap_user_login_log
ADD CONSTRAINT wap_user_login_log_f FOREIGN KEY (user_name)
REFERENCES wap.wap_user (user_name);
如下语句符合规范
ALTER TABLE wap.wap_user_login_log
ADD CONSTRAINT fk_wap_user_login_log FOREIGN KEY (user_name)
REFERENCES wap.wap_user (user_name);
规则1:唯一索引应以”uk_”+”表名_”+”字段名”命名
示例
如下语句不符合规范(唯一索引未以uk_开头)
CREATE UNIQUE INDEX wap.wap_user_username_u
ON wap.wap_user(username);
如下语句符合规范
CREATE UNIQUE INDEX wap.uk_wap_user_username
ON wap.wap_user(username);
规则2:普通索引应以”idx_”+”表名_”+“字段名”命名
示例
如下语句不符合规范(不符合索引命名规范)
CREATE INDEX wap.wap_user_user_id_idx
ON wap.wap_user(user_id);
如下语句符合规范
CREATE INDEX wap.idx_wap_user_user_id
ON wap.wap_user(user_id);
规则3:bitmap索引应以”bidx_”+”表名_”+“字段名”命名
示例
如下语句不符合规范(不符合bitmap索引命名规范)
CREATE BITMAP INDEX wap.idx_wap_user_profile
ON wap.wap_user(profile);
如下语句符合规范
CREATE BITMAP INDEX wap.bidx_wap_user_profile
ON wap.wap_user(profile);
规则1:视图命名应以“v_”+“表名[_表名[_表名]]”命名
示例
如下语句不符合规范(视图和表是不可以同名的,如下语句会引起错误且不符合规范)
CREATE VIEW wap.wap_user
AS
SELECT first_name ,last_name ,job_id
FROM wap.wap_user;
如下语句符合规范
CREATE VIEW wap.v_wap_user
AS
SELECT first_name ,last_name ,job_id
FROM wap.wap_user;
规则1:同义词命名要求和其所指向的对象同名
示例
如下语句不符合规范(增加了syn_前缀)
CREATE PUBLIC SYNONYM wap.wap_user FOR wap.syn_wap_user;
如下语句符合规范
CREATE PUBLIC SYNONYM wap.wap_user FOR wap.wap_user;
规则1:函数命名以”func_”开头,后接函数的功能
示例
如下语句不符合规范(未以fun_开头)
CREATE FUNCTION wap.get_money
BEGIN
……
END;
如下语句符合规范
CREATE FUNCTION wap.func_get_money
BEGIN
……
END;
规则1:存储过程以“prc_”开头,后接功能描述
示例
如下语句不符合规范(未以prc_开头)
CREATE PROCEDURE wap.update_user
BEGIN
……
END;
如下语句符合规范
CREATE PROCEDURE wap.prc_update_user
BEGIN
……
END;
规则1:包以“pkg_”开头,后接功能描述
示例
如下语句不符合规范(未以pkg_开头)
CREATE PACKAGE wap.update_user
BEGIN
……
END;
如下语句符合规范
CREATE PACKAGE wap.pkg_update_user
BEGIN
……
END;
规则1:数据库链以“dl_”+“$SID_$USER”命名
示例
如下语句不符合规范(假定链接到sid=david并且使用用户guoyue链接)
CREATE DATABASE LINK wap.dblink1
CONNECT TO guoyue
IDENTIFIED BY guoyue
USING ‘david’;
如下语句符合规范
CREATE DATABASE LINK wap.dl_david_guoyue
CONNECT TO guoyue
IDENTIFIED BY guoyue
USING ‘david’;
规则1:触发器以“tri_”+表名+“_ins/del/upd”+”_before/after”命名
示例
如下语句不符合规范(未遵循命名规范)
CREATE TRIGGER wap.trigger1
AFTER DELETE ON wap.wap_user
BEGIN
……
END;
如下语句符合规范
CREATE TRIGGER wap.tri_wap_user_del_after
AFTER DELETE ON wap.wap_user
BEGIN
……
END;
规则1:物化视图以“mv_”+“表名[_表名]”命名
示例
如下语句不符合规范(命名不是以mv_开头,且使用了视图的命名规则)
CREATE MATERIALIZED VIEW wap.v_wap_user
AS
SELECT * FROM wap.wap_user;
如下语句符合规范
CREATE MATERIALIZED VIEW wap.mv_wap_user
AS
SELECT * FROM wap.wap_user;
规则1:临时表以“tmp_”开头,后接功能描述
示例
如下语句不符合规范
CREATE GLOBAL TEMPORARY TABLE wap.tab_tmp1
(
user_name varchar2(100),
pass_word varchar2(16)
);
如下语句符合规范
CREATE GLOBAL TEMPORARY TABLE wap.tmp_wap_user
(
user_name varchar2(100),
pass_word varchar2(16)
);
规则2:如果是在上线/割接中被重命名的表,命名应是原表名+“_YYYYMMDD”
示例
如下语句不符合规范(临时表以old结尾,而非日期结尾)
ALTER TABLE wap_user TO wap.wap_user_old;
如下语句符合规范
ALTER TABLE wap_user TO wap.wap_user_20100416;
规则1:数据库用户名以字母开头,字母和数字混合且长度不超过8个字符,同时,密码必须包含小写字母,大写字母,数字,特殊字符四种组合且不少于8位
示例
如下语句不符合规范(用户名以数字开头且超过8位,密码只有小写字母且不足8位)
CREATE USER 12345guoyue identified by guoyue;
如下语句符合规范
CREATE USER guoyue IDENTIFIED BY Oracle123456&8(;
规则1:数据库设计文档中,必须包含表数据保留时间;
规则2:数据库设计文档中,必须包含表在最大保留时间下的数据量;
规则3:数据库设计文档中,如果表为分区表,必须包含分区条件;
规则4:数据库设计文档中,必须包含表的读写频率;
规则5:单SEGMENT (如单个普通表,分区表的单个分区,单个普通索引,分区索引的单个分区)原则上不得超过2GB大小;
规则6:和其他表有关联的表,和其他表功能一致的字段类型以及长度,尽量使用相同的列名;
规则7:禁止依靠设计数据库表之间的主外键关系来保证数据一致性;
规则8:需要UPDATE的字段,不得设计为分区条件字段;
建议1:对于需要同步到数据仓库的表,原则上必须包含同步频率以及同步机制;
建议2:原则上每个表应设计一个主键;
建议3:原则上不建议使用大对象类型(CLOB,BLOB,LOGN)等类型字段,如需设计这些字段,需有特别说明;
建议4:如无特别需要,原则上,字符类型选择变长字段,数字类型选择NUMBER;
建议5:如无特别需要,原则上不得设定表的并发度,压缩等属性;
建议6:对于易混淆的字段,建议加上备注;
规则1:无特别说明,每个表的索引,不得超过5个;
规则2:单字段上的索引不得超过2个;(即一个单字段最多可在上面建立一个单字段索引和一个组合索引包含这个字段)
规则3:复合索引原则上不得超过3个字段;
规则4:原则上,分区表的索引必须是分区索引;
建议1:频繁出现在where字句里的字段建议建立索引;
建议2:用来和其他表关联的字段建议建立索引;
建议3:索引字段建议有高的选择性和过滤性(count(distinctid)/count(*)>0.6);
建议4:对于枚举值较少的字段,建议不要创建B-tree索引,建议建立bitmap索引;
建议5:在where子句里作为函数参数的字段,不能创建索引,不建议建立函数索引;
建议6:建立索引的时候,建议考虑到SELECT和INSERT,UPDATE,DELETE的平衡;
建议7:一般建议在查询数据量10%以下使用索引;
建议8:WHERE子句的查询条件构成索引字段前导字段;
建议9:选择性更高的字段放在组合字段索引的前导字段;
建议10:如果字段选择性接近,则把频繁查询的字段放在前面;
建议11:如果字段查询频率相同,则把表中的数据的排列顺序所依据的字段放在前面;
建议12:进行GROUP BY或者是ORDER BY的字段应在组合字段索引的前导字段;
规则1:所有序列应设置CACHE值为不低于100
建议1:如果要求获得的字段具有强连续和强排序性,则不适宜使用序列
规则1:频繁更新的表上,不得建立refreshfastoncommit类型的物化视图
建议1:如非必要,不建议使用物化视图,可采用程序控制的表来进行数据的同步
规则1:视图中不允许出现ORDER BY排序
规则2:基于多表关联的视图,必须在字段名前指定表别名
建议1:视图的基础数据尽量从表中获取,尽量不要嵌套视图
规则1:存储过程,必须有异常捕获代码
规则2:存储过程中严禁使用GOTO语句进行跳转
规则3:有循环更新的存储过程,必须进行批量提交,且必须进行事物控制
规则4:存储过程中如果打开了dblink,则在存储过程正常或者异常退出必须关闭所有打开的dblink
规则5:存储过程中如果使用了游标,则在存储过程正常或者异常退出必须关闭所有打开的游标
规则6:存储过程中如果有更新,必须在异常捕获代码中做回退操作
建议1:存储过程每次被更新,应在注释中说明更新的内容,更新的日期,以及更新的责任人,并且在更新前保留旧版本代码
规则1:函数中,如果进行了事物处理,必须有异常捕获代码
规则2:函数中严禁使用GOTO语句进行跳转
规则3:有循环更新的函数,必须进行批量提交,且必须进行事物控制
规则4:函数中如果打开了dblink,则在函数正常或者异常退出必须关闭所有打开的dblink
规则5:函数中如果使用了游标,则在函数正常或者异常退出必须关闭所有打开的游标
规则6:函数中如果对数据进行了更新操作,必须在异常捕获代码中做回退操作
建议1:函数每次被更新,应在注释中说明更新的内容,更新的日期,以及更新的责任人,并且在更新前保留旧版本代码
建议2:函数尽量只是实现复杂的计算功能,不对数据库进行更新操作
规范1:如无必要,不得设计触发器,任何触发器的设计,必须得到DBA批准
规范2:应用的完整性不应由触发器保证,而是通过代码的事务控制;
建议1:有高度一致性依赖的逻辑,触发器应设计为BEFORE而非AFTER方式
本访问规范中主要是访问数据库数据时对性能有影响的SQL语句的写法,且无特别说明,本规则基于ORACLE数据库。
本规则中列举的各项访问建议中,从逻辑上,对实现业务需求无太大区别,但访问数据库的性能有比较大的差异,因此该部分描述的大部分为建议,但是,在合适的情况下,请尽量遵守该规则;
规则1:当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个COLUMN上.这样一来,就可以减少解析的时间并减少那些由COLUMN歧义引起的语法错误.
规则2:禁止进行字段数据类型的隐式转换,所有转换必须进行明确的数据类型转换
说明:隐式转换会导致字段上的索引失效,而进行显式转换,会提醒到开发人员该种操作会导致索引失效
规则3:禁止在多表关联的时候,在非索引字段上的关联;
规则4:进行模糊查询时,禁止条件中字符串直接以“%”开头;
建议1:尽量使用DECODE来简化SQL访问数据库的次数
示例:
如下两个语句实现的功能
SELECT COUNT(*),SUM(salary)
FROM hr.employees
WHERE = department_id = 20
AND first_name LIKE ‘SMITH%’;
SELECT COUNT(*),SUM(salary)
FROM hr.employees
WHERE = department_id = 30
AND first_name LIKE ‘SMITH%’;
可以使用DECODE改写为如下语句
SELECT COUNT(DECODE(department_id,20,’*',NULL)) d20_count,
COUNT(DECODE(department_id,30,’*',NULL)) d30_count,
SUM(DECODE(department_id,20,salary,NULL)) d20_sal,
SUM(DECODE(department_id,30,salary,NULL)) d30_sal
FROM hr.employees
WHERE first_name LIKE ‘SMITH%’;
建议2:避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.
示例
如下语句使用的是HAVING子句
SELECT last_name, avg(salary)
FROM hr.employees
GROUP BY last_name
HAVING last_name != ’Grant’
AND last_name!= ’Fay’
改写使用WHERE的语句如下
SELECT last_name, avg(salary)
FROM hr.employees
WHERE last_name != ’Grant’
AND last_name!= ’Fay’
GROUP BY last_name
建议3:一次UPDATE多个字段的时候,应一次查询完成
示例
如下语句同时UPDATE两个字段
UPDATE guoyue.employees
SET salary=(SELECT MAX(salary)
FROM guoyue.employees),
employee_id=(SELECT MAX(employee_id) + 1
FROM guoyue.employees)
WHERE employee_id = 198;
使用下列语句的写法效率更高
UPDATE guoyue.employees
SET(salary,employee_id)
=(SELECT MAX(salary),MAX(employee_id) + 1
FROM guoyue.employees)
WHERE employee_id = 198;
建议4:使用EXISTS/NOT EXISTS替代IN/NOT IN
示例
如下使用IN的操作效率比较低
SELECT *
FROM hr.employees
WHERE employee_id > 0
AND department_id IN
(SELECT department_id FROM hr.departments
WHERE department_name LIKE ‘IT%’)
如下使用EXISTS的操作效率比较高
SELECT *
FROM hr.employees emp
WHERE employee_id > 0
AND EXISTS
(SELECT 1
FROM hr.departments dep
WHERE dep.department_id = emp.department_id
AND dep.department_name LIKE ‘IT%’)
建议5:采用表连接替代EXIST
示例
如下语句使用EXIST来进行判定,效率会低下
SELECT first_name
FROM hr.employees emp
WHERE EXISTS
(SELECT 1
from hr.departments dep
where emp.department_id = dep.department_id
AND dep.department_name like ‘IT%’
)
如下写法会比较高效
SELECT first_name
FROM hr.employees emp,hr.departments dep
WHERE emp.department_id = dep.department_id
AND dep.department_name like ‘IT%’
建议继续学习:
- hbase介绍 (阅读:11032)
- 基于SSD的数据库性能优化 (阅读:7412)
- TT的作者出新作品鸟:kyoto tycoon (阅读:6844)
- 规范自己的JavaScript书写 (阅读:5964)
- PHP编码规范 (阅读:4340)
- 国内互联网公司数据库访问层调查 (阅读:3135)
- 分清“语言/规范”以及“平台/实现”,以及跨平台.NET开发 (阅读:3174)
- 数据库程序开发原则:不要删除数据 (阅读:2934)
- Android 4.0设计规范 优先导读 十大改变 (附全文翻译pdf) (阅读:2730)
- 编码风格不是编码规范 (阅读:2601)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:三少 来源: OracleDBA Blog
- 标签: 数据库 规范
- 发布时间:2011-01-30 19:17:37
- [55] Oracle MTS模式下 进程地址与会话信
- [55] IOS安全–浅谈关于IOS加固的几种方法
- [54] 如何拿下简短的域名
- [53] android 开发入门
- [53] 图书馆的世界纪录
- [52] Go Reflect 性能
- [49] 读书笔记-壹百度:百度十年千倍的29条法则
- [49] 【社会化设计】自我(self)部分――欢迎区
- [38] 程序员技术练级攻略
- [33] 视觉调整-设计师 vs. 逻辑