ADO.NET(內含存儲過程講解)
在現在的很多IT企業當中,都會用到存儲過程這個概念,那么,什么是存儲過程呢?存儲過程有什么好處呢?在實際的運用當中,我們怎么去用存儲過程這個技術,這是我們今天文章討論的主要內容。
首先我們說下用數據源綁定的方式實現省市聯動.
一、畫好省市界面
我們要把省市數據庫里面的所有的省份和直轄市加載到第一個下拉菜單當中。
先確定下sql語句:select *from dbo.TblArea where AreaPid=0
添加配置文件和sqlHelper。
二、添加配置文件和sqlHelper
三、綁定省數據
下面實現下一個功能,選中一個省在下面對應顯示市。
我們在省的下拉菜單的選擇項改變事件寫代碼:
四、加載市的代碼
下面我們看下問題代碼:
五、錯誤代碼剖析
如果我先綁定數據源,后設置下拉菜單。就報錯了。
六、報錯信息
七、把數據源放到前面的情況,想想為什么會報錯呢?
調試一下,第一步,第二步都沒有問題。
八、調試看到的錯誤一
九、調試看到的錯誤二
所以我們再看下sql語句執行的是什么?
可以打開事件探查器進行觀測。
十、打開事件探查器
因為設置DataSouce的數據源對象的時候會觸發SelectedIndexChanged事件
在這個事件中,要獲取當前選中項的SelectedValue,但是,這時還沒有設置ValueMember,所以SelectedValue現在還根本沒有具體的列的值,所以就報錯了。
如果我就是想先:設置數據源的話,那么,我需要這樣修改代碼。
十一、修改后的代碼
十二、注意:用別名的時候統一用別名
接下來咱們說下:連接查詢(join)
什么時候用連接呢?咱們之前說過聯合union,聯合是把多個結果集連在一起。連接是把多張表列給連接在一起。
連接基於笛卡爾積的。
十三、笛卡爾積圖解
我們先看下交叉連接:
十四、快速創建兩張表
十五、分別向學生表和成績表中插入幾條數據
十六、交叉連接
我們再說下:內連接
十七、內連接
多表內連接。無論幾張表連接,每次執行都是兩張表進行連接。
十八、多表進行連接
注意:on只用於主外建的條件篩選,其余條件都用where
那么下面我們就來處理怎么才能處理沒有參加考試的同學。
十九、左外聯
二十、沒有參加考試的同學
在外連接判斷是否為空的時候,建議使用主鍵。
二十一、右外聯
左外聯和右外聯的執行的順序,首先,拿到笛卡爾積-篩選出來相等的-添加外部行
二十二、外聯接查詢基本過程
下面我們看幾個案例:
案例1:查詢所有學生的姓名、年齡及所在班級
二十三、案例一
案例2:查詢年齡超過20歲的學生的姓名、年齡及所在班級
作業
案例3:查詢學生姓名、年齡、班級及成績
作業
案例4:查詢所有學生(參加及未參加考試的都算)及成績
詳細說明:
學號,姓名,英語成績,是否參加了考試’是’、’否’
案例5:請查詢出所有沒有參加考試(在成績表中不存在的學生的姓名)。
作業:練習1:查詢所有英語及格的學生姓名、年齡及成績
練習2:查詢所有參加考試的,english分數不為null學生姓名、年齡及成績(內聯接)
練習3:查詢所有學生(參加和未參加考試)的學生姓名、年齡、成績,如果沒有參加考試顯示缺考,如果小於english&math60分顯示不及格
接下來,我們再說個自連接的問題
二十四、自連接
如果上面的表中數據太多不好理解的話,請看下面的簡單演示:
二十五、新建一張表並插入數據
二十六、自連接演示
面試題:
單張表A數據量過百萬,關聯表B數據過千萬,如何查詢優化
- 根據查詢,建索引
- 先從A,B表中過濾出我要查的數據,存儲到臨時表里面
- 應該把B表分多張來存儲
下面我們說說臨時表
二十七、臨時表的存儲位置
建表的時候前面加個#
就表示這張表是張臨時表。
二十八、創建臨時表
我們創建的臨時表,當斷開連接的時候就沒有了。
全局臨時表
加##
可以在多個會話中共享,斷開連接之后就沒有了。
二十九、創建全局臨時表
下面我們看下視圖
視圖一般是不存儲數據的,sql server有一種索引視圖的可以存數據,視圖就是用來看數據的。比如說剛才的復雜的子查詢得寫一堆的子查詢,然后可以得到這些結果.別人想查的話每次都得執行一大堆的查詢.我們能不能把查詢結果保存起來,用戶看的時候直接從視圖里看就行了.
三十、創建視圖
視圖的好處:篩選表中的行,降低數據庫的復雜程度
防止未經許可的用戶訪問敏感數據—操作表是得有些權限,創建完表以后,我再創建一些視圖,如果用戶只有查詢的權限,那么我根本不授予你查詢表的權限,而是只授予你查詢視圖的權限。即便是你攻破了數據庫用戶也是只能看到視圖。
本身視圖並不存儲數據,它里的數據來源自查詢的。表中數據改了,根據視圖當中查詢的數據也改了。
在視圖中的查詢不能使用order by,
三十一、視圖中不能用order by
如果我就想讓它排序怎么辦呢?
三十二、正規的視圖排序方法
為什么在視圖里面不能用order by呢?order by把數據變成有序的了。視圖變成別人的數據源,是集合不能有序。
三十三、指定top
為什么指定top就可以了呢?本身order by以后的數據是有序的,top查詢完成以后,這個數據就又變成無序的了。又變成一個集合了,集合就能成為數據源的。
再基於視圖進行升序排序就怎么樣都行了。
接下來我們看下
在sql里面怎么聲明變量,怎么寫if語句,怎么寫循環,怎么編程。
三十四、SQL編程聲明變量並賦值
三十五、聲明變量的第二種寫法,打印出來是川川
三十六、聲明和賦值常見的幾種情況
三十七、set和select賦值時的區別
上面我們所說的這些都是局部變量,局部變量使用的時候前面加一個@符號,全局變量使用的時候前面加兩個@符號。全局變量不是我們聲明的,也不是我們賦值的,全局變量是系統有的那么幾個。只能拿來用,我們沒有資格對其聲明或者賦值。
三十八、部分全局變量
大家想看所有的全局變量,可以在幫助里面-搜索
三十九、在幫助中搜索所有的全局變量
可以通過全局變量做以下的事情:
四十、幾個常用的全局變量
下面說說if-else 還有循環
四十一、if-else, while
計算平均分數並輸出,如果平均分數超過60分輸出成績最高的三個學生的成績,否則輸出后三名的學生
四十二、題目答案
作業:
1.如果english不及格的人超過半數(考試題出難了),則給每個人增加2分,循環加,直到不及格的人數少於一半。
2.把所有未及格的人的成績都加及格(把所有小於60分的學生,變成60就成了)
下面我們說說事務:
什么叫事務呢?我們做一個事情,分好幾個步驟,每個步驟都做完才認為是成功,否則的話失敗。
如,轉賬問題:
假定錢從A轉到B,至少需要兩步:
A的資金減少
然后B的資金相應增加
事務的ACID特性:
事務是作為單個邏輯工作單元執行的一系列操作。一個邏輯工作單元必須有四個屬性,稱為原子性、一致性、隔離性和持久性 (ACID) 屬性,只有這樣才能成為一個事務。
原子性
事務必須是原子工作單元;對於其數據修改,要么全都執行,要么全都不執行。
一致性
事務在完成時,必須使所有的數據都保持一致狀態。在相關數據庫中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構(如 B 樹索引或雙向鏈表)都必須是正確的。
隔離性
由並發事務所作的修改必須與任何其他並發事務所作的修改隔離。事務識別數據時數據所處的狀態,要么是另一並發事務修改它之前的狀態,要么是第二個事務修改它之后的狀態,事務不會識別中間狀態的數據。這稱為可串行性,因為它能夠重新裝載起始數據,並且重播一系列事務,以使數據結束時的狀態與原始事務執行的狀態相同。
持久性
事務完成之后,它對於系統的影響是永久性的。該修改即使出現系統故障也將一直保持。
下面我們看看怎么在程序中怎么去寫事務:
四十三、Sql sever默認是自動提交事務
案例:
四十四、案例
下面我們簡單的看下鎖
四十五、鎖的問題
四十五2、隱士事務
下面我們講解今天的重點:存儲過程
我們先來說說為什么要用存儲過程,怎么去寫,怎么去調。在ADO里面怎么去用。
為什么要用存儲過程呢?第一,我們以前寫代碼,要執行一堆的sql語句,得通過應用程序把sql語句發送給服務器,然后才能執行,sql語句越長,交互的數據量越大,性能越低.
這個時候我們把所有的代碼封裝到存儲過程里面,就像函數一樣封裝起來.當我們要使用的時候,直接調一個存儲過程的名稱,就搞定了.
這樣的話,減少了網絡流通量.再一個,存儲過程是提前在數據庫里面建好的,已經編譯過了,直接調用執行就行了,不需要在編譯了.
再一個可以防止我們的sql注入攻擊.
允許代碼重用.在數據庫里面建一個存儲過程,只要用到這個功能,調它就行了.
系統中有些存儲過程,我們也可以自己定義一些存儲過程.
系統中的存儲過程就以sp或xp開頭.
四十六、看下有多少個數據庫
四十七、查看系統存儲過程源代碼
四十八、看下當前數據庫里面有多少張表
四十九、看下存儲過程的源代碼
自定義的存儲過程我們以usp開頭
五十、沒有參數,沒有返回值的存儲過程
五十一、自定義存儲過程求和
五十二、修改存儲過程
五十三、修改存儲過程二
五十四、修改存儲過程三
接下來我們介紹下輸出參數
五十五、輸出參數
輸出參數也非常的重要,很多時候參數執行完后要拿到一個值,就可以通過輸出參數拿到這個值。
還記得我們之前的博文中說過帶參數的sql語句么?帶參數的sql語句最終執行的時候,就是調的存儲過程來執行的.下面執行的時候給大家看一下.
我們之前的案例,像給學生提分的案例就可以拿存儲過程來做.
編寫存儲過程
作業:考試題出難了,降低及格分數線,(將該題目封裝為一個存儲過程。)
編寫存儲過程usp_upGrade
要求傳入參數:@pass float
調用存儲過程,及格分數線,給沒及格的人提分
接下來我們說下怎么通過ADO.net來調用存儲過程。
寫段簡單的代碼,向bank表中插入條記錄:
五十六、通過ADO.net調用存儲過程---畫個界面
五十七、常規的方法
但是這樣寫報錯了,大家看看是什么錯?
五十八、系統報的錯誤
五十九、再加個參數,報錯就沒了,原因是少給了一個參數
六十、修改后的代碼
下面我們寫調存儲過程進行插入,首先數據庫里面得有存儲過程。所以,在數據庫里面建個存儲過程。
六十一、建好存儲過程
六十二、打開對象資源管理器,記下存儲過程名
六十三、帶參數的sql語句調的存儲過程
六十四、告訴command對象執行的是什么
六十五、使用存儲過程實現插入代碼
六十六、執行的過程當中又報錯了
沒給它寫參數,很多剛入行的程序員都會出現這樣的問題,其實,老程序員也會出現這樣的問題。大家在遇到這樣的問題的時候,請不要緊張,靜下心來找找,就行了。
六十七、執行之前增加參數
下面我們通過存儲過程寫下存儲過程版的增,刪,查,改。
六十八、添加配置文件
六十九、需要插入的表
這是我們需要插入數據的表,后兩列是默認值,所以插入前兩列就行了。
七十、畫好我們需要的界面
在寫之前還是需要觀察一下我們上面寫的存儲過程版的增加和帶參數的Sql語句有什么不一樣的地方呢?
七十一、存儲過程版的增加和帶參數的Sql語句有什么不一樣的地方
七十二、新建存儲過程SqlHelper添加命名空間
七十三、執行insert、delete、update的存儲過程版SqlHelper
七十四、執行返回單個值的方法
七十五、執行返回Reader
七十六、執行返回DataTable
插入代碼:SqlHelperProc位置:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Configuration; 6 using System.Data; 7 using System.Data.SqlClient; 8 9 namespace _03SqlHelper加配置文件加存儲過程實現表的增刪查改 10 { 11 /// <summary> 12 /// 通過存儲過程來實現SqlHelper 13 /// </summary> 14 public static class SqlHelperProc 15 { 16 //需要添加引用 17 private static readonly string constr = ConfigurationManager.ConnectionStrings["sql"].ConnectionString; 18 #region 執行insert、delete、update 19 20 public static int ExecuteNonQuery(string sql, CommandType cmdType, params SqlParameter[] pms) 21 { 22 using (SqlConnection con = new SqlConnection(constr)) 23 { 24 using (SqlCommand cmd = new SqlCommand(sql, con)) 25 { 26 cmd.CommandType = cmdType; 27 if (pms != null) 28 { 29 //添加參數 30 cmd.Parameters.AddRange(pms); 31 } 32 con.Open(); 33 //當執行存儲過程的時候到底要調哪個ado.net方法,依賴於存儲過程中封裝的是什么sql語句,如果是增刪改則調ExecuteNonQuery();,返回單個值的則調ExecuteScalar()如果是查詢大量數據則調ExecuteReader(). 34 //當存儲過程中封裝的代碼較為復雜時,可以考慮根據最終存儲過程調用完畢后需要的返回值來決定,如果最后存儲過程查詢出了大批數據需要獲取,則用Reader,單個值還是用ExecuteScalar(),如果執行完畢存儲過程不需要什么返回值,則可以直接調用ExecuteNonQuery()來執行。 35 return cmd.ExecuteNonQuery(); 36 } 37 } 38 } 39 #endregion 40 41 #region 執行返回單個值的方法 42 public static object ExecuteScalar(string sql, CommandType cmdType, params SqlParameter[] pms) 43 { 44 using (SqlConnection con = new SqlConnection(constr)) 45 { 46 using (SqlCommand cmd = new SqlCommand(sql, con)) 47 { 48 cmd.CommandType = cmdType; 49 if (pms != null) 50 { 51 cmd.Parameters.AddRange(pms); 52 } 53 con.Open(); 54 return cmd.ExecuteScalar(); 55 } 56 } 57 } 58 #endregion 59 60 #region 執行返回Reader 61 public static SqlDataReader ExecuteReader(string sql, CommandType cmdType, params SqlParameter[] pms) 62 { 63 SqlConnection con = new SqlConnection(constr); 64 using (SqlCommand cmd = new SqlCommand(sql, con)) 65 { 66 cmd.CommandType = cmdType; 67 if (pms != null) 68 { 69 cmd.Parameters.AddRange(pms); 70 } 71 try 72 { 73 con.Open(); 74 return cmd.ExecuteReader(CommandBehavior.CloseConnection); 75 } 76 catch 77 { 78 con.Close(); 79 con.Dispose(); 80 throw; 81 } 82 } 83 } 84 #endregion 85 86 #region 執行返回DataTable 87 public static DataTable ExecuteDataTable(string sql, CommandType cmdType, params SqlParameter[] pms) 88 { 89 using (SqlDataAdapter adapter=new SqlDataAdapter(sql,constr)) 90 { 91 adapter.SelectCommand.CommandType = cmdType; 92 if (pms!=null) 93 { 94 adapter.SelectCommand.Parameters.AddRange(pms); 95 } 96 DataTable dt = new DataTable(); 97 adapter.Fill(dt); 98 return dt; 99 } 100 } 101 #endregion 102 } 103 }
下面我們試着用下:
我們發現上面的SqlHelper不光可以執行存儲過程,如果把cmdType變成Test的話,也可以執行sql語句,這個存儲過程和sql語句都是可以執行的。
在寫存儲過程的時候有個輸出參數,在調用的時候可以拿到,當通過ADO調的時候怎么拿到那個輸出參數呢?
七十七、寫好執行插入的存儲過程
七十八、最后插入的代碼
七十九、最后的報錯,什么原因呢?
我的代碼沒有問題,體統就是報這個錯,大家見過么?幫我解答一下子。
作者近期文章列表:
C#基礎教程(完全免費,獻給代碼愛好者的最好禮物。注:本作者分享自己精心整理的C#基礎教程,無任何商業目的。 希望與更多的代碼愛好者交流心得,也請高手多多指點!!!) |
|
三層及其它內容 | 遞歸 |
三層(一) | |
三層相關案例(及常見的錯誤) | |
三層實例(內涵Sql CRUD) | |
手寫代碼生成器 | |
SQL數據庫 ADO.net | 數據庫的應用圖解一 |
數據庫的應用詳解二 | |
ADO.NET(內涵效率問題) | |
ADO.NET實例教學一 | |
面向過程,面向對象中高級 | 面向過程,面向對象的深入理解一 |
面向過程,面向對象的深入理解二 | |
面向對象的深入理解三 | |
winform基礎 | Winform基礎 |
winform中常用的控件 | |
面向過程 | 三種循環的比較 |
C#中的方法(上) | |
我們常見的數組 | |
面向對象 | 思想的轉變 |
C#中超級好用的類 | |
C#中析構函數和命名空間的妙用 | |
C#中超級好用的字符串 | |
C#中如何快速處理字符串 | |
值類型和引用類型及其它 | |
ArrayList和HashTable妙用一 | |
ArrayList和HashTable妙用二 | |
文件管理File類 | |
多態 | |
C#中其它一些問題的小節 | |
GDI+ | 這些年我收集的GDI+代碼 |
這些年我收集的GDI+代碼2 | |
HTML概述以及CSS | 你不能忽視的HTML語言 |
你不能忽視的HTML語言2精編篇 | |
你不能忽視的HTML語言3 | |
CSS基本相關內容--中秋特別奉獻 | |
CSS基本相關內容2 | |
JavaScript基礎 | JavaScript基礎一 |
jQuery | jQuery(內涵: jquery選擇器) |