SQL語句全解析

1、基本的建庫、建表操做(增刪改查略去不講)

--建立數據庫School
Create database School

--使用數據庫
Use School

--建立學生表(SID爲自增主鍵,Ssex有Check約束,且全部字段,均不爲空)
create  table Student(SID int identity not null primary key,Sname nvarchar(30) not null,Sage int not null, Ssex nvarchar(5) check(Ssex='男' or Ssex='女') not null);

alter  table Student alter column Sage nvarchar(30) not null;(修改表)

--建立課程表(CID爲自增主鍵,且均不爲空)
create table Course(CID int identity not null primary key,Cname nvarchar(30) not null,TID int not null);

--建立成績表(SID爲自增主鍵,且均不爲空)
create table Score(SID int identity not null primary key,CID int not null,Score int not null);

--修改爲績表,爲其添加一個外鍵CID約束
alter table Score
add constraint FK_SC foreign key(CID) references Course(CID);


--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC 
--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC--修改課程表,刪除其原來的外鍵約束
alter table Course
drop constraint FK_SC 
--修改爲績表,爲其添加一個外鍵CID約束
alter table Score
add constraint FK_SC foreign key(CID) references Course(CID);
--修改爲績表,爲其添加一個外鍵CID約束
alter table Score
add constraint FK_SC foreign key(CID) references Course(CID);
--修改爲績表,爲其添加一個外鍵CID約束
alter table Score
add constraint FK_SC foreign key(CID) references Course(CID);
--修改爲績表,爲其添加一個外鍵CID約束
alter table Score
add constraint FK_SC foreign key(CID) references Course(CID);


--級聯刪除(B表應用A表主鍵作外鍵,A表刪除一條信息時也要把B的一條信息給刪除)

--建立索引
create fulltext index on Change (id)


 

---建立表TestA
create table TestA
(
id varchar(20) primary key,
password varchar(20) not null
)

--建立表Test並添加外鍵
create table TestB
(
id int identity(1,1) primary key,
name varchar(50) not null,
uerid varchar(20), 
foreign key (uerid) references TestA(id) on delete cascade--聲明級聯刪除
)


--建立新表,同時與其餘表關聯, 當刪除父記錄時 同時刪除該記錄也就是當刪除orders表中的一條記錄
create table orderdetails
( orderid int not null , id int not null , description varchar(123) not null,
 --設置主鍵 
 constraint pkOrderdetails primary key (orderid,id), 
 --設置外鍵,級聯操做 
 constraint fkOrderContainsDetails foreign key (orderid) references orders(orderid)
 on update no action on delete cascade)---當更新操做時不級聯,當刪除操做時級聯

--聲明一個臨時表,在刪除數據以前,將將要刪除的數據插入臨時表裏,主要用到output, deleted.字段
declare @Test as Table(tname nvarchar(30),tage nvarchar(30),tsex nvarchar(30))
delete Student
output deleted.Sname,deleted.Sage,deleted.Ssex into @Test
 where Sname='趙雷'
select * from @Test
select * from Student;
--聲明一個臨時表,在插入數據以前,將將要插入的數據插入臨時表,主要用到output ,inserted.字段
declare @Test1 as Table(tname nvarchar(30),tage nvarchar(30),tsex nvarchar(30))
insert into Student output inserted.Sname,inserted.Sage,inserted.Ssex into @Test1 values('Olive','1990-01-16','女');
select * from @Test1
2、經常使用的系統存儲過程

--如何修改數據庫名稱
sp_renamedb 'db_oldName','db_newName'
--數據庫名稱
select db_Name()
--應用程序程序名稱
select app_name()
--獲取登陸者名字
select suser_sname()
--獲取字段定義的長度
select col_length('Student','Sname')
--獲取架構名
select object_schema_name(object_id('tb'))
--獲取字段名稱
select col_name(object_id('Student'),2)
--查看數據庫
sp_helpdb

--獲取表的數據結構及相關信息
sp_help Student


--查看錶信息
sp_tables Student
--查看字段信息
sp_columns Student
--查看索引
sp_helpIndex Student
--查看存儲過程
sp_helptext 'ShowAllChuKuInfo'
--查看約束
sp_helpConstraint Student


--查看觸發器定義
sp_helptext 'InsertTwo'
--sp_helptrigger 用於查看觸發器的屬性
sp_helptrigger 'InsertTwo'

3、經常使用的操做和經常使用函數

ABS:ABS函數返回數值表達的絕對值
語法:ABS(numeric_expression)能夠是整型、短整型、微短整型、小數、浮點數、貨幣、實型或小貨幣型數。
ACOS:ACOS函數是一個數學函數,它返回以弧度表示的角度,即:ARCCOS。
語法:ACOS(float_expression)變量是浮點數數據類型,表示角度的餘弦。
ASIN:反正弦函數。
SIN:它返回表達式中的正弦值。
語法:SIN( float_expression)float_expression是浮點型的資料
COS:它返回表達式中的餘弦值。
語法:COS( float_expression)float_expression是浮點型的資料。
TAN:它返加表達式的正切值。
COT:它返回表達式中的餘切值。
ATAN:反正切函數。
SIGN:若是表達式爲正,SIGN函數返回1,若是表達爲負,SIGN返回-1,若是表達式爲0,則函數返回0。
CEILING:返回不小於給定的數值表達式的最小整數。
語法:CEILING(numeric_expression)小數、浮點、整數、實數、貨幣等類型。
例如:SELECT CEILING(1.45)返回值爲2
SELECT CEILING (-1.45)返回值爲-1
FLOOR:返回不大於給定的數值表達式的最大整數。
語法:FLOOR(numeric_expression)小數、浮點、整數、實數、貨幣等類型。
例如:SELECT FLOOR(1.45)返回值爲1
SELECT FLOOR (-1.45)返回值爲-2
ASCII:ASCII函數返回整數,表示字符表達式最左邊的字符的ASCII代碼值。
語法:ASCII(character_expression)
例:ASCII(‘AB’)返回65。
CHAR:字符串函數,用於將ASCII碼整數轉換爲字符。
語法:CHAR(integer_expression)變量是0~255間的正整數。
例如:CHAR(65)返回‘A’
CHARINDEX:字符串函數,返回想要的查找字符串,在目標字符中的起始位置。
語法:CHARINDEX(‘PATTERN’,EXPRESSION[,START_LOCATION]);
例如:CHARINDE(‘A’,‘BCDEA’,2)返回值爲5,其2爲從第幾個字符進行搜索不寫默認爲從第一個位置。
AVG:AVG是個集合函數,它計算數值列的平均值,忽略空值,若是使用了DISTINCT則對重複的值只取一次進行平均。
語法;AVG([ALL|DISTINCT] expression)
ALL是缺省值。
例如:SELECT DISTINCT(AGE)FROM TABLE1 若是任意行有NULL值,則此行被忽略。
COUNT:是一個集合函數,它返回的整數表明表達式中值的個數通爲一個列,DISTINCT和COUNT一塊兒使用時,返回單一值的個數。
語法:COUNT({[ALL|DISTINCT] EXPRESSION |*})
例如:SELECT COUNT(COLUMN1)FROM TABLE1,
返回COLUMN1中沒有空值的行數,若是是使用*將返回表中全部行的數目。
使用DISTINCT則返回惟一值的個數。
SUM:SUM是一個集合函數,返回表格中選定的數值型列中的值的總和。
語法:SUM([ALL|DISTINCT]expression)
MAX:MAX返回表達式中的最大值,
語法:MAX(expression)
MIN:MIN返回表達式中的最小值,
語法:MIN(expression)
GETDATE:GETDATE是一個函數,它返回系統日期和時間。
語法:GETDATE()
DATEADD:DATEADD返回根據日期時間添加的日期,
語法:DATEADD(datepart,number,date)
變量:DATEPART是用於計算的日期單位。有必定的格式。
NUMBER是指添加至日期變量中的日期單位數。
DATE:格式化爲日期的字符串,或日期時間型的列名、變量或參數。
例如:SELECT DATEADD(DAY,7,GETDATE())
DATEDIFF:返回兩個指定日期的日期單位差異。
語法:DATEDIFF(datepart,date,date)
例如:DATEDIFF(day,datevar,getdate())
返回值爲DATEVAR和當前日期相差的天數。
DATEPART:返回的整數表示日期中的日期單位。
語法:DATEPART(datepart,date)
例如:DATEPART(month,getdate())
返回值爲當前日期的月份數。
YEAR:顯示所提供日期的年,
語法:YEAR(DATE)
MONTH:顯示所提供日期的月,
語法:MONTH(DATE) 

DAY:顯示所提供日期的天,
語法:DAY(DATE)
CAST:CAST語句用來進行數據類型的轉換。
語法:CAST(expression AS datatype)
例如:CAST(MYDATE AS VARCHAR)
把MYDATE 轉換成可變字符類型。
CONVERT:用來進行資料類的轉換。
語法:CONVERT(data_type,expression)
例如:SELECT ‘my birthday is today’+convert(varchar(12),getdate( ))
把日期轉換成字符串類型,用加號與前邊相連。
EXP:返回以E爲底的N次冪。
語法:EXP(float_expression)
例如:EXP(0)返回值爲1。
LOG:LOG函數返回浮點表達式的天然對數。
語法:LOG(float_expression)
LOG10:LOG函數返回浮點表達式的以10爲底的對數值。
語法:LOG10(float_expression)
ROUND:ROUND返回給出的數學表達式的,並四捨五入至指定的精度。
語法:ROUND(numeric_expression,length[,funcion])
變量:numeric_expression爲數值型表達式
length是四捨五入的精度,小數點後邊的數,當爲負值時,數字表達式在小數點左邊進行四捨五入。
Function值爲0時表達式四捨五入,若是不爲0,將數字表達式舍位。
SQUARE:求平方
語法:SQUARE(float_expression)
SQRT:求平方根
語法:SQRT(float_expression)
STR:SQRT能夠將數值型轉換爲字符型資料,容許控制小數的格式。
語法:STR(float_expression[,length[,decimal]])
變量:length:想要的字符串的總長度。缺省爲10。
decimal:是小數點右邊的位數。四捨五入。若是不寫長度則爲取整,小數後四
舍五入。
ISNULL:ISNULL可有非空資料代替NULL。
語法:ISNULL(expression,value)
例如:SELECT ISNULL(NULL,'ABC')
LEFT:LEFT函數返回字符表達式從左邊開始的給定的字節數。若是該整數是一個負數, 就返回NULL。
語法:LEFT(character_expression,integer_expression)
變量:character_expression能夠是變量、常量、或表中的列。
Integer_expression爲要返回的字符數。
RIGHT:RIGHT函數返回字符表達式從右邊開始的給定的字節數。若是該整數是一個負
數,就返回NULL。
語法:LEFT(character_expression,integer_expression)
變量:character_expression能夠是變量、常量、或表中的列。
Integer_expression爲要返回的字符數。
LEN:LEN函數提供了字符串表達式中的字符的長度。
語法:LEN(string-expression)
例如:LEN(‘ABCE’)值爲4
LOWER:LOWER函數將大寫字符轉換爲小寫字符。
語法:LOWER(character_expression)
變量是字符表達式。
UPPER:UPPER函數將小寫字符轉換爲大寫字符。
語法:UPPER(character_expression)
變量是字符表達式。
REVERSE:REVERSE返回字符串表達式的倒序。
語法:REVERSE(character_expression)
例如:REVERSE(‘PAM’)結果爲‘MAP’
LTRIM:LTRIM刪除字符表的前導空格。
語法:LTRIM(character_expression)
  變量是字符表達式。
RTRIM:RTRIM刪除字符表的後繼空格。
語法:RTRIM(character_expression)
 變量是字符表達式。
NULLIF:若是一對錶達式相等,NULLIF函數就返回NULL,若是它們不相等,NULLIF函數就返回第一個表達式的值。
  語法:NULLIF(expression1,expression2)
  變量:expression能夠數值型,也能夠是字符串。
  例如:SELECT NULLIF(134,135)返回值爲134。
PI:PI函數返回pi的值3。1415926
REPLACE:REPLACE用串表達式3取代串表達式1中的表達式2。
  語法:REPLACE(‘string1’,‘string2’,‘string3’)
  例如:SELECT REPLACE(‘mydog’,‘dog’,‘car’)
本例中,用CAR取代了MYDOG中的DOG,結果爲MYCAT。
STUFF:函數能夠將表達式的一部分用所提供的另外一個字符串替代,替代部分用起始位置和長度來定義。
語法:STUFF(character_expression,start,length,character_expression)
LENGTH:是決定要替換的字符數。
例如:STUFF(‘MY DOG FIDO’,8,4,‘SALLY’)
SUBSTRING:返回字符型的一部分。
語法:SUBSTRING(expression,start,length)
例如:SUBSTRING(‘MICROSOFT’,6,4)
返回SOFT。
REPLICATE:REPLICATE將字符串表達式複製用戶定義的次數。
語法:REPLICATE(character_expression,integer-expression)
例如:REPLCATE(‘2’,5)


-try catch使用
--打開try catch功能
set xact_abort on 
begin try
 begin tran
 insert into Student(SID) values(-1)
 commit tran
 print 'commited'
 end try
 begin catch
 rollback
 print 'rolled back'
 end catch  


--獲取當前月有多少天
select DATEPART
(day,
DATEADD(DAY,-1,
CAST(cast(YEAR(getdate()) as nvarchar)+'-'+cast(month(getdate()) as nvarchar)+'-01' as datetime)
)
)


--取到小數第二位四捨五入
Select Convert(Numeric(20,2), IsNull(50.01634,0))
--50.02


--一個月第一天
select DATEADD(mm,DateDiff(mm,0,getdate()),0)


--DateAdd當添加的值和初試值均爲0時,返回的時間爲1900-01-01 00:00:000

select DATEADD(mm,0,0);


--如何查詢本日、本月、本年的記錄SQL
--本年:
select * from Stduent where year(date)=year(getdate()) 


--本月:
select * from Stduent where year(date)=year(getDate()) And month(date)=month(getdate())
--本日:
select * from Stduent where year(date)=year(getDate()) And month(date)=month(getdate()) and Day(date)=Day(getDate())  

--昨天的記錄:
datediff(day,[Datetime],getdate())=1  把Datetime換爲你的相應字段,getdate()-Datetime即爲時間差。
--本月記錄:
SELECT * FROM 表 WHERE datediff(month,[dateadd],getdate())=0
--本週記錄:
SELECT * FROM 表 WHERE datediff(week,[dateadd],getdate())=0
--本日記錄:
SELECT * FROM 表 WHERE datediff(day,[dateadd],getdate())=0

--本週的星期一   
SELECT  DATEADD(wk,  DATEDIFF(wk,0,getdate()),  0)  
select DATEADD(wk,datediff(wk,0,getdate()),0);
--一年的第一天  
SELECT  DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0)  
select DATEADD(yy,DateDiff(yy,0,getdate()),0)
--季度的第一天   
SELECT  DATEADD(qq,  DATEDIFF(qq,0,getdate()),  0)  
 select DATEDIFF(qq,0,GETDATE())
 select DATEDIFF(WK,0,GETDATE())
 select DATEDIFF(MM,0,GETDATE())
 select DATEDIFF(yy,0,getdate())
--當天的半夜   
SELECT  DATEADD(dd,  DATEDIFF(dd,0,getdate()),  0)  
select DATEADD(dd,datediff(dd,0,getdate()),0)
select DATEADD(dd,datediff(dd,0,getdate()),0)
--去年的最後一天 
 SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0)) 
 select  DATEADD(ms,-3,dateadd(yy,datediff(yy,0,getdate()),0)) 
--本年的第一天
select DATEADD(YY,DATEDIFF(yy,0,getdate()),0)
--本年的最後一天
select dateadd(MS,-3,DATEADD(yy,datediff(yy,0,getdate()),0))
--本月的第一天 
select DATEADD(mm,datediff(mm,0,GETDATE()),0);
--本月的最後一天
select DATEADD(ms,-3,DateAdd(mm,datediff(mm,0,getdate()),0))
--本年的最後一天
   SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate())+1,  0))
--本月的第一個星期一
select  DATEADD(wk,  DATEDIFF(wk,0,                                                         
                               dateadd(dd,6-datepart(day,getdate()),getdate()) ),  0)  
--本週的星期一
select DATEADD(wk,datediff(wk,0,getdate()),0);  


--顯示星期幾
select datename(weekday,getdate());


--顯示本月的天數
select DATEDIFF(dd,getdate(),DATEADD(mm,1,getdate()));

--顯示某年某月有多少天
create   Function DaysInMonth1(@datetime datetime)
returns int
as
begin
return Day(datepart(dd,dateadd(ms,-3,dateadd(mm,datediff(mm,0,@datetime)+1,0))))
end
select dbo.DaysInMonth1('2012-2-13');

--顯示本週的星期一
select DATEADD(WK,DATEDIFF(wk,0,getdate()),0)


--獲取當前數據庫中全部用戶的表
select * from sysobjects where xtype='U'   

--隨機取出條數據
select top 3 * from Student order by newid() 

select NEWID()
--查找表中多餘的重複記錄
select * from Student where SID in( select SID from Student  group by SID having COUNT(Sname)>1)

 

create table Tb(TID int identity(1,1),TName nvarchar(10) unique)
delete from Tb
insert into Tb select 'Olive'
--重置自增ID
dbcc checkident(Tb,reseed,4)
insert into Tb select 'Olive1'
delete Tb where TName='Olive' 
insert into Tb select 'Olive'
insert into Tb Select 'MoYao'
select * from Tb


--關鍵字waitfor 主要有waitfor delay(推遲執行),waitfor time (特定時間執行)
waitfor delay '00:00:08'
print('Hello ,Im waitfrom delay')
waitfor time '20:49:50'
print('Hello,Im waitfor time')

 

--檢測數據庫是否存在
if( exists(select * from sys.databases where name='School'))
select * from Student
go
--檢測數據表是否存在
if( exists(select * from sys.objects where name='Student'))
select * from Student order by SID desc
go
--檢測數據列是否存在
if(exists(select * from sys.all_columns where object_id=object_id('Student') and name='Sname'))
select * from Student
go


--同時無條件的查詢兩個不相關的表,所得新表字段爲兩表字段之和,信息條數爲兩個信息條數的乘積 (即爲:兩表的笛卡爾積)      
select T.*,Student.* from T ,Student
--交叉鏈接即爲上邊所講的那種鏈接
select T.*,Student.* from T cross join Student

 

--隨機數都可以產生0-1之間的隨機數
select RAND();
select RAND(CHECKSUM(NEWID()))
--隨機數0-9
select ABS(RAND())
select ABS(checksum(newid()))%10
--隨機數a-b之間
select a+ABS(checksum(newid()))%(b-a+1)
select 1+ABS(checksum(newid()))%100

--SubString字符串截取
select SUBSTRING('Olive116',1,5)
--left從左邊截取字符串
select LEFT('Olive',3)
--right從右邊截取字符串
select RIGHT('Olive',4)
--字符串替換
select REPLACE('OOLive','o','1')
--反轉排序
select REVERSE('Olive')
--刪除指定的長度並在指定的起點處插入另外一組字符
select STUFF('OliveOOO',6,3,'Hello')
--以指定的次數重複字符串的值
select replicate('Olive',3)
--返回表達式中第一次出現的位置
select PATINDEX('%Olive%','Hello!Olive')
--返回字符串中指定表達式的開始位置
select CHARINDEX('O','Hello,Olive')
--返回輸入表達式的第一個字符的整數值
select UNICODE('o')
--返回由數字數據轉換來的字符數據
select STR(123.1314,4),LEN(STR(123.3212,321))
select STR(123.1334,4,4)
--發音匹配度
select Sname,SOUNDEX(Sname) from Student
--difference()簡化兩個字符串發音類似度,返回0-4之間的值來反應兩個字符的類似度,值越大就越類似
select Sname,SOUNDEX(Sname),DIFFERENCE(Sname,'Olive') from Student
--查詢重複記錄
select * from Student where SID in (select SID from Student group by SID having COUNT(SID)>0)
--刪除重複的記錄(並保留SID最小的記錄)
delete from Student where 
SID in (select SID  from Student group by SID having COUNT(SID)>0) 
and SID not in(select MIN(SID) from Student group by SID having count(SID)>0)


 --雙引號
 select '''''' as result


--isnumeric()判斷是不是數字是爲1否爲0
select ISNUMERIC('a')
--isdate()判斷是否爲日期是爲1否爲0
select ISDATE('2012-3-2')



4、存儲過程、函數、觸發器、事務、遊標

(1)存儲過程

 

--建立存儲過程(無參)
create procedure ShowTestA 
as
select * from TestA
--修改存儲過程(有參,且爲輸出參數)
alter procedure ShowTestA
@LastName varchar(10) = null output
as
if @LastName is null
begin
     print 'null'
     print '123'
end
else
begin 
 print @LastName
 print '456'
 end
 exec ShowTestA
 exec ShowTestA 'Olive'


(2)自定義函數(關鍵點:函數和存儲過程 區別主要在於函數必須聲明返回值類型)

   
--用戶自定義函數(返回時間)
create function DayOnly(@date datetime)
returns varchar(12)
as
begin
return convert(varchar(12),@date,101)
end   

select dbo.DayOnly(getdate())

--用戶自定義函數(返回表)
drop function TestATable
create function TestATable(@Name nvarchar(10))
returns table
as
return select * from TestA where id=@Name
select * from TestA
select * from TestATable('12')

 

--用戶自定義函數輸入參數、返回表
create function ResultTable(@Name nvarchar(10))
returns @Result table (Rid varchar(10),Rpwd varchar(10))
as
begin
insert into @Result select * from TestA where id=@Name
return
end
select * from ResultTable('12')

 

(3)觸發器

--建立觸發器
create trigger UpdateStudent
on Student
for insert
as
update Student set Sname='O(∩_∩)O哈哈~' where SID=( select Inserted.SID from Inserted)
insert into Student select 'MM','1988-11-11','男'
select * from Student order by SID Desc


.禁用觸發器

alter table Sales.SalesOrderDetail
disabletrigger all --這裏的all能夠是具體的觸發器名

.刪除觸發器

drop trigger orderDetailNotDiscontinued

.修改觸發器

alter trigger tr_title
on mytable
for insert,update
as
if update(title)
begin
print('title1')
end 

 

--觸發器的相關函數Update()
create trigger UpdateTest
on Student
for insert,update
as
if update(SName)----若是update()中的字段有更新的話就爲true不然爲false
select Inserted.Sname from Inserted
insert into Student select 'OLIVEVEVE','1989-12-22','女'


--觸發器(插入新的數據,而且在插入後更新剛插入的輸入的姓名)
create trigger InsertTwo 
on Student 
after insert
as
update Student set Sname='OOOO' where SID=( select inserted.SID from Inserted)

insert into Student select 'MoYao','1989-11-15','男'
select * from Student


其中inserted表是一個臨時表
存儲的是將要插入的信息
這個觸發器的目的是檢查將要插入的信息是否符合規定
(在product表裏沒有特殊的記錄)
這個例子是check約束所不能解決的了的

use AdventureWorks
go
create trigger orderDetailNotDiscontinued
on Sales.SalesOrderDetail
 afterinsert,update
as
if exists
 (
select 'true' from Inserted i
join Production.Product p
on i.ProductID= p.ProductID
where p.DiscontinuedDateis not null
 )
begin
print('error appear.')
rollback tran
end

 

(4)事務

sql事務是使用SQL server自身的事務:在存儲過程當中直接使用Begin Tran,Rollback Tran,Commit Tran實現事務:
優勢:執行效率最佳
限制:事務上下文僅在數據庫中調用,難以實現複雜的業務邏輯。
begin try
 begin tran
 insert into Student(SID) values(-1)
 commit tran
 print 'commited'
 end try
 begin catch
 rollback
 print 'rolled back'
 end catch  


TransactionScope事務
TransactionScope事務類,它可使代碼塊成爲事務性代碼。並自動提高爲分佈式事務
優勢:實現簡單,同時可以自動提高爲分佈式事務
那麼如何解決數據庫併發問題呢?
解決此問題的辦法就是爲數據庫加鎖,以防止多個組件讀取數據,經過鎖住事務所用的數據,能保證開鎖以前,只有本事務才能訪問數據庫。這樣就避免了交叉存取的問題

 

(5)遊標

--遊標:數據集合裏的上下移動的指針
drop cursor StudentCursor
--聲明變量
declare @SID int
declare @Sname nvarchar(30)
declare @Sage nvarchar(30)
declare @Ssex nvarchar(5)
--聲明遊標
declare StudentCursor cursor  for
select * from Student 
--打開遊標
open StudentCursor
--將遊標移向下一行,將獲取的數據放入以前聲明的變量中
fetch next from StudentCursor into @SID,@Sname,@Sage,@Ssex
--判斷是否獲取數據成功,@@fetch_status爲系統全局變量,0-表示成功,1-表示取不到數據,2-超出了最後一條數據
while @@fetch_status=0
begin
print(Cast(@SID as varchar)+':'+@Sage+':'+@Ssex)
--提取下一條記錄
fetch next from StudentCursor into  @SID,@Sname,@Sage,@Ssex
end 
close StudentCursor
deallocate StudentCursor

 

--存儲過程當中使用遊標(遊標的做用域)
create procedure TestStudentCursor
as
--聲明變量填充遊標檢索到的數據
declare @SID int
declare @Sname nvarchar(30)
declare @Sage nvarchar(30)
declare @Ssex nvarchar(5)
--聲明存儲過程內部的全局遊標
declare StudentCursor  cursor global for
select * from Student
--打開遊標
open StudentCursor
--讀取下一條數據,並將數據填充到以前聲明的變量中
fetch next from StudentCursor into @SID,@Sname,@Sage,@Ssex
--判斷是否取到數據,且取到的數據是否符合要求
while(@SID<5) and (@@fetch_status=0)
begin
--打印數據
print(cast(@SID as varchar)+'::'+@Sname+'::'+@Sage)
--讀取下一條數據
fetch next from StudentCursor into @SID,@Sname,@Sage,@Ssex
end
--關閉遊標
close StudentCursor
--釋放遊標
deallocate StudentCursor

--執行存儲過程
exec TestStudentCursor

 

 

5、實用功能

(1)分頁


分頁的幾種寫法(性能效果最好的是top/max 和Row_number()兩種方法)

--寫法1,not in/top
select top 50 * from pagetest
where id not in (select top 9900 id from pagetest order by id)
order by id
--寫法2,not exists
select top 50 * from pagetest
where not exists
(select 1 from (select top 9900 id from pagetest order by id)a  where a.id=pagetest.id)
order by id
--寫法3,max/top
select top 50 * from pagetest
where id>(select max(id) from (select top 9900 id from pagetest order by id)a)
order by id
--寫法4,row_number()
select top 50 * from
(select row_number()over(order by id)rownumber,* from pagetest)a
where rownumber>9900

select * from
(select row_number()over(order by id)rownumber,* from pagetest)a
where rownumber>9900 and rownumber<9951

select * from
(select row_number()over(order by id)rownumber,* from pagetest)a
where rownumber between 9901 and 9950


--分頁函數(先循環插入100000000條數據而後再分頁)
create table  #FYTable (id int identity(1,1),title nvarchar(20),con nvarchar(20))
declare @title nvarchar(300),
        @con nvarchar(300)
declare @start int,@end int
set @start=0
set @end=1000000
set @title='Olive'
set @con='I love'
while @start<@end
begin
 insert into #FYTable select @title,@con
 set @start=@start+1
 end
select * from #FYTable
create procedure dbo.FenYe
@count int,@yeshu int
as
select top(@yeshu) * from #FYTable where id not in (select top(@count*@yeshu) id from #FYTable)

(2)排序

--排序函數
select SName,Sage,SSex from(
select SName,Sage,Ssex ,Rank() over(order by sage) as rank from Student
) as a where a.rank>1 and a.rank<9;


(3)錶行列轉換

--數據錶行列轉換(case when then)
create table Factory( FID int,FDepartment nvarchar(20),FMeterial nvarchar(20), FNumber int)
insert into Factory values(1,'工廠1','材料1',1);
insert into Factory values(1,'工廠2','材料1',1);
insert into Factory values(1,'工廠2','材料2',2);
insert into Factory values(1,'工廠2','材料3',1);
insert into Factory values(1,'工廠3','材料3',1);
insert into Factory values(1,'工廠2','材料1',2);
insert into Factory values(1,'工廠3','材料2',1);
select * from Factory

select  FDepartment,
SUM(case FMeterial when '材料1' then FNumber else 0 end) as 材料1,
SUM(case FMeterial when '材料2' then FNumber else 0 end) as 材料2,
SUM(case FMeterial when '材料3' then FNumber else 0 end) as 材料3
from Factory group by FDepartment



--行列轉換函數Pivot

create table Sell
(
[Year] int,[Quarter] nvarchar(2),Quantity int
)
insert into Sell values(2011,'Q1',12)
insert into Sell values(2011,'Q2',13)
insert into Sell values(2011,'Q2',14)
insert into Sell values(2011,'Q3',15)
insert into Sell values(2011,'Q2',12)
insert into Sell values(2011,'Q3',13)
insert into Sell values(2011,'Q4',15)
insert into Sell values(2011,'Q4',17)
insert into Sell values(2011,'Q4',11)
insert into Sell values(2012,'Q3',13)
insert into Sell values(2012,'Q4',15)
insert into Sell values(2012,'Q2',17)
insert into Sell values(2012,'Q4',11)
insert into Sell values(2012,'Q3',13)
insert into Sell values(2012,'Q1',15)
insert into Sell values(2012,'Q1',17)
insert into Sell values(2012,'Q4',11)
select * from Sell


select * from Sell Pivot(sum(Quantity) for [Quarter] in (Q1,Q2,Q3,Q4) )as p
select [Year], SUM(case when [Quarter]='Q1' then Quantity end) as Q1,
               SUM(case when [Quarter]='Q2' then Quantity end) as Q2,
               SUM(case when [Quarter]='Q3' then Quantity end) as Q3,
               SUM(case when [Quarter]='Q4' then Quantity end) as Q4
               from Sell group by [Year]


--case when then 用例
drop table T
go
create table T (TID int identity(1,1) not null  primary key,Quantity int not null,ProductID int not null,[Type] int not null)
go
insert into T select 2,12,1
insert into T select 6,12,2
insert into T select 3,10,2
insert into T select 8,10,1
insert into T select 2,12,1
select * from T
go
--統計每種商品有多少件
select ProductID,SUM(case when [Type]=1 then Quantity else -Quantity end) from T group by ProductID

--使用case when 爲表的新列填充不一樣的數據
alter table T add Descriptions nvarchar(20) null
go
update T set Descriptions= case when [Type]=1 then '現存'
                                when [Type]=2 then '售出'
                                else '未知'
                                end
go                


--怎麼把這樣一個表
--year  month amount
--1991   1     1.1
--1991   2     1.2
--1991   3     1.3
--1991   4     1.4
--1992   1     2.1
--1992   2     2.2
--1992   3     2.3
--1992   4     2.4
--查成這樣一個結果
--year  m1  m2  m3  m4
--1991  1.1   1.2   1.3   1.4
--1992  2.1   2.2   2.3   2.4
create table #DateTest([year] int,[month] int,amount float)
drop table #DateTest
insert into #DateTest 
select 1991,1,1.1
union select 1991,2,1.2
union select 1991,3,1.3
union select 1991,4,1.4
union select 1992,1,1.1
union select 1992,2,1.2
union select 1992,3,1.3
union select 1992,4,1.4
select * from #DateTest
--根據月份的不一樣分爲不一樣的字段,而後再按照年份分組
select [year],sum(case [MONTH] when 1 then amount else 0   end) as m1,sum(case [MONTH] when 2 then amount  else 0 end) as m2,sum(case [MONTH] when 3 then amount else 0 end) as m3,sum(case [MONTH] when 4 then amount else 0 end) as m4 from #DateTest group by [year]


--有兩個表A和B,均有key和value兩個字段,若是B的key在A中也有,就把B的value換爲A中對應的value。這道題的SQL語句怎麼寫?
create table #A(keys int,value varchar(20))
create table #B(keys int,value varchar(20))
insert into #A values(1,'aa'),(2,'ab'),(3,'ac')
insert into #B values(1,'aa'),(2,'a'),(3,'a')
--先將更新#B中value的值更新爲#A中value的值,同時限定#B中的keys=#A.Keys 同時#B.value<>#A.value
update #B set value=(select a.value from #A a where a.keys=#B.keys) where #B.keys in(select #B.keys from #B,#A where #A.keys=#B.keys and #A.value<>#B.value)
select * from #B
select * from #A
delete from #A
delete from #B
--先刪除#A,#B同樣的部分,而後再根據兩表中Keys 的相等進行更新
update #B set #B.value=s.value from (select * from #A except select * from #B) as s where #B.keys=s.Keys


--原表: 
--courseid coursename score 
--1   java          70 
--2      oracle       90 
--3      xml            40 
--4      jsp             30 
--5      servlet     80 
--爲了便於閱讀,查詢此表後的結果顯式以下(及格分數爲60): 
--courseid coursename score mark 
--1        java         70  pass 
--2        oracle     90  pass 
--3        xml          40  fail 
--4         jsp          30  fail 
--5    servlet    80     pass 
create table #B1(id int identity(1,1),coursename varchar(30),score int )
insert into #B1 values('java',70),('oracle',90),('xml',40),('jsp',30),('servlet',80)
select * from #B1
--case when 的使用
select id,coursename,score, case when score > 60 then 'pass' 
                                       else 'fail'
                                       end as mark from #B1                                

--原表: 
--id proid proname 
--1 1 M 
--1 2 F 
--2 1 N 
--2 2 G 
--3 1 B 
--3 2 A 
--查詢後的表: 
--id pro1 pro2 
--1 M F 
--2 N G 
--3 B A
create table C(id int,proid int,proname varchar(2))
insert into C values(1,1,'M'),(1,2,'F'),(2,1,'N'),(2,2,'G'),(3,1,'B'),(3,2,'A')
select * from C
select id,(select proname from C c where proid=1 and cc.id=c.id ) as pro1,(select proname from C c2 where proid=2 and c2.id=cc.id ) as pro2 from C cc group by id

--以下
--表a 
--列    a1 a2 
--記錄  1  a 
--      1  b 
--      2  x 
--      2  y 
--      2  z 
--用select能選成如下結果嗎? 
--1 ab 
--2 xyz
create table #D (a1 varchar(2),a2 varchar(2))
insert into  #D values ('1','a'),('1','b'),('2','x'),('2','y'),('2','z')
create table #D1 (id varchar(2),value varchar(2))
alter table #D1 alter column value  varchar(20)
insert into #D1 select distinct(a1),'' from #D
declare @id varchar(2),@value varchar(20)
declare LianJie cursor for select * from #D
open LianJie
fetch next from LianJie into @id,@value
while @@FETCH_STATUS=0
begin 
update #D1 set value=value+@value whereid=@id
fetch next from LianJie  into @id,@value
end
close LianJie
deallocate  LianJie
select * from #D
select * from #D1


 

 

--3. 表內容:
--2005-05-09 勝
--2005-05-09 勝
--2005-05-09 負
--2005-05-09 負
--2005-05-10 勝
--2005-05-10 負
--2005-05-10 負
--若是要生成下列結果, 該如何寫sql語句?
--                       勝負
--2005-05-09  2    2
--2005-05-10  1    2
create table #E (dt varchar(20),shengfu nvarchar(20))
insert into #E values('2012-9-15','勝'),('2012-9-15','勝'),('2012-9-15','負'),('2012-9-15','負'),('2012-9-16','勝'),('2012-9-16','勝'),('2012-9-16','負')
select * from #E
select  dt, SUM(case when shengfu='勝' then 1 else 0 end) as 勝,SUM(case when shengfu='負' then 1 else 0 end) as 負 from #E group by dt

--表中有A B C三列,用SQL語句實現:當A列大於B列時選擇A列不然選擇B列,當B列大於C列時選擇B列不然選擇C列
create table #E1 (A int ,B int,C int)
insert into #E1 values(1,3,5),(6,4,2),(8,7,9)
select * from #E1
select case when A>B then A else B end as AB,case when B>C then B else C end as BC from #E1

table1
月份          部門業績
一月份      01      10
一月份      02      10
一月份      03      5
二月份      02      8
二月份      04      9
三月份      03      8
table2
部門     部門名稱
     國內業務一部
     國內業務二部
     國內業務三部
     國際業務部
table3 (result)
部門部門名稱  一月份      二月份      三月份
 國內業務一部    10        null      null
  國內業務二部   10         8        null
  國內業務三部   null       5        8
  國際業務部   null      null      9
create table #F([month] nvarchar(20), bumen nvarchar(20), yeji int)
insert into #F values('一月份','01',10),('一月份','02',10),('一月份','03',5),('二月份','02',8),('二月份','04',9),('三月份','03',8)
create table #F1(bumen nvarchar(20),bumenmingcheng nvarchar(20))
insert into #F1 values('01','國內業務一部'),('02','國內業務二部'),('03','國內業務三部'),('04','國際業務部')
select * from #F1
select f.bumen ,f1.bumenmingcheng,sum(case when f.[month]='一月份' then f.yeji else null end) as 一月份,
sum(case when f.[month]='二月份' then f.yeji else null end) as 二月份,
sum(case when f.[month]='三月份' then f.yeji else null end) as 三月份 from #F f,#F1 f1 where f.bumen=f1.bumen group by f.bumen,f1.bumenmingcheng

drop table #Str
create table #Str(id int identity(1,1),str11 varchar(20), [type] int )
insert into #Str values('how',1),('are',1),('you',1),('fine',2),('thank',2),('you',2)
select * from #Str
create table #Str1(ss nvarchar(100),id int )
insert into #Str1 select distinct '',([type]) from #Str
select * from #Str1
declare @id1 int,@str1 nvarchar(100)
declare StrCursor cursor for select str11,[type] from #Str
open StrCursor
fetch next from StrCursor into @str1,@id1
while @@FETCH_STATUS=0
begin
 update #Str1 set ss=ss+@str1 whereid=@id1
 fetch next from StrCursor into @str1,@id1

 end
 close StrCursor
 deallocate StrCursor
 select * from #Str1


 --Post
 create Table Post(id int identity(1,1) primary key,title nvarchar(200),content text,CreateDate nvarchar(30))
 --Comments
 create Table Comments(Cid int identity(1,1) primary key,id int,content text,CreateDate nvarchar(30))
insert into Post select '我從遠方趕來','我爲她而狂野,我爲你來看我不顧一切',cast(GETDATE() as nvarchar)
insert into Comments values
(1,'不枉此行呀',CAST(getdate() as nvarchar)),
(1,'這一個不能停留過久的世界',cast(getdate() as nvarchar)),
(1,'無可取代',cast(getdate() as nvarchar))
select * from Comments
create table #Ts (id int,com nvarchar(max))
insert into #Ts select distinct(id),'' from Comments
declare @ii int,@com nvarchar(max)
declare TsCursor cursor for select id ,content from Comments
open TsCursor
fetch next from TsCursor into @ii,@com
while @@FETCH_STATUS=0
begin
update #Ts set com=com+@com whereid=@ii
fetch next from TsCursor into @ii,@com
end
close TsCursor
deallocate TsCursor
相關文章
相關標籤/搜索