SQL Server 筆記整理

讀書時遺失的筆記!現在偶爾的機會找到了!真的很不錯的筆記!比較全面!在這裏和大家共享!希望能幫到一些人!畢竟是在校時的產物!認知有限!如有錯誤還請幫忙指正!([email protected])謝謝!

use master

go

if exists(select * from sysdatabases where name='student')

drop database student

 

--創建數據庫

create database student

on

(

        name='student',

        filename='D:\DBExercise\sudent.mdf',

        size=10,

        filegrowth=10%,

        maxsize=100

)

log on

(

        name='student.ldf',

        filename='D:\DBExercise\student.ldf',

        size=5,

        filegrowth=10%        

)

go

 

--創建表

if exists(select * from sysobjects where name='stuInfo')

drop table stuInfo

if exists(select * from sysobjects where name='stuMarks')

drop table stuMarks

go

use student

go

create table stuInfo

(

        stuName nvarchar(50) not null,

        stuNo nvarchar(20) not null,

        stuSex char(2) not null,

        stuAge int not null,

        stuSeat int identity(1,1) not null,

        stuAddress nvarchar(100) not null

)

go

create table stuMarks

(

        ExamNo nvarchar(20) not null,

        stuNo nvarchar(20) not null,

        writtenExam int not null,

        labExam int not null

)

go

  

--向表中添加約束

alter table stuInfo

add constraint pk_stuNo primary key(stuNo)

alter table stuMarks

add constraint fk_stuNo foreign key(stuNo) references stuInfo(stuNo)

alter table stuInfo

add constraint df_stuAddress default('地址不詳') for stuAddress

go

 

--向表中填充數據

insert into stuInfo(stuName,stuNo,stuSex,stuAge,stuAddress)

values('張秋離','s25301','男',19,'北京海淀')

insert into stuInfo(stuName,stuNo,stuSex,stuAge,stuAddress)

values('李斯文','s25303','女',20,'河南洛陽')

insert into stuInfo(stuName,stuNo,stuSex,stuAge,stuAddress)

values('李文才','s25302','男',17,default) 

insert into stuInfo(stuName,stuNo,stuSex,stuAge,stuAddress)

values('歐陽俊雄','s25304','男',21,'新疆') 

insert into stuInfo(stuName,stuNo,stuSex,stuAge,stuAddress)

values('梅嘲諷','s25318','女',18,default)

 

insert into stuMarks

values('s271811','s25303',93,59)

insert into stuMarks

values('s271813','s25302',63,91)

insert into stuMarks

values('s271816','s25301',90,83)

insert into stuMarks

values('s271817','s25318',63,53)

go

 

--檢測表中數據

select * from stuInfo

select * from stuMarks

 

--本次考試的缺考人數

if exists(select * from sysobjects where name='newTable_1')

drop table newTable_1

select 應到人數=(select count(*) from stuInfo),

                實到人數=(select count(*) from stuMarks),

                缺考人數=((select count(*) from stuInfo)-(select count(*) from stuMarks)) into newTable_1

select * from newTable

--提取學員的成績信息並保存結果,包括學員姓名,學號,筆試成績和機試成績,是否通過

if exists(select * from sysobjects where name='newTable_2')

drop table newTable_2

select stuName,stuInfo.stuNo,writtenExam,labExam,ispass=

       case

               when writtenExam>=60 and labExam>=60 then 1

               else 0

       end 

into newTable_2 from stuInfo left join stuMarks on stuInfo.stuNo=stuMarks.stuNo

 

print('提分前的學員考試情況表')

select 學員姓名=stuName,學員編號=stuNo,

筆試成績=case when writtenExam is null then '缺考'else convert(varchar(20),writtenExam) end,

機試成績=case when labExam is null then '缺考' else convert(varchar(20),labExam) end,

是否通過=case when ispass=1 then '是' else '否' end

from newTable_2

                                                                                                        

--比較筆試平均分和機試平均分,較底者進行提分,但最高分不能超過97

declare @avg_write int ,@avg_lab int                --聲明兩個變量

 

select @avg_write=avg(writtenExam), @avg_lab=avg(labExam)from newTable_2 where writtenExam is not null and labExam is not null

--print('筆試平均分:'+convert(nvarchar(20),@avg_write))

--print('機試平均分:'+convert(nvarchar(20),@avg_lab))

if( @avg_write<@avg_lab)

        while(1=1)

        begin

                update newTable_2 set writtenExam=writtenExam+2

                if(select max(writtenExam)from newTable_2)>=97

                break

        end

else

        while(1=1)

        begin

                update newTable_2 set labExam=labExam+2

                if(select max(labExam) from newTable_2)>=97

                break

        end

update newTable_2 set ispass=case

                                                                when writtenExam>=60 and labExam>=60 then 1

                                                                else 0

                                                        end

print('提分後的學員成績表')

select * from newTable_2

 

--提分後,統計學員的成績和通過情況

 

select 學員姓名=stuName,學員編號=stuNo,

筆試成績=case when writtenExam is null then '缺考'else convert(varchar(20),writtenExam) end,

機試成績=case when labExam is null then '缺考' else convert(varchar(20),labExam) end,

是否通過=case when ispass=1 then '是' else '否' end

from newTable_2

set noCount on

 

--提分後統學員的通過率

declare @count int ,@pass int

select @count=count(*) from stuInfo

select @pass=count(*) from newTable_2 where ispass=1

 

select 總人數=@count,

        通過人數=@pass,

        通過率=(convert(nvarchar(20),(@pass*100)/@count))+'%'

 

 

 

 

----------事務---------

 

 

if exists(select * from sysobjects where name='bank')

drop table bank

create table bank

(

        name nvarchar(20) not null,

        money money not null

)

go

insert into bank

values('Tom',800)

insert into bank

values('Jim',10)

 

alter table bank

add constraint ck_money check(money>1)

 

select * from bank

 

--Tom要轉帳元給jim,有上表可知Tom的錢壓根就沒有那麼多的,如果用update將Tom 的

--減少,而jim的增加,則會出現的情況是:Tom 的沒有減少Jim卻增加了

--這樣銀行就虧損了,顯然銀行是不同意這樣的事情發生的

--那麼爲了使更改前後兩者的數據保持一直我們就採取事務來處理類似的問題

 

begin transaction

set nocount on        ====》設定不顯示影響行數

declare @errorSum int 

set @errorSum=0

update bank set money=money-1000 where name='Tom'

set @errorSum=@errorSum+@@error

--print(convert(nvarchar(20),@errorSum))

update bank set money=money+1000 where name='Jim'

set @errorSum=@errorSum+@@error

--print(convert(nvarchar(20),@errorSum))

 

--select * from bank  --此時雖說系統報錯了,但jim的錢還是多了,而Tom的卻沒有變化

if @errorSum<>0

        begin

                print('交易有誤!')

                rollback transaction

        end

else 

        begin

                print('交易成功!')

                commit transaction

        end

go

 

print('轉帳後的系統存根:')

select * from bank

go

 

 

 

 

-----------索引---------------

 

 

--對於上面的stuMarks表創建索引

if exists(select name from sysindexes where name='ix_writtenExam')

drop index stuMarks.ix_writtenExam

 

create nonclustered index ix_writtenExam

on stuMarks(writtenExam)

with fillfactor=30           ===》它表示創建索引時每個索引頁的數據填充率

go

 

--應用索引

select * from stuMarks

(index=ix_writtenExam)

 where writtenExam between 60 and 90

 

 

 

 

---------視圖----------

 

 

--========注:對視圖的修改會影響到原始數據==========

if exists(select * from sysobjects where name='view_student')

drop view view_student

go

create view view_student

as

select 姓名=stuName,學號=stuInfo.stuNo,筆試成績=writtenExam,機試成績=labExam,平均分=(writtenExam+labExam)/2

from stuInfo left join stuMarks on stuInfo.stuNo=stuMarks.stuNo

go

select * from view_student

go

 

 

 

--===================存儲過程=================

 

 

--所有的系統存儲過程都是以sp_開頭的,存放在master數據庫中的

 

--***************常用系統存儲過程的應用**************

exec sp_databases       --列出當前系統中的存儲過程

exec sp_renamedb 'oldname','newname'    --改變數據庫名稱

 

use student

go

exec sp_tables           

exec sp_columns stuInfo

exec sp_help stuInfo      --查看stuInfo表的所有信息

exec sp_helpconstraint stuInfo     --查看錶的約束

 

exec sp_helpindex stuMarks      --查看錶的索引

exec sp_helptext 'view_writtenExam'   --查看視圖的語句文本

exec sp_stored_procedures    --當前數據庫中的存儲過程列表

 

 

--系統存儲過程xp_cmdshell可以實現DOS命令下的一些操作

--如果要創建一個數據庫在D:\Issac中,但D盤中沒有Issac文件夾,即可調用此存儲過程實現創建

 

exec xp_cmdshell 'md D:\Issac',no_output     --no_output是輸出返回信息,可選

 

 

 

 

--==========自定義存儲過程============

 

--***********不帶參數的存儲過程*************

use student

go

if exists(select * from sysobjects where name='proc_getAvgOfWrite')

drop procedure proc_getAvgOfWrite

go

create proc proc_getAvgOfWrite

as

declare @avgWrite float

select @avgWrite=avg(writtenExam)from stuMarks

print(convert(nvarchar(20),@avgWrite))

go

exec proc_getAvgOfWrite

 

 

--***************帶參數的存儲過程****************

 

 

--*******輸入參數********

use student

go

if exists(select * from sysobjects where name='proc_getNotPass')

drop procedure proc_getNotPass

go

create proc proc_getNotPass

@writtenPass=60 int ,   --輸入參數筆試及格線

@labPass=60 int            --輸入參數機試及格線

as

print('本次考試沒有通過的學員:')

select stuName,stuInfo.stuNo,writtenExam,labExam from stuInfo inner join stuMarks on 

stuInfo.stuNo=stuMarks.stuNo

where writtenExam<@writtenPass or labExam<@labPass

go

exec proc_getNotPass 70,65

--注:如果試題一般則調用存儲過程時可以不帶參數,如果試題偏易我們可以帶上參數,

--    至於帶幾個參數視情況而定,後面的參數形式多樣.....

 

 

 

--**********輸出參數**********

 

 

--如果調用的存儲過程需要有返回值(一個或多個),則需要帶有輸出參數的存儲過程

use student

go

if exists(select * from sysobjects where name='proc_getNotpass')

drop procedure proc_getNotpass 

go

create proc proc_getNotpass

@notPassSum int output ,    --默認爲輸入參數

@writtePass int =60  ,

@labPass int 

as

print('本次考試筆試及格線是:'+convert(nvarchar(20),@writtePass))

print('本次考試機試及格線是:'+convert(nvarchar(20),@labPass))

print('不及格的總體情況如表:')

select stuName,stuInfo.stuNo,writtenExam,labExam from stuInfo

inner join stuMarks on stuInfo.stuNo=stuMarks.stuNo

where writtenExam<@writtePass or labExam<@labPass

 

select @notPassSum=count(*)from stuMarks where writtenExam<@writtePass or labExam<@labPass

go

 

declare @sum int   --定義變量用於存儲返回的結果@notPassSum

exec proc_getNotpass @sum output ,75,63

 

print('本次考試沒有通過的學員人數是:'+convert(nvarchar(20),@sum))

 

 

 

--===================觸發器=================

user(id,name,age,address,telphone,email)

test(id,uid,content)

        

        create trigger 觸發器名 

        on 表或視圖

        for|after|instead of --操作時機

        insert,update,delete

        as

        sql語句

 

   eg1:

        create trigger user_tri

        on user

        after insert 

        as

        delete from test where id=(select count(*) from test)

        go

 

********當執行對錶 user 的 insert 操作時,會緊接着執行對 test 表的 delete 操作

 

   eg2:

        create trigger user_tri

        on user

        after insert

        as 

        update test set content=content+user.id

        from user,test

        where user.id=test.uid

 

********當執行對 user 表 insert 的命令時,會執行對 test 表中 content 字段的修改 

 

 

   eg3:

        create trigger user_tri

        on user

        after update

        as

        if update (age)

        begin

        raiserror('Error',10,1)

        rollback transaction

        end

 

*******當執行對 user 表中 age 執行 update 命令時會調用 raiserror,raiserror是聯機叢書中定義的方法,返回服務器消息,並取消對 user 表中 age 的修改。

 

 

 

   eg4:

        create trigger user_tri

        on user

        after insert

        as

        if 

        (select count(*) from user,test

        where user.id=test.uId)>

--可以在觸發器邏輯中使用 @@ROWCOUNT 函數以區分單行插入和多行插入。

begin

delete order_test from order_test,inserted

where order_test.orderid=inserted.orderid and

inserted.customerid not in (select customerid from cust_test)

end

 

無效:

use northwind

alter table 表名

disable trigger 觸發器名

 

重新有效:

use northwind

alter table 表名

enable trigger 觸發器名

 

刪除觸發器 

use northwind

drop trigger 觸發器名,觸發器名

 

 

select GetDate()   --獲取當前系統時間

select DateAdd(dd,3,(select GetDate()))    --將指定的數值添加到指定的日期的部分中

select datediff(MM,'01/01/09','05/02/09')         --兩個日期間指定日期部分的差

select datepart(day,'01/23/2009')        --日期指定部分的整數形式

select abs(-45)              --絕對值

select ceiling(43.5)                 --大於或等於指定值的最小整數

select floor(43.5)                 --小於或等於指定值的最大整數

select charindex('Tom','Jim and Tom is good frients')   --獲得指定字符串在另一個字符串中的起始位置

select len('Issac')                 --指定字符串的長度

select upper('issac')     --轉換爲大寫

select Ltrim(' Tom ')      --去除左邊空格

select rtrim(' Tom ')      --去除右邊空格

select right('IssacAndTom',3)    --從指定字符串右邊返回指定長度字符串

select left('IssacAndTom',5)    --從指定字符串左邊返回指定長度字符串

select replace('IssacAndJim','Jim','Tom')       --替換字符串中的字符

select stuff('IssacAndJim',6,3,'Or')   --刪除指定字符串指定爲主的指定長度的字符串,並在該位置插入指定的新字符串

select power(5,2)     --表達式的冪值

select round(43.456,2)   --四捨五入到指定小數點後的位數

select current_user    --當前用戶的名

select system_user       --當前所登陸的用戶名字

select host_name()           --當前登陸者登陸的計算機名

select datalength('Issac')       --表達式長度

 

select * into A..accounts from B..account    --將數據庫B中的表account 複製到數據庫A中並重命名爲accounts

 

 

--得到表中無重複數據

 

select distinct * from tableName 

 

--將表中重複數據去除(這裏的重複是指:完全重複的記錄,也即所有字段均重複的記錄)

select distinct * into #Tmp from tableName

drop table tableName

select * into tableName from #Tmp

drop table #Tmp

 

--將表中重複數據去除(這裏的重複是指部分關鍵字段重複的記錄,比如Name字段重複,而其他字段不一定重複或都重複可以忽略。)

 

這類重複問題通常要求保留重複記錄中的第一條記錄,操作方法如下

 

假設有重複的字段爲Name,Address,要求得到這兩個字段唯一的結果集

 

select identity(int,1,1) as autoID, * into #Tmp from tableName

select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID

select * from #Tmp where autoID in(select autoID from #tmp2) 

 

  最後一個select即得到了Name,Address不重複的結果集(但多了一個autoID字段,實際寫時可以寫在select子句中省去此列)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章