T-SQL基礎(一)之簡單查詢

名詞解釋

SQL: Structured Query Language,結構化查詢語言,是一種在關系型數據庫中用于管理數據的標準語言。SQL是一種聲明式編程語言,即只需表明需要什么而無需關注實現細節(C#中的LINQ也是如此)。

SQL方言:在SQL標準的基礎上延伸的其它語言,如SQL Server中所使用的T-SQL。注意SQL方言未必完全支持所有的SQL標準。

T-SQL:Transact-SQL,微軟公司提供的用于SQL Server數據庫的SQL方言(擴展)。

SQL表達式運算

謂詞

SQL中謂詞是指運算結果為True,False或Unknown的邏輯表達式。T-SQL中的謂詞有IN,BETWEEN,LIKE等。

使用LIKE可以做模糊匹配,支持正則表達式:

-- 查找以x開頭的name
SELECT name FROM Xfh.dbo.UserInfo WHERE name LIKE 'x%';

-- 查找以兩個x開頭的name,_表示匹配單個字符
SELECT name FROM Xfh.dbo.UserInfo WHERE name LIKE '_x%';

 

需要注意的是,LIKE模糊匹配若以%開頭,則無法使用所用。如:LIKE '%x'

運算符

SQL中的運算符與高級編程語言(C#,JAVA)類似。當多個運算符出現在同一表達式中時,SQL Server會按照運算符的優先級進行計算。當搞不清楚優先級就使用括號,對比下面兩句SQL:

SELECT orderid FROM Sales.dbo.Orderes 
WHERE 
    custid=1 AND empid IN (1,2,3) 
    OR
    custid=85 AND empid IN  (4,5,6)


SELECT orderid FROM Sales.dbo.Orderes 
WHERE 
    (custid=1 AND empid IN (1,2,3)) 
    OR 
    (custid=85 AND empid IN  (4,5,6))

 

AND運算符的優先級高于OR,所以上述兩句SQL在邏輯上等價。但,很明顯第二句的WHERE條件邏輯上更清晰。

三值邏輯

SQL中表達式的運算結果有三種情況:True,False 與 Unknown

在查詢篩選中,只返回條件表達式(WHERE、HAVING、ON)運算結果為True的數據。

CHECK約束,返回表達式運算結果不為False的結果。

兩值邏輯

與T-SQL中的大多數謂詞不同,EXISTS使用兩值邏輯(True/False),而不是三值邏輯;

EXISTS( SELECT * FROM T_A WHERE Id=12)中,EXISTS謂語只關心匹配行是否存在,而不管SELECT中指定的屬性,就像整個SELECT子句是多余的一樣。SQL Server引擎在優化查詢時會忽略SELECT子句。所以,SELECT子句中的星號(*)對于性能沒有任何負面影響。

為節省微不足道的與星號(*)解析相關的額外成本,而犧牲代碼可讀性是不值得的。

NULL & Unknown

NULL表示值是Unknown狀態,SQL中不同的語言元素對于NULL有著不同的處理方式。

在使用NULL值時應注意以下幾點:

  • 將NULL與其它值進行比較,不管該值是否為NULL,結果均為Unknown

  • 應使用IS NULL或IS NOT NULL來判斷值是否為NULL

  • INSERT未給列指定值則插入NULL

  • GROUP BY和ORDER BY子句會將多個NULL值視為相等

  • 標準SQL的UNIQUE約束將NULL是為彼此不同

  • T-SQL中的UNIQUE約束認為多個NULL是相等的

  • COUNT(*)的特殊性

    若列名為tag的例中存在a,NULL,c,d幾行數據,那么COUNT(*)返回4而COUNT(tag)則返回3

NULL參與的邏輯運算結果很可能是Unknown(三值邏輯也是引發應用錯誤的重要原因),除非運算結果不依賴于Unknown,示例如下。

Unknown參與AND運算結果:

Expression 1Expression 2Result
TRUE UNKNOWN UNKNOWN
UNKNOWN UNKNOWN UNKNOWN
FALSE UNKNOWN FALSE

Unknown參與OR預算結果:

Expression 1Expression 2Result
TRUE UNKNOWN TRUE
UNKNOWN UNKNOWN UNKNOWN
FALSE UNKNOWN UNKNOWN

查詢

SQL中的查詢是指,SELECT語句經過一些列邏輯處理而獲取數據的過程。

幾條建議:

  • SQL中的關鍵字均使用大寫字母

  • SQL語句均使用分號結尾

  • SQL中使用對象的完全限定名,如:DbName.dbo.TableName

查詢語句執行順序

SQL中查詢語句的邏輯處理過程與實際查詢過程(物理查詢過程)是有差異的,即,SELECT語句的執行順序與書寫順序是有差異的。按照SELECT語法規定書寫的SQL語句較為符合英語語法習慣(對人類友好),但SELECT語句的實際執行則按照如下順序進行(對機器友好):

  • FROM
  • JOIN ON
  • WHERE
  • GROUP BY
  • HAVING
  • SELECT
  • 表達式
  • DISTINCT
  • ORDER BY
  • TOP/OFFSET FETCH

OFFSET FETCH可以看作是ORDER BY子句的一部分

?? SQL基于集合理論,查詢結果集(表結果)是無順尋的(雖然看起來結果集像按照某種順序排列),除非顯式的使用ORDER BY子句指定順尋,但使用ORDER BY字句后結果集將被作為游標對待,而非表結果。

FROM子句用于指定需要查詢的數據源,WHERE語句對數據源中的數據做基于行的篩選。通常WHERE子句可以決定查詢是否使用索引,及使用哪些索引,對于查詢優化有著重要意義。

GROUP BY子句用于對查詢結果集進行分組,GROUP BY之后的所有操作都是對組而非行的操作。在查詢結果中,每組最終由一個單行來表示。這意味著,GROUP BY之后的所有子句中指定的表達式必須對每組返回一個標量(單個值)。

HAVING用于對GROUP BY產生的組進行篩選。

SELECT語句用于指定返回到查詢結果集中的列,生成查詢結果表。注意,在SELECT子句之前執行的子句無法使用SELECT子句中的列的別名,否則會返回Invalid column name錯誤。

TOP不是標準SQL,是T-SQL專有功能,用于限制查詢返回的指定行數或百分比:

-- 返回Table中的10條數據
SELECT TOP(10) * FROM Table;

-- 返回Table中10%的數據
SELECT TOP(10) PERCENT * FROM Table;

 

OFFSET-FETCH有著與TOP類似的功能,但它是標準SQL,可用于分頁查詢:

-- 取第51至60行的10條數據
SELECT * FROM Table
ORDER BY Id DESC
OFFSET 50 ROWS FETCH NEXT 10 ROWS ONLY;

 

注意SQL SERVER中,OFFSET-FETCH要與ORDER BY結合使用,否則會報錯:

Invalid usage of the option NEXT in the FETCH statement.

同時操作

SQL中有all-at-once operations(同時操作)的概念,即出現在同一邏輯處理階段的所有表達式在同一時間進行邏輯計算。

因為同時操作的原因,下面示例中orderyear+1中的oderyear是無效的,SQL會報錯:Invalid column name 'orderyear'

SELECT orderid,YEAR(orderdate) AS orderyear,orderyear+1 AS nextyear FROM Sales.dbo.Orders;

 

同樣,由于同時操作的原因,SQL Server不支持短路操作。如,WHERE子句中的多個表達式的計算并沒有確定的順序。

CASE...WHEN...

CASE表達式是標量表達式,返回一個符合條件的值。注意,CASE是表達式,不是語句,與COUNT類似。

CASE表達式有兩種使用方式:

  • CASE后面帶有列名
SELECT 
Name,
CASE Age
    WHEN 70 THEN '雙慶'
    WHEN 50 THEN '知天命'
    ELSE '未成年'
END
FROM WJChi.dbo.UserInfo;

 

  • CASE后面不帶列名
SELECT 
Name,
CASE 
    WHEN Name='雪飛鴻' THEN '666'
    WHEN Age=70 THEN '雙慶'
    WHEN Age>=18 THEN '成年'
    ELSE '你猜'
END
FROM Xfh.dbo.UserInfo;

 

CASE表達式中若為指定ELSE的返回值,則默認為ELSE NULL

查詢分類

查詢可分為:

  • 單表查詢

    查詢中最簡單的一種形式。高并發,分布式系統中常用。通常單表查詢僅需一句SELECT語句即可,簡單且數據庫

  • 聯接查詢

    INNER JOIN、LEFT JOIN、RIGHT JOIN、CROSS JOIN

  • 子查詢

    SQL可以在一個查詢語句中編寫另外一個查詢語句,即嵌套查詢。最外面的查詢結果集返回給調用者,稱為外部查詢。內部查詢的結果集被用于外部查詢,稱為子查詢。

  • 表表達式

    派生表、公用表表達式、視圖等

聚合函數

聚合函數對多行數據進行運算后返回標量(聚合),只有SELECT、HAVING、ORDER BY語句中可以使用聚合函數;

開窗函數

開窗函數是對基本查詢中的每一行按組(窗口)進行運算,并得到一個標量。行的窗口使用OVER子句定義。

鎖與事務隔離級別

SQL Server默認情況下,查詢語句會申請共享鎖。共享鎖可以阻止對數據進行修改,詳細信息可參閱:SQL Server中鎖與事務隔離級別

小結

相較于增刪改而言,查詢是比較復雜的,也是數據庫優化的關注重點。本文主要介紹了T-SQL查詢的基礎知識,對于較為復雜的查詢,如:關聯、表表達式、集合運算等將在后續文章中介紹。

書籍推薦

《SQL SERVER 2012 T-SQL 基礎教程》
《SQL SERVER 性能優化與管理的藝術》
《SQL SERVER基礎教程》

推薦閱讀

NULL and UNKNOWN (Transact-SQL)
SQL Server中鎖與事務隔離級別
數據庫兩大神器【索引和鎖】
SQL SERVER開窗函數

posted @ 2018-11-02 22:27 雪飛鴻 閱讀(...) 評論(...) 編輯 收藏
耐克篮球多少钱