1. ORACLE的SQL書寫規范
/**
ORACLE的SQL規范,目的避免SQL執行錯誤,提高SQL腳本的質量;
一般執行SQL在command模式下,所以每個完整的語句需要在後面加上斜杠("/"),特別是過程或函數必須在其後加上斜杠("/")
多條非過程SQL語句在最後面一條語句後加上斜杠("/"),如insert、update、delete。在執行完,做下commit;
例子以表名TEST1說明,注意:create_str使用的varchar2類型,長度5000,如果SQL太長,要調整長度。
*/
declare
create_str varchar2(5000) := 'create table TEST1(ID int,REALNAME varchar2(32))';
count_flag number;
begin
select count(*)
into count_flag
from user_tables
where table_name = 'TEST1';
if count_flag < 1 then
execute immediate create_str;
else
execute immediate 'drop table TEST1';
execute immediate create_str;
--欄位註解規范
execute immediate 'COMMENT ON COLUMN "TEST1"."ID" IS ''編號''';
execute immediate 'COMMENT ON COLUMN "TEST1"."REALNAME" IS ''姓名''';
end if;
end;
/
declare
add_str varchar2(5000) := 'alter table TEST1 add NICKNAME varchar(32)';
count_flag number;
begin
select count(*)
into count_flag
from user_tab_columns
where table_name = 'TEST1'
and column_name = 'NICKNAME';
if count_flag < 1 then
execute immediate add_str;
--欄位註解規范
execute immediate 'COMMENT ON COLUMN "TEST1"."NICKNAME" IS ''昵稱''';
end if;
end;
/
declare
add_str varchar2(5000) := 'alter table TEST1 modify NICKNAME varchar(100)';
count_flag number;
begin
select count(*)
into count_flag
from user_tab_columns
where table_name = 'TEST1'
and column_name = 'NICKNAME';
if count_flag = 1 then
execute immediate add_str;
--欄位註解規范
execute immediate 'COMMENT ON COLUMN "TEST1"."NICKNAME" IS ''昵稱''';
end if;
end;
/
declare
add_str varchar2(5000) := 'alter table TEST1 drop column NICKNAME';
count_flag number;
begin
select count(*)
into count_flag
from user_tab_columns
where table_name = 'TEST1'
and column_name = 'NICKNAME';
if count_flag = 1 then
execute immediate add_str;
end if;
end;
/
declare
create_str varchar2(5000) := 'create index IDX_TEST1_ID on TEST1(id)';
count_flag number;
begin
select count(*) into count_flag from user_indexes where table_name='TEST1' and index_name='IDX_TEST1_ID';
if count_flag < 1 then
execute immediate create_str;
else
execute immediate 'drop index IDX_TEST1_ID';
execute immediate create_str;
end if;
end;
/
declare
create_str varchar2(5000) := 'create sequence SEQ_TEST1 minvalue 1 maxvalue 999999999999 start with 1 increment by 1';
count_flag number;
begin
select count(*) into count_flag from user_sequences where sequence_name='SEQ_TEST1';
if count_flag < 1 then
execute immediate create_str;
else
execute immediate 'drop sequence SEQ_TEST1';
execute immediate create_str;
end if;
end;
/
insert into TEST1
(id, realname, nickname)
select 1, '網名', '網蟲'
from al
where not exists (select * from TEST1 where id = 1);
/
update TEST1 set realname='網名', nickname='網蟲' where id=1;
/
delete from TEST1 t where t.id=1;
/
2. 如何書寫高效的SQL語句
優化SQL查詢:如何寫出高性能SQL語句
1、首先要搞明白什麼叫執行計劃?
執行計劃是資料庫根據SQL語句和相關表的統計信息作出的一個查詢方案,這個方案是由查詢優化器自動分析產生欀如一條SQL語句如果用來從一個10萬條記錄的表中查1條記錄,那查詢優化器會選擇「索引查找」方式,如果該表進行了歸檔,當前只剩下5000條記錄了,那查詢優化器就會改變方案,採用 「全表掃描」方式。
可見,執行計劃並不是固定的,它是「個性化的」。產生一個正確的「執行計劃」有兩點很重要:
(1) SQL語句是否清晰地告訴查詢優化器它想干什麼?
(2) 查詢優化器得到的資料庫統計信息是否是最新的、正確的?
2、統一SQL語句的寫法
對於以下兩句SQL語句,程序員認為是相同的,資料庫查詢優化器認為是不同的。
select * from al
select * From al
其實就是大小寫不同,查詢分析器就認為是兩句不同的SQL語句,必須進行兩次解析。生成2個執行計劃。
所以作為程序員,應該保證相同的查詢語句在任何地方都一致,多一個空格都不行!
3、不要把SQL語句寫得太復雜
我經常看到,從資料庫中捕捉到的一條SQL語句列印出來有2張A4紙這么長。一般來說這么復雜的語句通常都是有問題的。我拿著這2頁長的SQL語句去請教原作者,結果他說時間太長,他一時也看不懂了。可想而知,連原作者都有可能看糊塗的SQL語句,資料庫也一樣會看糊塗。
一般,將一個Select語句的結果作為子集,然後從該子集中再進行查詢,這種一層嵌套語句還是比較常見的,但是根據經驗,超過3層嵌套,查詢優化器就很容易給出錯誤的執行計劃。因為它被繞暈了。像這種類似人工智慧的東西,終究比人的分辨力要差些,如果人都看暈了,我可以保證資料庫也會暈的。
另外,執行計劃是可以被重用的,越簡單的SQL語句被重用的可能性越高。而復雜的SQL語句只要有一個字元發生變化就必須重新解析,然後再把這一大堆垃圾塞在內存里。可想而知,資料庫的效率會何等低下。
4、使用「臨時表」暫存中間結果
簡化SQL語句的重要方法就是採用臨時表暫存中間結果,但是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,後面的查詢就在tempdb中了,這可以避免程序中多次掃描主表,也大大減少了程序執行中「共享鎖」阻塞「更新鎖」,減少了阻塞,提高了並發性能。