1. 程式人生 > >sqlserver知識點彙總(這段時間複習和回顧了一下sqlserver的一些知識),供大家參考和學習!

sqlserver知識點彙總(這段時間複習和回顧了一下sqlserver的一些知識),供大家參考和學習!

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 資料操作語言) */

相關推薦

no