# SQL的ISNULL()函式對於資料型態的隱性規則 ### 情境 想要用 **特定學生姓名** 去查閱此學生是否已註冊(已註冊為1,未註冊為0)若無此學生資料則回傳-1 ### SQL 資料表與型態範例 ##### 1.先創造資料表名為: Students ##### 2.定義資料表欄位與其型態 | 欄位名稱 | 資料型態 | | -------- | -------- | | student_id | bigint | | student_name | varchar(30) | | is_registered | bit | ##### 3.新增幾個學生範例供參考 | student_id | student_name | is_regesitered | | -------- | -------- | -------- | | 1 | Gary | 0 | | 2 | Max | 0 | | 3 | Tina | 1 | | 4 | Linda | 0 | ### SQL語法與遇到問題 ISNULL ( 檢查運算式 , 取代值 ) 檢查運算式內結果是否為null,若為null則用**取代值**取代 把找出is_registered的sql貼到檢查運算式,取代值設為-1表示沒有資料 ```sql= DECLARE @IsRegistered smallint; DECLARE @Name nvarchar(30)='Cleo'; SET @IsRegistered= ISNULL((SELECT TOP(1) is_registered FROM Students WITH(NOLOCK) WHERE student_name =@Name),-1); SELECT @IsRegistered; ``` 本以為這樣直觀的寫法會是預期的結果 但得到的@IsRegistered卻是**1** ### 原因 後來查了[微軟文件關於ISNULL](https://docs.microsoft.com/zh-tw/sql/t-sql/functions/isnull-transact-sql?view=sql-server-ver15)的功能解釋 其中提到了 >check_expression 為要檢查 NULL 的運算式。 check_expression 可為任何類型。 replacement_value 為 check_expression 是 NULL 時,要傳回的運算式。 replacement_value 必須是能夠隱含轉換成 check_expression 類型的類型。 replacement_value 必須是能夠 ***隱含轉換*** 成 check_expression 類型的類型 也就是說上述的sql語法,因為我們的check_expression ```sql= SELECT TOP(1) is_registered FROM Students WITH(NOLOCK) WHERE student_name =@Name ``` 取出來的is_registered在db內是設定成 **bit** (只有0或1的選項) 而我們的取代值-1不可能轉換成bit... ### 解決方法 其實解決方法很簡單 把得出來的is_registered用smallint型態的變數取存入再進行ISNULL()自我判定結果就好 ```sql= SET @IsRegistered= (SELECT TOP(1) is_registered FROM Students WITH(NOLOCK) WHERE student_name =@Name); SET @IsRegistered = ISNULL(@IsRegistered,-1); ``` 就是這麼簡單 並不是太複雜或是深奧的觀念 但是有時候這種基礎規則沒有好好記得反而增加找問題的時間成本... ###### tags: `sql` `database`