• SQL空值陷阱【MySQL、Oracle】


    SQL 是一种声明式的语言,我们只需要描述想要的结果(WHAT),而不关心数据库如何实现(HOW);虽然 SQL 比较容易学习,但是有一些容易混淆和出错的概念。今天就来说说 SQL 中的空值陷阱和避坑方法。

    本文使用的示例表结构如下:

    示例数据:

    INSERT INTO departments VALUES 
            ( 10
            , 'Administration'
            , 200
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 20
            , 'Marketing'
            , 201
            , 1800
            );
                                    
    INSERT INTO departments VALUES 
            ( 30
            , 'Purchasing'
            , 114
            , 1700
            );
                    
    INSERT INTO departments VALUES 
            ( 40
            , 'Human Resources'
            , 203
            , 2400
            );
    
    INSERT INTO departments VALUES 
            ( 50
            , 'Shipping'
            , 121
            , 1500
            );
                    
    INSERT INTO departments VALUES 
            ( 60 
            , 'IT'
            , 103
            , 1400
            );
                    
    INSERT INTO departments VALUES 
            ( 70 
            , 'Public Relations'
            , 204
            , 2700
            );
                    
    INSERT INTO departments VALUES 
            ( 80 
            , 'Sales'
            , 145
            , 2500
            );
                    
    INSERT INTO departments VALUES 
            ( 90 
            , 'Executive'
            , 100
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 100 
            , 'Finance'
            , 108
            , 1700
            );
                    
    INSERT INTO departments VALUES 
            ( 110 
            , 'Accounting'
            , 205
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 120 
            , 'Treasury'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 130 
            , 'Corporate Tax'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 140 
            , 'Control And Credit'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 150 
            , 'Shareholder Services'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 160 
            , 'Benefits'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 170 
            , 'Manufacturing'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 180 
            , 'Construction'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 190 
            , 'Contracting'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 200 
            , 'Operations'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 210 
            , 'IT Support'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 220 
            , 'NOC'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 230 
            , 'IT Helpdesk'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 240 
            , 'Government Sales'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 250 
            , 'Retail Sales'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 260 
            , 'Recruiting'
            , NULL
            , 1700
            );
    
    INSERT INTO departments VALUES 
            ( 270 
            , 'Payroll'
            , NULL
            , 1700
            );
    
    
    
    
    INSERT INTO jobs VALUES 
            ( 'AD_PRES'
            , 'President'
            , 20080
            , 40000
            );
    INSERT INTO jobs VALUES 
            ( 'AD_VP'
            , 'Administration Vice President'
            , 15000
            , 30000
            );
    
    INSERT INTO jobs VALUES 
            ( 'AD_ASST'
            , 'Administration Assistant'
            , 3000
            , 6000
            );
    
    INSERT INTO jobs VALUES 
            ( 'FI_MGR'
            , 'Finance Manager'
            , 8200
            , 16000
            );
    
    INSERT INTO jobs VALUES 
            ( 'FI_ACCOUNT'
            , 'Accountant'
            , 4200
            , 9000
            );
    
    INSERT INTO jobs VALUES 
            ( 'AC_MGR'
            , 'Accounting Manager'
            , 8200
            , 16000
            );
    
    INSERT INTO jobs VALUES 
            ( 'AC_ACCOUNT'
            , 'Public Accountant'
            , 4200
            , 9000
            );
    INSERT INTO jobs VALUES 
            ( 'SA_MAN'
            , 'Sales Manager'
            , 10000
            , 20080
            );
    
    INSERT INTO jobs VALUES 
            ( 'SA_REP'
            , 'Sales Representative'
            , 6000
            , 12008
            );
    
    INSERT INTO jobs VALUES 
            ( 'PU_MAN'
            , 'Purchasing Manager'
            , 8000
            , 15000
            );
    
    INSERT INTO jobs VALUES 
            ( 'PU_CLERK'
            , 'Purchasing Clerk'
            , 2500
            , 5500
            );
    
    INSERT INTO jobs VALUES 
            ( 'ST_MAN'
            , 'Stock Manager'
            , 5500
            , 8500
            );
    INSERT INTO jobs VALUES 
            ( 'ST_CLERK'
            , 'Stock Clerk'
            , 2008
            , 5000
            );
    
    INSERT INTO jobs VALUES 
            ( 'SH_CLERK'
            , 'Shipping Clerk'
            , 2500
            , 5500
            );
    
    INSERT INTO jobs VALUES 
            ( 'IT_PROG'
            , 'Programmer'
            , 4000
            , 10000
            );
    
    INSERT INTO jobs VALUES 
            ( 'MK_MAN'
            , 'Marketing Manager'
            , 9000
            , 15000
            );
    
    INSERT INTO jobs VALUES 
            ( 'MK_REP'
            , 'Marketing Representative'
            , 4000
            , 9000
            );
    
    INSERT INTO jobs VALUES 
            ( 'HR_REP'
            , 'Human Resources Representative'
            , 4000
            , 9000
            );
    
    INSERT INTO jobs VALUES 
            ( 'PR_REP'
            , 'Public Relations Representative'
            , 4500
            , 10500
            );
    
    
    
    
    INSERT INTO employees VALUES 
            ( 100
            , 'Steven'
            , 'King'
            , 'SKING'
            , '515.123.4567'
            , DATE('2003-06-17')
            , 'AD_PRES'
            , 24000
            , NULL
            , NULL
            , 90
            );
    
    INSERT INTO employees VALUES 
            ( 101
            , 'Neena'
            , 'Kochhar'
            , 'NKOCHHAR'
            , '515.123.4568'
            , DATE('2005-09-21')
            , 'AD_VP'
            , 17000
            , NULL
            , 100
            , 90
            );
    
    INSERT INTO employees VALUES 
            ( 102
            , 'Lex'
            , 'De Haan'
            , 'LDEHAAN'
            , '515.123.4569'
            , DATE('2001-01-13')
            , 'AD_VP'
            , 17000
            , NULL
            , 100
            , 90
            );
    
    INSERT INTO employees VALUES 
            ( 103
            , 'Alexander'
            , 'Hunold'
            , 'AHUNOLD'
            , '590.423.4567'
            , DATE('2006-01-03')
            , 'IT_PROG'
            , 9000
            , NULL
            , 102
            , 60
            );
    
    INSERT INTO employees VALUES 
            ( 104
            , 'Bruce'
            , 'Ernst'
            , 'BERNST'
            , '590.423.4568'
            , DATE('2007-05-21')
            , 'IT_PROG'
            , 6000
            , NULL
            , 103
            , 60
            );
    
    INSERT INTO employees VALUES 
            ( 105
            , 'David'
            , 'Austin'
            , 'DAUSTIN'
            , '590.423.4569'
            , DATE('2005-06-25')
            , 'IT_PROG'
            , 4800
            , NULL
            , 103
            , 60
            );
    
    INSERT INTO employees VALUES 
            ( 106
            , 'Valli'
            , 'Pataballa'
            , 'VPATABAL'
            , '590.423.4560'
            , DATE('2006-02-05')
            , 'IT_PROG'
            , 4800
            , NULL
            , 103
            , 60
            );
    
    INSERT INTO employees VALUES 
            ( 107
            , 'Diana'
            , 'Lorentz'
            , 'DLORENTZ'
            , '590.423.5567'
            , DATE('2007-02-07')
            , 'IT_PROG'
            , 4200
            , NULL
            , 103
            , 60
            );
    
    INSERT INTO employees VALUES 
            ( 108
            , 'Nancy'
            , 'Greenberg'
            , 'NGREENBE'
            , '515.124.4569'
            , DATE('2002-08-17')
            , 'FI_MGR'
            , 12008
            , NULL
            , 101
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 109
            , 'Daniel'
            , 'Faviet'
            , 'DFAVIET'
            , '515.124.4169'
            , DATE('2002-08-16')
            , 'FI_ACCOUNT'
            , 9000
            , NULL
            , 108
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 110
            , 'John'
            , 'Chen'
            , 'JCHEN'
            , '515.124.4269'
            , DATE('2005-09-28')
            , 'FI_ACCOUNT'
            , 8200
            , NULL
            , 108
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 111
            , 'Ismael'
            , 'Sciarra'
            , 'ISCIARRA'
            , '515.124.4369'
            , DATE('2005-09-30')
            , 'FI_ACCOUNT'
            , 7700
            , NULL
            , 108
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 112
            , 'Jose Manuel'
            , 'Urman'
            , 'JMURMAN'
            , '515.124.4469'
            , DATE('2006-03-07')
            , 'FI_ACCOUNT'
            , 7800
            , NULL
            , 108
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 113
            , 'Luis'
            , 'Popp'
            , 'LPOPP'
            , '515.124.4567'
            , DATE('2007-12-07')
            , 'FI_ACCOUNT'
            , 6900
            , NULL
            , 108
            , 100
            );
    
    INSERT INTO employees VALUES 
            ( 114
            , 'Den'
            , 'Raphaely'
            , 'DRAPHEAL'
            , '515.127.4561'
            , DATE('2002-12-07')
            , 'PU_MAN'
            , 11000
            , NULL
            , 100
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 115
            , 'Alexander'
            , 'Khoo'
            , 'AKHOO'
            , '515.127.4562'
            , DATE('2003-05-18')
            , 'PU_CLERK'
            , 3100
            , NULL
            , 114
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 116
            , 'Shelli'
            , 'Baida'
            , 'SBAIDA'
            , '515.127.4563'
            , DATE('2005-12-24')
            , 'PU_CLERK'
            , 2900
            , NULL
            , 114
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 117
            , 'Sigal'
            , 'Tobias'
            , 'STOBIAS'
            , '515.127.4564'
            , DATE('2005-07-24')
            , 'PU_CLERK'
            , 2800
            , NULL
            , 114
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 118
            , 'Guy'
            , 'Himuro'
            , 'GHIMURO'
            , '515.127.4565'
            , DATE('2006-11-15')
            , 'PU_CLERK'
            , 2600
            , NULL
            , 114
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 119
            , 'Karen'
            , 'Colmenares'
            , 'KCOLMENA'
            , '515.127.4566'
            , DATE('2007-08-10')
            , 'PU_CLERK'
            , 2500
            , NULL
            , 114
            , 30
            );
    
    INSERT INTO employees VALUES 
            ( 120
            , 'Matthew'
            , 'Weiss'
            , 'MWEISS'
            , '650.123.1234'
            , DATE('2004-07-18')
            , 'ST_MAN'
            , 8000
            , NULL
            , 100
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 121
            , 'Adam'
            , 'Fripp'
            , 'AFRIPP'
            , '650.123.2234'
            , DATE('2005-04-10')
            , 'ST_MAN'
            , 8200
            , NULL
            , 100
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 122
            , 'Payam'
            , 'Kaufling'
            , 'PKAUFLIN'
            , '650.123.3234'
            , DATE('2003-05-01')
            , 'ST_MAN'
            , 7900
            , NULL
            , 100
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 123
            , 'Shanta'
            , 'Vollman'
            , 'SVOLLMAN'
            , '650.123.4234'
            , DATE('2005-10-10')
            , 'ST_MAN'
            , 6500
            , NULL
            , 100
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 124
            , 'Kevin'
            , 'Mourgos'
            , 'KMOURGOS'
            , '650.123.5234'
            , DATE('2007-11-16')
            , 'ST_MAN'
            , 5800
            , NULL
            , 100
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 125
            , 'Julia'
            , 'Nayer'
            , 'JNAYER'
            , '650.124.1214'
            , DATE('2005-07-16')
            , 'ST_CLERK'
            , 3200
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 126
            , 'Irene'
            , 'Mikkilineni'
            , 'IMIKKILI'
            , '650.124.1224'
            , DATE('2006-09-28')
            , 'ST_CLERK'
            , 2700
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 127
            , 'James'
            , 'Landry'
            , 'JLANDRY'
            , '650.124.1334'
            , DATE('2007-01-14')
            , 'ST_CLERK'
            , 2400
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 128
            , 'Steven'
            , 'Markle'
            , 'SMARKLE'
            , '650.124.1434'
            , DATE('2008-03-08')
            , 'ST_CLERK'
            , 2200
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 129
            , 'Laura'
            , 'Bissot'
            , 'LBISSOT'
            , '650.124.5234'
            , DATE('2005-08-20')
            , 'ST_CLERK'
            , 3300
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 130
            , 'Mozhe'
            , 'Atkinson'
            , 'MATKINSO'
            , '650.124.6234'
            , DATE('2005-10-30')
            , 'ST_CLERK'
            , 2800
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 131
            , 'James'
            , 'Marlow'
            , 'JAMRLOW'
            , '650.124.7234'
            , DATE('2005-02-16')
            , 'ST_CLERK'
            , 2500
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 132
            , 'TJ'
            , 'Olson'
            , 'TJOLSON'
            , '650.124.8234'
            , DATE('2007-04-10')
            , 'ST_CLERK'
            , 2100
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 133
            , 'Jason'
            , 'Mallin'
            , 'JMALLIN'
            , '650.127.1934'
            , DATE('2004-06-14')
            , 'ST_CLERK'
            , 3300
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 134
            , 'Michael'
            , 'Rogers'
            , 'MROGERS'
            , '650.127.1834'
            , DATE('2006-08-26')
            , 'ST_CLERK'
            , 2900
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 135
            , 'Ki'
            , 'Gee'
            , 'KGEE'
            , '650.127.1734'
            , DATE('2007-12-12')
            , 'ST_CLERK'
            , 2400
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 136
            , 'Hazel'
            , 'Philtanker'
            , 'HPHILTAN'
            , '650.127.1634'
            , DATE('2008-02-06')
            , 'ST_CLERK'
            , 2200
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 137
            , 'Renske'
            , 'Ladwig'
            , 'RLADWIG'
            , '650.121.1234'
            , DATE('2003-07-14')
            , 'ST_CLERK'
            , 3600
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 138
            , 'Stephen'
            , 'Stiles'
            , 'SSTILES'
            , '650.121.2034'
            , DATE('2005-10-26')
            , 'ST_CLERK'
            , 3200
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 139
            , 'John'
            , 'Seo'
            , 'JSEO'
            , '650.121.2019'
            , DATE('2006-02-12')
            , 'ST_CLERK'
            , 2700
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 140
            , 'Joshua'
            , 'Patel'
            , 'JPATEL'
            , '650.121.1834'
            , DATE('2006-04-06')
            , 'ST_CLERK'
            , 2500
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 141
            , 'Trenna'
            , 'Rajs'
            , 'TRAJS'
            , '650.121.8009'
            , DATE('2003-10-17')
            , 'ST_CLERK'
            , 3500
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 142
            , 'Curtis'
            , 'Davies'
            , 'CDAVIES'
            , '650.121.2994'
            , DATE('2005-01-29')
            , 'ST_CLERK'
            , 3100
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 143
            , 'Randall'
            , 'Matos'
            , 'RMATOS'
            , '650.121.2874'
            , DATE('2006-03-15')
            , 'ST_CLERK'
            , 2600
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 144
            , 'Peter'
            , 'Vargas'
            , 'PVARGAS'
            , '650.121.2004'
            , DATE('2006-07-09')
            , 'ST_CLERK'
            , 2500
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 145
            , 'John'
            , 'Russell'
            , 'JRUSSEL'
            , '011.44.1344.429268'
            , DATE('2004-10-01')
            , 'SA_MAN'
            , 14000
            , .4
            , 100
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 146
            , 'Karen'
            , 'Partners'
            , 'KPARTNER'
            , '011.44.1344.467268'
            , DATE('2005-01-05')
            , 'SA_MAN'
            , 13500
            , .3
            , 100
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 147
            , 'Alberto'
            , 'Errazuriz'
            , 'AERRAZUR'
            , '011.44.1344.429278'
            , DATE('2005-03-10')
            , 'SA_MAN'
            , 12000
            , .3
            , 100
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 148
            , 'Gerald'
            , 'Cambrault'
            , 'GCAMBRAU'
            , '011.44.1344.619268'
            , DATE('2007-10-15')
            , 'SA_MAN'
            , 11000
            , .3
            , 100
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 149
            , 'Eleni'
            , 'Zlotkey'
            , 'EZLOTKEY'
            , '011.44.1344.429018'
            , DATE('2008-01-29')
            , 'SA_MAN'
            , 10500
            , .2
            , 100
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 150
            , 'Peter'
            , 'Tucker'
            , 'PTUCKER'
            , '011.44.1344.129268'
            , DATE('2005-01-30')
            , 'SA_REP'
            , 10000
            , .3
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 151
            , 'David'
            , 'Bernstein'
            , 'DBERNSTE'
            , '011.44.1344.345268'
            , DATE('2005-03-24')
            , 'SA_REP'
            , 9500
            , .25
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 152
            , 'Peter'
            , 'Hall'
            , 'PHALL'
            , '011.44.1344.478968'
            , DATE('2005-08-20')
            , 'SA_REP'
            , 9000
            , .25
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 153
            , 'Christopher'
            , 'Olsen'
            , 'COLSEN'
            , '011.44.1344.498718'
            , DATE('2006-03-30')
            , 'SA_REP'
            , 8000
            , .2
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 154
            , 'Nanette'
            , 'Cambrault'
            , 'NCAMBRAU'
            , '011.44.1344.987668'
            , DATE('2006-12-09')
            , 'SA_REP'
            , 7500
            , .2
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 155
            , 'Oliver'
            , 'Tuvault'
            , 'OTUVAULT'
            , '011.44.1344.486508'
            , DATE('2007-11-23')
            , 'SA_REP'
            , 7000
            , .15
            , 145
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 156
            , 'Janette'
            , 'King'
            , 'JKING'
            , '011.44.1345.429268'
            , DATE('2004-01-30')
            , 'SA_REP'
            , 10000
            , .35
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 157
            , 'Patrick'
            , 'Sully'
            , 'PSULLY'
            , '011.44.1345.929268'
            , DATE('2004-03-04')
            , 'SA_REP'
            , 9500
            , .35
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 158
            , 'Allan'
            , 'McEwen'
            , 'AMCEWEN'
            , '011.44.1345.829268'
            , DATE('2004-08-01')
            , 'SA_REP'
            , 9000
            , .35
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 159
            , 'Lindsey'
            , 'Smith'
            , 'LSMITH'
            , '011.44.1345.729268'
            , DATE('2005-03-10')
            , 'SA_REP'
            , 8000
            , .3
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 160
            , 'Louise'
            , 'Doran'
            , 'LDORAN'
            , '011.44.1345.629268'
            , DATE('2005-12-15')
            , 'SA_REP'
            , 7500
            , .3
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 161
            , 'Sarath'
            , 'Sewall'
            , 'SSEWALL'
            , '011.44.1345.529268'
            , DATE('2006-11-03')
            , 'SA_REP'
            , 7000
            , .25
            , 146
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 162
            , 'Clara'
            , 'Vishney'
            , 'CVISHNEY'
            , '011.44.1346.129268'
            , DATE('2005-11-11')
            , 'SA_REP'
            , 10500
            , .25
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 163
            , 'Danielle'
            , 'Greene'
            , 'DGREENE'
            , '011.44.1346.229268'
            , DATE('2007-03-19')
            , 'SA_REP'
            , 9500
            , .15
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 164
            , 'Mattea'
            , 'Marvins'
            , 'MMARVINS'
            , '011.44.1346.329268'
            , DATE('2008-01-24')
            , 'SA_REP'
            , 7200
            , .10
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 165
            , 'David'
            , 'Lee'
            , 'DLEE'
            , '011.44.1346.529268'
            , DATE('2008-02-23')
            , 'SA_REP'
            , 6800
            , .1
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 166
            , 'Sundar'
            , 'Ande'
            , 'SANDE'
            , '011.44.1346.629268'
            , DATE('2008-03-24')
            , 'SA_REP'
            , 6400
            , .10
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 167
            , 'Amit'
            , 'Banda'
            , 'ABANDA'
            , '011.44.1346.729268'
            , DATE('2008-04-21')
            , 'SA_REP'
            , 6200
            , .10
            , 147
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 168
            , 'Lisa'
            , 'Ozer'
            , 'LOZER'
            , '011.44.1343.929268'
            , DATE('2005-03-11')
            , 'SA_REP'
            , 11500
            , .25
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 169  
            , 'Harrison'
            , 'Bloom'
            , 'HBLOOM'
            , '011.44.1343.829268'
            , DATE('2006-03-23')
            , 'SA_REP'
            , 10000
            , .20
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 170
            , 'Tayler'
            , 'Fox'
            , 'TFOX'
            , '011.44.1343.729268'
            , DATE('2006-01-24')
            , 'SA_REP'
            , 9600
            , .20
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 171
            , 'William'
            , 'Smith'
            , 'WSMITH'
            , '011.44.1343.629268'
            , DATE('2007-02-23')
            , 'SA_REP'
            , 7400
            , .15
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 172
            , 'Elizabeth'
            , 'Bates'
            , 'EBATES'
            , '011.44.1343.529268'
            , DATE('2007-03-24')
            , 'SA_REP'
            , 7300
            , .15
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 173
            , 'Sundita'
            , 'Kumar'
            , 'SKUMAR'
            , '011.44.1343.329268'
            , DATE('2008-04-21')
            , 'SA_REP'
            , 6100
            , .10
            , 148
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 174
            , 'Ellen'
            , 'Abel'
            , 'EABEL'
            , '011.44.1644.429267'
            , DATE('2004-05-11')
            , 'SA_REP'
            , 11000
            , .30
            , 149
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 175
            , 'Alyssa'
            , 'Hutton'
            , 'AHUTTON'
            , '011.44.1644.429266'
            , DATE('2005-03-19')
            , 'SA_REP'
            , 8800
            , .25
            , 149
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 176
            , 'Jonathon'
            , 'Taylor'
            , 'JTAYLOR'
            , '011.44.1644.429265'
            , DATE('2006-03-24')
            , 'SA_REP'
            , 8600
            , .20
            , 149
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 177
            , 'Jack'
            , 'Livingston'
            , 'JLIVINGS'
            , '011.44.1644.429264'
            , DATE('2006-04-23')
            , 'SA_REP'
            , 8400
            , .20
            , 149
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 178
            , 'Kimberely'
            , 'Grant'
            , 'KGRANT'
            , '011.44.1644.429263'
            , DATE('2007-05-24')
            , 'SA_REP'
            , 7000
            , .15
            , 149
            , NULL
            );
    
    INSERT INTO employees VALUES 
            ( 179
            , 'Charles'
            , 'Johnson'
            , 'CJOHNSON'
            , '011.44.1644.429262'
            , DATE('2008-01-04')
            , 'SA_REP'
            , 6200
            , .10
            , 149
            , 80
            );
    
    INSERT INTO employees VALUES 
            ( 180
            , 'Winston'
            , 'Taylor'
            , 'WTAYLOR'
            , '650.507.9876'
            , DATE('2006-01-24')
            , 'SH_CLERK'
            , 3200
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 181
            , 'Jean'
            , 'Fleaur'
            , 'JFLEAUR'
            , '650.507.9877'
            , DATE('2006-02-23')
            , 'SH_CLERK'
            , 3100
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 182
            , 'Martha'
            , 'Sullivan'
            , 'MSULLIVA'
            , '650.507.9878'
            , DATE('2007-06-21')
            , 'SH_CLERK'
            , 2500
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 183
            , 'Girard'
            , 'Geoni'
            , 'GGEONI'
            , '650.507.9879'
            , DATE('2008-02-03')
            , 'SH_CLERK'
            , 2800
            , NULL
            , 120
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 184
            , 'Nandita'
            , 'Sarchand'
            , 'NSARCHAN'
            , '650.509.1876'
            , DATE('2004-01-27')
            , 'SH_CLERK'
            , 4200
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 185
            , 'Alexis'
            , 'Bull'
            , 'ABULL'
            , '650.509.2876'
            , DATE('2005-02-20')
            , 'SH_CLERK'
            , 4100
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 186
            , 'Julia'
            , 'Dellinger'
            , 'JDELLING'
            , '650.509.3876'
            , DATE('2006-06-24')
            , 'SH_CLERK'
            , 3400
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 187
            , 'Anthony'
            , 'Cabrio'
            , 'ACABRIO'
            , '650.509.4876'
            , DATE('2007-02-07')
            , 'SH_CLERK'
            , 3000
            , NULL
            , 121
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 188
            , 'Kelly'
            , 'Chung'
            , 'KCHUNG'
            , '650.505.1876'
            , DATE('2005-06-14')
            , 'SH_CLERK'
            , 3800
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 189
            , 'Jennifer'
            , 'Dilly'
            , 'JDILLY'
            , '650.505.2876'
            , DATE('2005-08-13')
            , 'SH_CLERK'
            , 3600
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 190
            , 'Timothy'
            , 'Gates'
            , 'TGATES'
            , '650.505.3876'
            , DATE('2006-07-11')
            , 'SH_CLERK'
            , 2900
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 191
            , 'Randall'
            , 'Perkins'
            , 'RPERKINS'
            , '650.505.4876'
            , DATE('2007-12-19')
            , 'SH_CLERK'
            , 2500
            , NULL
            , 122
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 192
            , 'Sarah'
            , 'Bell'
            , 'SBELL'
            , '650.501.1876'
            , DATE('2004-02-04')
            , 'SH_CLERK'
            , 4000
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 193
            , 'Britney'
            , 'Everett'
            , 'BEVERETT'
            , '650.501.2876'
            , DATE('2005-03-03')
            , 'SH_CLERK'
            , 3900
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 194
            , 'Samuel'
            , 'McCain'
            , 'SMCCAIN'
            , '650.501.3876'
            , DATE('2006-07-01')
            , 'SH_CLERK'
            , 3200
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 195
            , 'Vance'
            , 'Jones'
            , 'VJONES'
            , '650.501.4876'
            , DATE('2007-03-17')
            , 'SH_CLERK'
            , 2800
            , NULL
            , 123
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 196
            , 'Alana'
            , 'Walsh'
            , 'AWALSH'
            , '650.507.9811'
            , DATE('2006-04-24')
            , 'SH_CLERK'
            , 3100
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 197
            , 'Kevin'
            , 'Feeney'
            , 'KFEENEY'
            , '650.507.9822'
            , DATE('2006-05-23')
            , 'SH_CLERK'
            , 3000
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 198
            , 'Donald'
            , 'OConnell'
            , 'DOCONNEL'
            , '650.507.9833'
            , DATE('2007-06-21')
            , 'SH_CLERK'
            , 2600
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 199
            , 'Douglas'
            , 'Grant'
            , 'DGRANT'
            , '650.507.9844'
            , DATE('2008-01-13')
            , 'SH_CLERK'
            , 2600
            , NULL
            , 124
            , 50
            );
    
    INSERT INTO employees VALUES 
            ( 200
            , 'Jennifer'
            , 'Whalen'
            , 'JWHALEN'
            , '515.123.4444'
            , DATE('2003-09-17')
            , 'AD_ASST'
            , 4400
            , NULL
            , 101
            , 10
            );
    
    INSERT INTO employees VALUES 
            ( 201
            , 'Michael'
            , 'Hartstein'
            , 'MHARTSTE'
            , '515.123.5555'
            , DATE('2004-02-17')
            , 'MK_MAN'
            , 13000
            , NULL
            , 100
            , 20
            );
    
    INSERT INTO employees VALUES 
            ( 202
            , 'Pat'
            , 'Fay'
            , 'PFAY'
            , '603.123.6666'
            , DATE('2005-08-17')
            , 'MK_REP'
            , 6000
            , NULL
            , 201
            , 20
            );
    
    INSERT INTO employees VALUES 
            ( 203
            , 'Susan'
            , 'Mavris'
            , 'SMAVRIS'
            , '515.123.7777'
            , DATE('2002-06-07')
            , 'HR_REP'
            , 6500
            , NULL
            , 101
            , 40
            );
    
    INSERT INTO employees VALUES 
            ( 204
            , 'Hermann'
            , 'Baer'
            , 'HBAER'
            , '515.123.8888'
            , DATE('2002-06-07')
            , 'PR_REP'
            , 10000
            , NULL
            , 101
            , 70
            );
    
    INSERT INTO employees VALUES 
            ( 205
            , 'Shelley'
            , 'Higgins'
            , 'SHIGGINS'
            , '515.123.8080'
            , DATE('2002-06-07')
            , 'AC_MGR'
            , 12008
            , NULL
            , 101
            , 110
            );
    
    INSERT INTO employees VALUES 
            ( 206
            , 'William'
            , 'Gietz'
            , 'WGIETZ'
            , '515.123.8181'
            , DATE('2002-06-07')
            , 'AC_ACCOUNT'
            , 8300
            , NULL
            , 205
            , 110
            );
    View Code

    NULL 即是空

    在数据库中,空值(NULL)是一个特殊的值,通常用于表示缺失值或者不适用的值。比如,填写问卷时不愿意透露某些信息会导致录入项的缺失,在公司的组织结构中总会有一个人(董事长/总经理)没有上级领导。

    首先一点,空值与数字 0 并不相同。假如我问你:你的钱包里有多少钱?如果你知道里面没有钱,可以说是零;如果你不确定,那么就是未知,但不能说没有。当我们需要创建一个表来存储这个信息的时候,应该是 NULL;除非我们能够确定钱包里面没有钱或者有多少钱。

    另外,空值与空字符串('')也不相同,原因和上面类似。但是 Oracle 是一个例外,我们会在下文具体讨论。

    在大多数编程语言中,访问 null 值通常会导致错误;但是 SQL 不会出错,只是会影响到运算的结果而已。

    三值逻辑

    在大多数编程语言中,逻辑运算的结果只有两种情况,不是真(True)就是假(False)。但是对于 SQL 而言,逻辑运算还可能是未知(Unknown):


    引入三值逻辑主要是为了支持 NULL,因为 NULL 代表的是未知数据。因此,SQL 中的逻辑运算与(AND)、或(OR)以及非(NOT)的结果如下:


    对于 AND 运算符而言,真和未知的与运算有可能是真,也有可能是假;因此,最终的结果是未知。

    SQL 中的 WHERE、HAVING 以及 CASE WHEN 子句只返回逻辑运算结果为真的数据,不返回结果为假或未知的数据。

    空值比较

    当我们使用比较运算符(=、<>、<、> 等)与 NULL 进行比较时,结果既不是真也不是假,而是未知;因为 NULL 表示未知,也就意味着可能是任何值。以下运算的结果都是未知:

    NULL = 0
    NULL <> 0
    NULL <= 0
    NULL = NULL
    NULL != NULL

    NULL 与任何值都不相等,甚至两个 NULL 也不想等;因为我们不能说两个未知的值相同,也不能说它们不相同。

    对于比较运算而言,NULL 和 NULL 不相同;但是某些 SQL 子句中的 NULL 值被看作相同的值,例如 GROUP BY。具体参考下文。

    那么,如何判断一个值是否是 NULL 呢?为此,SQL 引入了两个谓词(WHERE 子句):IS NULL和IS NOT NULL。以下示例用于查找 manager 为空的员工: 

    -- 使用比较运算符判断空值
    SELECT employee_id, first_name, last_name, manager_id
      FROM employees
     WHERE manager_id = NULL;
    employee_id|first_name|last_name|manager_id|
    -----------|----------|---------|----------|
    
    -- 使用 IS NULL 判断空值
    SELECT employee_id, first_name, last_name, manager_id
      FROM employees
     WHERE manager_id IS NULL;
    employee_id|first_name|last_name|manager_id|
    -----------|----------|---------|----------|
            100|Steven    |King     |          |

    其中,第一个查询使用比较运算符判断空值,不会返回任何结果;第二个查询使用 IS NULL 判断空值,返回了正确的结果。

    除了标准的IS [NOT] NULL之外,还有一些数据库扩展的运算符可以用于空值比较:

    -- MySQL
    SELECT employee_id, first_name, last_name, manager_id
      FROM employees
     WHERE manager_id <=> NULL;
    employee_id|first_name|last_name|manager_id|
    -----------|----------|---------|----------|
            100|Steven    |King     |          |

    MySQL 中的<=>可以用于等值比较,支持两个 NULL 值。

    以下查询的结果也不会返回任何结果:

    SELECT employee_id, first_name, last_name, manager_id
      FROM employees
     WHERE (1 = NULL) OR (1 != NULL);

    因为根据上面的三值逻辑,两个未知结果的 OR 运算最终还是未知。

    前文我们说过,空字符串不是 NULL;但是 Oracle 中的空字符串被看作 NULL。例如: 

    -- Oracle
    SELECT 1
      FROM dual
     WHERE '' IS NULL;
    VAL|
    ---|
      1|
    
    -- 其他数据库
    SELECT 1 AS val
     WHERE '' IS NULL;
    val|
    ---|

    当然,我们如果使用等值(=)运算符判断空字符串与 NULL,结果仍然为空。

    NOT IN 与空值

    对于 WHERE 条件中的 IN 和 NOT IN 运算符,使用的是等值比较。所以如果 NOT IN 碰到了 NULL 值,永远不会返回任何结果。例如:

    SELECT employee_id, first_name, last_name, manager_id
    FROM employees
    WHERE 1 NOT IN (NULL, 2);

    因为上面的条件实际上等价于:

    SELECT employee_id, first_name, last_name, manager_id
    FROM employees
    WHERE 1 != NULL AND 1 != 2;

    1 不等于 NULL 的结果是未知,1 不等于 2 的结果是真,未知和真的 AND 运算结果还是未知。

    如果使用 NOT IN,一定要确保括号中的值不会出现 NULL;或者尽量使用 NOT EXISTS。

    函数与空值

    一般来说,函数和表达式的参数中如果存在 NULL,其结果也是 NULL。当然也有一些例外,比如聚合函数。

    以下查询返回的都是 NULL:

    SELECT ABS(NULL), 1 + NULL
      FROM employees
     WHERE employee_id = 100;
    ABS(NULL)|1 + NULL|
    ---------|--------|
       [NULL]|  [NULL]|

    一个未知值的绝对值仍然未知,1 加上一个未知值结果还是未知。

    但是一个常见的例外是字符串与 NULL 的连接:

    -- Oracle
    SELECT CONCAT('Hello', NULL)
      FROM employees
     WHERE employee_id = 100;
    CONCAT('HELLO',NULL)|
    --------------------|
    Hello               |
    
    -- MySQL
    SELECT CONCAT('Hello', NULL)
      FROM employees
     WHERE employee_id = 100;
    CONCAT('Hello', NULL)|
    ---------------------|
                   [NULL]|

    Oracle 将 NULL 看作空字符串,所以查询结果为“Hello”;MySQL 中 NULL 参数导致 CONCAT 函数结果为 NULL;SQLite 没有提供 CONCAT 函数。

    另外,Oracle 中的 || 也将 NULL 看作空字符串;其他数据库 || 中的 NULL 将参数会产生 NULL 结果。

    聚合函数(SUM、COUNT、AVG 等)通常会在进行计算之前删除 NULL 数据:

    SELECT SUM(salary + commission_pct) sum1,
           SUM(salary) + SUM(commission_pct) sum2,
           COUNT(salary),
           COUNT(commission_pct)
      FROM employees;
    SUM1    |SUM2    |COUNT(SALARY)|COUNT(COMMISSION_PCT)|
    --------|--------|-------------|---------------------|
    311507.8|691423.8|          107|                   35|

    第一个 SUM 函数返回的是 salary 和 commission_pct 都不为空的数据总和;第而个 SUM 函数返回的是 salary 不为空的数据总和加上 commission_pct 不为空的数据总和,所以比第一个数据大;COUNT 函数结果显示 salary 有 107 条记录不为空,commission_pct 只有 35 条记录不为空。

    如果输入数据都是 NULL 值,除了 COUNT 函数之外的其他聚合函数返回 NULL:

    SELECT COUNT(*), COUNT(commission_pct), AVG(commission_pct), SUM(commission_pct)
      FROM employees
     WHERE commission_pct IS NULL;
    COUNT(*)|COUNT(COMMISSION_PCT)|AVG(COMMISSION_PCT)|SUM(COMMISSION_PCT)|
    --------|---------------------|-------------------|-------------------|
          72|                    0|             [NULL]|             [NULL]|

    COUNT(*) 总是返回数据的行数,不受空值的影响;COUNT(commission_pct) 返回了零;AVG 和 SUM 返回了 NULL。

    DISTINCT、GROUP BY、UNION 与空值

    SQL 中的分组操作将所有的 NULL 值分到同一个组,包括 DISTINCT、GROUP BY 以及窗口函数中的 PARTITION BY。例如: 

    SELECT DISTINCT commission_pct
      FROM employees;
    commission_pct|
    --------------|
            [NULL]|
              0.40|
              0.30|
              0.20|
              0.25|
              0.15|
              0.35|
              0.10|
    
    SELECT commission_pct
      FROM employees
     GROUP BY commission_pct;
    commission_pct|
    --------------|
            [NULL]|
              0.40|
              0.30|
              0.20|
              0.25|
              0.15|
              0.35|
              0.10|

    从上面的示例可以看出,commission_pct 为空的数据有 72 条,但是分组之后只有一个 NULL 组。

    除此之外,UNION 操作符也将所有的 NULL 看作相同值:

    SELECT manager_id
      FROM employees
     WHERE manager_id IS NULL
     UNION
    SELECT manager_id
      FROM employees
     WHERE manager_id IS NULL;
    manager_id|
    ----------|
        [NULL]|

    如果将 UNION 换成 UNION ALL,查询结果将会保留 2 个 NULL 值。

    ORDER BY 与空值

    SQL 标准没有定义 NULL 值的排序顺序,但是为 ORDER BY 定义了 NULLS FIRST 和 NULLS LAST 选项,用于明确指定空值排在其他数据之前或者之后。

    不同数据库对此提供了不同的实现:

    SELECT employee_id, manager_id
      FROM employees
     WHERE employee_id IN (100, 101, 102)
     ORDER BY manager_id;
    
    -- Oracle
    EMPLOYEE_ID|MANAGER_ID|
    -----------|----------|
            101|       100|
            102|       100|
            100|    [NULL]|
    
    -- MySQL
    employee_id|manager_id|
    -----------|----------|
            100|    [NULL]|
            101|       100|
            102|       100|

    其中,Oracle 默认将 NULL 作为最大值,升序时排在最后;MySQL默认将 NULL 作为最小值,升序时排在最前。

    另外,Oracle提供了扩展的 NULLS FIRST 和 NULLS LAST 选项:

    -- Oracle
    SELECT employee_id, manager_id
      FROM employees
     WHERE employee_id IN (100, 101, 102)
     ORDER BY manager_id NULLS FIRST;
    employee_id|manager_id|
    -----------|----------|
            100|    [NULL]|
            101|       100|
            102|       100|

    我们也可以使用 CASE 表达式实现类似的效果。以下示例与 NULLS LAST 作用相同,而且所有数据库都可以使用:

    SELECT employee_id, manager_id
      FROM employees
     WHERE employee_id IN (100, 101, 102)
     ORDER BY CASE WHEN manager_id IS NULL THEN 1
                   ELSE 0
              END,
              manager_id;
    employee_id|manager_id|
    -----------|----------|
            101|       100|
            102|       100|
            100|    [NULL]|

    首先,CASE 表达式将 manager_id 为空的数据转换为 1,非空的数据转换为 0,所以空值排在其他数据之后;第二个排序字段 manager_id 确保了非空的数据从小到大排序。

    空值处理函数

    由于空值的特殊性,我们在分析数据时经常需要进行空值和其他值的转换。为此,SQL 提供了两个标准的空值函数:COALESCE 和 NULLIF。

    COALESCE(exp1, exp2, …) 函数用于将 NULL 转换为其他值。当 exp1 不为空时返回 exp1,否则检查 exp2;如果 exp2 不为空时返回 exp2,依次类推。例如:

    SELECT COALESCE(NULL, NULL, 3)
      FROM employees
     WHERE employee_id = 100;
    COALESCE(NULL, NULL, 3)|
    -----------------------|
                          3|

    由于前面两个参数都是 NULL,COALESCE 最终返回了 3。

    COALESCE 函数也可以使用 CASE 表达式改写如下:

    CASE WHEN exp1 IS NOT NULL THEN exp1
         WHEN exp2 IS NOT NULL THEN exp2
         ...
         ELSE expN
    END

    NULLIF(exp1, exp2) 函数用于将指定值转换为 NULL。当 exp1 等于 exp2 时,返回 NULL;否则,返回 exp1 。NULLIF 最常见的用途是防止除零错误,例如:

    SELECT 1 / NULLIF(0, 0) -- 1 / 0
    FROM employees
    WHERE employee_id = 100;

    示例中的 NULLIF 将第一个零转换为 NULL,因此查询结果返回 NULL;如果直接使用 1 / 0,查询将会返回除零错误。MySQL 中的除零错误由 sql_mode 变量控制。

    NULLIF 函数同样可以使用 CASE 表达式改写如下:

    CASE WHEN exp1 = exp2 THEN NULL
    ELSE exp1
    END

    利用 CASE 表达式,我们还可以轻松实现多个值到 NULL 的转换:

    CASE WHEN expr IN (value1, value2, …)
    THEN NULL
    ELSE expr
    END

    COALESCE 和 NULLIF 实际上是 CASE 表达式的两种缩写形式。

    除了标准 SQL 函数之外,数据库还提供了一些专用的函数:

    • Oracle 中的 NVL(expr1, expr2) 相当于 2 个参数的 COALESCE。另外,NVL2(expr1, expr2, expr3) 如果第一个参数不为空,返回第二个参数的值;否则,返回第三个参数的值;
    • MySQL 中的 IFNULL(expr1, expr2) 相当于 2 个参数的 COALESCE。另外,IF(expr1, expr2, expr3) 如果第一个参数为真(expr1 <> 0 并且 expr1 不为空),返回第二个参数的值;否则,返回第三个参数的值;

    字段约束与空值

    如果不允许字段中存在未知或者缺失的数据,可以使用字段的 NOT NULL 约束。

    对于唯一约束(UNIQUE),多个 NULL 被看作是不同的值;因此,唯一约束字段中可以存在多个空值。不过 SQL Server 是个例外:

    CREATE TABLE t_unique(id INT UNIQUE);
    INSERT INTO t_unique VALUES(1);
    INSERT INTO t_unique VALUES(NULL);
    INSERT INTO t_unique VALUES(NULL); 
    
    SELECT * FROM t_unique;
    id|
    ------|
    [NULL]|
    [NULL]|
    1|
    
    SELECT * FROM t_unique;
    id|
    ------|
    [NULL]|

    如果是复合索引,情况略有不同:

    CREATE TABLE t_unique2(c1 INT, c2 INT, UNIQUE(c1,c2));
    
    INSERT INTO t_unique2 VALUES(1, 1);
    INSERT INTO t_unique2 VALUES(NULL, NULL);
    INSERT INTO t_unique2 VALUES(NULL, NULL); -- SQL Server 产生唯一键冲突错误
    INSERT INTO t_unique2 VALUES(1, NULL);
    INSERT INTO t_unique2 VALUES(1, NULL); -- Oracle 和 SQL Server 产生唯一键冲突错误

    其中,SQL Server 只允许有一个记录的全部索引字段为空;如果某个字段不为空,Oracle 和 SQL Server 只允许有一个记录的其他索引字段为空。

    另外,检查约束(CHECK)对于 NULL 的处理与 WHERE 条件正好相反:只要数据的检查结果不是假都可以插入成功。例如: 

    CREATE TABLE t_check (
      c1 INT CHECK (c1 >= 0),
      c2 INT CHECK (c2 >= 0),
      CHECK (c1 + c2 <= 100)
    );
    
    INSERT INTO t_check VALUES (5, 5);
    INSERT INTO t_check VALUES (NULL, NULL);
    INSERT INTO t_check VALUES (200, NULL);
    
    SELECT * FROM t_check;
    c1    |c2    |
    ------|------|
         5|     5|
    [NULL]|[NULL]|
       200|[NULL]|

    如果 c1 和 c2 都有值的话,都必须大于等于零并且和值小于等于 100;c1 和 c2 都可以为空;如果其中之一为空,另一个字段的值可以大于 100。

  • 相关阅读:
    Spring 原生SQL查询
    Spring 使用注解查询 JPQL 按对象查询
    JAVA 判断输入流是否为空
    Spring-AOP教程
    错误笔记5, Spring datatable Error creating bean with name 'userController'
    Spring 分页查询
    前端传数据到servlet数据乱码
    sql 分页查询
    移动APP性能测试
    【8】接口、多态
  • 原文地址:https://www.cnblogs.com/johnvwan/p/12157792.html
Copyright © 2020-2023  润新知