1. 程式人生 > 其它 >sql server 筆記

sql server 筆記

因為沒書,又因為需要這個知識,所以在網上找資源看電子書,學完了就看博文再學sql知識,再鞏固一下

推薦一個好地方,菜鳥工具,那裡有許多教程

ps:裡面的許多例項是看的視訊,然後自己寫的,所以沒寫詳情的內容對資料庫...2333

sql server 2005的自學筆記

還有就是命名的問題,這是最後寫的,對於表的命名,可以不寫as,也可以不加雙引號,直接寫就行了,但是名稱和表之間要有空格。我下面寫的有點繁瑣...格式的優化可以看目錄自連線後的,那都比較好點...

庫有兩種:系統預設的庫、自己建的庫

什麼是資料庫?

俠義:儲存資料的倉庫

廣義:可以對資料進行儲存和管理的軟體以及資料本身統稱為資料庫

資料庫是由表、關係、操作組成的。

為什麼要資料庫?

幾乎所有的應用軟體的後臺都需要資料庫
資料庫儲存的空間小,容易持久儲存
一般都是mdf,ldf字尾的這兩個檔案(資料庫移植較容易)
儲存比較安全
容易維護和升級
簡化對資料的操作
為將來的學習oracle準備
b/s架構包含資料庫
db又叫資料庫

ps:如果連線不上,可能沒開啟對應的sql服務,建議在附件那裡找服務,然後啟用sql server 服務

資料結構和資料庫的區別

都是研究資料的儲存與操作

資料庫是在應用軟體級別研究資料的儲存和操作

資料結構是在系統軟體級別研究資料的儲存與操作

什麼是連線

sql server是客戶端,是訪問後臺的資料庫,庫和訪問庫不一樣,

只有對應的資料庫服務開啟,才能去連線資料庫,所以連線很重要

命令只能單行傳送,不能一塊傳送

資料庫是如何儲存的?

欄位、記錄、表、屬性、約束(主鍵、外來鍵、唯一鍵、非空、check、default)、觸發器

資料庫是如何操作的

insert、update、delete、T-SQL、儲存過程、函式、、觸發器

如何顯示資料

select等

為什麼會有系統庫?

使用者建立的庫需要系統來維護,最核心的是master,不能刪,改,否則會影響系統資料正常

新建資料庫-----資料庫--右鍵---新建

資料庫建立有兩個檔案,一個是資料檔案,一個是日誌檔案,用於記錄操作

刪除庫直接右鍵刪除---點選關閉現有連線刪除會更好,在刪除不了的情況下。類似關閉相關程序

資料庫如何分離和附加

不能直接複製黏貼對資料庫進行拷貝

右擊資料庫名字---任務---分離----然後把那一行對號點完,確保資料的時效性、完整性,然後再去對應的路徑下去複製ldf、mdf檔案

然後附加

怎樣附加?

先右鍵資料庫,點選附加,在對應資料庫的路徑下找到mdf、ldf進行附加、只需要附加ldf會自動附加

對不同版本資料庫進行附加出現的相容性問題
右擊資料庫,點選生成指令碼,然後選擇版本 、

使用者名稱的伺服器角色sysadmin就是sa許可權

要想下載資料庫,就得先分離才能繼續複製、移動
額,貌似2005沒有這個功能
。。。
2008有

新的使用者並且進行改密碼

1.剛進去點選window身份驗證登入(或者管理身份sa新增

右鍵----新增使用者名稱

把強制密碼過期去掉,這樣不會報錯

但是建立的使用者沒有許可權

資訊產生的重複叫冗餘

表的相關資料

能夠唯一標識一個事物的叫主鍵

關係型資料庫:表示事物與事物之間的關係,也可以通過主鍵外來鍵進行連線

外來鍵:來自另外一個表的引用的索引(自己概括的)

欄位:一個事物的某一個的特徵

記錄:欄位的組合 表示的是一個具體的事物

表:記錄的組合、表示的是同一型別事物的集合

表、欄位、記錄的關係

欄位是事物的屬性
記錄是事物本身
表是事物的集合

一行叫做元組

列、屬性:欄位的另一種稱謂

整體的叫做表

nvarchar是任意字元,字元長度可變化(無論是全形還是半形,每個字元都佔用兩個位元組)

在sql中,圖形化介面中,點選執行sql,會把重複的給自動去掉

在輸入相同資料後,點選再下星號,就可以避免重複而自動刪掉

,但會使主鍵新增失敗,需要對id進行更改數字來開啟主鍵

主鍵、外來鍵有點繞。。

---右鍵--關係---三個點點----設定主鍵、外來鍵

外來鍵來自另一個表的主鍵

還得確保資料型別的相同

create table 建立表 最後的一個欄位不建議寫逗號,因為Oracle命令逗號執行失敗

關於命令

先建立表---再建立主鍵---型別要注意是nvarchar,不是nvchar,是否為空的確定,空就是null,非空就是not null

--是註釋

建立的第二個表
是emp
其實可以把constraint 名字 去掉,系統會自定義
不去掉就是自己自定義
先設定主鍵  primary key
然後定義屬性
再設定外來鍵   foreign key
外來鍵要設定參考物件  references

ps:重新整理建議點選新增查詢的庫重新整理,不然出來的很慢,23333

約束是什麼?

對一個表中的屬性操作的限制叫做約束

分類:主鍵約束(不允許重複元素、避免資料的冗餘)

外來鍵約束(通過外來鍵約束,從語法上保證了本事物所關聯的其他事物一定是存在的)

事物事物之間通過外來鍵來體現的

check約束:檢查約束也就是條件約束

create table student
(
stu_id int primary key,
stu_sal int check (stu_sal>=1000 and stu_sal<=8000)
)

意思為:插入進去在表中為student的,主鍵值為1,工資為。。。

default:保證事物屬性有一定的值

唯一約束:unique

唯一鍵可以為空

保證了事物屬性的取值不允許重複

但是隻能有一個為空

自動增長為identity

 identity表示該欄位的值會自動更新,不需要我們維護,通常情況下我們不可以直接給identity修飾的字元賦值,否則編譯時會報錯
 m表示的是初始值,n表示的是每次自動增加的值
如果m和n的值都沒有指定,預設為(1,1)
要麼同時指定m和n的值,要麼m和n都不指定,不能只寫其中一個值,不然會出錯

create table student1
(
id int primary key identity(200,10),
name nchar(8) not null,
sex nchar(1) not null,
)
insert student1 (name,sex) values ('張三','男');

drop table 表名 是刪除表

在設定是否為空時,預設不寫就是允許為空

在唯一約束下輸入values,需要同時對values里加入唯一約束,不然語句錯誤,除非時指定的在表名後加插入屬性

然後可以檢視select * from 表名 看全部的輸入內容

表和約束的區別:

資料庫是通過表來解決事物的儲存問題

資料庫通過約束來解決事物取值的有效性和合法性的問題

建表的過程就是指事物屬性及事物屬性各種約束的過程

什麼是關係:

表和表之間的聯絡

通過設定不同形式的外來鍵來寶石表和表之間的關係

分類:一對一、一對多、多對多

說明分類:
假設A、B
一對一:
既可以把表A的主鍵充當表B的外來鍵
也可以把表B的主鍵充當表A的外來鍵
一對多:
把表A的主鍵充當B表的外來鍵
或把A表的主鍵新增到B的表充當B表的外來鍵
多對多:
一邊的一個對另一邊的多個,反過來也成立,就行
需要單獨的再建一個表,來進行資料互動

多對多的一個例子:

折磨人。。

create table js
(
js_id int primary key,
js_name nvarchar(200)

)
create table bjsj
(
--只能組合是主鍵
bj_id int foreign key references bj(bj_id),
js_id int foreign key references js(js_id),
ke nvarchar(20),
constraint pk_bj_id_js_id primary key (bj_id,js_id,ke)
--主鍵約束,先定義名字,然後把bjid和jsid,ke充當主鍵,然後者三個都是主鍵,如果只設置前兩個,就會出現錯誤在重複時。
)

關係圖

欄位表示的是特徵
記錄表示的是這個事物
表表示的是同一個事物的集合

當設定關係時,被點選的是外來鍵,然後再對

主鍵:能夠唯一表示一個事物的一個欄位或者多個欄位的組合

含有主鍵的叫主鍵表

主鍵通常是整數,不建議用字串當主鍵,除非是叢集式服務

主鍵的值不允許被修改,除非本記錄被刪除

主鍵不要定義成id,而要定義成表名id或者表名_id,這是那個命名規則,方便看

要用代理主鍵,不要使用業務主鍵:

業務含義:就是有顯示含義的

任何表都是不建議用業務主鍵

通常用在表中獨立新增一個整形的編號來充當主鍵欄位

外來鍵:如果一個表的諾幹個欄位是來自另外諾幹個表的主鍵或唯一鍵,則這個諾幹欄位就是外來鍵

外來鍵通常是來自另外表的主鍵而不是唯一鍵,因為唯一鍵可能會有null,即為空

外來鍵不一定來自另外的表,也可能來自本表的主鍵

含有外來鍵的表叫外來鍵表,外來鍵欄位來自的那一張叫主鍵表

主鍵表和外來鍵表的刪除?

先刪外來鍵表,要刪主鍵表,會報錯,會導致外來鍵表的資料引用失敗

查詢

計算列

select * from 表名
*代表所有的
from 表名  表示從表名中查詢
相同的,可以把*用屬性元素來表示
select bj_id,bj_name from bj;

as可以省略,儘量使用給雙引號名命名

select 數字 from 表名;
沒啥用,就是看行數,我認為

oracle不允許單引號,相容性問題,最好雙引號

distinct

select distinct bj_id  from bj;

主要是不同的,通過查詢語句,把不同的給顯示出來(也可以過濾掉重複的null)

當有兩個,就是整體上過濾。。。那兩個組合相同的過濾,只有兩個都重複,才會過濾

也不能
select bj_num distinct bj_id from bj;
邏輯上有衝突

between

where是對條件的抉擇

select * from bj where bj_num>=20 and bj_num <=50;
select * from bj where bj_num between 20 and 50;
--查詢bj表中的大20和小50的行
select * from bj where bj_num<=20 or bj_num>=50;
select * from bj where bj_num not between 20 and 50;
--是小於20或者大於50的

in

屬於若干個孤立的值

select * from bj where bj_id in (1,2,3)
--在1,2,3的表中的值
select * from bj where bj_id not in (1,2,3)
--不在1,2,3的值得確定
select * from bj where bj_id<>1 and bj_id<>2 and bj_id<>3
--資料庫中有兩種 !=或者<>

top

select top 2 * from bj;
--輸出前兩個
select top 15 percent * from bj;
--取多少百分比來,如果要是多一點,就近一位
select top 4 * from bj
where bj_id between 1 and 3
order by bj_id desc;
--在前四個並且選擇在包含1到3的,按照降序來,如果不寫,預設是升序
--desc是降序

null

null不能參與<> != = 的運算

可以參與is is not的

select * from where bj_id is not null;

0和null不一樣,null空值,零表示一個確定的值

任何資料型別都允許null

create table a1(name nvarchar(200),id int,date datetime);
insert into a1 values(null,null,null);
select * from a1;

一個具體的值不能和一個沒值的相加不能運算(null不能和任何資料運算,否則永遠為空)

可以避免這個

select ename,sai*15+isnull(comm,0) from emp;
如果是null,即返回0,不然就返回comm的值

order by

select * from 表名 order by 屬性;

預設升序

如果屬性有兩個,就是按照優先順序,先按照前一個屬性,再按照後一個屬性

asc表示升序

desc表示降序

select * from emp order by name desc,sal;
這是先對name進行降序,然後對sal進行升序
select * from emp order by name,sal desc;
這是先對name進行升序,再對sal進行降序

如果不指定欄位的排序標準,預設是asc升序

模糊查詢

select * from bj where bj_num like '%0%';

只有關鍵字0的

基本格式:

select 欄位的集合 from 表名 where 某個欄位的名字 like 匹配的條件

匹配的條件通常用含有萬用字元

萬用字元

%

A%首字母為A的
%A%有含有a的
%A偽字母含有A的

_

select * from emp where ename like '_A%';
ename只要第二個字母是A的就輸出

[a-f]只能是a到f的任意單個字元

select * from emp where ename like '_[A-F]%';
把ename中的第二個字元是a到f的記錄輸出

[a,f]

a或者f

[^A-F]

把ename的第二個字元不是a到f的

條件必須用單引號裱起來

雙引號圈起來表示字串、別名

當有百分號時,需要用\來

檢視含有%的

select * from student where name like '%/%%';
類似的用還有_等
\字元當作轉義字元的標誌
用m也可以
select * from student where name like '%m%%';
一般用\

聚合函式

函式分類:

單行函式、多行函式

區別:

返回的值不一樣

多行:多行返回一個值

聚合函式是撮合函式

聚合函式的分類:

max()
min()
avg()平均值
count() 求個數

例子:

select lower(name) from emp;
返回小寫的表中的name屬性的行數,lower()是單行函式
select max(name) from emp;
返回一行
select count(*) from emo; 
返回emp表中所有記錄的個數(重複的也被當作有效的記錄)
可以用distinct來區分
select count(distinct gongzi) from emp;
返回是去掉重複的 
ps:當有null的時候,count只會對除了null的有效,null不會被當作記錄

例子2

select max(lar) "最高工資",min(lar) "最低工資", count(*) ”共計數“ from emp;
注意,要是有select的後面語句有單行和多行,內容是不匹配的,會報錯

過濾掉空的、不同的

select count(distinct comm) from emp;

group by

切換表,可以用

use 表名;
select bj_name,avg(bj_num)"平均人數"
from bj
group by bj_name;

使用group by之後select中只能出現分組後的整體資訊,不能出現組內的詳細資訊

使用兩個group by的屬性,有優先順序

select deptno,job,avg(sal)
from emp group by deptno,job
order by deptno;
--這是先排序對deptno,再按照deptno,再按照job分類,再進行平均工資的計算

也可以更高階

select deptno,job,avg(sal)“平均工資”,count(*)"人數",sum(sal),“總工資”
,min(sal)"最低工資"
from emp group by deptno,job
order by deptno;

把表中的記錄按照不同的欄位分成不同的組

group a,b,c,d
先按照啊a分組,如果a相同,再b分組....
最後統計的是最小組的資訊

having

對分組之後的資訊進行過濾

select deptno,job,avg(sal)  as “平均工資”
from emp group by deptno
order by deptno;
having avg(sal)>=2000
--對分組後的平均工資大於2000的進行篩選
也可以對deptno執行過濾
別名不能作為having的過濾引數

where與having

select deptno,avg(sal) "平局工資"
from emp
where ename not like '%A%' --對原始的資料過濾
group deptno  --對分組後的進行過濾
having avg(sal)>2000;
--這個是工資大於2000,且名字包含A的例子

ps:where必須寫在having的前面,順序不可顛倒

having時通常會先使用group by(必須)

如果用group by ,但是用的having,會把所有的記錄當成一組來過濾

having和where不能出現別名的使用,只能用原始的欄位

單行函式是每一行都返回一個結果

多行函式是多行只返回一個結果

標準輸入模板

先where再group再having再order

where不允許使用聚合函式

對於group by的使用,有兩個,就是最後一個是作為其他的聚合函式的結果

into的使用

在select後和from前面,into 新表名把查詢的結果放到一個表內

連線查詢

將兩個表或者兩個以上的表以一定的連線條件連線起來,從中檢索出滿足條件的順序

內連線

select ... from A,B

引用兩個表叫做笛卡爾集

可以說是第一個表的所有行與第二個第一行結合,然後與第二行結合,依次....

產生結果:

行數是A,B的乘積

列數是A,B之和

select ...from A,B where ...

對產生的笛卡爾積進行過濾

select ... from A join B on ...

select "E".ename "員工名字","D".dname"部門名稱"
from emp"E"
join dept "D"
on 1=1
join是連線條件
on是必須有的,不能省略,on是連線條件,即是判斷
其實可以對別名不起,這件事為了方便記錄
這裡可以使用所謂的中文來
select”部門表”.deptno"部門編號”  
from emp "員工表"  
join dept"部門表”
on 1=1
但是通常是英文
on作為判斷來篩選
select "E".ename“"員工姓名”,"D" .dname“部門名稱”
from emp "E"
join dept "D"--join是連線
on "E".deptno = "D".deptno
就是在emp表中的ename和連線的dept中的dname下的資料中,把emp.deptno和dept.deptno相同的連線在一塊的寫出來
擋在過濾on上的一些指定內容,如
on "j".js_name='aa'
這些值的等於必須用單引號,與萬用字元一樣

SQL92標準和SQL99標準的區別:

select ... from A,B where...    sql92

select ... from A join B on ...    sql99
結果一樣,習慣用99,理解方面,自己觀點

例項

工資大於4000

select emp.ename,dept.dname
from emp
join dept
on emp.deptno=dept.deptno
--因為有重複的,所以選擇相等的來過濾重複的
where emp.sal>2000

工資大於2000的姓名和部門和工資等級

select * 
from emp "E"
join dept "D"
on "E".deptno="D".deptno
join salgrade "S"
on "E".sal >= "S".losal and "E".sal <= "S".hisal
where "E".sal > 2000
where  還得必須放後面,不然會語法錯誤
select * from emp
join dept
on emp.deptno=dept.deptno
having dept.deptno=10
這是錯誤的,having是針對分組後的篩選
select * from emp
join dept
on 1=1
where dept.deptno > 10;
這樣是對的
也可以這樣
select * from emp
join dept
on  dept.deptno > 10;
輸出工資前三的員工的姓名、工資、工資等級
select top 3 ”E“.name,"E".sal,"E".grade,"D".dname
from emp "E"
join dept "D"
on emp.deptno=dept.deptno
join salgrade ”S“
on "E".sal between "S".losaland ”S“.hisal
order by ”E“.sal desc 
要是說E的名字中不包含A就是
where ”E“.ename not like '%A%'
只能在rder by前新增
找出每個部門的編號  部門的所有的員工平均工資 平均工資等級
select "T".deptno,"T".avg_sal "部門平均工資","S".grade"工資等級"
from(
select deptno,avg(sal)  "avg_sal"
from  emp
group by deptno 
 )"T"
 join salgrade "S"
 on between "T".avg_sal between "S".losal and "S".hisal
求出emp表中的所有領導的姓名
select * from
where empno in (select mgr from emp)
求出emp表中的不是領導的姓名---還得考慮是否為空
select * from
where empno isnull (select mgr from emp,0)
求平均薪資最高的部門和平均工資
select top 1 deptno"部門編號",avg(sal)"平均工資
from emp
group by deptno
order by avg(sal) desc
在使用jon時,可以使用on不用where進行
select
* 
from emp
join dept
on emp.deptno=dept.deptno and emp.sal>2000
on中寫連線條件,也可以寫過濾條件
等價於
select
* 
from emp
join dept
on emp.deptno=dept.deptno
where emp.sal>2000

查詢的順序

select top ...

from A

join B

on...

join c

on...

where...

group  by...

having...

order by...
--把工資大於1500的所有員工按部門分組,,把平均工資大於2000的前兩個然後部門、等級
select  “T”.*,dept.dname,"S".grade
from dept
join(
select top 2 deptno,avg(sal) "avg_sal"
from emp
where sal>1500
group by deptno
having avg(sal)>2000
order by avg(sal) desc--降序,這個select是對最高的前2個進行篩選,有平均工
--資、和員工
)“T”
on  dept.deptno="T".deptno
join salgrade 
on "T".avg(sal) between salgrade.losal and salgrade.hisal

外連線

不但返回滿足連線條件的記錄,而且會返回部分不滿足的記錄

左連線

不但返回滿足連線條件的記錄,而且會返回左表不滿足的記錄

右連線

不但返回滿足連線條件的記錄,而且會返回右表不滿足的記錄

預設的join是inner,不寫也中

實際意義:

返回一個事物及其該事物的相關資訊,如果該事物沒有相關資訊,則輸出null

完全連線

join前加full的

就是把左右連線在一塊了

內容包含:

兩個表中匹配的所有記錄

左表中那些在右表中找不到的記錄,這些記錄的右邊全為null

右表中那些在左表中找不到的記錄,這些記錄的左邊全為null

交叉連線

select  * 

emp from cross

join dept

等價笛卡爾集

select * from emp,dept

或者

select  * 

emp from 

join dept

on 1=1

自連線

一張表自己和自己連線起來查詢

自連線是一張表的左表與右表的第一個相對,然後第二個...

用聚合函式求最高薪資
select * from emp
where sal=(select max(sal) from emp)
--因為where不能使用聚合函式,所以得用括號圈起來的語句
select * from emp"E1",emp"E2"
連續兩個對一個表的記錄、
有兩種方法
第一種:
select * from emp"E1",emp"E2"
第二種:
select * from emp"liwai"
join emp  "liwai2"
on 1=1

不用聚合函式求薪資最高的員工資訊

這個有點難,按照自己搜尋學的總結一下

先建立相關表,和行

CREATE TABLE
    T_Number (
        num int
    );
 
INSERT INTO T_Number(num) VALUES(5);
INSERT INTO T_Number(num) VALUES(23);
INSERT INTO T_Number(num) VALUES(-6);
INSERT INTO T_Number(num) VALUES(7);

如果想得到23最大,就是得到沒有比23還大的數,我們可以先得到比23少的數

select lesser.num,greater.num
from t_number lesser,t_number greater
where lesser.num<greater.num

這樣就會得到左面第一行的所有比23小的

然後對左表進行篩選

select num 
from t_number
where num not in
(
select lesser.num
from t_number lesser,t_number greater
where lesser.num<greater.num
)

這樣也對,但是如果有兩個23,就會出現差錯,所以要用distinct來進行過濾

select distinct num 
from t_number
where num not in
(
select lesser.num
from t_number lesser,t_number greater
where lesser.num<greater.num
)

233333

聯合

mgr表示上司

empno表示下屬

這個表只是一部分

然後

只需要對上司的等於下屬的標號就行,因為這樣會把有上司和員工的給篩選出來

select e1.ename,e1.sal,e2.ename"上司的名字"
from emp e1
join emp e2
on e1.mgr=e2.empno--對有關係的進行選擇
如果要是在mgr上有null
union
ename,sal,'最大老闆'
from emp  where mgr is null;
--可以看到把null變了

表和表之間的資料以縱向的方式連線在一起叫聯合

聯合的注意:

若干個select 子句輸出的列數必須是相等的

而且

必須得是相容的,與上一個select的

小結

主鍵必須有值,不能為空,可以用identity進行起始值的,或者自己設定

當進行了identity的設定,可以不用對其進行賦值,當某個記錄刪除時,還會按照刪除的那個繼續遞增

刪除一個表的行

delete from 表名 where 屬性=xxxx

檢視

簡化查詢

避免了程式碼的冗餘,屬性大量重複sql的語句

什麼是檢視?

從程式碼上看是一個select語句

試圖邏輯上被當作一個虛擬表看待

檢視格式

create view 檢視的名字

as

select 的語句
--select前面不能加begin、後後能加end

檢視的優點

增加資料的保密性

簡化查詢

檢視的缺點

增加了資料庫維護的成本

檢視只是簡化查詢,不能加快查詢

檢視不是物理表、是虛擬表

不建議通過檢視更新檢視所依附的原始表的資料或結果

檢視命名一般以v開頭,v_xxx_xxxxxx

檢視的select語句必須的為所指定的列取別名

事務

事物一系列操作要麼成功、要麼失敗

事務主要保證資料的合理性和併發處理的能力

通俗說:

事務可以保證避免資料處於一種不合理的狀態

利用事務可以實現多個使用者對資源共享的同時訪問

事務必須的保證多個使用者對資源共享同時訪問,資料庫給使用者的反應是合理的

事務和執行緒的關係

事務也是通過鎖來解決很多問題

執行緒同步就是通過鎖來解決的

髒讀”可重複讀

幻讀“通過設定事務的優先順序可避免

第三方外掛要想完成預期功能,一般必須藉助資料庫的事務機制

事務的三種執行模式:

自動提交事務:

每條單獨的語句都是一個事務。如果成功執行,則自動提交;如果錯誤,則自動回滾.

顯式事務:

每個事務均以BEGIN TRANSACTION語句顯式開始,以COMMIT或ROLLBACK語句顯式結束。

隱性事務:

在前一個事務完成時新事務隱式啟動,但每個事務仍以COMMOIT或ROLLBACK語句

事務的四個屬性:原子性、一致性、隔離性、永續性

原子性:事務是一個完整的操作。事務的各步操作是不可分的(原子的)﹔要麼都執行,要麼都不執行。
一致性:當事務完成時,資料必須處於一致狀態,要麼處於開始狀態要麼處於結束狀態不允許出現中間狀態。
隔離性:指當前的事務與其他未完成的事務是隔離的。在不同的隔離級別下,事務的讀取操作,可以得到的結果是不同的。
永續性:事務完成後,它對資料庫的修改被永久保持,事務日誌能夠保持事務的永久性。

分頁查詢

emp表

最高的前三個工資的所有資訊

select top 3 *
from emp
order by sal desc;

工資從高到低,輸出是前3到6個的

select top 3 *
from emp
where empno not in 
(select top 3 empno order by sal desc)
order by sal desc;

工資從高到低,輸出是前7到9個的

select top 3 *
from emp
where empno not in 
(select top 6 empno order by sal desc)
order by sal desc;

一些小知識的自我總結:

業務主鍵和邏輯主鍵

業務主鍵是使用有業務意義的欄位做主鍵,比如身份證號,銀行賬號等;

邏輯主鍵是使用沒有任何業務意義的欄位做主鍵。因為很難保證業務主鍵不會重複(身份證號重複)、不會變化(賬號升位),因此推薦使用邏輯主鍵。

主鍵有兩種定義方式:

1.
...
id int primary key not null,
...
2.
...
id int not null,
primary key (id)
...

關於nvarchar、nchar、char的

在看nvarchar和char的時候,發現還是用nvarchar比較好,在業務不算太大,對資料的要求不太多,nvarchar可以根據實際長度來儲存資料長度,但是檢索資料慢,同比char,在設定幾個就是幾個,不足的用空格代替,但這樣會對記憶體的儲存造成一定壓力。

char是英文一個位元組、漢字兩個位元組

ncarchar英文漢字都是兩個位元組

varchar是和nvarchar一樣效率,但字元的佔有跟char一樣

nchar佔用空間比char大。比如char格式下一個字母只佔用一個位元組,漢字佔用兩個,nchar所有字元都佔用兩個位元組。

修改表結構

新增表

alter table 表名 add 屬性 資料型別 是否為空;

刪除表的某一屬性

alter table 表名 drop 屬性

資料操縱語言

除了int的insert插入不帶單引號,其他的都帶

INSERT INTO T_Person(Id,Name,Age) VALUES(1,'Jim',20);

更新語句

update T_Person set age=age+1 where name='tom' or age<25

刪除表

delete from 表名
刪除指定記錄
insert into T_Person values(1,'陳優秀',24)
select * from T_Person;
delete from T_Person where age >20;

WHERE 中可以使用的邏輯運算子:or、and、not、<、>、=、>=、<=、!=、<>等.

還有一種模糊查詢

select * from T_Employee where fname like '_arry';
--這是查前面一個的字元
select * from T_Employee where fname like '%n%';
--這是查詢含有n的模糊匹配

in包含於

select * from T_Employee where fage in(21,23,25)
--在表中的21,23,25的出來
--下面的兩個等價
...
where fage >= 23 and fage <=30
where fage between 23 and 30

聚合函式是對分組操作結果進行運算

sql server函式

abs()求絕對值

ceiling()最大上限

floor()最大下限

round()四捨五入

LEN():求字串長度。LEN('abc')=3
LOWER()、UPPER():轉小寫、大寫

LTRIM():去掉字串左側空格
RTRIM():去掉字串右側空格

GETDATE():取當前日期時間
DATEADD(datepart,number,date):計算增加以後的日期。引數 date 為待計算的日期,引數 datepart 為計量單位(YEAR,YY,MONTH,MM,DAY,DD 等)DATEADD(DAY,3,date)為計算日期 date 的 3 天后的日期,DATEADD(MONTH,-8,date)為計算日期 date 的 8 個月前的日期
DATEDIFF(datepart,startdate,enddate):計算兩個日期之間的差額。datepart 為計量單位
DATEPART(datepart,date):返回一個日期的特定的部分

--查詢員工入職年數.SELECT FName,FInDate,DATEDIFF(YEAR,FInDate,GETDATE())FROM T_Employee;
查詢各入職年數的員工個數.
SELECT DATEDIFF(YEAR,FInDate,GETDATE()),COUNT(*) 
FROM T_Employee
GROUP BY DATEDIFF(YEAR,FInDate,GETDATE());

空值處理

select isnull(fname,'佚名') 姓名 from empolyee

流控制函式

CASE expression
WHEN value1 THEN return_value1
WHEN value2 THEN return_value2
WHEN value3 THEN return_value3
ELSE default_return_value
END

在網上看一個例子,很實用

--有一張表T_Scroes,記錄比賽成績:
--Date    Name  Scroe
--2008-8-8  拜仁  勝
--2008-8-9  奇才  勝
--2008-8-8  湖人  勝
--2008-8-10 拜仁  負
--2008-8-8  拜仁  負
--2008-8-12 奇才  勝

--要求輸出下面格式:
--Name 勝 負
--拜仁 1  2
--湖人 1  0
--奇才 2  0

-注意:在中文字串前加 N,比如 N'勝'

emmmm

select name,

sum

(case score

when n'勝' then 1

else 0

end

)as 勝,

sum

(

case score

when n'負' then 1

else 0

end

)as 負

from t_score

group by  name;

還有datetime也是一個數據型別,他的格式是xxxx-xx-xx xx:xx 也需要加引號說明的