《SQLSERVER2012之T-SQL教程》T-SQL單表查詢(二)

表結構與數據:https://github.com/XuePeng87/TSQLV4git

謂詞和運算符

1) 謂詞

    T-SQL支持的謂詞例子包括IN、BETWEEN和LIKE。github

    IN能夠檢查一個值或是一個標量表達式是否至少等於集合中的一個元素。例以下面查詢,將返回1024八、10249或10250的訂單:sql

SELECT orderid, empid, orderdate 
FROM Sales.Orders 
WHERE orderid IN (10248, 10249, 10250);

    BETWEEN謂詞能夠檢查一個值是否在制定範圍內,其包括兩個指定的邊界值。例以下面查詢,將返回包括在10300~10310範圍內的訂單:函數

SELECT orderid, empid, orderdate 
FROM Sales.Orders 
WHERE orderid BETWEEN 10300 AND 10310;

    LIKE謂詞能夠檢查一個字符串值是否知足指定的模式。例如,下面的查詢返回姓氏以字母D開始的僱員:測試

SELECT empid, firstname, lastname 
FROM HR.Employees 
WHERE lastname LIKE N'D%';

    注意字符串"D%"前綴字母N的使用,他表明National(國家),用來表示字符串是一個Unicode數據類型數據類型(NCHAR或NVARCHAR),而不是一個常規字符數據類型(CHAR或VARCHAR)。因爲lastname屬性的數據類型爲NVARCHAR(40),因此字母N做爲字符串前綴。spa

2) 運算符

    T-SQL支持的比較運算符包括:=、>、<、>=、<=、<>、!=、!>和!<。後三個不是標準的。code

    若是須要鏈接邏輯表達式,可使用邏輯運算符:OR和AND。排序

    T-SQL支持4個明顯的算數運算符:+、-、*、/,以及%運算符。索引

    注意,在T-SQL中,涉及兩個操做數的標量表達式的數據類型,是按兩個數據類型優先級中的較高優先級肯定的。若是兩個操做數的數據類型相同,表達式結果是相同的數據類型。例如:兩個INT相除將生成一個整數,5/2=2,而不是2.5了。若是但願計算正數的結果是一個浮點類型,則須要強制轉換操做數爲適當的類型:ci

SELECT CAST(5 AS NUMERIC(12, 2)) / CAST (2 AS NUMERIC(12, 2));

    下面描述了運算符的優先級(從高到低):

  1. "()",圓括號,小括號;
  2. *、/、%;
  3. +(正號)、-(符號)、+(加號)、+(串聯)、-(減號);
  4. =、>、<、>=、<=、<>、!=、!>、!<(比較運算符);
  5. NOT;
  6. AND;
  7. BETWEEN、IN、LIKE、OR;
  8. =(賦值);

CASE表達式

    CASE表達式是一個標量表達式,返回一個基於條件邏輯的值。須要注意的是,CASE是表達式而不是語句,它不容許你控制活動流或是作一些基於條件邏輯的操做。不過,它的返回值是基於條件邏輯的。因爲CASE是一個標量表達式,所以能夠在任何容許使用標量表達式的地方使用它。例如,在SELECT、WEHERE、HAVING、ORDER BY中,以及在CHECK約束中。

    CASE表達式具備「簡單」和「搜索」兩種格式。首先看一個簡單格式的例子:

SELECT productid, productname, categoryid, 
	CASE categoryid 
		WHEN 1 THEN 'Beverages'
		WHEN 2 THEN 'Condiments'
		WHEN 3 THEN 'Confections'
		WHEN 4 THEN 'Dairy Products'
		WHEN 5 THEN 'Grains/Cereals'
		WHEN 6 THEN 'Meat/Poultry'
		WHEN 7 THEN 'Produce'
		WHEN 8 THEN 'Seafood'
		ELSE 'Unkonwn Categroy'
	END AS categoryname 
FROM Production.Products;

    簡單格式在CASE關鍵字後具備單個測試值或表達式,與WHEN子句中的可能值列表進行比較。

    在看一個搜索格式的例子:

SELECT orderid, custid, val, 
	CASE 
		WHEN val < 1000.00					 THEN 'Less than 1000' 
		WHEN val BETWEEN 1000.00 AND 3000.00 THEN 'Between 1000 and 3000' 
		WHEN val > 3000.00					 THEN 'More than 3000' 
		ELSE 'Unknown' 
	END AS valuecategory 
FROM Sales.OrderValues;

    搜索格式更加靈活,容許在WHEN中制定謂詞或邏輯表達式,而不是限制與進行相等比較。
    T-SQL支持的某些函數,能夠看做是CASE表達式的縮寫形式,如ISNULL、COALESCE、IIF和CHOOSE。這4和函數中只有COALESCE是標準的。此外,IIF和CHOOSE僅在SQL Server2012中可使用。

    ISNULL函數能夠接收兩個參數做爲輸入,並返回第一個非NULL的參數值,若是兩個參數值均爲NULL,則返回NULL。例如,ISNULL(col1,''),若是col1值不是NULL的話,那麼返回col1,若是col1是NULL的話,則返回空字符串。

    COALESCE函數與其相似,只是它支持兩個或更多參數,並返回第一個非NULL值,若是全部參數均爲NULL的話,則返回NULL。

    IIF和CHOOSE函數,是爲了支持更容易從Microsoft Access遷移。函數IIF(<logical_exp>,<exp1>,<exp2>),若是Logical_exp爲TRUE,則返回exp1,不然返回exp2。

    函數CHOOSE(<index>,<exp1>,<exp2>,...,<expn>),返回列表中指定索引的表達式。

NULL標記

    T-SQL支持用於表示缺失值的NULL標記,並使用三值邏輯。TRUE、FALSE和UNKNOWN,T-SQL遵循這方面的標準。

    邏輯表達式僅涉及已有或是現值,其計算結果爲TRUE或FALSE,但當邏輯表達式涉及NULL時,其計算結果爲UNKNOWN。例如salary>0,當salary等於1000時,結果爲TRUE。當salary等於-1000時,結果爲FALSE。當salary是NULL時,結果爲UNKNOWN。

    先來看看,SQL是怎麼處理計算結果爲TRUE和FALSE的表達式。例如salary>0出如今查詢篩選中(WHERE或HAVING),將返回表達式計算爲TRUE的行或組,那些結果爲FALSE的會被篩選掉。一樣,若是謂詞salary>0出如今表的CHECK約束中,全部行的表達式計算爲TRUE的INSERT或UPDATE語句會被接收,而那些計算結果爲FALSE的會被拒絕。

    接下來看看錶達式計算結果爲UNKNOWN的處理方式。對於查詢篩選而言,SQL的正確處理定義是接收TRUE,意味着FALSE和UNKNOWN會被篩選掉。相反,對於CHECK約束而言,SQL的正確處理定義是「拒絕FALSE」,因此TRUE和UNKNOWN會被接受。

    UNKNOWN一個棘手的問題是,當否認它時,仍然會獲得UNKNOWN值。例如,給出的謂語NOT(salary>0),當salary(工資)爲NULL時,salary>0的結果爲UNKNOWN,而且NOT UNKNOWN還是UNKNOWN。比較兩個NULL標記(NULL=NULL)結果也是UNKNOWN。所以SQL提供了IS NULL和IS NOT NULL來比較NULL。看幾個例子:

SELECT custid, country, region, city 
FROM Sales.Customers 
WHERE region = N'WA';

    執行上面的SQL既不會返回region不是WA的行,也不會返回region爲NULL的行。

SELECT custid, country, region, city 
FROM Sales.Customers 
WHERE region <> N'WA';

    執行上面的SQL既不會返回region屬性等於WA的行,也不會返回region爲NULL的行。

SELECT custid, country, region, city 
FROM Sales.Customers 
WHERE region = NULL;

    執行上面的SQL什麼都不會返回,由於region爲NULL的行與NULL比較會獲得UNKNOWN,而查詢篩選只支持TRUE。

SELECT custid, country, region, city 
FROM Sales.Customers 
WHERE region IS NULL;

    執行上面的SQL會返回region爲NULL的行。

SELECT custid, country, region, city 
FROM Sales.Customers 
WHERE region <> N'WA' OR region IS NULL;

    執行上面的SQL會返回region不是WA的和region是NULL的行。

    注意,對於分組和排序,兩個NULL表示被視爲相等。即GROUP BY將全部NULL分紅一組,ORDER BY也將全部NULL排序在一塊兒,標準SQL將NULL標記在現值以前排序,仍是以後排序留給了產品實施,T-SQL是在現值以前對NULL標記排序。

    爲了強制執行UNIQUE約束,標準SQL將NULL標記視爲彼此不一樣。相反地,T-SQL在UNIQUE約束中認爲NULL標記是相等的。

同時操做

    SQL支持一個稱做同時操做的概念,意思是出如今贊成邏輯處理階段的全部表達式在同一時間點進行邏輯計算,例如:

SELECT col1, col2 
FROM dbo.T1 
WHERE col1 <> 0 AND col2/col1 > 2

    這是關於同時操做的一個例子,但願返回col2/col1>2的全部行。所以有可能表中行col1是等於0的,不能夠將0作除數,因此在col2/col1 > 2以前判斷col1<>0,若是col1爲0那麼表達式會短路。

    遺憾的是,SQL Server不支持短路,它基於標準SQL的同事操做概念,SQL Server能夠按任意順序自由處理WHERE子句中的表達式。因此若是先執行了col2/col1>2這個表達式,而col1爲0,那麼就會致使執行失敗。

    有幾種方法能夠避免同時操做致使執行失敗。例如,CASE表達式中的WHEN子句的計算順序是有保證的,能夠按以下方式修改:

SELECT col1, col2 
FROM dbo.T1 
WHERE 
	CASE
		WHEN col1 = 0 THEN 'no'
		WHEN col2/col1 > 2 THEN 'yes'
		ELSE 'no'
	END = 'yes'

    或者使用數據方法來避免除以零的錯誤:

SELECT col1, col2 
FROM dbo.T1 
WHERE (col1 > 0 AND col2 > 2 * col1) OR (col1 < 0 AND col2 < 2 * col1);
相關文章
相關標籤/搜索