[研究] ASP.NET、SQL Server、空字串、null 的恩怨情仇
2020-12-24
空字串 : 有個箱子,只是沒放東西。ASP.NET (C#) 是 "", MS-SQL Server 是 ''
null : 連箱子都沒有。
Undefined (未定義) : 是否為箱子都不知道。
****************************************
在測試網頁上開發的查詢功能時,
<asp:SqlDataSource ID="SqlDataSource_Production_sub_type" runat="server" ConnectionString="<%$ ConnectionStrings:pmsConnectionString %>"
SelectCommand="SELECT N'*' AS [Production_sub_type], N'<全部>' AS [Production_sub_type_display],'0' AS Priority
UNION
SELECT distinct [Production_sub_type], [Production_sub_type] AS [Production_sub_type_display],'1' AS Priority FROM [ProductionList] ORDER BY Priority "></asp:SqlDataSource>
次類別 (Production_sub_type):<asp:DropDownList ID="DropDownList_Production_sub_type" runat="server" DataSourceID="SqlDataSource_Production_sub_type" DataTextField="Production_sub_type_display" DataValueField="Production_sub_type"></asp:DropDownList><br />
因為 table 中某些 records 的該欄位是 '' (空字串),結果下拉選單選到該項時候,查不到,選到其他項,正常。
****************************************
測試
string queryString = SqlDataSource1.SelectCommand;
... (略)
queryString = queryString + queryString.Replace("@Production_sub_type", "N'" + DropDownList_Production_sub_type.SelectedValue + "'");
... (略)
把 queryString 內容丟到 SSMS ( Microsoft SQL Server Management Studio) 中執行是正常的。
****************************************
敝人盡量不用 null (可能有人讚同,有人反對,有人無意見)
(1)以前上課的老師建議
(2)個人經歷,例如
單一 table 倒沒甚麼問題,如過是多個 table 做 join 做 count、加、減、總和 或某些運算,
敝人碰過 SSMS 上可以正常執行一道複雜的 SQL (沒有參數),
ASP.NET 的 GirdView 無法顯示的情況,就是因為產出的欄位有些數值、有些null
(詳情不記得,或許可以用 SQL 語法 CASE WHEN 處理後,再給 GridView 就可以顯示)
(3) SQL 語法判斷欄位值一般用 fieldName = '某值'
就算那個值是空字串也是這樣寫,但若是 null,要寫 filedname is null,指令下法不一致
所以 ASP.NET 網頁下拉選單選擇沒有值的項目,DB 要考慮把 '' 和 null 項目都撈出
ASP.NET 中 SQL 語法可能要寫成
WHERE (fieldname=@DropDownListChoice or (@DropDownListChoice=N'' and fieldname is null))
SQL 語法變麻煩了,如果這個欄位是數個 table join 時 on 的條件使用,那複雜度....
或者該欄位 '' 和 null 意義不同,ASP.NET 下拉選單可能要替 null 另給個名稱,例如 "null",
但好死不死,某些 table 的某些欄位的部分欄位值中有稱為 "null" 的字串值 ( 不是 null )
( Web API / Web Service 呼叫別系統而取得,儲存下來的 )
(4)不想欄位中又是 null,又是 "" (空字串)
--------------------
不用 null,SQL Server 的 Database Schema - Table Schema 設計
SQL Server 的資料表(table)「設計」時新增一個欄位(field)時候,預設是「允許Null」,且預設值是 null
敝人習慣把「允許Null」勾選拿掉,
若「資料型態」為字串類的,敝人會把預設值設定為 ''
若「資料型態」為數值類的,敝人會把預設值設定為 ''
若「資料型態」為日期類的,敝人會把預設值設定為 getdate() 或某個日期
若「資料型態」為布林值類的 (bit),敝人會把預設值設定為 1 或 0
(註:bit 後來不太用,因為原本需求只是表示 "未完成" 和 "完成",
後來需求又變,要求增加一種或 N 種狀態 (ex : 填寫中、階段X、階段Y、、,
只好把 bit 換成 nvarchar、int或其他,不然就新增一個欄位來用,
然後修改所有受影響的諸多程式 )
--------------------
不用 null 後,ASP.NET (WebForm) 的 .aspx 困擾與設計
<asp:SqlDataSource ID="SqlDataSource1" ..(略)
<InsertParameters>
<asp:Parameter Name="Production_sub_type" Type="String" />
要改成下面,不然如果沒有輸入值,會自動把空字串 "" 轉成 null,因為敝人設定欄位不允許 null,就出錯了
<asp:Parameter Name="Production_sub_type" Type="String" DefaultValue="" ConvertEmptyStringToNull="false" />
日期欄位
<asp:Parameter Name="CreateDateTime" Type="DateTime" />
改為
<asp:Parameter Name="CreateDateTime" Type="DateTime" DefaultValue="<%: DateTime.Now%>" ConvertEmptyStringToNull="false" />
或
<asp:Parameter Name="CreateDateTime" Type="string" DefaultValue='<%: DateTime.Now.ToString("yyyy-MM-dd")%>' ConvertEmptyStringToNull="false" />
另外就是 需求者 希望該筆資料沒有填寫或送出時,
時間欄位和數值欄位不要顯示值 (只好在 GirdView 的 RowDataBound 或 DataBound 或其他地方動手腳)
--------------------
不用 null 後,ASP.NET (WebForm) 的 .aspx.cs 困擾與設計
也是這次碰到的情況,想到可能是 "" 被轉成 null 所以查不到
SqlDataSource1.SelectCommand = @"
-- DECLARE @Product_ancestor_name nvarchar(50)
-- SET @Product_ancestor_name=N''
SELECT * FROM [ProductList]
WHERE ... (略)
AND (@Product_sub_type ='*' or Product_sub_type=@Product_sub_type)
改成下面
AND (@Product_sub_type ='*' or Product_sub_type=@Product_sub_type or ( Product_sub_type='' and @Product_sub_type is null ))
但是無效 (有寫錯?)
後來在
SqlDataSource1.SelectParameters.Add("Product_sub_type", DropDownList_Product_sub_type.SelectedValue );
下方增加一行
SqlDataSource1.SelectParameters["Product_sub_type"].ConvertEmptyStringToNull = false;
成功解決。
註:另一種方式是 DropDownList 的 SELECT 用 WHERE 條件排除掉 "",讓 DropDownList 沒得選 "",但似乎不完善。
****************************************
至於倒底怎樣最好,看情況,見人見智吧。
(完)
沒有留言:
張貼留言