<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      淺析Sql Server參數化查詢

      說來慚愧,工作差不多4年了,直到前些日子被DBA找上門讓我優化一個CPU占用很高的復雜SQL語句時,我才突然意識到了參數化查詢的重要性。

      相信有很多開發者和我一樣對于參數化查詢認識比較模糊,沒有引起足夠的重視

      錯誤認識1.不需要防止sql注入的地方無需參數化
        參數化查詢就是為了防止SQL注入用的,其它還有什么用途不知道、也不關心,原則上是能不用參數就不用參數,為啥?多麻煩,我只是做公司內部系統不用擔心SQL注入風險,使用參數化查詢不是給自己找麻煩,簡簡單單拼SQL,萬事OK

      錯誤認識2.參數化查詢時是否指定參數類型、參數長度沒什么區別
        以前也一直都覺的加與不加參數長度應該沒有什么區別,僅是寫法上的不同而已,而且覺得加參數類型和長度寫法太麻煩,最近才明白其實兩者不一樣的,為了提高sql執行速度,請為SqlParameter參數加上SqlDbType和size屬性,在參數化查詢代碼編寫過程中很多開發者忽略了指定查詢參數的類型,這將導致托管代碼在執行過程中不能自動識別參數類型,進而對該字段內容進行全表掃描以確定參數類型并進行轉換,消耗了不必要的查詢性能所致。根據MSDN解釋:如果未在size參數中顯式設置Size,則從dbType參數的值推斷出該大小。如果你認為上面的推斷出該大小是指從SqlDbType類型推斷,那你就錯了,它實際上是從你傳過來的參數的值來推斷的,比如傳遞過來的值是"username",則size值為8,"username1",則size值為9。那么,不同的size值會引發什么樣的結果呢?且經測試發現,size的值不同時,會導致數據庫的執行計劃不會重用,這樣就會每次執行sql的時候重新生成新的執行計劃,而浪費數據庫執行時間。

      下面來看具體測試

      首先清空查詢計劃

      DBCC FREEPROCCACHE

      傳值username,不指定參數長度,生成查詢計劃

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserName=@UserName";
          //傳值 username,不指定參數長度
          //查詢計劃為(@UserName varchar(8))select * from Users where UserName=@UserName
          comm.Parameters.Add(new SqlParameter("@UserName", SqlDbType.VarChar) { Value = "username" });
          comm.ExecuteNonQuery();
      }

       

      傳值username1,不指定參數長度,生成查詢計劃

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserName=@UserName";
          //傳值 username1,不指定參數長度
          //查詢計劃為(@UserName varchar(9))select * from Users where UserName=@UserName
          comm.Parameters.Add(new SqlParameter("@UserName", SqlDbType.VarChar) { Value = "username1" });
          comm.ExecuteNonQuery();
      }

      傳值username,指定參數長度為50,生成查詢計劃

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserName=@UserName";
          //傳值 username,指定參數長度為50
          //查詢計劃為(@UserName varchar(50))select * from Users where UserName=@UserName
          comm.Parameters.Add(new SqlParameter("@UserName", SqlDbType.VarChar,50) { Value = "username" });
          comm.ExecuteNonQuery();
      }

       

      傳值username1,指定參數長度為50,生成查詢計劃

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserName=@UserName";
          //傳值 username1,指定參數長度為50
          //查詢計劃為(@UserName varchar(50))select * from Users where UserName=@UserName
          comm.Parameters.Add(new SqlParameter("@UserName", SqlDbType.VarChar,50) { Value = "username1" });
          comm.ExecuteNonQuery();
      }

       

      使用下面語句查看執行的查詢計劃

      SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects 
      WHERE sql LIKE '%Users%'  and sql not like '%syscacheobjects%'

      結果如下圖所示

       可以看到指定了參數長度的查詢可以復用查詢計劃,而不指定參數長度的查詢會根據具體傳值而改變查詢計劃,從而造成性能的損失。

      這里的指定參數長度僅指可變長數據類型,主要指varchar,nvarchar,char,nchar等,對于int,bigint,decimal,datetime等定長的值類型來說,無需指定(即便指定了也沒有用),詳見下面測試,UserID為int類型,無論長度指定為2、20、-1查詢計劃都完全一樣為(@UserIDint)select*from Users where UserID=@UserID

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserID=@UserID";
          //傳值 2,參數長度2
          //執行計劃(@UserID int)select * from Users where UserID=@UserID
          comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int, 2) { Value = 2 });
          comm.ExecuteNonQuery();
      }
      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserID=@UserID";
          //傳值 2,參數長度20
          //執行計劃(@UserID int)select * from Users where UserID=@UserID
          comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int, 20) { Value = 2 });
          comm.ExecuteNonQuery();
      }
      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserID=@UserID";
          //傳值 2,參數長度-1
          //執行計劃(@UserID int)select * from Users where UserID=@UserID
          comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int, -1) { Value = 2 });
          comm.ExecuteNonQuery();
      }

      這里提一下,若要傳值varchar(max)或nvarchar(max)類型怎么傳,其實只要設定長度為-1即可

      using (SqlConnection conn = new SqlConnection(connectionString))
      {
          conn.Open();
          SqlCommand comm = new SqlCommand();
          comm.Connection = conn;
          comm.CommandText = "select * from Users where UserName=@UserName";
          //類型為varchar(max)時,指定參數長度為-1
          //查詢計劃為 (@UserName varchar(max) )select * from Users where UserName=@UserName
          comm.Parameters.Add(new SqlParameter("@UserName", SqlDbType.VarChar,-1) { Value = "username1" });
          comm.ExecuteNonQuery();
      }

      當然了若是不使用參數化查詢,直接拼接SQL,那樣就更沒有查詢計劃復用一說了,除非你每次拼的SQL都完全一樣

      總結,參數化查詢意義及注意點

      1.可以防止SQL注入

      2.可以提高查詢性能(主要是可以復用查詢計劃),這點在數據量較大時尤為重要

      3.參數化查詢參數類型為可變長度時(varchar,nvarchar,char等)請指定參數類型及長度,若為值類型(int,bigint,decimal,datetime等)則僅指定參數類型即可

      4.傳值為varchar(max)或者nvarchar(max)時,參數長度指定為-1即可

      5.看到有些童鞋對于存儲過程是否要指定參數長度有些疑惑,這里補充下,若調用的是存儲過程時,參數無需指定長度,如果指定了也會忽略,以存儲過程中定義的長度為準,不會因為沒有指定參數長度而導致重新編譯,不過還是建議大家即便時調用存儲過程時也加上長度,保持良好的變成習慣

       

        

      posted @ 2012-04-21 08:07  懶惰的肥兔  閱讀(40500)  評論(83)    收藏  舉報
      主站蜘蛛池模板: 成人一区二区三区在线午夜| 香蕉久久久久久久av网站| 日韩av日韩av在线| 中文国产成人精品久久不卡| 久久婷婷综合色丁香五月| 久久国产精品乱子乱精品| 欧美 喷水 xxxx| 极品白嫩少妇无套内谢| 亚洲在av极品无码天堂| 亚洲一区成人av在线| 亚洲va在线∨a天堂va欧美va| 麻豆国产97在线 | 欧美| 精品亚洲精品日韩精品| 大地资源网第二页免费观看| 99精品人妻少妇一区| 日韩精品中文字幕一线不卡| 毛片久久网站小视频| 亚洲国产高清av网站| 国产区精品福利在线熟女| 男人j进入女人j内部免费网站| 99福利一区二区视频| 亚洲人成网站在线播放动漫| 无码国产69精品久久久久网站| 荆门市| 日韩精品人妻av一区二区三区 | 亚洲综合久久一区二区三区| 欧美老少配性行为| 超碰人人超碰人人| 亚洲美免无码中文字幕在线| 中文字幕一区二区三区四区五区| 亚洲精品国产第一区二区| 在线看无码的免费网站| 亚洲日本欧洲二区精品| 马边| 日韩熟妇| 亚洲爆乳少妇无码激情| 久久精品国产99久久久古代| 免费国产va在线观看| 久久亚洲av午夜福利精品一区| 人成午夜免费视频无码| 你拍自拍亚洲一区二区三区|