微軟BI 之SSIS 系列 - 對於平面文件中 NULL 值處理過程中容易極易混淆的幾個細節


開篇介紹

最近有人問我有關文件處理中空值處理的相關問題:
  1. OLE DB Destination 中的 Keep Nulls 如何控制 NULL 值的顯示?
  2. 為什么選中了 Keep Nulls 但是數據庫中沒有 NULL 值?
  3. 為什么在 Flat File Source 中勾選上了 Retain null values..但目標表上顯示的是一個當前日期,而不是 NULL ?
單開此文來解釋這些非常容易混淆的概念。

項目需求和文件處理中的問題

在比較純粹的 ETL 項目中都會碰到對空值的處理,特別是對以文件數據源中的控制處理。不同的項目,不同的設計,對最終輸出值的控制是不一樣的。
就 SSIS 對平面文件 NULL 值的處理,可以有這么幾個實際開發中會碰到的問題或者需求,如果文件源中有空值 -
  1. 如何讓它在輸出到目標表的時候使用目標表列的默認值?
  2. 如何讓它在輸出到目標表的時候顯示 NULL ?
  3. 如何讓它在輸出到目標表的時候顯示空白字符串 ?

普遍性的概念理解上的誤區

通常情況下,在以平面文件為數據源的 ETL 處理過程中,對於數據源中的空值的控制往往涉及到源控件和目標控件,例如 Flat File Source 和 OLE DB Destination。但是,即使經驗和豐富的 ETL 開發人員也非常容易混淆這幾種不同配置的差異,並且特別對於 DEFAULT VALUE 這一點常常被忽略掉了。
我看到的一篇博客 - http://www.sqlservercentral.com/articles/Integration+Services+(SSIS)/61818/ 這位作者本身的介紹的出發點沒有錯,但是就沒有正確區分 OLE DB Destination 中 Fast Load 和 非 Fast Load 對於這個 NULL 值的影響。
包括之前我遇到的一個面試,面試我的人錯誤的認為對於空值的輸出只有 NULL 和 空白字符串兩種方式,而漏掉了 DEFAULT 處理。但是這一個細節其實是非常重要的,了解這一個特性可以避免在 ETL 中加入條件判斷,類型轉換來確保目標列的值不是 NULL 或者空白字符串。
 
所以這些小細節是非常容易出錯,概念的混淆也是普遍性的。因此,這篇文章以不同的測試案例總結讓大家區分不同的配置對空值的影響,最終理解這些細節。

概括與總結

我先用下面這幅圖來說明這個區別,后面是詳細的比較案例,最后再來解釋這些區別的原因。
數據源如下圖所示,是一個以逗號分隔的文本文件,注意到第4行的逗號分隔部分的內容是一個空字符串,而第5行是沒有值,表示空值。
測試目標表部分結構, 注意到 Middle Name 和 Hire Date 這兩列上有 Default 約束。
IF OBJECT_ID('T005_STAGING_EMPLOYEE') IS NOT NULL
DROP TABLE T005_STAGING_EMPLOYEE GO

CREATE TABLE [T005_STAGING_EMPLOYEE_1] ( ID INT PRIMARY KEY IDENTITY(1,1), [FIRSTNAME] VARCHAR(50), [LASTNAME] VARCHAR(50), [MIDDLENAME] VARCHAR(50) DEFAULT('-'), [NAMESTYLE] VARCHAR(50), [TITLE] VARCHAR(50), [HIREDATE] VARCHAR(50) DEFAULT(GETDATE()), [BIRTHDATE] VARCHAR(50), [EMAILADDRESS] VARCHAR(50) )

第一個測試  

Flat File Source  - Retain null values from the source as null values in the data flow - 默認不選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View。
Mapping 中自動標識列忽略掉。
配置完成后保存並執行包,查看表結果,第四行輸出的是空白字符串。

第二個測試  

Flat File Source  - Retain null values from the source as null values in the data flow - 默認不選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View - Fast Load。
看似查詢結果沒有什么變化,和第一個測試案例中的是一樣的。

第三個測試  

Flat File Source  - Retain null values from the source as null values in the data flow - 選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View。
保存並執行,查看數據表結果,第4行的 MIDDLE NAME 自動轉換為 NULL 了。

第四個測試  

Flat File Source  - Retain null values from the source as null values in the data flow - 選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View - Fast Load。
保存並執行包,查看結果, 會發現第4行的 Middle Name 使用了默認值 "-"。

第五個測試 

Flat File Source  - Retain null values from the source as null values in the data flow - 選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View - Fast Load。
Keep Nulls - 選中。
保存並執行,查看數據表結果,第4行的 MIDDLE NAME 此時又變成NULL 了。

第六個測試 

Flat File Source  - Retain null values from the source as null values in the data flow - 不選中。
OLE DB Destination - Data Access Mode - 選擇 Table or View - Fast Load。
Keep Nulls - 選中。
保存運行之后的查詢結果是空白字符串。

案例測試的結論

通過以上六個測試案例,可以看到當文件數據源中包含有空值的時候,不同的設置輸出到數據表中的結果是不一樣的,大概有三種:
  1. 空白字符串
  2. NULL 值
  3. 數據表中列的默認值
簡單總結一下,不同的配置對空值的處理結果。

第一階段 - Flat File Source 對空值的轉換過程

我們第一點要理解 Flat File Source  中 "Retain null values from the source as null values in the data flow" 的作用,很容易理解:
默認不選中 - 只要是空值就轉成空白字符串向下輸出
選中 - 只要是空值就轉成 NULL向下輸出
 
可以打開一個監視器,看看在從 FF_SRC_EMPLOYEE 到 OLD_DST_STAGING_EMPLOYEE_1 的過程中,選中與否的區別。
默認不選中的情況下,空值變成字符串。
選中之后的效果。
這是一定要理解的第一點,自 FF_SRC_EMPLOYE 它輸出以后,最終到數據表中是否為 NULL 就已經與它自身無關了。只用理解它何時輸出為 NULL 何時輸出為空字符串就可以了。

第二階段 OLE DB Destination 對空值的處理過程

無論是 Fast Load 模式還是非 Fast Load 模式,只要接受上游空間向下輸出的是非空值,即非NULL值,那么上游數據是什么,下游就接受成什么。

因此,即使是文件數據源中存在 NULL 空值,但是只要 Flat File Source 中的 Retain null values from the source as null values in the data flow 勾選上,那么空值在文件源段向下輸出時就已經變成空白字符串。所以在 OLE DB Destination 中無論設置什么模式,最終都不會影響空白字符串的輸出,因為空白字符串是有值的,長度為0的字符串。

只有當 Flat File Source 中的 Retain null values from the source as null values in the data flow 勾選上的時候,空值為轉換為 NULL 值,這時 OLE DB Destination 中的設置才會影響到最終輸出的值。

Access Mode 中各種配置對 NULL 值的處理方式
  1. Table or view - 對 NULL 不處理,上游是 NULL 值,它最終輸出就是 NULL 值。
  2. Table or view - fast load 加上默認不選中 Keep nulls - 如果目標列沒有 DEFAULT 默認約束的話,那么輸出到目標列就是 NULL 值;如果目標列有 DEFAULT 默認約束的話,那么輸出到目標列使用的就是 DEFAULT 默認約束中的值。
  3. Table or view - fast load + 選中 Keep nulls - 無論目標列有沒有 DEFAULT 默認約束,都將保留 NULL 值。
再回頭來看這個總結就很容易了,比如在面試中被問到 - 如果文件源中有空值,如何讓它在輸出到目標表的時候使用目標表列的默認值? 那么就很容易回答了!

所以,把 Flat File Source 和 OLE DB Destination 分開來看,只考慮如何控制 Flat File Source 它的輸出是否為 NULL,只考慮 OLE DB Destination 中對 NULL 值的不同處理方式,分成這樣兩個階段這個概念就很容易理解了。並且,理解了上面這些內容,就不會再認為只要選中了 Flat File Source 中的 Retain null values from the source as null values in the data flow,文件中的 NULL 值就會輸出到目標表了。

當然,這里面涉及到了 OLE DB Destination 控件中兩個不同的加載模式 - Fast Load 和 非 Fast Load,包括其它的幾個配置選項,會單獨放到一篇文章中去講解。

更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)   如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM