~ubuntu-branches/ubuntu/wily/sqlite3/wily

« back to all changes in this revision

Viewing changes to nulls.html

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2012-06-13 21:43:48 UTC
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: package-import@ubuntu.com-20120613214348-uy14uupdeq0hh04k
Tags: upstream-3.7.13/www
Import upstream version 3.7.13, component www

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 
2
<html><head>
 
3
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
 
4
<title>NULL Handling in SQLite</title>
 
5
<style type="text/css">
 
6
body {
 
7
    margin: auto;
 
8
    font-family: Verdana, sans-serif;
 
9
    padding: 8px 1%;
 
10
}
 
11
 
 
12
a { color: #044a64 }
 
13
a:visited { color: #734559 }
 
14
 
 
15
.logo { position:absolute; margin:3px; }
 
16
.tagline {
 
17
  float:right;
 
18
  text-align:right;
 
19
  font-style:italic;
 
20
  width:300px;
 
21
  margin:12px;
 
22
  margin-top:58px;
 
23
}
 
24
 
 
25
.toolbar {
 
26
  text-align: center;
 
27
  line-height: 1.6em;
 
28
  margin: 0;
 
29
  padding: 0px 8px;
 
30
}
 
31
.toolbar a { color: white; text-decoration: none; padding: 6px 12px; }
 
32
.toolbar a:visited { color: white; }
 
33
.toolbar a:hover { color: #044a64; background: white; }
 
34
 
 
35
.content    { margin: 5%; }
 
36
.content dt { font-weight:bold; }
 
37
.content dd { margin-bottom: 25px; margin-left:20%; }
 
38
.content ul { padding:0px; padding-left: 15px; margin:0px; }
 
39
 
 
40
/* rounded corners */
 
41
.se  { background: url(images/se.gif) 100% 100% no-repeat #044a64}
 
42
.sw  { background: url(images/sw.gif) 0% 100% no-repeat }
 
43
.ne  { background: url(images/ne.gif) 100% 0% no-repeat }
 
44
.nw  { background: url(images/nw.gif) 0% 0% no-repeat }
 
45
 
 
46
/* Things for "fancyformat" documents start here. */
 
47
.fancy img+p {font-style:italic}
 
48
.fancy .codeblock i { color: darkblue; }
 
49
.fancy h1,.fancy h2,.fancy h3,.fancy h4 {font-weight:normal;color:#044a64}
 
50
.fancy h2 { margin-left: 10px }
 
51
.fancy h3 { margin-left: 20px }
 
52
.fancy h4 { margin-left: 30px }
 
53
.fancy th {white-space:nowrap;text-align:left;border-bottom:solid 1px #444}
 
54
.fancy th, .fancy td {padding: 0.2em 1ex; vertical-align:top}
 
55
.fancy #toc a        { color: darkblue ; text-decoration: none }
 
56
.fancy .todo         { color: #AA3333 ; font-style : italic }
 
57
.fancy .todo:before  { content: 'TODO:' }
 
58
.fancy p.todo        { border: solid #AA3333 1px; padding: 1ex }
 
59
.fancy img { display:block; }
 
60
.fancy :link:hover, .fancy :visited:hover { background: wheat }
 
61
.fancy p,.fancy ul,.fancy ol { margin: 1em 5ex }
 
62
.fancy li p { margin: 1em 0 }
 
63
/* End of "fancyformat" specific rules. */
 
64
 
 
65
</style>
 
66
  
 
67
</head>
 
68
<body>
 
69
<div><!-- container div to satisfy validator -->
 
70
 
 
71
<a href="index.html">
 
72
<img class="logo" src="images/sqlite370_banner.gif" alt="SQLite Logo"
 
73
 border="0"></a>
 
74
<div><!-- IE hack to prevent disappearing logo--></div>
 
75
<div class="tagline">Small. Fast. Reliable.<br>Choose any three.</div>
 
76
 
 
77
<table width=100% style="clear:both"><tr><td>
 
78
  <div class="se"><div class="sw"><div class="ne"><div class="nw">
 
79
  <table width=100% style="padding:0;margin:0;cell-spacing:0"><tr>
 
80
  <td width=100%>
 
81
  <div class="toolbar">
 
82
    <a href="about.html">About</a>
 
83
    <a href="sitemap.html">Sitemap</a>
 
84
    <a href="docs.html">Documentation</a>
 
85
    <a href="download.html">Download</a>
 
86
    <a href="copyright.html">License</a>
 
87
    <a href="news.html">News</a>
 
88
    <a href="support.html">Support</a>
 
89
  </div>
 
90
<script>
 
91
  gMsg = "Search SQLite Docs..."
 
92
  function entersearch() {
 
93
    var q = document.getElementById("q");
 
94
    if( q.value == gMsg ) { q.value = "" }
 
95
    q.style.color = "black"
 
96
    q.style.fontStyle = "normal"
 
97
  }
 
98
  function leavesearch() {
 
99
    var q = document.getElementById("q");
 
100
    if( q.value == "" ) { 
 
101
      q.value = gMsg
 
102
      q.style.color = "#044a64"
 
103
      q.style.fontStyle = "italic"
 
104
    }
 
105
  }
 
106
</script>
 
107
<td>
 
108
    <div style="padding:0 1em 0px 0;white-space:nowrap">
 
109
    <form name=f method="GET" action="http://www.sqlite.org/search">
 
110
      <input id=q name=q type=text
 
111
       onfocus="entersearch()" onblur="leavesearch()" style="width:24ex;padding:1px 1ex; border:solid white 1px; font-size:0.9em ; font-style:italic;color:#044a64;" value="Search SQLite Docs...">
 
112
      <input type=submit value="Go" style="border:solid white 1px;background-color:#044a64;color:white;font-size:0.9em;padding:0 1ex">
 
113
    </form>
 
114
    </div>
 
115
  </table>
 
116
</div></div></div></div>
 
117
</td></tr></table>
 
118
<div class=startsearch></div>
 
119
  
 
120
 
 
121
 
 
122
<h2>NULL Handling in SQLite Versus Other Database Engines</h2>
 
123
 
 
124
<p>
 
125
The goal is
 
126
to make SQLite handle NULLs in a standards-compliant way.
 
127
But the descriptions in the SQL standards on how to handle
 
128
NULLs seem ambiguous. 
 
129
It is not clear from the standards documents exactly how NULLs should
 
130
be handled in all circumstances.
 
131
</p>
 
132
 
 
133
<p>
 
134
So instead of going by the standards documents, various popular
 
135
SQL engines were tested to see how they handle NULLs.  The idea
 
136
was to make SQLite work like all the other engines.
 
137
An SQL test script was developed and run by volunteers on various
 
138
SQL RDBMSes and the results of those tests were used to deduce
 
139
how each engine processed NULL values.
 
140
The original tests were run in May of 2002.
 
141
A copy of the test script is found at the end of this document.
 
142
</p>
 
143
 
 
144
<p>
 
145
SQLite was originally coded in such a way that the answer to
 
146
all questions in the chart below would be "Yes".  But the
 
147
experiments run on other SQL engines showed that none of them
 
148
worked this way.  So SQLite was modified to work the same as
 
149
Oracle, PostgreSQL, and DB2.  This involved making NULLs
 
150
indistinct for the purposes of the SELECT DISTINCT statement and
 
151
for the UNION operator in a SELECT.  NULLs are still distinct
 
152
in a UNIQUE column.  This seems somewhat arbitrary, but the desire
 
153
to be compatible with other engines outweighed that objection.
 
154
</p>
 
155
 
 
156
<p>
 
157
It is possible to make SQLite treat NULLs as distinct for the
 
158
purposes of the SELECT DISTINCT and UNION.  To do so, one should
 
159
change the value of the NULL_ALWAYS_DISTINCT #define in the
 
160
<tt>sqliteInt.h</tt> source file and recompile.
 
161
</p>
 
162
 
 
163
<blockquote>
 
164
<p>
 
165
<i>Update 2003-07-13:</i>
 
166
Since this document was originally written some of the database engines
 
167
tested have been updated and users have been kind enough to send in
 
168
corrections to the chart below.  The original data showed a wide variety
 
169
of behaviors, but over time the range of behaviors has converged toward
 
170
the PostgreSQL/Oracle model.  The only significant difference 
 
171
is that Informix and MS-SQL both treat NULLs as
 
172
indistinct in a UNIQUE column.
 
173
</p>
 
174
 
 
175
<p>
 
176
The fact that NULLs are distinct for UNIQUE columns but are indistinct for
 
177
SELECT DISTINCT and UNION continues to be puzzling.  It seems that NULLs
 
178
should be either distinct everywhere or nowhere.  And the SQL standards
 
179
documents suggest that NULLs should be distinct everywhere.  Yet as of
 
180
this writing, no SQL engine tested treats NULLs as distinct in a SELECT
 
181
DISTINCT statement or in a UNION.
 
182
</p>
 
183
</blockquote>
 
184
 
 
185
 
 
186
<p>
 
187
The following table shows the results of the NULL handling experiments.
 
188
</p>
 
189
 
 
190
<table border=1 cellpadding=3 width="100%">
 
191
<tr><th>&nbsp&nbsp;</th>
 
192
<th>SQLite</th>
 
193
<th>PostgreSQL</th>
 
194
<th>Oracle</th>
 
195
<th>Informix</th>
 
196
<th>DB2</th>
 
197
<th>MS-SQL</th>
 
198
<th>OCELOT</th>
 
199
</tr>
 
200
 
 
201
<tr><td>Adding anything to null gives null</td>
 
202
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
203
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
204
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
205
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
206
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
207
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
208
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
209
</tr>
 
210
<tr><td>Multiplying null by zero gives null</td>
 
211
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
212
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
213
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
214
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
215
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
216
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
217
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
218
</tr>
 
219
<tr><td>nulls are distinct in a UNIQUE column</td>
 
220
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
221
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
222
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
223
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
224
<td valign="center" align="center" bgcolor="#aaaad2">(Note 4)</td>
 
225
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
226
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
227
</tr>
 
228
<tr><td>nulls are distinct in SELECT DISTINCT</td>
 
229
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
230
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
231
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
232
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
233
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
234
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
235
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
236
</tr>
 
237
<tr><td>nulls are distinct in a UNION</td>
 
238
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
239
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
240
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
241
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
242
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
243
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
244
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
245
</tr>
 
246
<tr><td>"CASE WHEN null THEN 1 ELSE 0 END" is 0?</td>
 
247
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
248
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
249
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
250
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
251
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
252
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
253
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
254
</tr>
 
255
<tr><td>"null OR true" is true</td>
 
256
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
257
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
258
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
259
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
260
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
261
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
262
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
263
</tr>
 
264
<tr><td>"not (null AND false)" is true</td>
 
265
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
266
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
267
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
268
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
269
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
270
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
271
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
272
</tr>
 
273
</table>
 
274
 
 
275
<table border=1 cellpadding=3 width="100%">
 
276
<tr><th>&nbsp&nbsp;</th>
 
277
<th>MySQL<br>3.23.41</th>
 
278
<th>MySQL<br>4.0.16</th>
 
279
<th>Firebird</th>
 
280
<th>SQL<br>Anywhere</th>
 
281
<th>Borland<br>Interbase</th>
 
282
</tr>
 
283
 
 
284
<tr><td>Adding anything to null gives null</td>
 
285
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
286
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
287
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
288
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
289
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
290
</tr>
 
291
<tr><td>Multiplying null by zero gives null</td>
 
292
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
293
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
294
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
295
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
296
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
297
</tr>
 
298
<tr><td>nulls are distinct in a UNIQUE column</td>
 
299
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
300
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
301
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
302
<td valign="center" align="center" bgcolor="#aaaad2">(Note 4)</td>
 
303
<td valign="center" align="center" bgcolor="#aaaad2">(Note 4)</td>
 
304
</tr>
 
305
<tr><td>nulls are distinct in SELECT DISTINCT</td>
 
306
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
307
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
308
<td valign="center" align="center" bgcolor="#c7a9a9">No (Note 1)</td>
 
309
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
310
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
311
</tr>
 
312
<tr><td>nulls are distinct in a UNION</td>
 
313
<td valign="center" align="center" bgcolor="#aaaad2">(Note 3)</td>
 
314
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
315
<td valign="center" align="center" bgcolor="#c7a9a9">No (Note 1)</td>
 
316
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
317
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
318
</tr>
 
319
<tr><td>"CASE WHEN null THEN 1 ELSE 0 END" is 0?</td>
 
320
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
321
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
322
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
323
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
324
<td valign="center" align="center" bgcolor="#aaaad2">(Note 5)</td>
 
325
</tr>
 
326
<tr><td>"null OR true" is true</td>
 
327
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
328
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
329
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
330
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
331
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
332
</tr>
 
333
<tr><td>"not (null AND false)" is true</td>
 
334
<td valign="center" align="center" bgcolor="#c7a9a9">No</td>
 
335
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
336
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
337
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
338
<td valign="center" align="center" bgcolor="#a9c7a9">Yes</td>
 
339
</tr>
 
340
</table>
 
341
 
 
342
<table border=0 align="right" cellpadding=0 cellspacing=0>
 
343
<tr>
 
344
<td valign="top" rowspan=5>Notes:&nbsp;&nbsp;</td>
 
345
<td>1.&nbsp;</td>
 
346
<td>Older versions of firebird omits all NULLs from SELECT DISTINCT
 
347
and from UNION.</td>
 
348
</tr>
 
349
<tr><td>2.&nbsp;</td>
 
350
<td>Test data unavailable.</td>
 
351
</tr>
 
352
<tr><td>3.&nbsp;</td>
 
353
<td>MySQL version 3.23.41 does not support UNION.</td>
 
354
</tr>
 
355
<tr><td>4.&nbsp;</td>
 
356
<td>DB2, SQL Anywhere, and Borland Interbase 
 
357
do not allow NULLs in a UNIQUE column.</td>
 
358
</tr>
 
359
<tr><td>5.&nbsp;</td>
 
360
<td>Borland Interbase does not support CASE expressions.</td>
 
361
</tr>
 
362
</table>
 
363
<br clear="both">
 
364
 
 
365
<p>&nbsp;</p>
 
366
<p>
 
367
The following script was used to gather information for the table
 
368
above.
 
369
</p>
 
370
 
 
371
<pre>
 
372
-- I have about decided that SQL's treatment of NULLs is capricious and cannot be
 
373
-- deduced by logic.  It must be discovered by experiment.  To that end, I have 
 
374
-- prepared the following script to test how various SQL databases deal with NULL.
 
375
-- My aim is to use the information gather from this script to make SQLite as much
 
376
-- like other databases as possible.
 
377
--
 
378
-- If you could please run this script in your database engine and mail the results
 
379
-- to me at drh@hwaci.com, that will be a big help.  Please be sure to identify the
 
380
-- database engine you use for this test.  Thanks.
 
381
--
 
382
-- If you have to change anything to get this script to run with your database
 
383
-- engine, please send your revised script together with your results.
 
384
--
 
385
 
 
386
-- Create a test table with data
 
387
create table t1(a int, b int, c int);
 
388
insert into t1 values(1,0,0);
 
389
insert into t1 values(2,0,1);
 
390
insert into t1 values(3,1,0);
 
391
insert into t1 values(4,1,1);
 
392
insert into t1 values(5,null,0);
 
393
insert into t1 values(6,null,1);
 
394
insert into t1 values(7,null,null);
 
395
 
 
396
-- Check to see what CASE does with NULLs in its test expressions
 
397
select a, case when b<>0 then 1 else 0 end from t1;
 
398
select a+10, case when not b<>0 then 1 else 0 end from t1;
 
399
select a+20, case when b<>0 and c<>0 then 1 else 0 end from t1;
 
400
select a+30, case when not (b<>0 and c<>0) then 1 else 0 end from t1;
 
401
select a+40, case when b<>0 or c<>0 then 1 else 0 end from t1;
 
402
select a+50, case when not (b<>0 or c<>0) then 1 else 0 end from t1;
 
403
select a+60, case b when c then 1 else 0 end from t1;
 
404
select a+70, case c when b then 1 else 0 end from t1;
 
405
 
 
406
-- What happens when you multiple a NULL by zero?
 
407
select a+80, b*0 from t1;
 
408
select a+90, b*c from t1;
 
409
 
 
410
-- What happens to NULL for other operators?
 
411
select a+100, b+c from t1;
 
412
 
 
413
-- Test the treatment of aggregate operators
 
414
select count(*), count(b), sum(b), avg(b), min(b), max(b) from t1;
 
415
 
 
416
-- Check the behavior of NULLs in WHERE clauses
 
417
select a+110 from t1 where b<10;
 
418
select a+120 from t1 where not b>10;
 
419
select a+130 from t1 where b<10 OR c=1;
 
420
select a+140 from t1 where b<10 AND c=1;
 
421
select a+150 from t1 where not (b<10 AND c=1);
 
422
select a+160 from t1 where not (c=1 AND b<10);
 
423
 
 
424
-- Check the behavior of NULLs in a DISTINCT query
 
425
select distinct b from t1;
 
426
 
 
427
-- Check the behavior of NULLs in a UNION query
 
428
select b from t1 union select b from t1;
 
429
 
 
430
-- Create a new table with a unique column.  Check to see if NULLs are considered
 
431
-- to be distinct.
 
432
create table t2(a int, b int unique);
 
433
insert into t2 values(1,1);
 
434
insert into t2 values(2,null);
 
435
insert into t2 values(3,null);
 
436
select * from t2;
 
437
 
 
438
drop table t1;
 
439
drop table t2;
 
440
</pre>
 
441