2012-07-13

SQL Server 2012 :認識 FORMAT 字串函數


適用版本:SQL Server 2012。

FORMAT() 字串函數
傳回以指定格式與選擇性文化特性所格式化的值。

將 FORMAT 函數用於將日期/時間與數值視為字串的地區設定感知格式化作業。
一般類型轉換仍可繼續使用 CAST 或 CONVERT。

語法:
FORMAT ( value, format [, culture ] )


注意事項:


引數 format、culture 是使用 .NET Framework 所支援的功能與文化特性。



請參考以下的範例程式碼:

EX1:認識 FORMAT 字串函數:格式化日期


-- FORMAT 字串函數:格式化日期與時間
DECLARE @td1 DATETIME2 = SYSDATETIME()

SELECT FORMAT( @td1, 'd') N'簡短日期', 
 FORMAT( @td1, 'D') N'完整日期',
 FORMAT( @td1, 'f') N'完整日期和簡短時間',
 FORMAT( @td1, 'F') N'完整日期和完整時間',
 FORMAT( @td1, 't') N'簡短時間',
 FORMAT( @td1, 'T') N'完整時間'
GO


-- 01_FORMAT 字串函數:格式化日期與時間



-- FORMAT 字串函數:使用文化特性與格式化日期
-- 格式模式使用 d:ShortDatePattern
DECLARE @td1 DATETIME ='20010203'

SELECT FORMAT( @td1, 'd', 'en-US') N'en-US_英文 - 美國',
 FORMAT( @td1, 'd', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( @td1, 'd', 'zh-TW') N'zh-TW_中文 - 台灣', 
 FORMAT( @td1, 'd', 'zh-CN') N'zh-CN_中文 - 中國',
 FORMAT( @td1, 'd', 'ko-KR') N'ko-KR_韓文 - 韓國'
GO


-- 02_FORMAT 字串函數:使用文化特性與格式化日期



-- FORMAT 字串函數:使用文化特性與格式化日期
-- 格式模式使用 D:LongDatePattern
DECLARE @td1 DATETIME ='20010203'

SELECT FORMAT( @td1, 'D', 'en-US') N'en-US_英文 - 美國',
 FORMAT( @td1, 'D', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( @td1, 'D', 'zh-TW') N'zh-TW_中文 - 台灣', 
 FORMAT( @td1, 'D', 'zh-CN') N'zh-CN_中文 - 中國',
 FORMAT( @td1, 'D', 'ko-KR') N'ko-KR_韓文 - 韓國'
GO


-- 03_FORMAT 字串函數:使用文化特性與格式化日期



-- FORMAT 字串函數:使用文化特性與格式化日期
-- 格式模式使用 F:FullDateTimePattern (完整日期和完整時間)
DECLARE @td1 DATETIME ='20010203'

SELECT FORMAT( @td1, 'F', 'en-US') N'en-US_英文 - 美國',
 FORMAT( @td1, 'F', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( @td1, 'F', 'zh-TW') N'zh-TW_中文 - 台灣', 
 FORMAT( @td1, 'F', 'zh-CN') N'zh-CN_中文 - 中國',
 FORMAT( @td1, 'F', 'ko-KR') N'ko-KR_韓文 - 韓國'
GO


-- 04_FORMAT 字串函數:使用文化特性與格式化日期



-- FORMAT 字串函數:自訂格式字串格式化日期
DECLARE @td1 DATETIME2 = SYSDATETIME()

SELECT FORMAT( @td1, 'yyyyMMdd') N'8碼日期格式',
 FORMAT( @td1, 'yyyy年MM月dd日 (ddd)') N'完整日期和星期幾縮寫',
 FORMAT( @td1, 'yyyy年MM月dd日 (dddd)') N'完整日期和完整星期幾',
 FORMAT( @td1, 'yyyy年MM月dd日 (ddd)', 'ja-JP') N'完整日期和星期幾縮寫_日文 - 日本',
 FORMAT( @td1, 'yyyy年MM月dd日 (dddd)', 'ja-JP') N'完整日期和完整星期幾_日文 - 日本';

SELECT FORMAT( @td1, 'MMM') N'月份',
 FORMAT( @td1, 'dddd, MMMM, yyyy') N'自訂完整日期',
 FORMAT( @td1, 'hh:mm:ss tt') N'自訂 12 小時制',
 FORMAT( @td1, 'HH:mm:ss tt') N'自訂 24 小時制', 
 FORMAT( @td1, 'HH:mm:ss tt zzz') N'自訂 24 小時制和完整時區位移';
GO


-- 05_FORMAT 字串函數:自訂格式字串格式化日期



-- FORMAT 字串函數:自訂格式化時間
DECLARE @td1 DATETIME2 = SYSDATETIME()

SELECT @td1 N'完整日期與完整時間',
 FORMAT( @td1, '%s') N'秒(不補前置字元0)',
 FORMAT( @td1, 'ss') N'秒(兩位數)',
 FORMAT( @td1, '%m') N'分(不補前置字元0)',
 FORMAT( @td1, 'mm') N'分(兩位數)',
 FORMAT( @td1, '%h') N'12 小時制(不補前置字元0)',
 FORMAT( @td1, 'hh') N'12 小時制(兩位數)',
 FORMAT( @td1, '%H') N'24 小時制(不補前置字元0)',
 FORMAT( @td1, 'HH') N'24 小時制(兩位數)';
GO


-- 06_FORMAT 字串函數:自訂格式化時間



-- FORMAT 字串函數:使用文化特性與格式化日期(星期幾)
DECLARE @td1 DATETIME2 = SYSDATETIME()

SELECT FORMAT( @td1, '%d', 'en-US') N'月份中的日(不補前置字元0)_英文 - 美國',
 FORMAT( @td1, 'dd', 'en-US') N'月份中的日(兩位數)_英文 - 美國',
 FORMAT( @td1, 'ddd', 'en-US') N'星期幾縮寫_英文 - 美國',
 FORMAT( @td1, 'dddd', 'en-US') N'完整星期幾_英文 - 美國';

SELECT FORMAT( @td1, '%d', 'zh-TW') N'月份中的日(不補前置字元0)_中文 - 台灣',
 FORMAT( @td1, 'dd', 'zh-TW') N'月份中的日(兩位數)_中文 - 台灣',
 FORMAT( @td1, 'ddd', 'zh-TW') N'星期幾縮寫_中文 - 台灣',
 FORMAT( @td1, 'dddd', 'zh-TW') N'完整星期幾_中文 - 台灣';

SELECT FORMAT( @td1, '%d', 'ja-JP') N'月份中的日(不補前置字元0)_日文 - 日本',
 FORMAT( @td1, 'dd', 'ja-JP') N'月份中的日(兩位數)_日文 - 日本',
 FORMAT( @td1, 'ddd', 'ja-JP') N'星期幾縮寫_日文 - 日本',
 FORMAT( @td1, 'dddd', 'ja-JP') N'完整星期幾_日文 - 日本';
GO


-- 07_FORMAT 字串函數:使用文化特性與格式化日期(星期幾)



-- FORMAT 字串函數:使用文化特性與格式化日期(月份)
DECLARE @td1 DATETIME2 = SYSDATETIME()

SELECT FORMAT( @td1, '%M', 'en-US') N'數字月份(不補前置字元0)_英文 - 美國',
 FORMAT( @td1, 'MM', 'en-US') N'數字月份(兩位數)_英文 - 美國',
 FORMAT( @td1, 'MMM', 'en-US') N'月份縮寫_英文 - 美國',
 FORMAT( @td1, 'MMMM', 'en-US') N'完整月份_英文 - 美國';

SELECT FORMAT( @td1, '%M', 'zh-TW') N'數字月份(不補前置字元0)_中文 - 台灣',
 FORMAT( @td1, 'MM', 'zh-TW') N'數字月份(兩位數)_中文 - 台灣',
 FORMAT( @td1, 'MMM', 'zh-TW') N'月份縮寫_中文 - 台灣',
 FORMAT( @td1, 'MMMM', 'zh-TW') N'完整月份_中文 - 台灣';

SELECT FORMAT( @td1, '%M', 'ja-JP') N'數字月份(不補前置字元0)_日文 - 日本',
 FORMAT( @td1, 'MM', 'ja-JP') N'數字月份(兩位數)_日文 - 日本',
 FORMAT( @td1, 'MMM', 'ja-JP') N'月份縮寫_日文 - 日本',
 FORMAT( @td1, 'MMMM', 'ja-JP') N'完整月份_日文 - 日本';
GO


-- 08_FORMAT 字串函數:使用文化特性與格式化日期(月份)



-- FORMAT 字串函數:搭配查詢資料表,格式化日期
USE Northwind
GO
SELECT OrderID, OrderDate,
 FORMAT( OrderDate, 'D', 'en-US') N'en-US_英文 - 美國',
 FORMAT( OrderDate, 'D', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( OrderDate, 'D', 'zh-TW') N'zh-TW_中文 - 台灣',
 FORMAT( OrderDate, 'yyyy年MM月dd日 (dddd)', 'zh-TW') N'自訂完整日期與完整星期_zh-TW', 
 FORMAT( OrderDate, 'yyyy年MM月dd日 (dddd)', 'ja-JP') N'自訂完整日期與完整星期_日文 - 日本'
FROM Orders
GO


-- 09_FORMAT 字串函數:搭配查詢資料表,格式化日期






EX2:認識 FORMAT 字串函數:格式化貨幣

-- FORMAT 字串函數:使用文化特性和格式化貨幣
DECLARE @c1 int =12345

SELECT FORMAT( @c1, 'C', 'en-US') N'en-US_英文 - 美國',
 FORMAT( @c1, 'C', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( @c1, 'C', 'zh-TW') N'zh-TW_中文 - 台灣', 
 FORMAT( @c1, 'C', 'zh-CN') N'zh-CN_中文 - 中國',
 FORMAT( @c1, 'C', 'ja-JP') N'ja-JP_日文 - 日本',
 FORMAT( @c1, 'C', 'ko-KR') N'ko-KR_韓文 - 韓國'
GO


-- 10_FORMAT 字串函數:使用文化特性和格式化貨幣



-- FORMAT 字串函數:格式化貨幣,調整輸出小數點位數
-- 示範環境:zh-TW
DECLARE @c1 numeric(6,1) =12345.6

SELECT FORMAT( @c1, 'C0') N'貨幣格式:C0',
 FORMAT( @c1, 'C') N'貨幣格式:C',
 FORMAT( @c1, 'C1') N'貨幣格式:C1', 
 FORMAT( @c1, 'C2') N'貨幣格式:C2', 
 FORMAT( @c1, 'C3') N'貨幣格式:C3',
 FORMAT( @c1, 'C4') N'貨幣格式:C4',
 FORMAT( @c1, 'C5') N'貨幣格式:C5'
GO


-- 11_FORMAT 字串函數:格式化貨幣,調整輸出小數點位數



-- FORMAT 字串函數:搭配查詢資料表,格式化貨幣
USE Northwind
GO
SELECT ProductID, ProductName, UnitPrice,
 FORMAT( UnitPrice, 'C', 'en-US') N'en-US_英文 - 美國',
 FORMAT( UnitPrice, 'C', 'de-DE') N'de-DE_德文 - 德國', 
 FORMAT( UnitPrice, 'C', 'zh-TW') N'zh-TW_中文 - 台灣', 
 FORMAT( UnitPrice, 'C', 'zh-CN') N'zh-CN_中文 - 中國',
 FORMAT( UnitPrice, 'C', 'ja-JP') N'ja-JP_日文 - 日本',
 FORMAT( UnitPrice, 'C', 'ko-KR') N'ko-KR_韓文 - 韓國'
FROM Products
GO


-- 12_FORMAT 字串函數:搭配查詢資料表,格式化貨幣






EX3:認識 FORMAT 字串函數:格式化數字(Number)

-- FORMAT 字串函數:格式化數字(Number)
DECLARE @n1 numeric(7,2) =12345.67

SELECT FORMAT( @n1, 'N') N'格式化數字:N',
 FORMAT( @n1, '#,#.0') N'格式化數字:#,#.0',
 FORMAT( @n1, '#,#.00') N'格式化數字:#,#.00',
 FORMAT( @n1, '#,#.000') N'格式化數字:#,#.000'
GO


-- 13_FORMAT 字串函數:格式化數字(Number)



-- FORMAT 字串函數:搭配查詢資料表,格式化數字
USE Northwind
GO
WITH CTE01
AS
( SELECT OrderID, SUM(UnitPrice * Quantity*(1-Discount)) 'SubTotal'
 FROM [Order Details]
 GROUP BY OrderID )
SELECT OrderID, SubTotal,
 FORMAT( SubTotal, 'N') N'格式化數字:N',
 FORMAT( SubTotal, '#,#.0') N'格式化數字:#,#.0',
 FORMAT( SubTotal, '#,#.00') N'格式化數字:#,#.00',
 FORMAT( SubTotal, '#,#.0000') N'格式化數字:#,#.0000'
FROM CTE01;
GO


-- 14_FORMAT 字串函數:搭配查詢資料表,格式化數字






EX4:認識 FORMAT 字串函數:格式化百分比(Percent)

-- FORMAT 字串函數:格式化百分比(Percent)
-- 百分比:P,結果:乘以 100 並加上百分比符號來顯示的數字。
DECLARE @c1 numeric(6,6) =0.123456

SELECT FORMAT( @c1, 'P0') N'百分比格式:P0',
 FORMAT( @c1, 'P') N'百分比格式:P',
 FORMAT( @c1, 'P1') N'百分比格式:P1', 
 FORMAT( @c1, 'P2') N'百分比格式:P2', 
 FORMAT( @c1, 'P3') N'百分比格式:P3',
 FORMAT( @c1, 'P4') N'百分比格式:P4',
 FORMAT( @c1, 'P5') N'百分比格式:P5'
GO

-- 15_FORMAT 字串函數:格式化百分比(Percent)






EX5. 認識 FORMAT 字串函數:標準數值格式字串

-- FORMAT 字串函數:標準數值格式字串
DECLARE @c1 int = 12

SELECT FORMAT( @c1, 'D') N'十進位:D',
 FORMAT( @c1, 'E') N'指數 (科學記號):E',
 FORMAT( @c1, 'P') N'百分比:P',
 FORMAT( @c1, 'X') N'十六進位:X',
 FORMAT( @c1, 'X4') N'十六進位:X4',
 FORMAT( @c1, 'X8') N'十六進位:X8'
GO


-- 16_FORMAT 字串函數:標準數值格式字串





認識 FORMAT 字串函數

FORMAT() 字串函數
傳回以指定格式與選擇性文化特性所格式化的值。

語法:

FORMAT ( value, format [, culture ] )


引數說明

(1) value
要格式化之受支援資料類型的運算式。

(2) format
nvarchar 格式模式。

format 引數必須包含有效的 .NET Framework 格式字串,其可以是標準格式字串 (例如 "C" 或 "D"),也可是日期與數值的自訂字元模式 (如 "MMMM dd, yyyy (dddd)")。
不支援複合格式。

如需這些格式模式的完整說明,請參閱 .NET Framework 文件中,有關一般字串格式、自訂日期與時間式,以及自訂數字格式的資訊。 您不妨從格式類型主題開始著手。

(3) culture
指定文化特性的選擇性 nvarchar 引數。

如未提供 culture 引數,將會使用目前工作階段的語言。 此語言是以 SET LANGUAGE 陳述式隱含或明確加以設定。
culture 的引數可以是 .NET Framework 所支援的任何文化特性,而不限於 SQL Server 明確支援的語言

如果 culture 引數無效,FORMAT 將會產生錯誤。

傳回類型

nvarchar 或 null
傳回值的長度取決於 format。


注意事項

將 FORMAT 函數用於將日期/時間與數值視為字串的地區設定感知格式化作業。
一般類型轉換仍可繼續使用 CAST 或 CONVERT。

發生的錯誤如果不是非 valid 的 culture (如無效的 format),FORMAT 會傳回 Null。

FORMAT 必須仰賴既存的 .NET Framework Common Language Runtime (CLR)。

因為必須要有 CLR 才可執行此函數,所以無法從遠端進行。
從遠端處理需要 CLR 的函數,會導致遠端伺服器發生錯誤。

值參數的詳細資訊

下表是 value 引數所能接受的資料類型,其中還附有 .NET Framework 對應的資訊:

-- 17_ value 引數所能接受的資料類型





參考資料

FORMAT (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/hh213505

字串函數 (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms181984.aspx

--
格式化型別 -- .NET Framework 4
http://msdn.microsoft.com/library/26etazsy.aspx

DateTimeFormatInfo 類別
http://msdn.microsoft.com/zh-tw/library/system.globalization.datetimeformatinfo.aspx

CultureInfo 類別
http://msdn.microsoft.com/zh-tw/library/system.globalization.cultureinfo(v=vs.80).aspx

Language Codes
http://msdn.microsoft.com/zh-tw/library/ms533052(v=vs.85).aspx

--
T-SQL:認識日期時間的分隔符號;搭配使用 SET DATEFORMAT、SET LANGUAGE
http://sharedderrick.blogspot.tw/2012/06/t-sql-set-dateformatset-language.html

2012-07-11

SQL Server:認識 NULLIF 運算式


NULLIF 運算式
如果兩個指定的運算式相等,便傳回 Null 值。

NULLIF 運算式回傳值的規則,整理如下:

(1) 如果兩個運算式「不相等」,NULLIF 會傳回第一個 expression。
(2) 如果運算式「相等」,NULLIF 會傳回第一個 expression 之類型的 Null 值。

NULLIF 相當於兩個運算式相等且產生的運算式為 NULL 的搜尋 CASE 運算式。

語法:

NULLIF ( expression , expression )


NULL 值表示是未知的值。
NULL 值與空的值或零值不同。

兩個 Null 值永遠不會相等。

因為每個 NULL 的值都是未知的,兩個 Null 值之間、或是一個 NULL 與其他任何值之間的比較都會傳回未知的。





請參考以下的範例程式碼:

EX1:認識 NULLIF 運算式


-- NULLIF 運算式:資料庫定序:區分大小寫
SELECT NULLIF(1 ,2) , NULLIF(1,1), NULLIF('AB','Ab'), NULLIF('AB','AC')
GO


-- 01_NULLIF 運算式:資料庫定序:區分大小寫



-- NULLIF 運算式:資料庫定序:不區分大小寫
USE Northwind
GO
SELECT NULLIF(1 ,2) , NULLIF(1,1), NULLIF('AB','Ab'), NULLIF('AB','AC')
GO


-- 02_NULLIF 運算式:資料庫定序:不區分大小寫



-- NULLIF() 運算式:搭配變數
DECLARE @c1 INT =10 ,@c2 INT = NULL

SELECT NULLIF(@c1 , @c2) 
GO


-- 03_ NULLIF() 運算式:搭配變數





EX2:使用 NULLIF 運算式來處理分母為 0 的情形

-- 分母為 0,產生錯誤訊息:8134。
DECLARE @c1 INT=0

SELECT 100/@c1
GO
/*
錯誤訊息:
訊息 8134,層級 16,狀態 1,行 3
發現除以零的錯誤。
*/


-- 04_分母為 0,產生錯誤訊息:8134



-- 使用 NULLIF 運算式來處理分母為 0 的情形
DECLARE @c1 INT=0

SELECT 100/NULLIF(@c1,0) N'運算結果'
GO
/*
回傳:NULL
*/


-- 05_使用 NULLIF 運算式來處理分母為 0 的情形






EX3:比較 NULLIF 和 CASE

下列查詢會評估 UnitsInStock 和 ReorderLevel 資料行中的值是否相同,以顯示 NULLIF 和 CASE 之間的相似度。

第一個查詢使用 NULLIF。第二個查詢則使用 CASE 運算式。

NULLIF 相當於兩個運算式相等且產生的運算式為 NULL 的搜尋 CASE 運算式。

-- 使用 NULLIF 運算式
USE Northwind
GO
SELECT ProductID, ProductName, UnitsInStock, ReorderLevel, NULLIF(UnitsInStock, ReorderLevel) N'運算結果'
FROM Products
GO

-- 使用 CASE 運算式
SELECT ProductID, ProductName, UnitsInStock, ReorderLevel,
 CASE
  WHEN UnitsInStock = ReorderLevel THEN NULL
  ELSE UnitsInStock
 END N'運算結果'
FROM Products
GO


-- 06_比較 NULLIF 和 CASE





認識 NULLIF 運算式

如果兩個指定的運算式相等,便傳回 Null 值。
語法:

NULLIF ( expression , expression )


引數

expression
這是任何有效的純量運算式。

傳回類型

傳回與第一個 expression 相同的類型。

如果兩個運算式不相等,NULLIF 會傳回第一個 expression。
如果運算式相等,NULLIF 會傳回第一個 expression 之類型的 Null 值。

注意事項

NULLIF 相當於兩個運算式相等且產生的運算式為 NULL 的搜尋 CASE 運算式。

我們建議您不要在 NULLIF 函數中使用時間相依函數,例如 RAND()。
這可能會導致系統評估此函數兩次,並且傳回與兩個引動過程不同的結果。




參考資料

NULLIF (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms177562

運算式 (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms190286

T-SQL:認識 COALESCE() 函數
http://sharedderrick.blogspot.tw/2012/06/t-sql-coalesce.html

T-SQL:認識 COALESCE() 函數,補充範例
http://sharedderrick.blogspot.tw/2012/06/t-sql-coalesce_14.html

2012-07-09

SQL Server 2012 :認識 IIF 邏輯函數


適用版本:SQL Server 2012。

IIF 邏輯函數
根據布林運算式求得的解為 true 或 false 而傳回兩值之一。

雖然 IIF() 邏輯函數是 SQL Server 2012版本新增加的功能,但若你已經使用過 VBA(Visual Basic for Applications) 或是 SSRS 決策函數等,那你可能已經使用過 IIF 函數。

語法:

IIF ( boolean_expression, true_value, false_value )



請參考以下的範例程式碼

EX1:認識 IIF() 邏輯函數 與 CASE() 運算式

-- 使用 CASE() 運算式
DECLARE @c1 int =10, @c2 int = 20

SELECT 
 CASE WHEN (@c1 < @c2) THEN N'成立'
  ELSE N'不成立'
 END N'判斷結果'
GO

-- 使用 IIF() 邏輯函數
DECLARE @c1 int =10, @c2 int = 20

SELECT IIF(@c1 < @c2, N'成立', N'不成立') N'判斷結果'
GO


-- 01_認識 IIF() 邏輯函數 與 CASE() 運算式





EX2:IIF() 邏輯函數 與 CASE() 運算式:查詢資料表

-- 使用 CASE() 運算式
USE Northwind
GO
SELECT ProductID, ProductName, UnitsInStock, 
 CASE 
  WHEN UnitsInStock>50 THEN N'高於'
  ELSE N'低於'
 END N'安全庫存數量(50)'
FROM Products
GO

-- 使用 IIF() 邏輯函數
SELECT ProductID, ProductName, UnitsInStock, 
 IIF( UnitsInStock>50, N'高於', N'低於') N'安全庫存數量(50)'
FROM Products
GO


-- 02_IIF() 邏輯函數 與 CASE() 運算式:查詢資料表





EX3:巢狀 IIF (Nested IIF)

-- 巢狀 IIF (Nested IIF)
--執行邏輯判斷後,回傳:老爺、夫人、少爺、小姐
DECLARE @gender varchar(1), @maritalstatus varchar(1)
SET @gender ='M'
SET @maritalstatus = 'M'

SELECT IIF(@gender ='M', IIF(@maritalstatus='M','老爺','少爺' ), IIF(@maritalstatus='M','夫人','小姐' ));
GO


-- 03_巢狀 IIF (Nested IIF)



-- CASE() 運算式 與 CTE(一般資料表運算式)
-- 執行邏輯判斷後,回傳:老爺、夫人、少爺、小姐
WITH tPerson AS
 (
 SELECT * 
 FROM ( VALUES (1,'M','M'),  (2,'M','F'), (3,'F','M'), (4,'F','F')) t(eid, gender, maritalstatus)
 ) 
SELECT  eid, gender, maritalstatus,
 CASE 
  WHEN gender ='M' AND maritalstatus='M' THEN N'老爺'
  WHEN gender ='M' AND maritalstatus='F' THEN N'少爺'
  WHEN gender ='F' AND maritalstatus='M' THEN N'夫人'
  WHEN gender ='F' AND maritalstatus='F' THEN N'小姐'
 END N'稱呼'
FROM tPerson;
GO

-- 執行巢狀 IIF 與 CTE(一般資料表運算式)
-- 邏輯判斷後,回傳:老爺、夫人、少爺、小姐
WITH tPerson AS
 (
 SELECT * 
 FROM ( VALUES (1,'M','M'),  (2,'M','F'), (3,'F','M'), (4,'F','F')) t(eid, gender, maritalstatus)
 ) 
SELECT  eid, gender, maritalstatus,
 IIF(gender ='M', IIF(maritalstatus='M','老爺','少爺' ), IIF(maritalstatus='M','夫人','小姐' )) N'稱呼'
FROM tPerson;
GO


-- 04_執行巢狀 IIF _CASE() 運算式 與 CTE(一般資料表運算式)





EX4:IIF() 邏輯函數:錯誤 NULL

-- 包含 NULL 常數的 IIF
SELECT IIF ( 10 > 20, NULL, NULL ) N'判斷結果';
GO
/*
錯誤訊息:
訊息 8133,層級 16,狀態 1,行 1
CASE 規格中的結果運算式至少要有一個是 NULL 常數以外的運算式。
*/


-- 05_IIF() 邏輯函數:錯誤 NULL



-- 若是改由變數方式:包含 NULL 參數的 IIF
DECLARE @c1 INT = NULL;
DECLARE @c2 INT = NULL;

SELECT IIF ( 1 > 20, @c1, @c2) N'判斷結果';
GO
/*
回傳:NULL
*/


-- 06_IIF() 邏輯函數:回傳 NULL





EX5:IIF() 邏輯函數:回傳式的運算有問題時

-- 布林運算式為真,回傳第一個運算式
-- 其中,第二個運算式會產生分母為 0 的錯誤
DECLARE @c1 int =200, @c2 int=0

SELECT IIF(10>5, @c1+@c2, @c1/@c2)
GO


-- 07_布林運算式為真,回傳第一個運算式



-- 布林運算式為假,回傳第二個運算式
-- 其中,第二個運算式會產生分母為 0 的錯誤
DECLARE @c1 int =200, @c2 int=0

SELECT IIF(10>50, @c1+@c2, @c1/@c2)
GO
/*
錯誤訊息:
訊息 8134,層級 16,狀態 1,行 3
發現除以零的錯誤。
*/


-- 08_布林運算式為假,回傳第二個運算式





認識 IIF 邏輯函數

IIF 邏輯函數
根據布林運算式求得的解為 true 或 false 而傳回兩值之一。

語法:

IIF ( boolean_expression, true_value, false_value )


引數說明

(1) boolean_expression
有效的布林運算式。
此引數若不是布林運算式,將會引發語法錯誤。

(2) true_value
當 boolean_expression 求得的解為 true 時所要傳回的值。

(3) false_value
當 boolean_expression 求得的解為 false 時所要傳回的值。


傳回類型
從 true_value 及 false_value 的類型中,傳回優先順序最高的資料類型。


注意事項

IIF 是一種編寫 CASE 陳述式的簡略方法。
其會求得第一個引數所傳遞之布林運算式的解,然後依據求解結果,傳回另外兩個引數之一。

換言之,如果布林運算式為 true,即會傳回 true_value;如果布林運算式為 false 或不明,即會傳回 false_value。
true_value 及 false_value 可以是任何類型。

套用到布林運算式、NULL 處理及傳回類型之 CASE 陳述式的規則,也同樣會套用至 IIF。

IIF 轉換為 CASE 的事實,對此函數的其他方面行為也有影響。

由於 CASE 陳述式最多只可巢狀化到層級 10,因此 IIF 陳述式最多也只可巢狀化至層級 10。

此外,IIF 會以語意相等之 CASE 陳述式,並以遠端處理之 CASE 陳述式的所有行為,從遠端處理到其他伺服器。





參考資料

IIF (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh213574.aspx

CASE (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/ms181765.aspx

運算式範例 (報表產生器及 SSRS)
http://technet.microsoft.com/zh-tw/library/ms157328

IIf 函式 -- Visual Studio 2008
http://msdn.microsoft.com/zh-tw/library/27ydhh0d(v=vs.90).aspx

IIf 函數 -- Office Access 2007
http://office.microsoft.com/zh-tw/access-help/iif-function-HA001228853.aspx

2012-07-06

SQL Server 2012 :認識 CHOOSE 邏輯函數


適用版本:SQL Server 2012。

CHOOSE 邏輯函數
從數值清單傳回指定索引的項目。

CHOOSE 邏輯函數是 SQL Server 2012 版本新增加的函數,這類似於在 Office Access 內的 Choose 函數,會從引數清單選取並傳回值。

語法:

CHOOSE ( index, val_1, val_2 [, val_n ] )



請參考以下的範例程式碼:

EX1:認識 CHOOSE() 邏輯函數

 -- 認識 CHOOSE() 邏輯函數
SELECT CHOOSE( 4, N'營業員', N'組長', N'經理', N'協理') N'回傳結果'
GO

-- 變數與 CHOOSE() 邏輯函數
DECLARE @idx int =4

SELECT CHOOSE( @idx, N'營業員', N'組長', N'經理', N'協理') N'回傳結果'
GO


-- 01_認識 CHOOSE() 邏輯函數



-- CHOOSE() 邏輯函數:全部的引數都使用變數
DECLARE @idx int = 1, @var1 nvarchar(10) = N'值1', @var2 nvarchar(10) = N'值2', @var3 nvarchar(10) = N'值3'

SELECT CHOOSE(@idx, @var1, @var2, @var3) N'回傳結果'
GO


-- 02_CHOOSE() 邏輯函數:全部的引數都使用變數





EX2. CHOOSE() 邏輯函數、CASE() 運算式、資料表聯結

USE Northwind
GO
SELECT * FROM Categories
SELECT * FROM Products
GO

-- CHOOSE() 邏輯函數:查詢資料表
-- 估計的子樹成本:0.0033744
SELECT ProductID, ProductName, CategoryID,
 CHOOSE(CategoryID, 'Beverages', 'Condiments', 'Confections', 'Dairy Products', 'Grains/Cereals', 'Meat/Poultry', 'Produce', 'Seafood') 'CategoryName'
FROM Products
GO


-- 03_CHOOSE() 邏輯函數:查詢資料表



-- 04_CHOOSE() 邏輯函數:查詢資料表_估計的子樹成本



-- CASE() 運算式
-- 估計的子樹成本:0.0033744
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'
 END 'CategoryName'
FROM Products
GO

-- 05_CASE() 運算式:查詢資料表_估計的子樹成本



-- 資料表聯結
-- 估計的子樹成本:0.0103786
SELECT ProductID, ProductName, p.CategoryID, CategoryName
FROM Products p INNER JOIN Categories c
 ON c.CategoryID = c.CategoryID
GO


-- 06_資料表聯結:查詢資料表_估計的子樹成本



由上,整理這三段 T-SQL 所耗損的子樹成本:

(1) CHOOSE() 邏輯函數:查詢資料表 -- 估計的子樹成本:0.0033744
(2) CASE() 運算式 -- 估計的子樹成本:0.0033744
(3) 資料表聯結 -- 估計的子樹成本:0.0103786



EX4:輸入不存在的索引值

-- 索引值:0
SELECT CHOOSE( 0, N'營業員', N'組長', N'經理', N'協理') N'回傳結果'
GO
/*
回傳:NULL
*/

-- 超過的索引值
SELECT CHOOSE( 10, N'營業員', N'組長', N'經理', N'協理') N'回傳結果'
GO
/*
回傳:NULL
*/

-- 變數傳入:超過的索引值
DECLARE @idx int =10

SELECT CHOOSE( @idx, N'營業員', N'組長', N'經理', N'協理') N'回傳結果'
GO
/*
回傳:NULL
*/

-- 07_輸入不存在的索引值






參考資料

CHOOSE (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh213019.aspx

資料類型優先順序 (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/ms190309.aspx

邏輯函數 (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh213226

Choose 函數 -- Office Access 2007
http://office.microsoft.com/zh-tw/access-help/HA001228797.aspx


2012-07-04

SQL Server 2012 :認識 TRY_CAST 轉換函數


適用版本:SQL Server 2012。

TRY_CAST() 轉換函數
轉換運算式的資料類型;若轉換失敗,則傳回 Null。

語法:

TRY_CAST ( expression AS data_type [ ( length ) ] )


在 SSMS 管理工具上,TRY_CAST() 轉換函數卻是顯示:「不是可辨識的內建函數名稱」
但在功能上,仍是可以正常運作。




建議:

先學習 CAST() 轉換函數的使用方式。

先參考以下的資料:
CAST 和 CONVERT (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/ms187928




請參考以下的範例程式碼:

EX1:認識 CAST()、TRY_CAST() 轉換函數


-- CAST() 轉換函數,輸入字串:123,轉型為 int 
SELECT CAST('123' AS int) N'資料轉型為 int'
GO


-- 01_CAST() 轉換函數,輸入字串:123,轉型為 int



-- CAST() 轉換函數:輸入字串:A123,嘗試轉型為 int 
SELECT CAST('A123' AS int)
GO
/*
錯誤訊息:
訊息 245,層級 16,狀態 1,行 2
將 varchar 值 'A123' 轉換成資料類型 int 時,轉換失敗。
*/


-- 02_CAST() 轉換函數:輸入字串:A123,嘗試轉型為 int



-- TRY_CAST() 轉換函數:輸入字串:A123,嘗試轉型為 int
-- 但 TRY_CAST() 轉換函數,SSMS 管理工具卻顯示:不是可辨識的內建函數名稱
-- 若轉換失敗,則傳回 Null。
SELECT TRY_CAST('A123' AS int) N'資料轉型為 int'
GO
/*
回傳:NULL
*/


-- 03_TRY_CAST() 轉換函數:輸入字串:A123,嘗試轉型為 int



-- CAST() 轉換函數:GETDATE() 顯示目前的伺服器日期時間
SELECT GETDATE() N'尚未轉換_伺服器的日期時間',
   CAST(GETDATE() AS varchar(30)) N'CAST() 函數轉為字串',
   CONVERT(varchar(30), GETDATE(), 126) N'CONVERT() 函數轉為 ISO 8601 格式';
GO

-- CAST() 轉換函數:SYSDATETIME() 顯示目前的伺服器日期時間
SELECT SYSDATETIME() N'尚未轉換_伺服器的日期時間',
   CAST(SYSDATETIME() AS varchar(30)) N'CAST() 函數轉為字串',
   CONVERT(varchar(30), SYSDATETIME(), 126) N'CONVERT() 函數轉為 ISO 8601 格式';
GO


-- 04_CAST() 轉換函數:GETDATE()以及SYSDATETIME()



-- TRY_CAST() 轉換函數:GETDATE() 顯示目前的伺服器日期時間
-- 但卻顯示:不是可辨識的內建函數名稱
SELECT GETDATE() N'尚未轉換_伺服器的日期時間',
   TRY_CAST(GETDATE() AS varchar(30)) N'TRY_CAST() 函數轉為字串',
   CONVERT(varchar(30), GETDATE(), 126) N'CONVERT() 函數轉為 ISO 8601 格式';
GO

-- TRY_CAST() 轉換函數:SYSDATETIME() 顯示目前的伺服器日期時間
SELECT SYSDATETIME() N'尚未轉換_伺服器的日期時間',
   TRY_CAST(SYSDATETIME() AS varchar(30)) N'TRY_CAST() 函數轉為字串',
   CONVERT(varchar(30), SYSDATETIME(), 126) N'CONVERT() 函數轉為 ISO 8601 格式';
GO


-- 05_TRY_CAST() 轉換函數:GETDATE()以及SYSDATETIME()






EX2:TRY_CAST() 轉換函數:不允許從資料類型 int 明確轉換至 xml

-- TRY_CAST() 轉換函數:仍是有明確的錯誤
-- 這是因為整數是無法轉型為 XML 資料類型
SELECT TRY_CAST(4 AS xml) AS Result;
GO
/*
錯誤訊息:
訊息 529,層級 16,狀態 2,行 1
不允許從資料類型 int 明確轉換至 xml。
*/


-- 06_TRY_CAST() 轉換函數:不允許從資料類型 int 明確轉換至 xml






EX3:TRY_CAST() 轉換函數:判斷輸入的字串,是否可以轉換為數值

-- TRY_CAST() 轉換函數:輸入字串:A123,判斷輸入的字串,是否可以轉換為數值
DECLARE @cs1 varchar(100) ='A123', @cnt INT
SET @cnt=TRY_CAST(@cs1 AS int)

IF @cnt IS NOT NULL
 SELECT @cnt N'轉換結果'
ELSE
 SELECT N'轉換失敗' N'轉換結果'
GO


-- 07_TRY_CAST() 轉換函數:輸入字串:A123,判斷輸入的字串,是否可以轉換為數值



-- TRY_CAST() 轉換函數:輸入字串:123,判斷輸入的字串,是否可以轉換為數值
DECLARE @cs1 varchar(100) ='123', @cnt INT
SET @cnt=TRY_CAST(@cs1 AS int)

IF @cnt IS NOT NULL
 SELECT @cnt N'轉換結果'
ELSE
 SELECT N'轉換失敗' N'轉換結果'
GO


-- 08_TRY_CAST() 轉換函數:輸入字串:123,判斷輸入的字串,是否可以轉換為數值



-- TRY_CAST() 轉換函數,搭配使用 CASE 運算式
-- 輸入字串:A123
DECLARE @cs1 varchar(100) ='A123', @cnt INT
SET @cnt=TRY_CAST(@cs1 AS int)

SELECT 
 CASE WHEN @cnt IS NOT NULL
  THEN @cnt
  ELSE 0 
 END N'轉換結果'
GO


-- 09_TRY_CAST() 轉換函數,搭配使用 CASE 運算式






EX4:TRY_CAST() 轉換函數:搭配查詢資料表

-- TRY_CAST() 轉換函數:轉換為整數
USE Northwind
GO
SELECT  CustomerID, City, PostalCode,
 TRY_CAST(PostalCode AS int) N'PostalCode_TRY_CAST_整數'
FROM Customers
GO


-- 10_TRY_CAST() 轉換函數:轉換為整數



-- TRY_CAST() 轉換函數:轉換為整數,搭配 ISNULL() 函數
SELECT  CustomerID, City, PostalCode,
 TRY_CAST(PostalCode AS int) N'PostalCode_TRY_CAST_整數',
 ISNULL(TRY_CAST(PostalCode AS int), 0) N'PostalCode_TRY_CAST_ISNULL_整數'
FROM Customers
GO


-- 11_TRY_CAST() 轉換函數:轉換為整數,搭配 ISNULL() 函數







參考資料

TRY_CAST (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh974669

CAST 和 CONVERT (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/ms187928

TRY_CONVERT (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh230993

轉換函數 (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/hh231076

CASE (Transact-SQL)
http://msdn.microsoft.com/zh-tw/library/ms181765.aspx

2012-07-02

SQL Server 2012 SSRS 2012:Reporting Services 支援 xlsx、docx 檔案格式;不再有 xls 檔案受限於最大資料列: 65536 之問題



感謝 Alex Chuo 的通知:SSRS 2012:Reporting Services 支援 xlsx、docx 檔案格式;不再有 xls 檔案受限於最大資料列: 65536 之問題。




適用環境:
SQL Server 2012 版本。
Reporting Services 2012。

在 SQL Server 2012 Reporting Services 中,預設 Excel 轉譯器是與 Microsoft Excel 2007-2010 相容的版本。

在報表管理員和 SharePoint 清單的 [匯出] 功能表中,這就是 [Excel] 選項。

使用新版本 Excel 2007-2010 轉譯延伸模組有許多優點。

下表將比較 Excel 2003 與 Excel 轉譯器。

-- 00_使用新版本 Excel 2007-2010 轉譯延伸模組



改用新版本的 Excel 2007-2010(*.xlsx) 轉譯延伸模組:

(1) 可支援到 1,048,576 筆資料列。
(2) 可支援到 16,384 資料行。

也就是說,Excel 2007-2010 讓試算表的容量擴充到超過 1 百萬資料列和 1 萬 6 千資料行。





以下為使用 SSRS 2012 版本的畫面:

-- 01_SSRS_2012_檢視報表_另存新檔



-- 02_SSRS_2012_開啟或儲存Excel



-- 03_SSRS_2012_另存新檔_只能選xlsx



-- 04_SSRS_2012_超過65,536 列筆資料列







以下為使用 SSRS 2008 R2 版本的畫面:

-- 05_SSRS_2008_R2_檢視報表_另存新檔




但若是匯出的資料列筆數超過 65536,將會遭遇的錯誤訊息如下:

-- 06_SSRS_2008_R2_超過最大資料列_65536



'/Reports' 應用程式中發生伺服器錯誤。
--------------------------------------------------------------------------------

Excel 轉譯延伸模組 : 列數超過這種格式每個工作表的最大資料列限制; 需要的資料列: 113446,最大資料列: 65536 
描述: 在執行目前 Web 要求的過程中發生未處理的例外情形。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。 

例外詳細資訊: Microsoft.Reporting.WebForms.ReportServerException: Excel 轉譯延伸模組 : 列數超過這種格式每個工作表的最大資料列限制; 需要的資料列: 113446,最大資料列: 65536

原始程式錯誤: 

在執行目前 Web 要求期間,產生未處理的例外狀況。如需有關例外狀況來源與位置的資訊,可以使用下列的例外狀況堆疊追蹤取得。  

堆疊追蹤: 

[ReportServerException: Excel 轉譯延伸模組 : 列數超過這種格式每個工作表的最大資料列限制; 需要的資料列: 113446,最大資料列: 65536]

[ReportServerException: Excel 轉譯延伸模組 : 列數超過這種格式每個工作表的最大資料列限制; 需要的資料列: 113446,最大資料列: 65536 (rrRenderingError)]
   Microsoft.Reporting.WebForms.ServerReport.ServerUrlRequest(Boolean isAbortable, String url, Stream outputStream, String& mimeType, String& fileNameExtension) +1018
   Microsoft.Reporting.WebForms.ServerReport.InternalRender(Boolean isAbortable, String format, String deviceInfo, NameValueCollection urlAccessParameters, Stream reportStream, String& mimeType, String& fileNameExtension) +1329
   Microsoft.Reporting.WebForms.ServerModeSession.RenderReport(String format, Boolean allowInternalRenderers, String deviceInfo, NameValueCollection additionalParams, Boolean cacheSecondaryStreamsForHtml, String& mimeType, String& fileExtension) +209
   Microsoft.Reporting.WebForms.ExportOperation.PerformOperation(NameValueCollection urlQuery, HttpResponse response) +219
   Microsoft.Reporting.WebForms.HttpHandler.ProcessRequest(HttpContext context) +171
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +599
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +171

--------------------------------------------------------------------------------
版本資訊: Microsoft .NET Framework 版本:2.0.50727.4927; ASP.NET 版本:2.0.50727.4927 






匯出至 Microsoft Excel (報表產生器及 SSRS)

在 SQL Server 2012 Reporting Services 中,預設 Excel 轉譯器是與 Microsoft Excel 2007-2010 相容的版本。

在報表管理員和 SharePoint 清單的 [匯出] 功能表中,這就是 [Excel] 選項。

與 Excel 2003 相容的舊版現在已命名為 Excel 2003,而且使用該名稱列於功能表上。
根據預設,系統不會顯示 [Excel 2003] 功能表選項,但是管理員可以透過更新 RSReportServer 組態檔,顯示此選項。

若要使用 Excel 2003 轉譯器,從 SQL Server Data Tools (SSDT) 匯出報表,請更新 RSReportDesigner 組態檔。

不過,讓 Excel 2003 轉譯器顯示並不適用於所有案例。
因為 RSReportServer 組態檔位於報表伺服器上,所以您從中匯出報表的工具或產品必須連接至報表伺服器,以便讀取組態檔。

如果您在中斷連接或本機模式中使用工具或產品,讓 Excel 2003 轉譯器顯示就沒有任何作用。
[Excel 2003] 功能表選項會維持無法使用的狀態。

如果您在 RSReportDesigner 組態檔中,讓 Excel 2003 轉譯器顯示,就一定可以在 SQL Server Data Tools (SSDT) 報表預覽中使用 [Excel 2003] 功能表選項。

使用新版本 Excel 2007-2010 轉譯延伸模組有許多優點。

改用新版本的 Excel 2007-2010(*.xlsx) 轉譯延伸模組:

(1) 可支援到 1,048,576 筆資料列。
(2) 可支援到 16,384 資料行。

(3) Excel 2007 讓試算表的容量擴充到超過 1 百萬資料列和 1 萬 6 千資料行。

Excel 轉譯延伸模組會將報表轉譯成 Microsoft Excel 2007-2010 的原生格式。
此格式為 Office Open XML。

此轉譯器所產生之檔案的內容類型為 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 而檔案的副檔名為 .xlsx。

與 Microsoft Excel 2003 相容的舊版 Excel 轉譯延伸模組已重新命名為 Excel 2003。
根據預設,只能使用 Excel 轉譯延伸模組。

您必須更新 Reporting Services 組態檔,才能使用 Excel 2003 轉譯延伸模組。

此轉譯器所產生之檔案的內容類型為 application/vnd.ms-excel 而檔案的副檔名為 .xls。
此轉譯器可提供 Microsoft Excel 2003 的回溯相容性。

--
SQL Server 2012 中 SQL Server Reporting Services 已被取代的功能

(1) Microsoft Word 和 Microsoft Excel 1997-2003 轉譯
(2) Microsoft Word 和 Microsoft Excel 1997-2003 二進位交換檔案格式的 Reporting Services BIFF8 轉譯延伸模組 Reporting Services 報表。

SQL Server 2012 包含以 Microsoft Office 2007-2010 Open XML 格式轉譯的延伸模組。




參考資料

匯出至 Microsoft Excel (報表產生器及 SSRS)
http://msdn.microsoft.com/zh-tw/library/dd255234.aspx

SQL Server 2012 中 SQL Server Reporting Services 已被取代的功能
http://msdn.microsoft.com/zh-tw/library/ms143509.aspx

無法匯入超過 65,536 列是文字檔到 Excel 97、 Excel 2000、 Excel 2002 和 Excel 2003
http://support.microsoft.com/kb/120596/zh-tw

SQL Server 2008:SSIS 2008 與 Excel 2007(*.xlsx、*.xlsb)
http://sharedderrick.blogspot.com/2009/11/sql-server-2008ssis-2008-excel.html

SSIS 2005 與 Excel 2007 (*.xlsx , *.xlsb)
http://sharedderrick.blogspot.com/2008/01/ssis-excel-2007-xlsx-xlsb.html

使用 SSIS 將 SSRS 所產生 Excel 檔案,做適當的歸檔與分類
http://sharedderrick.blogspot.tw/2009/11/ssis-ssrs-excel.html

SQL Server Reporting Services (SSRS): Reporting Services in SQL Server 2012 (codename "Denali") will support XLSX, DOCX formats. Bye bye 65536 rows limit in XLS files ;)
http://blogs.msdn.com/b/farukcelik/archive/2012/02/01/sql-server-reporting-services-ssrs-reporting-services-in-sql-server-2012-codename-quot-denali-quot-will-support-xlsx-docx-formats-bye-bye-65536-rows-limit-in-xls-files.aspx