數據庫使用過程中一些零散的應用,記錄下來以便下次使用。
1、觸發器
剛才在項目中使用到觸發器,現在拿來做記錄,以便后續使用。
CREATE TRIGGER ON_DELETEON [OSCE].[dbo].[QuestionType]FOR DELETEASBEGINIF EXISTS (SELECT * FROM DELETED WHERE QT_TD> 38 AND QT_ID < 41)ROLLBACK;END
本觸發器的意思是:創建觸發器on_delete,確保數據庫表 [OSCE].[dbo].[QuestionType] 中的QT_ID是39、40的這兩條記錄不被刪除。如果刪除了,則回滾。
刪除觸發器:drop Trigger on_delete
2、索引
聚簇索引 是按照數據存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對于單行的檢索很快。
與非聚焦索引相比,聚集索引通常提供更快的數據訪問速度。
3、編寫外鍵約束
表[Test].[dbo].[QuestionInfo] 有三個字段:[id],[Name],[Mid]
表[Test].[dbo].[MTest],有三個字段:[Mid],[Mname],[Mage]
現在創建表QuestionInfo的字段Mid的外鍵約束,即表QuestionInfo的字段Mid是表[Test].[dbo].[MTest]主鍵。sql語句如下:
ALTER TABLE [Test].[dbo].[QuestionInfo] ADD constraint FK_MD FOREIGN KEY (Mid)references [Test].[dbo].[MTest](Mid)
刪除上述外鍵:alter table [Test].[dbo].[QuestionInfo] drop FK_MD
4、數據庫視圖
表[Test].[dbo].[QuestionInfo] 有三個字段:[id],[Name],[Mid]
表[Test].[dbo].[MTest],有三個字段:[Mid],[Mname],[Mage]
創建QuestionInfo_MTest視圖,加入[id],[Name],[Mid],[Mname],[Mage]
查詢函數:
SELECT dbo.QuestionInfo.id, dbo.QuestionInfo.Name, dbo.QuestionInfo.Mid, dbo.MTest.Mname, dbo.MTest.MageFROM dbo.MTest INNER JOIN dbo.QuestionInfo ON dbo.MTest.Mid = dbo.QuestionInfo.Mid自此建立視圖。
5、數據庫分頁
此處拿sqlserver舉例說明。在項目中有時為了分頁顯示數據,需要調用部分數據,如果邏輯處理由程序語言進行,必然會影響到其性能。鑒于數據庫的強大功能,將其交給數據庫是一個比較明智的選擇吧。
舉例說明備注:[MultiStationExamArrangement]是數據庫表,[MSEA_ID]是其中的一個不會重復的字段。現在需要查詢該表中10001-10050的數據。
數據庫分頁三種方式:
1)使用兩個select和兩個order。先按照某字段的排序,查找前10050條記錄,形成數據集。在進行倒序查找其前50條數據。
select top 50 * from ( select top 10050 * from [MultiStationExamArrangement] ORDER BY [MSEA_ID]) as temp order by MSEA_ID DESC
因為查到的數據是倒序排列,如果想得到正序,可以進一步處理(如果有必要):
SELECT * FROM ( select top 50 * from (select top 10050 * from [MultiStationExamArrangement] ORDER BY [MSEA_ID])as temp order by MSEA_ID DESC) AS TEMP order by MSEA_ID
2)使用兩個select,產生臨時序號。首先查找所有的相關數據,并增加新的列存儲記錄臨時序號,形成數據集。再根據數據集中的臨時序號查找相應的數據。
SELECT * FROM ( SELECT *,ROW_NUMBER() OVER(ORDER BY [MSEA_ID]) AS ROWRANK FROM [MultiStationExamArrangement] ) AS TEMP WHERE ROWRANK BETWEEN 10001 AND 10050
3)創建臨時表,產生臨時ID。首先創建一個只有自增ID和你需要查找相關記錄的的字段的臨時列表,并將你查找記錄的主鍵填入臨時表。再查詢臨時表,根據臨時ID查找相應的數據。此種方法較為復雜,但可擴展性比較大。
CREATE TABLE #TEMPTABLE ( INDEXID INT IDENTITY(0,1) NOT NULL, MSEA_ID INT )
INSERT INTO #TEMPTABLE(MSEA_ID) SELECT MSEA_ID FROM [MultiStationExamArrangement] ORDER BY MSEA_ID SELECT T.* FROM [MultiStationExamArrangement] T,#TEMPTABLE P WHERE P.MSEA_ID = T.MSEA_ID AND P.INDEXID BETWEEN 10000 AND 10049 DROP TABLE #TEMPTABLE
6、存儲過程
存儲過程PRocedure是一組為了完成特定功能的sql語句集合,經編譯后存儲在數據庫中,用戶通過指定的存儲過程的名稱來執行。存儲過程中可以包含邏輯控制語句和數據操作語句,它可以接受參數、輸出參數、返回單個或多個結果集以及返回值。由于存儲過程在創建時即在數據庫服務器中進行了編譯并存儲在數據庫中,所以存儲過程運行比單個sql語句集合要快,同時由于存儲過程在調用時只需要提供名稱和必要的參數信息,因此在一定程度上減少了網絡流量和網絡負擔。
存儲過程的優點:能夠實現較快的執行速度,減輕網絡流量(上文已解釋),可作為一種安全機制來充分利用(系統管理員可以對執行的某一個存儲過程進行權限限制,從而能夠實現對某些數據訪問的限制,避免非授權用戶對數據的訪問,保證數據安全)。
1)創建語言:
create proc | procedure pro_name [{@參數數據類型} [=默認值] [output], {@參數數據類型} [=默認值] [output], .... ]as SQL_statements
2)不帶參數存儲過程:
--創建存儲過程if (exists (select * from sys.objects where name = 'proc_get_student')) drop proc proc_get_studentgocreate proc proc_get_studentas select * from student;--調用、執行存儲過程exec proc_get_student;
3)帶參數存儲過程:
--帶參存儲過程if (object_id('proc_find_stu', 'P') is not null) drop proc proc_find_stugocreate proc proc_find_stu(@startId int, @endId int)as select * from student where id between @startId and @endIdgoexec proc_find_stu 2, 4;
4)帶傳出參數的存儲過程:
if (object_id('proc_getStudentRecord', 'P') is not null) drop proc proc_getStudentRecordgocreate proc proc_getStudentRecord( @id int, --默認輸入參數 @name varchar(20) out, --輸出參數 @age varchar(20) output--輸入輸出參數)as select @name = name, @age = age from student where id = @id and sex = @age;go-- declare @id int, @name varchar(20), @temp varchar(20);set @id = 7; set @temp = 1;exec proc_getStudentRecord @id, @name out, @temp output;select @name, @temp;print @name + '#' + @temp;
7、sqlserver中sql語句執行順序(摘抄)
SQL 不同于與其他編程語言的最明顯特征是處理代碼的順序。在大數編程語言中,代碼按編碼順序被處理,但是在SQL語言中,第一個被處理的子句是FROM子句,盡管SELECT語句第一個出現,但是幾乎總是最后被處處理。每個步驟都會產生一個虛擬表,該虛擬表被用作下一個步驟的輸入。這些虛擬表對調用者(客戶端應用程序或者外部查詢)不可用。只是最后一步生成的表才會返回 給調用者。如果沒有在查詢中指定某一子句,將跳過相應的步驟。
(8)SELECT (9)DISTINCT (11)<Top Num> <select list>(1)FROM [left_table](3)<join_type> JOIN <right_table>(2) ON <join_condition>(4)WHERE <where_condition>(5)GROUP BY <group_by_list>(6)WITH <CUBE | RollUP>(7)HAVING <having_condition>(10)ORDER BY <order_by_list>
邏輯查詢處理階段簡介:
1)from:對FROM子句中的前兩個表執行笛卡爾積(Cartesian product)(交叉聯接),生成虛擬表VT1
2)on:對VT1應用ON篩選器。只有那些使<join_condition>為真的行才被插入VT2
3)outer(join):如 果指定了OUTER JOIN(相對于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部聯接把左表標記為保留表,右外部聯接把右表標記為保留表,完全外部聯接把兩個表都標記為保留表)中未找到匹配的行將作為外部行添加到 VT2,生成VT3.如果FROM子句包含兩個以上的表,則對上一個聯接生成的結果表和下一個表重復執行步驟1到步驟3,直到處理完所有的表為止。
4)where:對VT3應用WHERE篩選器。只有使<where_condition>為true的行才被插入VT4.
5)group by:按GROUP BY子句中的列列表對VT4中的行分組,生成VT5.
6)cube|roolup:把超組(Suppergroups)插入VT5,生成VT6.
7)having:對VT6應用HAVING篩選器。只有使<having_condition>為true的組才會被插入VT7.
8)select:處理SELECT列表,產生VT8.
9)distinct:將重復的行從VT8中移除,產生VT9.
10)order by:將VT9中的行按ORDER BY 子句中的列列表排序,生成游標(VC10)
11)top:從VC10的開始處選擇指定數量或比例的行,生成表VT11,并返回調用者。
注:
步驟10,按ORDER BY子句中的列列表排序上步返回的行,返回游標VC10.這一步是第一步也是唯一一步可以使用SELECT列表中的列別名的步驟。這一步不同于其它步驟的 是,它不返回有效的表,而是返回一個游標。SQL是基于集合理論的。集合不會預先對它的行排序,它只是成員的邏輯集合,成員的順序無關緊要。對表進行排序 的查詢可以返回一個對象,包含按特定物理順序組織的行。ANSI把這種對象稱為游標。理解這一步是正確理解SQL的基礎。
因為這一步不返回表(而是返回游標),使用了ORDER BY子句的查詢不能用作表表達式。表表達式包括:視圖、內聯表值函數、子查詢、派生表和共用表達式。它的結果必須返回給期望得到物理記錄的客戶端應用程序。
在SQL中,表表達式中不允許使用帶有ORDER BY子句的查詢,而在T—SQL中卻有一個例外(應用TOP選項)。所以要記住,不要為表中的行假設任何特定的順序。換句話說,除非你確定要有序行,否則不要指定ORDER BY 子句。排序是需要成本的,SQL Server需要執行有序索引掃描或使用排序運行符。
2015.4.3日補充:
和sql語句的執行順序有關的是其性能的優化,其中之一是表關聯順序。sql語句執行時是按照從右到左的順序處理from子句中的表名,from子句中寫在最后的表也即是基礎表將被最先處理,因此在from子句中包含多個表的情況下,選擇記錄條數最少的表作為基礎表,在某種程度上將會極大的提高其性能。如果有3個以上的表,則選擇交叉表作為基礎表。
新聞熱點
疑難解答