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 也需要加引號說明的