SQL Server 常用高級語法筆記
自從用了EF後很少寫sql和存儲過程了,今天需要寫個比較複雜的報告,翻出了之前的筆記做參考,感覺這個筆記還是很有用的,因此發出來和大家分享。
1、case...end (具體的值)
case後面有值,相當於c#中的switch case
注意:case後必須有條件,並且when後面必須是值不能爲條件。
-----------------case--end---語法結構---------------------
select name , --注意逗號
case level --case後跟條件
when 1 then '骨灰'
when 2 then '大蝦'
when 3 then'菜鳥'
end as'頭銜'
from [user]
2、case...end (範圍)
case 後面無值,相當於c#中的if...else if...else....
注意:case後不根條件
------------------case---end--------------------------------
select studentId,
case
when english between 80 and 90 then '優'
when english between 60 and 79 then '良'
else '差'
end
from Score
------------------case---end--------------------------------
select studentId,
case
when english >=80 then '優'
when english >=60 then '良'
else '差'
end
from Score
-----------------------------------------------------
select *,
case
when english>=60 and math >=60 then '及格'
else '不及格'
end
from Score
3、if...eles
IF(條件表達式)
BEGIN --相當於C#裏的{
語句1
……
END --相當於C#裏的}
ELSE
BEGIN
語句1
……
END
--計算平均分數並輸出,如果平均分數超過分輸出成績最高的三個學生的成績,否則輸出後三名的學生
declare @avg int --定義變量
select @avg= AVG(english) from Score --爲變量賦值
select '平均成績'+CONVERT(varchar,@avg) --打印變量的值
if @avg<60
begin
select '前三名'
select top 3 * from Score order by english desc
end
else
begin
select '後三名'
select top 3 * from Score order by english
end
4、while循環
WHILE(條件表達式)
BEGIN --相當於C#裏的{
語句
……
BREAK
END --相當於C#裏的}
--如果不及格的人超過半數(考試題出難了),則給每個人增加分
select * from Score
declare @conut int,@failcount int,@i int=0 --定義變量
select @conut =COUNT(*) from Score --統計總人數
select @failcount =COUNT(*) from Score where english<100 --統計未及格的人數
while (@failcount>@conut/2)
begin
update Score set english=english+1
select @failcount=COUNT(*) from Score where english<100
set @i=@i+1
end
select @i
update Score set english=100 where english >100
5、索引
使用索引能提高查詢效率,但是索引也是佔據空間的,而且添加、更新、刪除數據的時候也需要同步更新索引,因此會降低Insert、Update、Delete的速度。只在經常檢索的字段上(Where)創建索引。
- 1)聚集索引:索引目錄中的和目錄中對應的數據都是有順序的。
- 2)非聚集索引:索引目錄有順序但存儲的數據是沒有順序的。
--創建非聚集索引
CREATE NONCLUSTERED INDEX [IX_Student_sNo] ON student
(
[sNo] ASC
)
6、子查詢
將一個查詢語句做爲一個結果集供其他SQL語句使用,就像使用普通的表一樣,被當作結果集的查詢語句被稱爲子查詢。所有可以使用表的地方几乎都可以使用子查詢來代替。
select * from (select * from student where sAge<30) as t --被查詢的子表必須有別名
where t.sSex ='男' --對子表中的列篩選
轉換爲兩位小數:CONVERT(numeric(10,2), AVG(english))
只有返回且僅返回一行、一列數據的子查詢才能當成單值子查詢。
select '平均成績', (select AVG(english) from Score) --可以成功執行
select '姓名', (select sName from student) --錯誤,因爲‘姓名’只有一行,而子表中姓名有多行
select * from student where sClassId in(select cid from Class where cName IN('高一一班','高二一班')) --子查詢有多值時使用in
7、分頁
--分頁1
select top 3 * from student
where [sId] not in (select top (3*(4-1)) [sid] from student)--4表示頁數
select *, row_number() over(order by [sage] desc ) from student-- row_number() over (order by..)獲取行號
--分頁2
select * from
(select *, row_number() over(order by [sid] desc ) as num from student)as t
where num between (Y-1)*T+1 and Y*T
order by [sid] desc
--分頁3
select * from
(select ROW_NUMBER() over( order by [UnitPrice] asc) as num,* from [Books] where [publisherid]=1 )as t
where t.num between 1 and 20 --要查詢的開始條數和結束條數
8、連接
select sName,sAge,
case
when english <60 then '不及格'
when english IS null then '缺考'
else CONVERT(nvarchar, english)
end as'英語成績'
from student as s
left join Score as c on s.sid =c.sid
內連接 inner join...on...
查詢滿足on後面條件的數據
外連接
左連接
left join...on...
先查出左表中的所有數據
再使用on後面的條件對數據過濾
右連接
right join...on...
先查出右表中的所有數據
再使用on後面的條件對數據過濾
全連接
full join ...on...
(*)交叉連接
cross join 沒有on
第一個表的每一行和後面表的每一行進行連接
沒有條件。是其它連接的基礎
9.視圖
優點:
- 篩選表中的行
- 防止未經許可的用戶訪問敏感數據
- 降低數據庫的複雜程度
創建視圖
create view v_Demo
as
select ......
10、局部變量
---------------------------------局部變量--------------------------
--聲明變量:使用declare關鍵字,並且變量名已@開頭,@直接連接變量名,中間沒有空格。必須指明變量的類型,同時還可以聲明多個不同類型的變量。
declare @name nvarchar(30) ,@age int
--變量賦值:
--1、使用set 給變量賦值,只能給一個變量賦值
set @age=18
set @name ='Tianjia'
select @age,@name --輸出變量的值
--2、使用select 可以同時爲多個變量賦值
select @age=19,@name='Laoniu'
--3、在查詢語句中爲變量賦值
declare @sum int =18 --爲變量賦初值
select @sum= SUM(english) from Score --查詢語句中賦值
select @sum --輸出變量值
--4、變量作爲條件使用
declare @sname nvarchar(10)='張三'
declare @sage int
select @sage=sage from student where sName=@sname
select @sage
--5、使用print輸出變量值,一次只能輸出一個變量的值,輸出爲文本形式
print @sage
11、全局變量
--------------------------全局變量(系統變量)----------------------------------
select * from student0
select @@error --最後一個T-SQL錯誤的錯誤號
select @@max_connections--獲取創建的同時連接的最大數目
select @@identity --返回最近一次插入的編號
12、事務
事務:同生共死
指訪問並可能更新數據庫中各種數據項的一個程序執行單元(unit)--也就是由多個sql語句組成,必須作爲一個整體執行
這些sql語句作爲一個整體一起向系統提交,要麼都執行、要麼都不執行
語法步驟:
- 開始事務:BEGIN TRANSACTION
- 事務提交:COMMIT TRANSACTION
- 事務回滾:ROLLBACK TRANSACTION
判斷某條語句執行是否出錯:
全局變量@@ERROR;
@@ERROR
只能判斷當前一條T-SQL語句執行是否有錯,爲了判斷事務中所有T-SQL語句是否有錯,我們需要對錯誤進行累計;
---------------------------模擬轉賬----------------------------
declare @sumError int=0 --聲明變量
begin tran
update bank set balance=balance-1000 where cId='0001'
set @sumError=@sumError+@@error
update bank set balance=balance+1000 where cId='0002'
set @sumError=@sumError+@@error
if (@sumError=0)
commit tran --提交成功,提交事務
else
rollback tran --提交失敗,回滾事務
13、存儲過程
存儲過程---就像數據庫中運行方法(函數)
和C#裏的方法一樣,由存儲過程名/存儲過程參數組成/可以有返回結果。
前面學的if else/while/變量/insert/select 等,都可以在存儲過程中使用。
優點:
- 執行速度更快 - 在數據庫中保存的存儲過程語句都是編譯過的
- 允許模塊化程序設計 - 類似方法的複用
- 提高系統安全性 - 防止SQL注入
- 減少網絡流通量 - 只要傳輸 存儲過程的名稱
系統存儲過程
- 由系統定義,存放在master數據庫中
- 名稱以“sp”開頭或”xp”開頭
創建存儲過程:
定義存儲過程的語法
CREATE PROC[EDURE] 存儲過程名
@參數1 數據類型 = 默認值 OUTPUT,
@參數n 數據類型 = 默認值 OUTPUT
AS
SQL語句
參數說明:
參數可選
參數分爲輸入參數、輸出參數
輸入參數允許有默認值
EXEC 過程名 [參數]
----------------------例--------------------------
if exists (select * from sys.objects where name='usp_GroupMainlist1')
drop proc usp_GroupMainlist1
go
create proc usp_GroupMainlist1
@pageIndex int, --頁數
@pageSize int, --條數
@pageCount int output--輸出共多少頁
as
declare @count int --共多少條數據
select @count =count(*) from [mainlist] --獲取此表的總條數
set @pageCount=ceiling(@count*1.0/@pageSize)
select * from
(select *,row_number() over(order by [date of booking] desc) as 'num' from [mainlist]) as t
where num between(@pageSize*(@pageIndex-1)+1) and @pageSize*@pageIndex
order by [date of booking] desc
-------------------------------------------------------------------------------------------
--調用
declare @page int
exec usp_GroupMainlist1 1,100,@page output
select @page
14、常用函數
1)ISNULL(expression,value)
如果expression不爲null返回expression表達式的值,否則返回value的值
2)聚合函數
avg() -- 平均值 統計時注意null不會被統計,需要加上isnull(列名,0)
sum() -- 求和
count() -- 求行數
min() -- 求最小值
max() -- 求最大值
3)字符串操作函數
LEN() --計算字符串長度
LOWER() --轉小寫
UPPER () --大寫
LTRIM() --字符串左側的空格去掉
RTRIM () --字符串右側的空格去掉
LTRIM(RTRIM(' bb '))
LEFT()、RIGHT() -- 截取取字符串
SUBSTRING(string,start_position,length)
-- 參數string爲主字符串,start_position爲子字符串在主字符串中的起始位置(從1開始),length爲子字符串的最大長度。
SELECT SUBSTRING('abcdef111',2,3)
REPLACE(string,oldstr,newstr)
Convert(decimal(18,2),num)--保留兩位小數
4)日期相關函數
GETDATE() --取得當前日期時間
DATEADD (datepart , number, date )--計算增加以後的日期。參數date爲待計算的日期;參數number爲增量;參數datepart爲計量單位,可選值見備註。DATEADD(DAY, 3,date)爲計算日期date的3天后的日期,而DATEADD(MONTH ,-8,date)爲計算日期date的8個月之前的日期
DATEDIFF ( datepart , startdate , enddate ) --計算兩個日期之間的差額。 datepart 爲計量單位,可取值參考DateAdd。
-- 獲取日期的某一部分 :
DATEPART (datepart,date)--返回一個日期的特定部分 整數
DATENAME(datepart,date)--返回日期中指定部分 字符串
YEAR()
MONTH()
DAY()
15、sql語句執行順序
5>…Select 5-1>選擇列,5-2>distinct,5-3>top
1>…From 表
2>…Where 條件
3>…Group by 列
4>…Having 篩選條件
6>…Order by 列
16、分組查詢group by...having
對group by分組後的數據進行過濾在分組查詢中,查詢的列名必須出現在group by後或者在聚合函數中:
--查詢平均工資大於兩千塊錢的部門
select department_id,avg(wages)
from employee
where department_id is not null
group by department_id
having avg(wages)>2000
17、臨時表
方法一:
create table #臨時表名(字段1 約束條件,
字段2 約束條件,
.....)
create table ##臨時表名(字段1 約束條件,
字段2 約束條件,
.....)
方法二:
select * into #臨時表名 from 你的表;
select * into ##臨時表名 from 你的表;
注:以上的#
代表局部臨時表,##
代表全局臨時表
drop table #Tmp --刪除臨時表#Tmp
create table #Tmp --創建臨時表#Tmp
(
ID int IDENTITY (1,1) not null, --創建列ID,並且每次新增一條記錄就會加1
WokNo varchar(50),
primary key (ID) --定義ID爲臨時表#Tmp的主鍵
);
Select * from #Tmp --查詢臨時表的數據
truncate table #Tmp --清空臨時表的所有數據和約束
詳細說明:http://www.cnblogs.com/Hdsome/archive/2008/12/10/1351504.html
18、表值函數Create FUNCTION [dbo].[GetUPR]
(
@upr varchar(2) --傳入函數中的參數
)
RETURNS @tab TABLE
(
UPR varchar(2) --返回表的字段,這裏只有一個字段
)
AS
BEGIN
if(@upr='0')
begin
insert @tab
select 'U'
union select 'P'
union select 'R'
end
else
begin
insert @tab
select @upr
end
RETURN ;
END
19、標量值函數
-- =============================================
-- 根據訂單號獲取銷售員1的郵箱
-- =============================================
Create FUNCTION [dbo].[GetSalManAEmailByOrderNo]
(
@orderNo varchar(16)
)
RETURNS varchar(128)
AS
BEGIN
declare @salManAEmail varchar(128)
select @salManAEmail=EMailA from UserDB.dbo.EmployeeInfo where EmployeeID in
(
select EmployeeInfoID from SalesManInfo where SalesManCode in
(
select SalesManA from OrderInfo where SalesOrder=@orderNo
)
)
RETURN ( @salManAEmail)
END
20、觸發器
CREATE TRIGGER trigger_name
ON {table_name | view_name}
{FOR | After | Instead of } [ insert, update,delete ]
AS
sql_statement
詳細說明:http://www.cnblogs.com/yank/p/4193820.html
作者:rdst
文章源自:http://www.cnblogs.com/rdst/p/4727063.html