1. 程式人生 > >sql日常總結

sql日常總結

一、sql基礎

  1. 查詢city欄位以A或L或N開頭的資料
SELECT * FROM Persons WHERE City LIKE '[ALN]%'
  1. 查詢city欄位不以A或L或N開頭的資料
SELECT * FROM Persons WHERE City LIKE '[!ALN]%'
  1. 連線符
select concat(id,’的學號’,cardno,’的卡號’);  #Mysql語法
select 'hello'||'oracle' test from dual;   #Oracle語法(oracle也可以用上邊的concat)
  1. 字串
select substr('hello',0,3) from dual    --下標1與0效果一樣   結果:hel
select length('hello') from dual   --結果:5
select replace('hello','l','x') from dual   --結果:hexxo
  1. 數值
select round(45.926,2) from dual  --45.93  四捨五入
select trunc(45.926,2) from dual  --45.92  截斷
select mod(1600,300) from dual    --100
  1. 日期
select  ename,round((sysdate-hiredate)/7) from emp –入職週數
select ename,round(months_between(sysdate,hiredate)) from emp  --入職月數
select add_months(sysdate,3) from dual  --3個月後的日期   2018/3/26 21:29:19
  1. to_char函式
select ename,to_char(hiredate,'yyyy-mm-dd') from emp --1981--02—20
select ename,to_char(hiredate,'fmyyyy-mm-dd') from emp --1981-2-20
select to_char(sysdate,'yyyy-mm-dd hh :mi:ss') from dual—分鐘是mi
  1. to_number函式
select to_number('10')+to_number('12') from dual --將字串轉換為數字
--查詢1980和1985年入職的員工
select * from emp where to_char(hiredate,'yyyy')=1980 or to_char(hiredate,'yyyy')=1985
  1. to_date函式
select * from emp where hiredate between '1890-01-01' and '1982-12-31'  #mysql語法
#oracle不能像上邊那樣寫,因為hiredate是日期型別,與字串型別匹配不上
select * from emp where hiredate between to_date('1980-01-01','yyyy-mm-dd') and to_date('1980-12-31','yyyy-mm-dd')  #oracle語法
  1. decode函式(只有oracle有該函式)
select job, decode(job, 
'CLERK', '業務員',
'SALESMAN','銷售員',
'其他'
) from emp;
#以下語法(case/when)可以替換是那個邊的表達
select job,
case job 
   when 'CLERK' then '業務員'
   when 'SALESMAN' then '銷售員'
     else '其他'
       end
from emp;
  1. 約束
create table  person(

pid number(5),
pname varchar2(30) not null,
gender number(1),
tele varchar2(11) ,

constraint pk_pid primary key(pid),-- constraint後是起的名字
constraint check_gender check(gender in(0,1)),--性別只能是1或2
constraint unique_key unique(tele)
)
  1. 外來鍵
create table   orders(   --訂單
oid number(5) primary key,
totalprice number(8,2)
)

create table orderdetail(  --訂單項   鍵盤,滑鼠是兩個訂單項,屬於同一訂單
oidid number primary key,
price number(8,2),
name varchar2(30),
oid number(5),--外來鍵
constraint fk_orderdetail_orders foreign key(oid) references orders(oid)
);
  1. 聚合函式不能寫在where之後
SELECT city FROM weather WHERE temp_lo = max(temp_lo); #語法錯誤,修改為如下寫法是正確的
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather);  #語法正確
  1. where與having的區別
WHERE在分組和聚合計算之前選取輸入行(它控制哪些行進入聚合計算);而HAVING在分組和聚合之後選取輸出行。
因此,WHERE 子句不能包含聚合函式;因為試圖用聚合函式判斷那些行將要輸入給
聚合運算是沒有意義的。 相反,HAVING子句總是包含聚合函式。當然,你可以寫不使用聚合的HAVING 子句,但這樣做沒什麼好處,因為同樣的條件用在WHERE階段會更有效。

二、資料型別

  1. 浮點型
float(m,d);   #單精度浮點型    8位精度(4位元組)     m總個數,d小數位
double(m,d);  #雙精度浮點型    16位精度(8位元組)    m總個數,d小數位
  1. char與varchar
char:
固定長度;例如某欄位定義為10個長度,該欄位存了一個漢字”是”,這個漢字佔兩個字元,剩下八個字元會自動填滿;最大長度255,長度沒有預設長度,必須顯式指定長度
varchar2:
長度不固定,同上,剩下八個用不到的字元空間會釋放出去。Varchar2與mysql裡的varchar一樣;最大長度3999(即可以放2000箇中文或3999個英文),沒有預設長度,必須指定長度;
  1. number
number:預設長度是8
number(3):存的最大數是999
number(3,2):存的最大數是9.99
  1. date:
相當於mysql裡的datetype,mysql裡的date只有年月日,datetype還包括時分秒
  1. timestamp:
也是日期型別,相對於date來說,精度高,最多可以保留到秒後9位小數
  1. long
相當於mysql裡的longtext,即大文字,可以支援兩個G
  1. clob:
可以放四個G內容
  1. blob:
可以放四個G內容,存放電影,圖片等;
  1. 定點數
#浮點型在資料庫中存放的是近似值,而定點型別在資料庫中存放的是精確值。 
decimal(m,d) 引數m<65,指的是總個數;d<30且 d<m,指的是小數位個數。

三 、注意點

  1. union與union all
   UNION 結果集中的列名總是等於 UNION 中第一個 SELECT 語句中的列名。
  1. 刪除資料——delete與truncate
delete from person where name=’tom’;# delete from person刪除全部資料;
truncate person;  # 刪除全部資料
delete:可以回滾,也可以閃回;
delete刪除會產生磁碟碎片,且不釋放空間;truncate不會產生磁碟碎片;
truncate先摧毀表結構,再重構表結構;delete只刪除資料而已;
  1. savepoint事物儲存點
insert into person(pid,pname,gender,tele) values('1','tom','1','13222229090');
savepoint a;
update  person set tele='1111111111' where   pid='1';
savepoint b;
select * from  person;
rollback to a;  #回滾到事物儲存點a之前
  1. 檢視 view 檢視可以理解為一個虛表,封裝了一條複雜的查詢語句,檢視可以隱藏敏感列; 語法:create view 檢視名 as sql查詢語句(最後是複雜的sql查詢語句,可以用括號括起來)
先登入管理員使用者,為當前使用者(scott)提供建立檢視的許可權:grant create any view to scott;
create view person_view as (select pname from  person where  pid='1');#建立檢視
select * from   person_view;--查出來的是姓名
#優點:隱藏敏感列:比如隱藏工資與獎金列
create view view_emp as(select empno,ename,job,mgr,hiredate,deptno from emp)
select * from    view_emp;
修改(update)檢視的話,會將視圖裡涉及到的表資料修改,所以一般建立檢視時將檢視設計成只讀:
create or replace  view person_view  as (select pname from  person where  pid='1') with read only;   #此時該檢視就不能update了
  1. 序列——sequence auto increment語法只有mysql有,oracle沒有;序列主要是做主鍵自增的,是獨立於表之外的物件;
create sequence seq_person;   --建立序列,沒有與任何表產生關係,獨立於表之外
select seq_person.nextval from dual  --1  每執行一次,得到的結果依次加1
select seq_person.currval from dual   --檢視當前的值
insert into person(pid,pname) values (seq_person.nextval,'tom');
# 序列一般單表單用,有幾個表就建立幾個序列,如果多個表操作同一張表的序列,容易出現斷層;
建立序列的複雜語法如下:

create sequence test
minvalue 3        --最小值,預設是1
increment by 2    --步增值,預設1
start with 5      --起始值,預設1
maxvalue 20       --最大值,預設值是18個9。不做迴圈的話,超過最大值會報錯
cycle             --迴圈  預設是nocycle
cache 5     --快取,預設快取的數是20(快取在記憶體裡),這裡的值必須小於每次迴圈出來的數的個數
select test.nextval from dual;上邊的複雜語法不能做主鍵自增,主鍵會衝突;即序列主要是做主鍵自增,也可以做其他事;
  1. 索引——index 也是獨立於表之外的物件;作用是提高查詢效率(相當於書的目錄);
使用索引規則:
1、表裡的資料經常被修改的話,不適合建索引;
2、資料量小時不用建立索引;
3、某些欄位不會被當成條件做查詢時,沒有必要建立索引

語法:create index 索引名 on 表名(欄位名);
eg: create index index_emp_ename on emp(ename);
select * from   emp where ename='SMITH';  --建索引前後查詢所花的時間:0.031  0.016
資料少的話效果不明顯,下邊建立500萬條資料
create table  t_test(
tid number,
tname varchar2(30)
)
begin
  for i in 1..5000000
    loop
      insert into t_test values(i,'測試資料'||i);
    end loop;
end;
create index test_index on t_test(tname);
select * from  t_test where tname='測試資料4565558';#這樣資料量大的話效果會很明顯;

複合索引:對錶裡多個欄位做索引
   create index index_emp on emp(ename,job);# 注意,此時只有將ename,job同時作為查詢條件時才會用到索引,不然不會用到索引的,比如select * from   emp where job='' and hiredate=''是不會用到索引的;
  1. 同義詞
給使用者分配建立同義詞的許可權:grant create synonym to scott;
同義詞相當於別名;

使用場景:一個使用者下想訪問另一個使用者下的某張表,可以這樣寫:
select * from   scott.emp;
此時為了訪問方便,可以建立同義詞:create public synonym emp for scott.emp  --public 可以不寫
以後查詢時:select * from emp;
刪除同義詞:drop public synonym emp --如果上邊加了public,這裡也要加上
  1. 資料匯入匯出 用於資料備份;
1、 exp system/root full=y; # 整庫匯出,基本不用;
2、按使用者匯入匯出:把scott使用者下的資料匯入maltose01使用者下:
注意:使用exp與imp這兩個命令的話,電腦上必須安裝oracle軟體,所以下邊的命令需要在虛擬機器裡執行
--先匯出
exp scott/[email protected]:1521/orcl file='c:\scott.dmp'
--再將上邊的資料匯入到另一個使用者
imp maltose01/[email protected]:1521/orcl file='c:\scott.dmp' full=y
3、按表匯入匯出(plSql工具右鍵表就能匯出該表)
--先匯出
exp scott/[email protected]:1521/orcl file='c:\scott.dmp' tables=emp,student,teacher
--再匯入到另一個使用者
imp maltose01/[email protected]:1521/orcl file='c:\scott.dmp' full=y  tables=emp,student,teacher