<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kxbin
    成功留給有準備的人
    posts - 10,  comments - 35,  trackbacks - 0

    NULL是數(shù)據(jù)庫中特有的數(shù)據(jù)類型,當一條記錄的某個列為NULL,則表示這個列的值是未知的、是不確定的。既然是未知的,就有無數(shù)種的可能性。因此,NULL并不是一個確定的值。

    這是NULL的由來、也是NULL的基礎,所有和NULL相關(guān)的操作的結(jié)果都可以從NULL的概念推導出來。

    判斷一個字段是否為NULL,應該用IS NULL或IS NOT NULL,而不能用‘=’。對NULL的判斷只能定性,既是不是NULL(IS NULL/IS NOT NULL),而不能定值。簡單的說,由于NULL存在著無數(shù)的可能,因此兩個NULL不是相等的關(guān)系,同樣也不能說兩個NULL就不相等,或者比較兩個NULL的大小,這些操作都是沒有意義,得不到一個確切的答案的。因此,對NULL的=、!=、>、<、>=、<=等操作的結(jié)果都是未知的,也就算說,這些操作的結(jié)果仍然是NULL。

    同理,對NULL進行+、-、*、/等操作的結(jié)果也是未知的,所以也是NULL。

    所以,很多時候會這樣總結(jié)NULL,除了IS NULL、IS NOT NULL以外,對NULL的任何操作的結(jié)果還是NULL。

    上面這句話總結(jié)的很精辟,而且很好記,所以很多時候人們只記得這句話,而忘了這句話是如何得到的。其實只要清楚NULL的真正含義,在處理NULL的時候就不會出錯。

    說了怎么多,來看一個經(jīng)典的例子:

    SQL> CREATE OR REPLACE PROCEDURE P1 (P_IN IN NUMBER) AS
    2 BEGIN
    3 IF P_IN >= 0 THEN 
    4 DBMS_OUTPUT.PUT_LINE('TRUE');
    5 ELSE
    6 DBMS_OUTPUT.PUT_LINE('FALSE');
    7 END IF;
    8 END;
    9 /

    過程已創(chuàng)建。

    SQL> CREATE OR REPLACE PROCEDURE P2 (P_IN IN NUMBER) AS
    2 BEGIN
    3 IF P_IN < 0 THEN 
    4 DBMS_OUTPUT.PUT_LINE('FALSE');
    5 ELSE
    6 DBMS_OUTPUT.PUT_LINE('TRUE');
    7 END IF;
    8 END;
    9 /

    過程已創(chuàng)建。

    上面兩個過程是否是等價的?對于熟悉C或JAVA的開發(fā)人員來說,可能認為二者是等價的,但是在數(shù)據(jù)庫中,則還要考慮到NULL的情況。

    當輸入為NULL時,可以看到上面兩個過程不同的輸出:

    SQL> SET SERVEROUT ON
    SQL> EXEC P1(NULL)
    FALSE

    PL/SQL 過程已成功完成。

    SQL> EXEC P2(NULL)
    TRUE

    PL/SQL 過程已成功完成。

    輸入為NULL時,上面兩個過程中的判斷的結(jié)果都是一樣的,不管是NULL >= 0還是NULL < 0結(jié)果都是未知,所以兩個判斷的結(jié)果都是NULL。最終,在屏幕上輸出的都是ELSE后面跟的輸出值。

    由于NULL所具有的特殊性,在處理數(shù)據(jù)庫相關(guān)問題時應該對NULL的情況額外考慮,否則很容易造成錯誤。
     

    由于引入了NULL,在處理邏輯過程中一定要考慮NULL的情況。同樣的,數(shù)據(jù)庫中的布爾值的處理,也是需要考慮NULL的情況,這使得布爾值從原來的TRUE、FALSE兩個值變成了TRUE、FALSE和NULL三個值。

    下面是TRUE和FALSE兩種情況進行布爾運算的結(jié)果:

    AND操作:

    AND

    TRUE

    FALSE

    TRUE

    TRUE

    FALSE

    FALSE

    FALSE

    FALSE

    OR操作:

    OR

    TRUE

    FALSE

    TRUE

    TRUE

    TRUE

    FALSE

    TRUE

    FALSE

    上面是熟悉的TRUE和FALSE兩個值進行布爾運算的結(jié)果,如果加上一個NULL的情況會怎樣?NULL的布爾運算是否會像NULL的算術(shù)運算那樣結(jié)果都是NULL呢?下面通過一個過程來進行說明:

    SQL> SET SERVEROUT ON SIZE 100000
    SQL> DECLARE
    2 TYPE T_BOOLEAN IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER;
    3 V_BOOL1 T_BOOLEAN;
    4 V_BOOL2 T_BOOLEAN;

    6 PROCEDURE P(P_IN1 BOOLEAN, P_IN2 BOOLEAN, P_OPERATOR IN VARCHAR2) AS
    7 V_RESULT BOOLEAN;
    8 BEGIN
    9 IF P_IN1 IS NULL THEN
    10 DBMS_OUTPUT.PUT('NULL ');
    11 ELSIF P_IN1 THEN
    12 DBMS_OUTPUT.PUT('TRUE ');
    13 ELSE
    14 DBMS_OUTPUT.PUT('FALSE ');
    15 END IF;
    16 
    17 IF P_OPERATOR = 'AND' THEN
    18 DBMS_OUTPUT.PUT('AND ');
    19 V_RESULT := P_IN1 AND P_IN2;
    20 ELSIF P_OPERATOR = 'OR' THEN
    21 DBMS_OUTPUT.PUT('OR ');
    22 V_RESULT := P_IN1 OR P_IN2;
    23 ELSE
    24 RAISE_APPLICATION_ERROR('-20000', 'INPUT PARAMETER P_OPERATOR ERROR');
    25 END IF;
    26 
    27 IF P_IN2 IS NULL THEN
    28 DBMS_OUTPUT.PUT('NULL');
    29 ELSIF P_IN2 THEN
    30 DBMS_OUTPUT.PUT('TRUE');
    31 ELSE
    32 DBMS_OUTPUT.PUT('FALSE');
    33 END IF;
    34 
    35 IF V_RESULT IS NULL THEN
    36 DBMS_OUTPUT.PUT(':NULL');
    37 ELSIF V_RESULT THEN
    38 DBMS_OUTPUT.PUT(':TRUE');
    39 ELSE
    40 DBMS_OUTPUT.PUT(':FALSE');
    41 END IF;
    42 DBMS_OUTPUT.NEW_LINE;
    43 END;
    44 
    45 BEGIN
    46 V_BOOL1(1) := TRUE;
    47 V_BOOL1(2) := FALSE;
    48 V_BOOL1(3) := NULL;
    49 V_BOOL2 := V_BOOL1;
    50 FOR I IN 1..V_BOOL1.COUNT LOOP
    51 FOR J IN 1..V_BOOL2.COUNT LOOP
    52 P(V_BOOL1(I), V_BOOL2(J), 'AND');
    53 P(V_BOOL1(I), V_BOOL2(J), 'OR');
    54 END LOOP;
    55 END LOOP; 
    56 END;
    57 /
    TRUE AND TRUE:TRUE
    TRUE OR TRUE:TRUE
    TRUE AND FALSE:FALSE
    TRUE OR FALSE:TRUE
    TRUE AND NULL:NULL
    TRUE OR NULL:TRUE
    FALSE AND TRUE:FALSE
    FALSE OR TRUE:TRUE
    FALSE AND FALSE:FALSE
    FALSE OR FALSE:FALSE
    FALSE AND NULL:FALSE
    FALSE OR NULL:NULL
    NULL AND TRUE:NULL
    NULL OR TRUE:TRUE
    NULL AND FALSE:FALSE
    NULL OR FALSE:NULL
    NULL AND NULL:NULL
    NULL OR NULL:NULL

    PL/SQL 過程已成功完成。

    由于NULL是未知,所以NULL AND NULL、NULL OR NULL、NULL AND TRUE和NULL OR FALSE的值都是未知的,這些的結(jié)果仍然是NULL。

    那么為什么NULL AND FALSE和NULL OR TRUE得到了一個確定的結(jié)果呢?仍然從NULL的概念來考慮。NULL是未知的,但是目前NULL的類型是布爾類型,因此NULL只有可能是TRUE或者FALSE中的一個。

    而根據(jù)前面的表格,TRUE AND FALSE和FALSE AND FALSE的結(jié)果都是FALSE,也就是說不管NULL的值是TRUE還是FALSE,它與FALSE進行AND的結(jié)果一定是FALSE。

    同樣的道理,TRUE AND TRUE和FALSE AND TRUE的結(jié)果都是TRUE,所以不管NULL取何值,NULL和TRUE的OR的結(jié)果都是TRUE。

    AND操作圖表變?yōu)椋?/span>

    AND

    TRUE

    FALSE

    NULL

    TRUE

    TRUE

    FALSE

    NULL

    FALSE

    FALSE

    FALSE

    FALSE

    NULL

    NULL

    FALSE

    NULL

    OR操作圖表變?yōu)椋?/span>

    OR

    TRUE

    FALSE

    NULL

    TRUE

    TRUE

    TRUE

    TRUE

    FALSE

    TRUE

    FALSE

    NULL

    NULL

    TRUE

    NULL

    NULL

    最后,仍然來看一個例子:

    SQL> SELECT * FROM TAB;

    TNAME TABTYPE CLUSTERID
    ------------------------------ ------- ----------
    PLAN_TABLE TABLE
    T TABLE
    T1 TABLE
    T2 TABLE
    T3 TABLE
    TEST TABLE
    TEST1 TABLE
    TEST_CORRUPT TABLE
    T_TIME TABLE

    已選擇9行。

    SQL> SELECT * FROM TAB WHERE TNAME IN ('T', 'T1', NULL);

    TNAME TABTYPE CLUSTERID
    ------------------------------ ------- ----------
    T TABLE
    T1 TABLE

    SQL> SELECT * FROM TAB WHERE TNAME NOT IN ('T', 'T1', NULL);

    未選定行

    對于IN和NOT IN與NULL的關(guān)系前面并沒有說明,不過可以對其進行簡單的變形:

    TNAME IN (‘T’, ‘T1’, NULL) < = > TNAME = ‘T’ OR TNAME = ‘T1’ OR TNAME = NULL

    根據(jù)前面的結(jié)果,當查詢到T或T1這兩條記錄時,WHERE條件相當于TRUE AND FALSE AND NULL,其結(jié)果是TRUE,因此返回了兩條記錄。

    TNAME NOT IN (‘T’, ‘T1’, NULL) < = > TNAME != ‘T’ AND TNAME != ‘T1’ AND TNAME != NULL。

    WHERE條件相當于TRUE AND TRUE AND NULL,或TRUE AND FA發(fā)現(xiàn)很多人對空字符串’’不是很清楚,這里簡單總結(jié)一下。

    以前我總說空字符串’’等價于NULL,但是有些人喜歡鉆牛角尖,所以我改一下說法,空字符串’’是NULL的字符類型的表現(xiàn)格式。

    也許有人會認為,NULL就是NULL,本身沒有類型的一說,但是我認為,NULL還是有類型的,只不過不同類型的NULL都用相同的關(guān)鍵字NULL來表示。而且,NULL本身也可以轉(zhuǎn)化為任意類型的數(shù)據(jù),因此給人的感覺是NULL沒有數(shù)據(jù)類型。

    其實NULL不但有數(shù)據(jù)類型,還有默認的數(shù)據(jù)類型,那就是字符類型。至于這個答案是如何推斷出來的,請看:http://yangtingkun.itpub.net/post/468/50132

    不過上面說的這個默認的數(shù)據(jù)類型是在極限的情況下測試出來的,如果只是給出一個NULL,那么它是可以代表任意的類型的。

    證明空字符串就是NULL是很容易的:

    SQL> SELECT 1 FROM DUAL WHERE '' = '';

    未選定行

    SQL> SELECT 1 FROM DUAL WHERE '' IS NULL;

    1
    ----------
    1

    SQL> SELECT DUMP(''), DUMP(NULL) FROM DUAL;

    DUMP DUMP
    ---- ----
    NULL NULL

    上面三個SQL語句,任意一個都足以證明空字符串’’就是NULL。

    有些人可能會說,既然’’就是NULL,為什么不能進行IS ’’的判斷呢?

    SQL> SELECT 1 FROM DUAL WHERE '' IS '';
    SELECT 1 FROM DUAL WHERE '' IS ''
    *
    第 1 行出現(xiàn)錯誤:
    ORA-00908: 缺失 NULL 關(guān)鍵字

    其實從上面的錯誤信息就可以看到答案。原因就是IS NULL是Oracle的語法,在Oracle運行的時刻’’是NULL,但是現(xiàn)在Oracle還沒有運行這句SQL,就由于語法不正確被SQL分析器擋住了。Oracle的語法并不包含IS ’’的寫法,所以,這一點并不能稱為’’不是NULL的理由。

    那么我為什么還要說’’是NULL的字符表示形式呢?因為’’和NULL還確實不完全一樣,對于NULL來說,它表示了各種數(shù)據(jù)類型的NULL值。而對于空字符串’’來說,雖然它也具有NULL的可以任意轉(zhuǎn)化為其他任何數(shù)據(jù)類型的特點,但是無論是從形式上還是從本質(zhì)上它都表現(xiàn)出了字符類型的特點。

    下面通過一個例子來證明’’本質(zhì)是字符類型的NULL。

    SQL> CREATE OR REPLACE PACKAGE P_TEST_NULL AS
    2 FUNCTION F_RETURN (P_IN IN NUMBER) RETURN VARCHAR2;
    3 FUNCTION F_RETURN (P_IN IN VARCHAR2) RETURN VARCHAR2;
    4 END;
    5 /

    程序包已創(chuàng)建。

    SQL> CREATE OR REPLACE PACKAGE BODY P_TEST_NULL AS 

    3 FUNCTION F_RETURN (P_IN IN NUMBER) RETURN VARCHAR2 AS
    4 BEGIN
    5 RETURN 'NUMBER';
    6 END;

    8 FUNCTION F_RETURN (P_IN IN VARCHAR2) RETURN VARCHAR2 AS
    9 BEGIN
    10 RETURN 'VARCHAR2';
    11 END;
    12 
    13 END;
    14 /

    程序包體已創(chuàng)建。

    SQL> SELECT P_TEST_NULL.F_RETURN(3) FROM DUAL;

    P_TEST_NULL.F_RETURN(3)
    ------------------------------------------------------------
    NUMBER

    SQL> SELECT P_TEST_NULL.F_RETURN('3') FROM DUAL;

    P_TEST_NULL.F_RETURN('3')
    ------------------------------------------------------------
    VARCHAR2

    SQL> SELECT P_TEST_NULL.F_RETURN('') FROM DUAL;

    P_TEST_NULL.F_RETURN('')
    ------------------------------------------------------------
    VARCHAR2

    SQL> SELECT P_TEST_NULL.F_RETURN(NULL) FROM DUAL;
    SELECT P_TEST_NULL.F_RETURN(NULL) FROM DUAL
    *
    第 1 行出現(xiàn)錯誤:
    ORA-06553: PLS-307: 有太多的 'F_RETURN' 聲明與此次調(diào)用相匹配

    從這一點上可以看出’’實際上已經(jīng)具備了數(shù)據(jù)類型。所以我將’’表述為空字符串是NULL的字符類型表現(xiàn)形式。LSE AND NULL,其最終結(jié)果是NULL或者FALSE,所以,查詢不會返回記錄。
     
     

    posted on 2012-08-30 16:13 kxbin 閱讀(320) 評論(0)  編輯  收藏 所屬分類: ORACLE轉(zhuǎn)發(fā)
    你恨一個人是因為你愛他;你喜歡一個人,是因為他身上有你沒有的;你討厭一個人是因為他身上有你有的東西;你經(jīng)常在別人面前批評某人,其實潛意識中是想接近他。

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(5)

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    J2EE

    java技術(shù)網(wǎng)站

    Linux

    平時常去的網(wǎng)站

    數(shù)據(jù)庫

    電影網(wǎng)站

    網(wǎng)站設計

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 在线精品亚洲一区二区小说| 国产精品高清视亚洲精品| 91香焦国产线观看看免费| 亚洲av午夜精品无码专区| 又色又污又黄无遮挡的免费视| 中文字幕在线视频免费| 亚洲精品午夜视频| 国产高清免费的视频| 欧洲人成在线免费| 亚洲AV无码精品国产成人| 亚洲AV无码专区在线播放中文| 亚洲免费网站观看视频| 女同免费毛片在线播放| 亚洲欧美日韩综合久久久 | 国产V亚洲V天堂A无码| 在线观看AV片永久免费| 中文字幕免费在线看线人动作大片| 亚洲福利秒拍一区二区| 亚洲日韩在线第一页| 在线观看免费人成视频色| 在线看片免费人成视频播| 亚洲第一se情网站| 91在线亚洲精品专区| 亚洲精品视频免费| 无人在线观看免费高清视频| a级毛片无码免费真人久久| 亚洲精品无码久久久久久| 无码乱人伦一区二区亚洲一| 亚洲AV成人潮喷综合网| 国产91色综合久久免费| 爽爽爽爽爽爽爽成人免费观看| 久久亚洲精品无码av| 亚洲国产品综合人成综合网站| 久久亚洲综合色一区二区三区| 国产在线19禁免费观看| 欧洲精品成人免费视频在线观看 | 性盈盈影院免费视频观看在线一区| 很黄很污的网站免费| 黄 色一级 成 人网站免费| 亚洲aⅴ天堂av天堂无码麻豆| 亚洲不卡在线观看|