SQL访问规范
程序中不能出现SELECT*,即使是选择全部选择项,也需要全部指明,这主要出于如下原因:第一:使用*相对比较慢,因为Oracle需要遍历更多的内部字典信息;第二:为避免以后相关表增加字段造成程序错误,比如INSERT INTO SELECT和SELECT INTO语句会报错;
多表关联查询不能出现笛卡尔积,如果在报表中为集聚表(或称中间表)生成多个维度组成的复合主键需要使用迪克尔积的,必须请数据组确认性能。
在进行DML操作(INSERT,UPDATE,DELETE)之前,必须对数据进行备份,使用如下语句:
方法一:表数据全部备份:
CREATE TABLE TAB_NAME_BAK AS SELECT * FROM TAB_NAME;
方法二:部分备份:对大表仅备份将要修改的数据:
CREATE TABLE TAB_NAME_BAK
AS SELECT * FROM TAB_NAME WHERE [选择出被操作数据的条件];
代码中INSERT语句必须写出全部列名,以保证表增加字段后语句执行不受影响:
如:INSERT INTO TAB(COL1,COL2)VALUES(COL1_VAL,COL2_VAL);
再如:
INSERT INTO TAB(COL1,COL2)
SELECT COL1_VAL,COL2_VAL FROM TAB_BB;
不能将COL1,COL2和COL1_VAL,COL2_VAL省略;
DML操作涉及到大数据量时,请分解为多次执行;
对于UPDATE和DELETE每次涉及数据量在1万条左右,并且每次执行完就提交;
对于INSERT INTO SELECT如果采用提示(/*+ append parallel */)可以处理百万级别的数据量。
对于一个完成了的事务,请用commit显示提交,这是避免锁争用的锁等待的需要,特别是对DML操作频繁的表;
使用“变量绑定”来处理一条SQL带不同常量多次执行的情况,动态绑定可以大大优化SQL的执行效率,还可以优化Oracle的内存使用。
在Java中,结合使用setXXX 系列方法,可以为不同数据类型的绑定变量进行赋值,从而大大优化了SQL 语句的性能。
JAVA情况下的动态绑定示例如下:
String v_id = 'xxxxx';
String v_sql = 'select name from tb_a where id = ? ';
stmt = con.prepareStatement( v_sql );
stmt.setString(1, v_id ); //为绑定变量赋值
stmt.executeQuery();
使用“变量绑定”来处理一条SQL带不同常量多次执行的情况,动态绑定可以大大优化SQL的执行效率,还可以优化Oracle的内存使用。
PERL绑定变量实例如下:
$modsql = qq{
insert into tmp_tai_rtkpi_mark
(tab_name,
kpi_id,
ne_id,
timepoint,
cacu_time,
start_time,
stop_time,
down_base,
up_base,
ajast_flag,
inuse_flag,
cal_data)
values
(?,?,?,?,?,?,?,?,?,?,?,?)
};
if ( !$dbh->prepare($modsql) ) {
writeToLog( "start SQL prepare Error!/n" . DBI::errstr . "/n/n" );
}
$sth_msg_in_DB = $dbh->prepare($modsql)
|| die( "start SQL prepare Error!/n" . $DBI::errstr . "/n" );
$sth_msg_in_DB->bind_param( 1, $kpiid_tab{$kpi_id} );
$sth_msg_in_DB->bind_param( 2, $kpi_id );
$sth_msg_in_DB->bind_param( 3, -1 );
$sth_msg_in_DB->bind_param( 4, -1 );
$sth_msg_in_DB->bind_param( 5, $current_time );
$sth_msg_in_DB->bind_param( 6, $start_time );
$sth_msg_in_DB->bind_param( 7, $end_time );
$sth_msg_in_DB->bind_param( 8, $temp_min );
$sth_msg_in_DB->bind_param( 9, $temp_max );
$sth_msg_in_DB->bind_param( 10, 0 );
$sth_msg_in_DB->bind_param( 11, 1 );
$sth_msg_in_DB->bind_param( 12, -1 );
$sth_msg_in_DB->execute() || die( "SQL Execute Error!/n" . $DBI::errstr . "/n" );
避免重复访问(一):同源单组单查询:
如下语句要避免:
SELECT CLASS,sum(COL) FROM TAB_TEST WHERE CLASS=’A’ UNION ALL
SELECT CLASS,sum(COL) FROM TAB_TEST WHERE CLASS=’B’ UNION ALL
SELECT CLASS,sum(COL) FROM TAB_TEST WHERE CLASS=’C’
改写成:
SELECT CLASS,sum(COL) FROM TAB_TEST GROUP BY CLASS
避免重复访问(二):竖向显示变横向显示
问题语句:
SELECT A.C1 AC1,A.C2 AC2,A.C3 AC3,
B.C1 BC1,B.C2 BC2,B.C3 BC3,
C.C1 CC1,C.C2 CC2,C.C3 CC3
FROM
(SELECT '123' X, 'SYNONYM' C1, sum(2) C2,count(1) C3
FROM TAB WHERE TABTYPE = 'SYNONYM') A,
(SELECT '123' X,'TABLE' C1, sum(2) C2,count(1) C3
FROM TAB WHERE TABTYPE = 'TABLE') B,
(SELECT '123' X,'VIEW' C1, sum(2) C2,count(1) C3
FROM TAB WHERE TABTYPE = 'VIEW') C
;
正确使用形式如下:
SELECT MAX(DECODE(TABTYPE,'SYNONYM','SYNONYM',NULL)) AC1,
MAX(DECODE(TABTYPE,'SYNONYM',sum(2),0)) AC2,
MAX(DECODE(TABTYPE,'SYNONYM',count(1),0)) AC3,
MAX(DECODE(TABTYPE,'TABLE','TABLE',NULL)) BC1,
MAX(DECODE(TABTYPE,'TABLE',sum(2),0)) BC2,
MAX(DECODE(TABTYPE,'TABLE',count(1),0)) BC3,
MAX(DECODE(TABTYPE,'VIEW','VIEW',NULL)) CC1,
MAX(DECODE(TABTYPE,'VIEW',sum(2),0)) CC2,
MAX(DECODE(TABTYPE,'VIEW',count(1),0)) CC3
FROM TAB
WHERE TABTYPE IN('TABLE','SYNONYM','VIEW')
GROUP BY TABTYPE;
避免重复访问(三):一个表同时更新另一个表的多个字段
问题SQL:使用TB_SOURCE表更新表TB_TARGET的多个字段
UPDATE TB_TARGET A SET
A.COL1 = (select B.COL1 from TB_SOURCE B where B.id = A.id) ,
A.COL2 = (select B.COL2 from TB_SOURCE B where B.id = A.id) ,
A.COL3 = (select B.COL3 from TB_SOURCE B where B.id = A.id) ,
A.COL4 = (select B.COL4 from TB_SOURCE B where B.id = A.id)
WHERE A.id IN ( select B.id from TB_SOURCE B)
正确使用形式如下:
UPDATE TB_TARGET A
SET (COL1, A.COL2, A.COL3, A.COL4 )=(SELECT B.COL1, B.COL2, B.COL3, B.COL4
FROM TB_SOURCE B WHERE B.id = A.id)
WHERE EXISTS (select 1 from TB_SOURCE B where B.id = A.id)
程序中必须显示关闭数据库连接,不仅正常执行完后需显示关闭,而且在异常处理块(例如java的exception段)也要显示关闭。来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/27573546/viewspace-761477/ ,如需转载,请注明出处,否则将追究法律责任。