sqlserver知識點彙總(這段時間複習和回顧了一下sqlserver的一些知識),供大家參考和學習!
阿新 • • 發佈:2019-01-21
use master
go
/*sqlserver中不區分大小寫*/
--這裡是單行註釋
/*這裡是多行註釋*/
create database test --建立資料庫
drop database test --刪除資料庫
/*以下建立資料庫的語法可以不用記,選中CREATE DATABASE,按F1就可檢視幫助文件,可
以直接拷貝文件中的demo語句,然後稍微修改下即可*/
CREATE DATABASE testDB
ON
( NAME = testDB_dat,
FILENAME = 'D:\test\testDBdat.mdf', --D盤下要有test資料夾
SIZE = 10,
MAXSIZE = 50,
FILEGROWTH = 5 )
LOG ON
( NAME = testDB_log,
FILENAME = 'D:\test\testDBlog.ldf', --D盤下要有test資料夾
SIZE = 5MB,
MAXSIZE = 25MB,
FILEGROWTH = 5MB );
GO
drop database testDB
--檢視當前系統中資料庫資訊
select * from sysdatabases
if exists(select * from sysdatabases)
print '有資料'
else
print '無資料'
if exists(select * from sysdatabases where name = 'testDB')
print 'testDB已存在'
else
print 'testDB不存在'
use master
go
if exists(select * from sysdatabases where name = 'testDB' )--預設只執行後面一行,所以要用begin end
begin
print '資料庫已存在,準備刪除'
drop database testDB
end
go
print '建立資料庫成功'
create database testDB
use testDB
/*
資料完整性=資料的有效性和正確性(完整性=有效,正確)
完整性約束
1.唯一約束(允許一行資料為空)
2.主鍵約束(唯一約束 + 非空約束)
3.預設值約束
4.check約束
5.主外來鍵約束
6.非空約束
一個表在不同的關係中既可以是主表又可以是子表
主外來鍵是一對多關係
*/
create table student(
--欄位名 資料型別 約束 (一般在此只加非空約束)
stuId int not null,
stuName varchar(20) not null,
stuAge int not null,
stuSex bit not null,
stuTel varchar(13) not null,
stuAddress varchar(30)
)
go
--新增主鍵約束
alter table student
add constraint PK_stuId primary key (stuId)
--新增唯一約束
alter table student
add constraint UQ_stuName unique (stuName)
--新增check約束
alter table student
add constraint CK_stuAge check (stuAge >=18 and stuAge <= 35)
--新增預設約束
alter table student
add constraint DF_stuAddress default ('地址不詳') for stuAddress
go
create table exam(
examId int not null,
stuId int not null, --外來鍵
labExam int not null,
writtenAxam int not null
)
go
--新增主鍵約束
alter table exam
add constraint PK_examId primary key (examId)
--新增check約束
alter table exam
add constraint CK_labExam check (labExam between 0 and 100)
--新增非空約束
alter table exam
add constraint NN_labExam check (labExam is not null)
--設定非空(alter table 表名 alter column 列名 該列的型別 NOT NULL)
alter table exam
alter column writtenAxam int not null
go
--新增check約束
alter table exam
add constraint CK_writtenAxam check (writtenAxam >= 0 and writtenAxam <= 100 )
--新增外來鍵約束
alter table exam --修改外來鍵表
add constraint FK_stuId
foreign key(stuId) references student(stuId)
--外來鍵表字段 主鍵表字段
go
--刪除約束(alter table 表名 drop constraint 約束名)
alter table exam
drop constraint FK_stuId
go
/*哪個是外來鍵表,就給它新增外來鍵約束
給表新增主外來鍵約束的時候遵循3個一致
1.外來鍵表外來鍵與主鍵表主鍵資料型別一致(語法規範)
2.長度一致(語法規範)
3.名稱一致(一般是專案規範,名稱最好是一致)
*/
use testDB
/*
啟動停止服務的3中方式
1.控制面板-->管理工具-->服務
2.Sql Server 配置管理器
3.使用命令啟動和停止服務 net start mssqlserver (這是啟動服務),net stop mssqlserver(這是停止服務)
*/
/*
開啟sqlserver資料庫的操作介面也可以使用命令:如下
win +R 輸入cmd
然後輸入ssms 開啟2008及以上版本的sqlserver管理器
然後輸入sqlwb 開啟2005版本的sqlserver管理器
也可以win +R 後,直接輸入ssms或者sqlwb (ssms是2008及以上版本,sqlwb是2005版本)
*/
/*
sqlserver中有些命令,如下:
sqlcmd 類似於sqlserver的控制檯,可以刪除表,查詢表等等操作
osql 使用外部檔案執行sql,自己可以寫一個bat(批處理)檔案來執行sql,以下是教你怎
麼寫批處理檔案
新建一個批處理檔案,以bat字尾結尾,檔名可以自己取,我這裡就叫做create.bat,在該文
件中編寫以下內容
net start mssqlserver
@echo off
echo ==============正在初始化資料庫,請稍後.....==============================
osql -E -i student.sql
echo ==============資料庫初始化完畢==============================
*/
go
/*
sysobjects表示物件資訊表,準確來說本質上是一個檢視(該檢視存
放的是表,檢視,索引,約束等等)每個資料庫都有一個此表
*/
select * from sysobjects
go
--檢視exam表在資料庫中是否存在
if exists(select * from sysobjects where name = 'exam')--預設只執行後面一行,所以要用begin end
/*
begin end 類似於java中的{}花括號,begin類似於java中的開
始花括號{,end類似於java中的結束花括號}
*/
begin
print '資料庫表已存在,準備刪除'
--刪除exam表
drop table exam
end
go
create table exam(
examId int not null,
stuId int not null, --外來鍵
labExam int not null,
writtenAxam int not null
)
print '建立表成功'
go
--新增主鍵約束
alter table exam
add constraint PK_examId primary key (examId)
--新增check約束
alter table exam
add constraint CK_labExam check (labExam between 0 and 100)
--新增非空約束
alter table exam
add constraint NN_labExam check (labExam is not null)
--設定非空(alter table 表名 alter column 列名 該列的型別 NOT NULL)
alter table exam
alter column writtenAxam int not null
go
--新增check約束
alter table exam
add constraint CK_writtenAxam check (writtenAxam >= 0 and writtenAxam <= 100 )
--新增外來鍵約束
alter table exam --修改外來鍵表
add constraint FK_stuId
foreign key(stuId) references student(stuId)
--外來鍵表字段 主鍵表字段
go
/*
標識列必須是int型別的
標識列不可以編輯
標識列先自增,再驗證,最後插入資料
*/
drop table employee
create table employee(
empId int identity(6,2) primary key, --如果種子和自增量都是1的話,可以省略不寫
empName varchar(30),
empAge int,
empAddress varchar(30)
--[name] varchar(20)
/*
欄位名和表名起名字的時候最好不要起有可能是關鍵字的名字,如
果怕是關鍵字或者你非要起這種敏感的名字最好是用[]括起來
*/
)
select * from employee
/*into關鍵字可以省略,但是最好不要省略,為
了規範,每行寫5個欄位,這樣比較好對齊和匹配
*/
insert into employee
(empName,empAge,empAddress)
values
('李四',21,'北門')
select * from student
insert into student
(stuId,stuName,stuAge,stuSex,stuTel,stuAddress)
values
(9,'王五',28,0,'1378888888',default)
/*
select * into 新表 from 舊錶 (相當於把表備份了,只備份
表結構與資料,約束消失)
*/
select * into student2 from student
select * from student2
----select 列名 into 新表 from 舊錶 (相當於把表備份了,只需要其中幾列)
select stuName,stuSex,stuAddress into student3 from student
select * from student3
----select 列名 as 別名 into 新表 from 舊錶 (相當於把表備份了,只需要其中幾列,可用as加別名)
select stuName as '姓名',stuSex as 性別,stuAddress 地址 into student4 from student
select * from student4
create table myUsers(
userName varchar(20),
userAddress varchar(30)
)
select * from myUsers
/*
insert into 表名 (列名1, 列名2) select
列名1, 列名2 from 表名
注意3點:
1.列的個數一致
2.對應列的資料型別一致
3.資料型別的長度一致(目標表的長度大於等於源表的長度)
*/
insert into myUsers
(userName, userAddress)
select
stuName, stuAddress
from
student
where
stuAddress = '地址不詳'
/*
insert into 表名 (列名1, 列名2)
select 列名1, 列名2
union
select 列名3, 列名4
注意:
1.不支援default關鍵字
2.當兩行資料相同時理解為一行(即union關
鍵字會自動過濾掉重複行,所以只插入一行資料)
3.使用union all關鍵字才可以插入多行重
復的記錄,所以是插入多行資料
*/
/*
使用union關鍵字的話,union關鍵字會自動過
濾掉重複行,所以只插入一行資料
*/
insert into myUsers
(userName, userAddress)
select '二狗子', '深圳' union
select '二狗子', '深圳' union
select '二狗子', '深圳'
/*
使用union all關鍵字才可以插
入多行重複的記錄,所以是插入多行資料
*/
insert into myUsers
(userName, userAddress)
select '二狗子', '江西省贛州市於都縣' union all
select '二狗子', '江西省贛州市於都縣' union all
select '二狗子', '江西省贛州市於都縣'
select * from myUsers
insert into myUsers
(userName, userAddress)
select '令狐沖', '華山' union all
select '楊過', '山谷' union all
select '張無忌', '光明頂' union all
select '韋小寶', 'default'
/*
模糊查詢,使用萬用字元
_下劃線代表任意一個字元,該符號只能匹配一個字元
%百分號表示0個或多個字元,即任意長度的字串
[]表示範圍
^[^]表示不屬於範圍,即範圍取反
*/
select * from myUsers where userName like '%[1-2]%'
select * from myUsers where userName not like '%[1-2]%'
select * from myUsers where userAddress like '%[^1-2]'
select * from myUsers where userName like '%[^1-2]%'
select * from myUsers where userName like '%[劉_久_]%'
select * from myUsers
/*
更新操作
update 表名 set 欄位名1 = 值
update 表名 set 欄位名1 = 值,欄位名2 = 值
update 表名 set 欄位名1 = 值,欄位名2 = 值 where 條件
*/
update myUsers set userName = '趙六哥哥' where userName = '趙1六'
update myUsers set userAddress = userAddress + '人民', userName = userName + '測試'
update myUsers set userAddress = subString(userAddress, 0, 100),
userName = userName + '測試'
where userName like '%二狗子%'
/*
truncate table 表名(刪除表中資料,和delete table 表名 是一樣的,效率
要比delete高,即刪除速度比delete快)
*/
truncate table student4
SELECT * FROM dbo.student4
/*
起別名:2種方式
可以使用as關鍵字起別名
也可以用=來起別名
*/
SELECT *,stuAddress AS '地址' FROM student
SELECT *,stuAddress AS 地址 FROM student
SELECT stu.*, '地址' = stu.stuAddress FROM student AS stu
SELECT stu.*,'地址' = stu.stuName + '籍貫在' + stu.stuAddress FROM student AS stu
UPDATE student SET stuAddress = '江西省贛州市' WHERE stuId = '9'
--新增列
ALTER TABLE student ADD hobby VARCHAR(30) NULL
ALTER TABLE student ADD schoolName VARCHAR(30) NULL
ALTER TABLE student ADD groupId VARCHAR(5)
--修改列
ALTER TABLE student ALTER COLUMN hobby VARCHAR(30) NULL
ALTER TABLE student ALTER COLUMN schoolName VARCHAR(25) NOT NULL
--
UPDATE student SET schoolName = '城關小學' WHERE stuId = '5'
UPDATE student SET schoolName = '' WHERE stuId = '5'
UPDATE student SET schoolName = NULL WHERE stuId = '1'
UPDATE student SET schoolName = 'null' WHERE stuId = '1'
--
SELECT * FROM student WHERE schoolName is NULL
SELECT * FROM student WHERE schoolName is NOT NULL
--常量列
SELECT *, 學校名稱 = schoolName, '城關小學' AS 小學名稱 FROM student
SELECT *, 學校名稱 = schoolName, '實驗小學' AS '校名' FROM student
/*
以下是一個sql的完整寫法
SELECT
列名1 AS 別名,
列名2 AS 別名
FROM
表名
WHERE
條件
GROUP BY
分組
HAVING
分組後的篩選
ORDER BY desc / asc
排序
*/
--限制固定行數
SELECT TOP 5 * FROM student
--返回百分之多少行
SELECT TOP 5 PERCENT * FROM student
/*
升降序
order by關鍵字可以用來排序
預設是asc升序
降序是desc
*/
--降序
SELECT * FROM student
ORDER BY
stuAge DESC
--升序(預設就是升序,所以ASC可以省略不寫)
SELECT TOP 3 * FROM student
ORDER BY
stuAge ASC
--
SELECT '我家在江西省贛州市於都縣'
SELECT 'hello world!' AS '列名'
SELECT 'ok' AS 列名
/*
字串函式
*/
/*
CHARINDEX函式,下標從1開始,如果沒找
到的話返回0,而在java中下標從0開始,沒找到的話返回-1
*/
SELECT CHARINDEX('on', 'my name is jiongjiong', 15)
--LEN函式
SELECT LEN('jack')
--LEN函式是求長度
SELECT stuName, stuAddress, LEN(stuAddress) AS '長度' FROM student
--RTRIM函式和LTRIM函式是去掉左右兩邊的空格
SELECT * FROM student WHERE RTRIM(LTRIM(stuAddress)) = '江西省贛州市'
SELECT * FROM student WHERE LTRIM(stuAddress) = '江西省贛州市'
UPDATE student SET stuAddress = ' 江西省 贛州市 ' WHERE stuId =19
SELECT * FROM student WHERE REPLACE(RTRIM(LTRIM(stuAddress)),' ','') = '江西省贛州市'
SELECT RIGHT('你好,世界', 3)
SELECT LEFT('你好,世界', 3)
SELECT REPLACE('如果你想哭的時候就倒立吧', '哭的', 'cry')
/*
日期函式
*/
SELECT GETDATE()
SELECT DATEADD(DD,10000,'1989-08-27')
/*
DATEADD()比較有用,比如求一個商品的保質期,從今天開
始計算,保質期是68天,那麼用該函式就很有用了
*/
SELECT DATEADD(DD,100, GETDATE())
SELECT DATENAME(DW, GETDATE())
SELECT DATENAME(WK, GETDATE())
SELECT DATEPART(DAY,GETDATE())
--
SELECT CURRENT_USER
SELECT SYSTEM_USER
SELECT HOST_NAME()
--
--SELECT stuAge + stuName FROM student --這樣會出錯
--使用CONVERT()函式,做型別轉換
SELECT CONVERT(VARCHAR(4),stuAge) + stuName FROM student
SELECT * FROM student
ORDER BY stuId ASC,
stuAge ASC
SELECT * FROM student
ORDER BY stuId,stuAge ASC
SELECT * FROM student
ORDER BY
stuAge asc,
stuId DESC
/*
聚合函式
*/
SELECT COUNT(*),
AVG(stuAge),
SUM(stuAge) / COUNT(stuAge),
SUM(stuAge),
MAX(stuAge),
MIN(stuAge)
FROM
student
SELECT * FROM student
/*
需要注意的
NUll不計算在內,如下示例
*/
SELECT COUNT(schoolName),COUNT(hobby), COUNT(*) FROM student
/*
分組和聚合函式同時使用,看下面示例
要顯示其他列,必須使用那個列進行分組GROUP BY
*/
SELECT groupId, stuAddress, AVG(stuAge)
FROM
student
GROUP BY
groupId,stuAddress
--
SELECT * FROM student
--
SELECT groupId, AVG(stuAge)
FROM
student
GROUP BY
groupId
HAVING AVG(stuAge) >=25
/*
where 和 having 的區別
where 對錶中的原始資料進行的篩選
having 對分組後使用聚合函式計算後的資料進行的篩選,與GROUP BY結合使用
*/
SELECT groupId, AVG(stuAge)
FROM
student
WHERE
stuAge > 20
GROUP BY
groupId
HAVING
AVG(stuAge) >=25
/*
in可以用or代替
*/
--使用or關鍵字
SELECT * FROM student WHERE stuAge = 18 OR stuAge = 27 OR stuAge = 26
--使用in關鍵字
SELECT * FROM student WHERE stuAge IN (18, 27, 26)
--使用BETWEEN AND 關鍵字
SELECT * FROM student WHERE stuAge BETWEEN 18 AND 27
--
SELECT * FROM student WHERE stuAge >= 18 AND stuAge <= 27
/*
如果要把某列顯示在使用聚合函式的列
中,那麼必須對他進行GROUP BY分組
*/
SELECT * FROM student WHERE NOT stuAge = 18
SELECT * FROM student WHERE stuAge <> 18
SELECT * FROM student WHERE stuAge != 18
SELECT * FROM student WHERE NOT (stuAge = 18)
SELECT * FROM student WHERE (NOT stuAge = 18)
SELECT * FROM student WHERE (stuAge <> 18)
SELECT * FROM student WHERE (stuAge != 18)
/*
聯接查詢 :當要同時顯示多個表資料的情況下
*/
/*
外聯接
左外聯接
右外聯接
*/
/*
左外聯接:改變表出現的順序有影響,因
為前面出現的是左表
左外聯接
第1種說法
第1步顯示內聯接所有資料
第2步看左表中是否有沒匹配的,有的話原樣列出,右表部分用NULL補齊
第2種說法
第1步列出左表所有資料
第2步右表與之匹配的顯示,其它用NULL補齊
最好是用第一種說法,第二種說法容易被迷惑,因為左表中的同一條資料可能出現多次
*/
SELECT
*
FROM
student AS stu --左表
LEFT JOIN
exam exa --右表 可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
SELECT
*
FROM
student AS stu --左表
LEFT JOIN
exam exa --右表 可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
/*
右外聯接
第1種說法
第1步顯示內聯接所有資料
第2步看右表中是否有沒匹配的,有的話原樣列出,左表部分用NULL補齊
*/
SELECT
*
FROM
student AS stu --左表
LEFT JOIN
exam exa --右表 可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
--可以調換下順序
SELECT
*
FROM
exam exa --左表
RIGHT JOIN
student AS stu--右表 可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
/*
內聯接 as可以省略,on後面的小括號()也可以省略,但是不建議省略小括號()
內聯接 顯示外來鍵表所有資料,並顯示主鍵表與之匹配的資料
內聯接:改變表出現順序沒有影響
*/
SELECT
stu.stuAddress,stu.stuName,exa.labExam, exa.writtenAxam, *
FROM
student AS stu
INNER JOIN
exam exa --可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
/*
內聯接的另一種寫法,這種寫法不推薦使用,2個表沒啥問題,3個表或3個表以上就容
易出錯,沒出錯算你運氣好
*/
SELECT *
FROM
student AS stu ,exam AS exa
WHERE
stu.stuId = exa.stuId
/*
完全外聯接 = 左外聯接 + 右外聯接
*/
SELECT
*
FROM
student AS stu
FULL JOIN
exam exa --可以省略as關鍵字
ON
(stu.stuId = exa.stuId)
/*
交叉聯接(笛卡爾積)
*/
SELECT
student.*, exam.*
FROM
exam,student
--
SELECT
student.*, exam.*
FROM
student
CROSS JOIN
exam
CROSS JOIN
student2
/*
T-SQL定義變數
宣告變數 DECLARE 變數名 資料型別
定義變數使用@符號
給變數賦值使用set關鍵字
*/
DECLARE @age INT
SET @age = 10
PRINT @age
--SELECT @age
PRINT '@age = ' + CONVERT(VARCHAR(5), @age)
SELECT @age = stuAge FROM student WHERE stuId = 10 --必須確保只有一條記錄
PRINT @age
PRINT '@age = ' + CONVERT(VARCHAR(5), @age)
--
DECLARE @stuAge INT
SELECT @stuAge = stuAge FROM student WHERE stuName = '李四'
SELECT * FROM student WHERE stuAge > @stuAge
/*
子查詢(一個查詢的結果作為另外一個查詢的條件
一般子查詢要保證返回結果只有一個(即一行,一列)in子查詢返回一列多行
子查詢從內往外讀(寫)
當要顯示多個表資料時使用聯結,只顯示一個表資料時使用子查詢
)
*/
SELECT * FROM student WHERE
stuAge > (SELECT stuAge FROM student WHERE stuName = '李四')
--
SELECT
*
FROM
student stu
INNER JOIN
exam exa
ON
(stu.stuId = exa.stuId)
WHERE
exa.writtenAxam > 95
--
SELECT
stu.*, exa.*
FROM
student AS stu, exam exa
WHERE
stu.stuId IN (SELECT stuId FROM exam WHERE exa.writtenAxam > 95)
AND
stu.stuId = exa.stuId
--
SELECT
*
FROM
student
WHERE
stuId IN (SELECT stuId FROM exam WHERE writtenAxam > 95)
--
SELECT
*
FROM
student
WHERE
stuId NOT IN (SELECT stuId FROM exam WHERE writtenAxam > 95)
--
IF EXISTS(SELECT * FROM student)
PRINT '有資料'
ELSE
PRINT '無資料'
--
IF EXISTS(SELECT * FROM student WHERE stuId = '199')
PRINT '有資料'
ELSE
PRINT '無資料'
--取反NOT EXISTS
IF NOT EXISTS(SELECT * FROM student WHERE stuId = '199')
PRINT '有資料'
ELSE
PRINT '無資料'
--第一種寫法
IF EXISTS(SELECT * FROM exam WHERE writtenAxam >= 80)
UPDATE exam SET writtenAxam = writtenAxam + 2
ELSE
UPDATE exam SET writtenAxam = writtenAxam + 5
--第二種寫法
DECLARE @score INT
SET @score = 5
IF EXISTS(SELECT * FROM exam WHERE writtenAxam >= 80)
SET @score = 2
UPDATE exam SET writtenAxam = writtenAxam + @score
--取常量列的2種方式如下
SELECT *, '是否通過' = '是' FROM student
SELECT *, 是否通過 = '是' FROM student
SELECT *, '是' AS '是否通過' FROM student
SELECT *, '是' AS 是否通過 FROM student
SELECT *, '是' '是否通過' FROM student --as關鍵字也可以省略
--
SELECT
* ,
'等級' =
CASE
WHEN labExam >= 90 THEN '優秀'
WHEN labExam >= 80 AND labExam <= 90 THEN '及格'
ELSE '不及格'
END
FROM exam
--
SELECT *, '計算結果' = 2 / 5 FROM student
SELECT *, '計算結果' = (2 * 1.0) / (5 * 1.0) FROM student
/*
執行順序
1.where
2.GROUP BY
3.having
4.ORDER BY
*/
/*
where和having都是條件篩選,不過它們有區別
where是對錶裡原始的資料進行的篩選,一般最先執行
having是對錶中資料分組使用聚合函式計算之後(經過加工)
的資料進行的篩選,having在where之後,having與GROUP BY配
合使用
*/
SELECT TOP 3 * FROM student
SELECT TOP 60 PERCENT * FROM student
SELECT * FROM student
/*
DISTINCT關鍵字是去掉重複值
*/
SELECT DISTINCT stuAddress AS '地址' FROM student
SELECT DISTINCT stuAddress '地址',stuAge AS 年齡 FROM student --相當於這2個欄位都要滿足重複值才會去重
select stuAddress,COUNT(distinct stuAddress) from student group by stuAddress
/*
左外聯接
1.首先列出內聯接資料
2.看左表是否還有沒匹配的,有的話原樣列出,右表部分用NULL補齊
總結:左外聯接要顯示左表的所有資料
*/
/*
當我們在一個結果集中顯示多張表資料的情況下,只能使用聯
結(子查詢做不到,因為子查詢只能顯示一張表的資料)
*/
/*
T-SQL : sqlserver特有
PL/SQL :Oracle特有
*/
/*
交叉聯接(基本不用)
一般不使用,返回資料的行數=左錶行數 * 右表資料行數
*/
/*
複習一些知識
CONVERT()函式,CAST()函式都是資料型別轉換函式
CONVERT(資料型別(長度), 變數或列名)
CAST(變數或列名 AS 資料型別(長度))
*/
/*
變數知識複習
變數:
區域性變數:
使用者自定義的變數,變數名以@開頭,可以讀寫
語法定義:DECLARE @變數名 資料型別(長度)
賦值有2中方式:第一種 set @變數名 = 值
第二種 以查詢結果為值
全域性變數:系統提供,以@@開頭,只讀的,也就是說由系
統賦值,我們取值
全域性變數由系統定義和維護,我們只能讀取,不能修改全
局變數的值
*/
DECLARE @myName VARCHAR(20)
SET @myName = '令狐沖'
PRINT @myName
DECLARE @myAge INT
SET @myAge = 19
SELECT @myAge AS '年齡'
--PRINT '年齡' + @myAge
--這裡使用CONVERT()函式
PRINT 'my年齡' + CONVERT(VARCHAR(3), @myAge)
--也可以使用CAST()函式
PRINT '我的年齡' + CAST(@myAge AS VARCHAR(3))
--
SELECT stuName, * FROM student
SELECT stuName FROM student
--
DECLARE @stuName VARCHAR(20)
SET @stuName = 'jack'
SELECT @stuName AS '英文名'
SET @stuName = 'tom'
PRINT @stuName
PRINT '**************'
SELECT @stuName = stuName FROM student WHERE stuId = '33'
SELECT @stuName AS '英文名'
/*
以下看起來像是聲明瞭全部變數,實際上還是區域性變數,只不過變數名叫作@testName這個名字了
*/
DECLARE @@testName VARCHAR(20)
SET @@testName = '張無忌'
PRINT @@testName
/*
SELECT在網格視窗顯示結果
PRINT在訊息視窗顯示結果
*/
/*
全域性變數
*/
--最後一個T-SQL錯誤的錯誤號
SELECT @@ERROR
--最後一次插入的標識值
SELECT @@IDENTITY
--當前使用的語言的名稱
SELECT @@LANGUAGE
--sqlserver的版本資訊
SELECT @@VERSION
--可以建立的同時連線的最大數目
SELECT @@MAX_CONNECTIONS
--受上一個sql語句影響的行數
SELECT @@ROWCOUNT
--本地伺服器的名稱
SELECT @@SERVERNAME
--服務名稱
SELECT @@SERVICENAME
--當前連線開啟的事務數
SELECT @@TRANCOUNT
/*
sql中的流程控制
把{}改成BEGIN AND
*/
--
SELECT * FROM exam
--
SELECT *, '等級' =
CASE
WHEN labExam < 60 THEN 'E'
WHEN labExam > 60 AND labExam <= 69 THEN 'D'
WHEN labExam BETWEEN 70 AND 79 THEN 'C'
WHEN labExam BETWEEN 80 AND 89 THEN 'B'
ELSE 'A'
END
FROM exam
/*
回顧下以前的知識
流程控制,分支判斷
多重判斷:巢狀if,階梯式if(可以是區間範圍,可以是定值),switch(只能是某個定值)
*/
/*
WHILE迴圈
*/
DECLARE @testIndex int
SET @testIndex = 0
WHILE(@testIndex < 10)
BEGIN
PRINT '第' + CAST((@testIndex + 1 ) AS VARCHAR(3))+ '次列印hello'
SET @testIndex = @testIndex + 1
END
/*
DDL 資料定義語言,比如建庫,建表,儲存過程,檢視後面加go(批處理)
*/
/*
檢視的優點或用途:
1.篩選表中的行
2.防止未經許可的使用者訪問敏感資料
3.降低資料庫的複雜程度(或者說降低sql的複雜度)
4.將多個物理資料庫抽象為一個邏輯資料庫
檢視特點:
檢視是為查詢服務的,不能通過檢視新增、修改、刪除資料,同一張
表可以根據需求建立不同的檢視
*/
/*
將多個物理資料庫抽象為一個邏輯資料庫,以下示例
CREATE VIEW 檢視名
AS
SELECT 表A.列1,表A.列2,表B.列1,表B.列2 FROM 資料庫名1.角色名.表名1 AS 表A
INNER JOIN 資料庫名2.角色名.表名2 AS 表B
ON (表A.主鍵 = 表B.外來鍵)
*/
--以下是資料庫名.角色名.表名
SELECT * FROM testDB.dbo.exam
SELECT * FROM testDB.dbo.student
go
--
CREATE VIEW test1 AS SELECT * FROM student WHERE stuSex = 0
GO
SELECT * FROM test1
go
alter VIEW test1 AS SELECT *,stuId AS 'id', stuName AS 'myName' FROM student WHERE stuSex = 0
GO
--更新檢視中的資料,對檢視中的資料的增加,刪除,修改時也會影響原表
UPDATE test1 SET stuName = '風清揚老前輩' WHERE id = 5
IF('a' = 'a')
PRINT '相等'
ELSE
PRINT '不相等'
IF('a' = 'A')
PRINT '相等'
ELSE
PRINT '不相等'
IF(1 = 1)
PRINT '相等'
ELSE
PRINT '不相等'
/*
事務知識複習:
事務什麼時候用:同時執行多個insert,update,delete,sql語句時使用
事務是作為單個邏輯工作單元執行的一系列操作,這些操作作為一個整體一起向系
統提交,要麼都執行,要麼都不執行,事務是一個不可分割的工作邏輯單元
事務必須具備一下4個屬性,簡稱ACID
1.原子性A
2.一致性C
3.隔離性I
4.永久性D
BEGIN TRANSACTION 開始事務
COMMIT TRANSACTION 提交事務
ROLLBACK TRANSACTION 回滾事務
事務分類
1.顯示事務:用BEGIN TRANSACTION 關鍵字明確指定事務的開始和明
確指定提交事務(COMMIT TRANSACTION )和明確指定回滾事務(ROLLBACK TRANSACTION)
2.隱式事務:不需要指定事務的開始即不需要使用BEGIN TRANSACTION關鍵字開始,但
是需要手工提交事務和手工回滾事務,如果要用隱式事務的話,需要設
置一個開關(即SET IMPLICIT_TRANSACTIONS ON)。你也可以理解為顯示事務和隱式事務沒什麼區
別,不同的地方就是,顯示需要用BEGIN TRANSACTION 關鍵字,隱式不需要用BEGIN TRANSACTION 關鍵字。
因為它已經是隱式事務了,就沒有必要每次都加上BEGIN TRANSACTION 了,但是我們必須在後面加
上提交事務(COMMIT TRANSACTION )和回滾事務(ROLLBACK TRANSACTION),必須手工去提交事務或手工回滾事務了
3.自動提交事務:這是sqlserver的預設模式,它將每條單獨的T-SQL語句視為一個事務
*/
/*
開啟隱式事務:SET IMPLICIT_TRANSACTIONS ON
關閉隱式事務:SET IMPLICIT_TRANSACTIONS OFF
*/
/*
還有一個問題:
我們暫時只能在一條conn上做事務,如果要在多條conn上做事務,一般借
助框架或容器,使用JTA(java TRANSACTION API)即java事務介面
*/
SELECT * FROM student
--
SELECT * FROM sys.sysindexes
/*
在sysobjects系統表中儲存著資料庫的所有物件,每個物件都有一個唯一的id號進行標識.
object_id就是根據物件名稱返回該物件的id.反之,object_name是根據物件id返回物件名稱.
select object_id(物件名)等同於:
select id from sysobjects where name=物件名
注: 如果引數是一個臨時表名,則必須指定所屬資料庫.你舉出的OBJECT_ID('Tempdb..##flowcount') 就屬於這
種情況.說明這個臨時表是資料庫Tempdb的.
select object_name(id號)等同於:
select name from sysobjects where id=id號
*/
--
SELECT * FROM sys.sysindexes WHERE id=object_id('student')
--
SELECT * FROM sysobjects WHERE id = object_id('student')
--
SELECT * FROM sysobjects WHERE name = OBJECT_NAME('2105058535')
/*
索引知識(可參考該網址 http://www.cnblogs.com/soundcode/p/4458974.html )
建立索引語法
CREATE [索引型別] INDEX 索引名稱
ON 表名(列名)
WITH FILLFACTOR = 填充因子值0~100
GO
索引分類
1.唯一索引(UNIQUE):不允許兩行具有相同的索引值(建立了唯一約束,系統將自動建立唯一索引)
2.主鍵索引:主鍵索引要求主鍵中的每個值是唯一的,(建立主鍵自動建立主鍵索引)
3.聚集索引(CLUSTERED):表中各行的物理順序與鍵值的邏輯(索引)順序相同,表中只能包含一個聚集索引,主鍵列預設為聚集索引
4.非聚集索引(NONCLUSTERED):表中各行的物理順序與鍵值的邏輯(索引)順序不匹配,表中可以有249個非聚集索引
*/
--檢測是否已經存在名字為IX_stuName的索引
IF EXISTS(SELECT * FROM sysindexes WHERE name = 'IX_stuName')--檢測名字為IX_stuName的索引是否存在,索引存放在sysindexes中
DROP INDEX student.IX_stuName --如果存在則刪除
/*
為姓名列建立非聚集索引,填充因子為%(百分比)
*/
--建立索引
CREATE NONCLUSTERED INDEX IX_stuName --建立一個非聚集索引
ON student(stuName) --為student表的stuName欄位建立索引
WITH FILLFACTOR = 60 -- 填充因子為60%
GO
STATISTICS_NORECOMPUTE
/*
指定按照某個索引進行查詢如下
SELECT 欄位1,欄位2 FROM 表名 WITH (INDEX = 索引名) WHERE 查詢條件
SELECT 欄位1,欄位2 FROM 表名 WITH (INDEX(索引名)) WHERE 查詢條件
指定按'IX_stuName'索引查詢
*/
--指定按索引IX_stuName進行查詢
SELECT * FROM student WITH(INDEX(IX_stuName))
WHERE stuName = '令狐沖'
--指定按索引IX_stuName進行查詢
SELECT * FROM student WITH(INDEX = IX_stuName)
WHERE stuName = '令狐沖'
--
SELECT * FROM student
GO
/*
儲存過程知識複習
儲存過程在業界以前常常作為衡量程式設計師水平的標準,大蝦們喜歡吹噓自己寫過幾千行的儲存過程,但是現在作為
java程式設計師,此功能被弱化,因為java程式講究的是與具體的資料庫相分離,但是作為.net程式設計師,依然要掌握好
此知識
PROCEDURE 也可以簡寫成 proc
建立儲存過程語法
CREATE PROCEDURE 儲存過程名
引數列表
--輸入引數 按值傳遞 (引數也可以給預設值)
--輸出引數 按引用傳遞
@引數名 資料型別 output --有output關鍵字就是輸出引數
@引數名 資料型別 --沒有output關鍵字就是輸入引數
@引數名 資料型別 [output] --如果是輸出引數的話,在建立儲存過程的時候需要加output關鍵字進行宣告,輸入引數不需要加output關鍵字
as
T-SQL程式設計,定義變數,流程控制,迴圈等等
GO
呼叫儲存過程
execute 儲存過程名稱,execute 可以簡寫成exec
呼叫儲存過程的時候,如果在建立儲存過程的時候有輸出引數,那麼在呼叫的時候也需要使用output關鍵字
*/
--
/*
建立無引數的儲存過程
*/
--
CREATE PROCEDURE test2
AS
SELECT * FROM student
GO
--呼叫儲存過程
EXECUTE test2
GO
/*
建立帶輸入引數的儲存過程
*/
CREATE PROCEDURE test3
@age INT,
@myScore INT
AS
PRINT '傳進來的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '傳進來的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
SET @age = @age + 10
SET @myScore = @myScore + 5
PRINT '修改後的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '修改後的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
GO
/*
呼叫儲存過程
*/
--第一種方式呼叫(建議使用這種方式呼叫)
EXECUTE test3 @age = 6,@myScore = 8
--第二種方式呼叫(不建議用這種方式呼叫)
EXEC test3 6,8
--
DECLARE @a INT --變數名字也可以叫@age,但是為了和儲存過程中的引數名區分,最好不要取和儲存過程中的引數名一樣的名字
DECLARE @b INT --變數名字也可以叫@myScore,但是為了和儲存過程中的引數名區分,最好不要取和儲存過程中的引數名一樣的名字
SET @a = 6
SET @b = 8
--EXEC test3 @a,@b
PRINT '-----------------我是憂傷的分割線-----------------'
EXEC test3 @age = @a,@myScore = @b
PRINT '----------呼叫完test3儲存過程之後-------------------'
PRINT @a
PRINT @b
GO
/*
測試儲存過程的按值和按引用傳遞
呼叫之後,可以看出,輸入引數是按值傳遞的,因為呼叫完之後,值沒有改變
呼叫之後,可以看出,輸出引數是按引用傳遞的,因為呼叫完之後,值改變了
*/
/*
建立帶輸入引數,輸出引數的儲存過程
呼叫之後,可以看出,輸入引數是按值傳遞的,因為呼叫完之後,值沒有改變
呼叫之後,可以看出,輸出引數是按引用傳遞的,因為呼叫完之後,值改變了
*/
ALTER PROCEDURE test4
@age INT, --輸入引數按值傳遞
@myScore INT OUTPUT --輸出引數按引用傳遞
--輸入引數 按值傳遞 (引數也可以給預設值)
--輸出引數 按引用傳遞
AS
PRINT '傳進來的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '傳進來的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
SET @age = @age + 10
SET @myScore = @myScore + 5
PRINT '修改後的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '修改後的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
GO
--
DECLARE @userAge INT
DECLARE @userScore INT
SET @userAge = 5
--SET @userScore = 13
EXECUTE test4 @age = @userAge,@myScore = @userScore OUTPUT
PRINT @userAge
PRINT @userScore
--
PRINT '-----------------我是憂傷的分割線-----------------'
EXECUTE test4 @userAge,@userScore OUTPUT
PRINT '-----------------我是憂傷的分割線-----------------'
EXECUTE test4 @userAge,@myScore = @userScore OUTPUT
PRINT '-----------------我是憂傷的分割線-----------------'
/*
呼叫儲存過程的時候需要注意的點
注意點:1.最好使用這種方式 EXECUTE 儲存過程名 @輸入引數名稱1 = 值1,@輸出引數名稱2 = 值2 output
2.也可以這樣呼叫儲存過程 EXECUTE 儲存過程名 值1,值2 output
3.也可以這樣呼叫儲存過程 EXECUTE 儲存過程名 值1,@輸出引數名稱2 = 值2 output
4.但是不可以這樣呼叫儲存過程 EXECUTE 儲存過程名 @輸入引數名稱1 = 值1, 值2 output
5.如果呼叫儲存過程的時候有多個引數的話,如果第一個引數你使用@輸入引數名稱1 = 值1 這樣的形式的話,後面的所
有引數都必須按照@引數名稱 = 值這樣的形式傳遞
6.所以呼叫儲存過程要麼就這樣呼叫(EXECUTE 儲存過程名 @輸入引數名稱1 = 值1,@輸出引數名稱2 = 值2 output ),要麼就這
樣呼叫(EXECUTE 儲存過程名 值1,值2 output),這2種呼叫方式比較一致和規範,但是還是建
議使用(EXECUTE 儲存過程名 @輸入引數名稱1 = 值1,@輸出引數名稱2 = 值2 output )這樣的方式呼叫,這種方式比
較好,引數名1=值1,引數名2=值2看起來比較清晰,一一對應,不容易把引數傳錯。
*/
--EXECUTE test4 @age = @userAge,@userScore OUTPUT --不能這樣呼叫,語法不允許
PRINT '-------------------呼叫完test4儲存過程之後-------------------'
PRINT @userAge
PRINT @userScore
/*
帶預設值的儲存過程
*/
CREATE PROCEDURE test5
@age INT = 20, --輸入引數按值傳遞,有預設值
@myScore INT OUTPUT --輸出引數按引用傳遞
--輸入引數 按值傳遞 (引數也可以給預設值)
--輸出引數 按引用傳遞
AS
PRINT '傳進來的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '傳進來的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
SET @age = @age + 10
SET @myScore = @myScore + 5
PRINT '修改後的引數age = ' + CONVERT(VARCHAR(4), @age)
PRINT '修改後的引數myScore = ' + CAST(@myScore AS VARCHAR(4))
GO
--
DECLARE @userAge INT
DECLARE @userScore INT
SET @userAge = 5
SET @userScore = 13
--
EXECUTE test5 @myScore = @userScore OUTPUT
PRINT @userAge
PRINT @userScore
PRINT '-----------------我是憂傷的分割線-----------------'
EXECUTE test5 @age = @userAge,@myScore = @userScore OUTPUT
PRINT '-------------------呼叫完test5儲存過程之後-------------------'
PRINT @userAge
PRINT @userScore
--銀行賬戶資訊表
CREATE TABLE bank(
cid INT IDENTITY PRIMARY KEY,
customerName VARCHAR(20), --顧客姓名
currentMoney MONEY --當前餘額
)
GO
SELECT * FROM bank
--新增約束
alter TABLE bank
ADD CONSTRAINT CK_currentMoney
CHECK(currentMoney >= 1)
GO
--銀行賬戶交易資訊表
CREATE TABLE traninfo(
tid INT IDENTITY PRIMARY KEY,
cid INT NOT NULL,
cdate DATETIME NOT NULL,
transType VARCHAR(20),
transMoney MONEY NOT NULL
)
SELECT * FROM traninfo
GO
--在bank表上建立新增觸發器
ALTER TRIGGER banktrigger1
ON bank
FOR INSERT
as
PRINT '新增觸發器觸發了,看看新增的資料'
SELECT * FROM inserted
GO
CREATE TRIGGER banktrigger2
ON bank
FOR UPDATE
AS
SELECT * FROM deleted
PRINT '修改觸發器觸發了,看看修改的資料'
SELECT * FROM inserted
GO
UPDATE bank SET currentMoney = currentMoney + 150 WHERE cid = 2
INSERT INTO bank(customerName,currentMoney) VALUES ('卓八',700.56)
SELECT * FROM bank
INSERT INTO bank(customerName,currentMoney) VALUES ('張三',1200.55)
INSERT INTO bank(customerName,currentMoney) VALUES ('李四',600.28)
INSERT INTO bank(customerName,currentMoney) VALUES ('王五',800.69)
GO
/*
觸發器知識複習
觸發器語法
CREATE TRIGGER trigger_name
ON table_name
[WITH encryption] --是否加密
FOR [DELETE,INSERT,UPDATE]
AS
T_SQL語句
GO
觸發器中涉及到2張虛擬表(deleted,inserted)
*/
--
ALTER TRIGGER traninfotrigger1
ON traninfo
FOR INSERT
AS
DECLARE @type VARCHAR(20)
DECLARE @money MONEY
DECLARE @cid int
SELECT @cid = cid, @type = transType, @money = transMoney FROM inserted
IF(@type = '存')
BEGIN
UPDATE bank SET currentMoney = currentMoney + @money WHERE cid = @cid
END
ELSE
BEGIN
UPDATE bank SET currentMoney = currentMoney - @money WHERE cid = @cid
END
GO
--
CREATE TRIGGER traninfotrigger2
ON traninfo
FOR INSERT
AS
DECLARE @type VARCHAR(20)
DECLARE @money MONEY
DECLARE @cid int
SELECT @cid = cid, @type = transType, @money = transMoney FROM inserted
IF(@type = '取')
BEGIN
SET @money = [email protected]
END
UPDATE bank SET currentMoney = currentMoney + @money WHERE cid = @cid
GO
--
INSERT INTO traninfo (cid, cdate, transType, transMoney) VALUES (1, GETDATE(), '取', 200)
SELECT * FROM traninfo
SELECT * FROM bank
INSERT INTO traninfo (cid, cdate, transType, transMoney) VALUES (3, GETDATE(), '存', 800)
GO
/*
注意點:
當SET IDENTITY_INSERT 表名 ON的時候,如果向資料表中插入資料,不能直接寫
INSERT INTO 表名2 SELECT * FROM 表名1這樣的語句來進行插入資料,要將表名2和表1的列顯示的寫出才行。
*/
--
CREATE TRIGGER traninfotrigger3
ON traninfo
FOR DELETE
as
IF(NOT EXISTS(SELECT * FROM sysobjects WHERE name = 'traninfoBackup'))
BEGIN
SELECT * INTO traninfoBackup FROM deleted
END
ELSE
BEGIN
--SET IDENTITY_INSERT traninfoBackup ON
INSERT INTO
traninfoBackup(cid, cdate, transType, transMoney)
SELECT
cid, cdate, transType, transMoney
FROM
deleted
--INSERT INTO traninfoBackup SELECT * FROM traninfo
END
GO
SELECT * FROM traninfo
--SET IDENTITY_INSERT traninfoBackup ON
DELETE FROM traninfo WHERE tid <= 3
DELETE FROM traninfo WHERE tid = 27
SELECT * FROM traninfoBackup
--SET IDENTITY_INSERT traninfoBackup OFF
INSERT INTO traninfoBackup (cid, cdate, transType, transMoney) VALUES (1, GETDATE(), '取', 200)
GO
--
CREATE TRIGGER bank5
ON bank
FOR UPDATE
as
DECLARE @oldMoney MONEY
DECLARE @newMoney MONEY
DECLARE @tranMoney MONEY
SELECT @oldMoney = currentMoney FROM deleted
SELECT @newMoney = currentMoney FROM inserted
SET @tranMoney = @oldMoney - @newMoney
PRINT '******************************************************************'
PRINT 'oldMoney = ' + CONVERT(VARCHAR(20), @oldMoney) + ' ' +
'newMoney = ' + CONVERT(VARCHAR(20), @newMoney) + ' ' +
'交易金額 = ' + CONVERT(VARCHAR(20), @tranMoney)
PRINT '******************************************************************'
IF(@tranMoney >= 20000 OR @tranMoney <= -20000)
BEGIN
PRINT '發生錯誤,交易金額最多兩萬'
SELECT * FROM bank
ROLLBACK TRANSACTION --回滾
END
GO
INSERT INTO traninfo (cid, cdate, transType, transMoney) VALUES (1, GETDATE(), '存', 13000)
SELECT * FROM bank
GO
/*
列級觸發器
UPDATE(列名) 判斷該列是否修改
*/
CREATE TRIGGER tri_update_traninfo
ON traninfo
FOR UPDATE
AS
IF UPDATE(cdate)
BEGIN
PRINT '交易失敗'
RAISERROR('安全警告:交易日期不能修改,由系統自動產生', 16, 1)
SELECT * FROM traninfo
ROLLBACK TRANSACTION
END
GO
UPDATE traninfo SET cdate = GETDATE()
SELECT * FROM traninfo
-- TRUNCATE TABLE traninfo
/*
TRUNCATE TABLE 表名 雖然也能刪除表中的資料,但是TRUNCATE TABLE是DDL(資料定義語言,所以不能帶where條件),如果要根據條件來刪
除表中的某些資料的話必須要使用delete(DML 資料操作語言)
*/