搜尋本站文章

2015-12-30

日期時間資料類型:ISNULL函數、IS [NOT] NULL 述詞,對時間值是 NULL 時的處理方式是不同的



SQL Server 的日期時間類型,例如有:datetimeoffset、datetime2、smalldatetime、datetime等。

若輸入資料值時,僅輸入日期值,卻未提供時間值時,系統自動以 1900-01-01 00:00:00.000,午夜零點零分零秒的方式來呈現。

這對 ISNULL函數、IS [NOT] NULL 述詞,在處理這類資料值時,就會有不同的行為。




請參考以下的範例:

USE tempdb
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[atb01]') AND type in (N'U'))
 BEGIN
  DROP TABLE [dbo].[atb01]
  CREATE TABLE [dbo].[atb01](
 [Sid] [int] PRIMARY KEY,
 [Aircode] [varchar](50) NULL,
 [Edate] [datetime] NULL)
 END
ELSE 
BEGIN
 CREATE TABLE [dbo].[atb01](
 [Sid] [int] PRIMARY KEY,
 [Aircode] [varchar](50) NULL,
 [Edate] datetime NULL)
END
GO

-- 新增四筆資料列
INSERT atb01 VALUES(1, 'A201',GETDATE())
INSERT atb01 VALUES(2, 'A202', '1900/01/01') -- 只給日期,未給時間。資料類型:[datetime]。
INSERT atb01(Sid, Aircode) VALUES(3,'A203')
INSERT atb01(Sid, Aircode) VALUES(4,'A204')
GO

-- 00 有 4 筆資料列
/*
已知:第二筆資料列,Edate資料行的資料類型是:[datetime]。
只輸入日期,未給時間。

查詢時,可觀察到,系統自動以 1900-01-01 00:00:00.000,午夜零點零分零秒的方式來呈現。
由於未提供時間值,仍是 NULL。
*/

SELECT Sid, Aircode, Edate FROM atb01



- 01_範例資料表,有4筆資料列







01 使用 ISNULL() 函數,3 筆資料列

-- 01 使用 ISNULL() 函數,3 筆資料列




/*
ISNULL 函數:以指定的取代值來取代 NULL。

使用 ISNULL() 函數,將會抓取到  3 筆資料列,包含:兩筆未提供任何值,以及一筆僅提供日期值的資料列。
*/

SELECT Sid, Aircode, Edate FROM atb01
WHERE ISNULL(Edate,'') = ''


-- 02_使用 ISNULL() 函數,抓到3筆資料列






02 使用 IS NULL 述詞,2 筆資料列



-- 02 使用 IS NULL 述詞,2 筆資料列 
/*

IS [NOT] NULL 述詞:判斷指定的運算式是否為 NULL。
若使用 IS [NOT] NULL 述詞來判斷 Edate 資料行是否為 NULL,將會抓取到 2 筆資料列。
*/

SELECT Sid, Aircode, Edate FROM atb01
WHERE Edate IS NULL



-- 03_IS [NOT] NULL 述詞,抓到2筆資料列






有些專案在設計時,若沒有輸入

1. 若沒有輸入日期時間時,前端程式將自動輸入 1900/01/01。
2. 後續接手的人員,可能改變此規則,改採取不輸入,讓系統存放 NULL 值,這又會是另一套規則。

或許,在某些狀況下, NULL 與 1900/01/01,對於此專案是具相同的意義。
但使用 ISNULL 函數與 IS NULL 述詞,卻是取得不同的結果。

若能修改原始資料值,具備一致的特性,則在 WHERE 條件式就可以精簡許多,也有機會可以使用索引來提升查詢效能。




ISNULL 函數

ISNULL 函數:以指定的取代值來取代 NULL。

語法:
ISNULL ( check_expression , replacement_value )

check_expression
這是要檢查 NULL 的運算式。check_expression 可以是任何類型。

replacement_value
這是 check_expression 是 NULL 時所傳回的運算式。replacement_value 必須是能夠隱含地轉換成 check_expresssion 類型的類型。




IS [NOT] NULL 述詞

判斷指定的運算式是否為 NULL。

語法:
expression IS [ NOT ] NULL

引數

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

NOT
指定執行布林結果的否定運算。 這個述詞會反轉它的傳回值,如果值不是 NULL,就傳回 TRUE,如果值是 NULL,就傳回 FALSE。

結果類型 Boolean

傳回碼值
如果 expression 的值是 NULL,IS NULL 會傳回 TRUE;否則,它會傳回 FALSE。
如果 expression 的值是 NULL,IS NOT NULL 會傳回 FALSE;否則,它會傳回 TRUE。

備註
若要判斷運算式是否為 NULL,請利用 IS NULL 或 IS NOT NULL 來取代比較運算子 (如 = 或 !=)。
當兩個引數或其中一個引數是 NULL 時,比較運算子會傳回 UNKNOWN。



參考資料

SQL Server:認識 ISNULL 函數
http://sharedderrick.blogspot.tw/2012/06/t-sql-isnull.html

ISNULL (Transact-SQL)
https://msdn.microsoft.com/zh-tw/library/ms184325(v=sql.120).aspx

資料類型 (Transact-SQL)
https://msdn.microsoft.com/zh-tw/library/ms187752(v=sql.120).aspx

IS [NOT] NULL (Transact-SQL)
https://msdn.microsoft.com/zh-tw/library/ms188795(v=sql.120).aspx

2015-12-24

執行個體的服務啟動帳戶(NT SERVICE\MSSQLSERVER),應該具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限

示範環境:
1. SQL Server 2014
2. 作業系統:Windows 10 與 Windows Server 2012 R2

以存取磁碟的效能來考量

執行個體的服務啟動帳戶,預設是使用「虛擬帳戶」:NT SERVICE\MSSQLSERVER,應該具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限。

依據預設值,是沒有具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限,請參考以下的示範:

建立資料庫:Instant01,資料檔案的初始值大小是:512 MB。

-- 01_建立範例資料庫


-- 02_未具備-執行磁碟區維護工作



建立此資料庫,需要費時:9,869 ms。




若服務啟動帳戶具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限,請參考以下的範例:

-- 03_已具備-執行磁碟區維護工作



建立資料庫,需要費時:778 ms。



測試結果

9,869 ms(預設值) 比上 778 ms(調整後),兩者差距:9,091 ms。



設定具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限

-- 04_使用 Local Security Policy



-- 05_設定具備「執行磁碟區維護工作(Perform volume maintenance tasks)」安全性原則的權限



-- 06_檢視_Perform volume maintenance tasks



中文版本

-- 07__使用-本機安全性原則



-- 08_找到多個相符合名稱



-- 09_設定具備-磁碟區維護工作



-- 10_檢視_磁碟區維護工作





立即檔案初始化(Instant File Initialization)

在 SQL Server 2005 及更新的版本中,可將資料檔立即初始化,以便快速執行資料庫或檔案群組的還原作業。

立即檔案初始化會回收使用過的磁碟空間,但不以零填滿該空間。而是在將新資料寫入檔案時,覆寫磁碟內容。

雖然記錄檔初始化仍然需要歸零,不過這項作業可以跟備份的資料傳輸作業平行進行。還原的向前復原步驟則要等到所有資料都已經傳輸而且整個記錄都已經初始化才會啟動。

附註附
立即檔案初始化僅適用於 Microsoft Windows XP、Windows Server 2003 或更新版本的系統。

若要使用立即檔案初始化,您必須在 Windows 帳戶之下執行 MSSQLSERVER 服務帳戶,並指派 Windows SE_MANAGE_VOLUME_NAME 特殊權限給該 Windows 帳戶。

此權限依預設會指定給 Windows Administrators 群組。

若您有系統管理員權限,即可將 Windows 帳戶新增至「執行磁碟區維護工作」安全性原則,藉以指派此權限。



Windows 7 和 Windows Server 2008 R2 中提供的新帳戶類型

Windows 7 和 Windows Server 2008 R2 有兩種新的服務帳戶類型,分別稱為「受管理的服務帳戶」(Managed Service Account,MSA) 和「虛擬帳戶」(Virtual Account)。

受管理的服務帳戶和虛擬帳戶的設計在於提供重要的應用程式 (例如 SQL Server) 並與自己的帳戶隔離,同時不需系統管理員手動管理服務主要名稱 (SPN) 和這些帳戶的認證。

這些帳戶可讓長期管理服務帳戶使用者、密碼和 SPN 的工作更輕鬆。

虛擬帳戶(Virtual Accounts)

Windows Server 2008 R2 和 Windows 7 中的虛擬帳戶是「受管理的本機帳戶」(Managed Local Account),會提供下列功能來簡化服務管理工作。

虛擬帳戶是自動管理的,而且虛擬帳戶可以在網域環境中存取網路。

如果在 Windows Server 2008 R2 或 Windows 7 上安裝 SQL Server 的期間針對服務帳戶使用預設值,則會使用以執行個體名稱做為服務名稱的虛擬帳戶,其格式為 NT SERVICE\。 

以虛擬帳戶執行的服務,會利用電腦帳戶的認證存取網路資源,其格式為 \$。 

指定虛擬帳戶啟動 SQL Server 時,請讓密碼空白。 如果虛擬帳戶無法註冊服務主要名稱 (SPN),請手動註冊 SPN。

注意事項

虛擬帳戶無法用於 SQL Server 容錯移轉叢集執行個體,因為虛擬帳戶在叢集的每一個節點上不會有相同的 SID。



執行磁碟區維護工作(Perform volume maintenance tasks)

此安全性原則設定會決定哪些使用者可以執行磁碟區或磁碟管理工作,例如重組現有的磁碟區、 建立或移除磁碟區,以及執行磁碟清理工具。

指派此使用者權限時請特別小心。
這個使用者權限的使用者可以瀏覽磁碟並擴充匯入包含其他資料的記憶體。

擴充的檔案開啟時,使用者可能可以讀取和修改取得的資料。




參考資料

執行磁碟區維護工作
https://technet.microsoft.com/zh-tw/library/dn221971.aspx

最佳化 SQL Server 中的備份和還原效能
https://technet.microsoft.com/zh-tw/library/ms190954(v=sql.105).aspx

設定 Windows 服務帳戶與權限
https://msdn.microsoft.com/zh-tw/library/ms143504(v=sql.120).aspx

執行磁碟區維護工作
https://technet.microsoft.com/zh-tw/library/dn221971.aspx