Added ON CONFLICT support to COPY. Updates to documentation. Bug fixes. (CVS 359)
FossilOrigin-Name: cf1538d71c9ce12d5e59f367e03642cbcaf6b717
This commit is contained in:
@@ -17,6 +17,15 @@ proc chng {date desc} {
|
||||
puts "<DD><P><UL>$desc</UL></P></DD>"
|
||||
}
|
||||
|
||||
chng {2002 Jan 30 (2.3.0 beta)} {
|
||||
<li>Added the ability to resolve constraint conflicts is ways other than
|
||||
an abort and rollback. See the documentation on the "ON CONFLICT"
|
||||
clause for details.</li>
|
||||
<li>NOT NULL constraints are honored.</li>
|
||||
<li>The COPY command puts NULLs in columns whose data is '\N'.</li>
|
||||
<li>In the COPY command, backslash can now be used to escape a newline.</li>
|
||||
}
|
||||
|
||||
chng {2002 Jan 28 (2.2.5)} {
|
||||
<li>Important bug fix: the IN operator was not working if either the
|
||||
left-hand or right-hand side was derived from an INTEGER PRIMARY KEY.</li>
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#
|
||||
# Run this Tcl script to generate the constraint.html file.
|
||||
#
|
||||
set rcsid {$Id: conflict.tcl,v 1.1 2002/01/30 16:17:25 drh Exp $ }
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
<title>Constraint Conflict Resolution in SQLite</title>
|
||||
</head>
|
||||
<body bgcolor=white>
|
||||
<h1 align=center>
|
||||
Constraint Conflict Resolution in SQLite
|
||||
</h1>}
|
||||
puts "<p align=center>
|
||||
(This page was last modified on [lrange $rcsid 3 4] UTC)
|
||||
</p>"
|
||||
|
||||
puts {
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>
|
||||
In most SQL databases, if you have a UNIQUE constraint on
|
||||
a table and you try to do an UPDATE or INSERT that violates
|
||||
that constraint, the database will aborts the operation in
|
||||
progress and rolls back the current transaction.
|
||||
This is the default behavior of SQLite.
|
||||
Beginning with version 2.3.0, though, SQLite allows you to
|
||||
define alternative ways for dealing with constraint violations.
|
||||
This article describes those alternatives and how to use them.
|
||||
</p>
|
||||
|
||||
<h2>Conflict Resolution Algorithms</h2>
|
||||
|
||||
<p>
|
||||
The default conflict resolution algorithm is to abort the
|
||||
operation in progress, rollback all changes, and cancel the
|
||||
current transaction. Call this algorithm "ABORT". Abort
|
||||
is the standard way of dealing with a constraint error
|
||||
in most SQL databases.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sometimes ABORT is not the most helpful way of dealing
|
||||
with constraint violations. Suppose, for example, you are
|
||||
inserting 1000 records into a database, all within a single
|
||||
transaction, but one of those records is malformed and causes
|
||||
a constraint error. With the default ABORT behavior, none
|
||||
of the 1000 records gets inserted. But sometimes it is
|
||||
desirable to just omit the single malformed insert and
|
||||
finish the other 999.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
SQLite defines two addition conflict resolution algorithms
|
||||
called "IGNORE" and "REPLACE".
|
||||
If you are trying to do multiple INSERTs or UPDATEs when a constraint
|
||||
fails for a single row and the conflict behavior is IGNORE, then
|
||||
that row remains uninserted or unmodified. But the overall operation
|
||||
is not aborted and no rollback occurs. If a constraint
|
||||
fails and the behavior is REPLACE, then SQLite tries to
|
||||
delete other rows in the table in order to eliminate the
|
||||
constraint problem. Again, the overall operation continues
|
||||
and no rollback occurs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The default conflict resolution algorithm is always ABORT
|
||||
but you can specify an alternative algorithm using special
|
||||
(non-standard) syntax on the INSERT and UPDATE commands.
|
||||
You can add the clause "ON CONFLICT <algorithm>" immediately
|
||||
after the "INSERT" or "UPDATE" keywords to specify the
|
||||
conflict resolution algorithm to use for that one operation.
|
||||
(Substitute "ABORT", "IGNORE", or "REPLACE" for <algorithm>,
|
||||
of course.)
|
||||
</p>
|
||||
|
||||
Consider this example:
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
CREATE TABLE t1(
|
||||
a INTEGER,
|
||||
b INTEGER,
|
||||
c INTEGER,
|
||||
UNIQUE(a,b)
|
||||
);
|
||||
INSERT INTO a VALUES(1,2,3);
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO a VALUES(2,3,4);
|
||||
INSERT INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In the last instruction, the UNIQUE constraint fails
|
||||
and the entire transaction is rolled back. The database
|
||||
now contains a single entry: {1,2,3}.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(2,3,4);
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(1,2,5);
|
||||
COMMIT;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>This time the "ON CONFLICT IGNORE" clause tells SQLite to use
|
||||
IGNORE semantics when a constraint fails. The second
|
||||
INSERT statement fails, but the database is
|
||||
not rolled back and there is no failure. The database
|
||||
now contains two rows: {1,2,3} and {2,3,4}.</p>
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
INSERT ON CONFLICT REPLACE INTO a VALUES(1,2,5);
|
||||
COMMIT;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Here the "ON CONFLICT REPLACE" clause tells SQLite to use REPLACE
|
||||
semantics. The {1,2,3} is deleted when the {1,2,5} row
|
||||
is inserted in order to satisfy the constraint. After
|
||||
the above, the database contains {1,2,5} and {2,3,4}.</p>
|
||||
|
||||
<h2>A Syntactic Shortcut</h2>
|
||||
|
||||
<p>On an INSERT, the "ON CONFLICT" keywords may be omitted for brevity.
|
||||
So you can say</p>
|
||||
|
||||
<blockquote><pre>
|
||||
INSERT IGNORE INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Instead of the more wordy:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Unfortunately, you cannot do this with an UPDATE.</p>
|
||||
|
||||
<h2>Changing The Default Conflict Resolution Algorithm</h2>
|
||||
|
||||
<p>You can change the default conflict resolution algorithm
|
||||
on a constraint-by-constraint basis using special (non-standard)
|
||||
syntax in CREATE TABLE and CREATE INDEX statements. The
|
||||
same "ON CONFLICT" clause that appears in INSERT and UPDATE
|
||||
statements is used but the clause is attached to the constraint
|
||||
in the CREATE TABLE statement. Like this:
|
||||
|
||||
<blockquote><pre>
|
||||
CREATE TABLE t1 (
|
||||
a INTEGER,
|
||||
b INTEGER,
|
||||
c INTEGER,
|
||||
UNIQUE(a,b) ON CONFLICT REPLACE
|
||||
);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The ON CONFLICT clause in the above table definition says that
|
||||
the default conflict resolution algorithm is REPLACE instead
|
||||
of ABORT. REPLACE will always be used unless you override
|
||||
this by saying "INSERT IGNORE" or "INSERT ABORT".</p>
|
||||
|
||||
<p>The ON CONFLICT clause can also appear on a NOT NULL constraint,
|
||||
a PRIMARY KEY constraint, and a CHECK constraint.
|
||||
(Note, however, that CHECK constraints are not currently enforced
|
||||
so the ON CONFLICT clause has no effect there.)</p>
|
||||
|
||||
<p>A NOT NULL constraint will normally ABORT if you try to insert
|
||||
a NULL. But if you substitute the REPLACE algorithm, it tries to insert
|
||||
the default value in place of the NULL. If there is no default value,
|
||||
then REPLACE is the same as ABORT for NOT NULL constraints.
|
||||
With the IGNORE algorithm on a NOT NULL, the INSERT or UPDATE
|
||||
is suppressed if the value is NULL.</p>
|
||||
|
||||
<h2>Portability</h2>
|
||||
|
||||
<p>The ON CONFLICT syntax is not standard SQL and will not
|
||||
(as far as is known) work on any other database product. Furthermore,
|
||||
the syntax might change in future versions of SQLite. So use it
|
||||
with appropriate discretion.</p>
|
||||
}
|
||||
|
||||
puts {
|
||||
<p><hr /></p>
|
||||
<p><a href="index.html"><img src="/goback.jpg" border=0 />
|
||||
Back to the SQLite Home Page</a>
|
||||
</p>
|
||||
|
||||
</body></html>}
|
||||
+11
-1
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the formatchng.html file.
|
||||
#
|
||||
set rcsid {$Id: formatchng.tcl,v 1.1 2001/12/22 19:27:41 drh Exp $ }
|
||||
set rcsid {$Id: formatchng.tcl,v 1.2 2002/01/30 16:17:25 drh Exp $ }
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@@ -81,6 +81,16 @@ occurred since version 1.0.0:
|
||||
and version 2.2.x database files will be identical and completely
|
||||
interchangeable.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">2.2.5 to 2.3.0</td>
|
||||
<td valign="top">2002-Jan-30</td>
|
||||
<td>Beginning with version 2.3.0, SQLite supports some additional syntax
|
||||
(the "ON CONFLICT" clause) in the CREATE TABLE and CREATE INDEX statements
|
||||
that are stored in the SQLITE_MASTER table. If you create a database that
|
||||
contains this new syntax, then try to read that database using version 2.2.5
|
||||
or earlier, the parser will not understand the new syntax and you will get
|
||||
an error. Otherwise, databases for 2.2.x and 2.3.x are interchangeable.</p>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
||||
|
||||
+96
-16
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the sqlite.html file.
|
||||
#
|
||||
set rcsid {$Id: lang.tcl,v 1.18 2001/12/22 19:27:41 drh Exp $}
|
||||
set rcsid {$Id: lang.tcl,v 1.19 2002/01/30 16:17:25 drh Exp $}
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@@ -31,7 +31,7 @@ by SQLite. Many low-level productions are omitted. For detailed information
|
||||
on the language that SQLite understands, refer to the source code.</p>
|
||||
|
||||
|
||||
<p>SQLite implements the follow SQL commands:</p>
|
||||
<p>SQLite implements the follow syntax:</p>
|
||||
<p><ul>
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ foreach {section} [lsort -index 0 -dictionary {
|
||||
{expression expr}
|
||||
{{BEGIN TRANSACTION} transaction}
|
||||
{PRAGMA pragma}
|
||||
{{ON CONFLICT clause} conflict}
|
||||
}] {
|
||||
puts "<li><a href=\"#[lindex $section 1]\">[lindex $section 0]</a></li>"
|
||||
}
|
||||
@@ -140,12 +141,47 @@ a alias for COMMIT.
|
||||
</p>
|
||||
}
|
||||
|
||||
Section {ON CONFLICT clause} conflict
|
||||
|
||||
Syntax {conflict-clause} {
|
||||
ON CONFLICT <algorithm>
|
||||
} {algorithm} {
|
||||
ABORT | IGNORE | REPLACE
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The ON CONFLICT clause is not a separate SQL command. It is a
|
||||
non-standard clause that can appear in many other SQL commands.
|
||||
It is given its own section in this document because it is not
|
||||
part of standard SQL and therefore might not be familiar.</p>
|
||||
|
||||
<p>The ON CONFLICT clause specifies an algorithm used to resolve
|
||||
constraint conflicts. The default algorithm is ABORT. When the
|
||||
ABORT algorithm is in use, any constraint violation causes the
|
||||
command to abort and the current transaction to be rolled back.
|
||||
This is the only behavior exhibited by most SQL engines. But
|
||||
SQLite allows two alternative behaviors: IGNORE and REPLACE.
|
||||
The IGNORE algorithm means that when a constraint violation occurs
|
||||
on a COPY, INSERT or UPDATE, the particular row that caused the constraint
|
||||
violation is not inserted or changed, but other rows effected by the
|
||||
COPY, INSERT, or UPDATE are insert or changed as usual.
|
||||
The command is not aborted and no rollback occurs.
|
||||
If the algorithm is REPLACE, then SQLite tries to
|
||||
delete preexisting rows from the table to remove the constraint
|
||||
violation before inserting or changing the row.</p>
|
||||
|
||||
<p>For additional information, see
|
||||
<a href="conflict.html">conflict.html</a>.</p>
|
||||
}
|
||||
|
||||
Section COPY copy
|
||||
|
||||
Syntax {sql-statement} {
|
||||
COPY <table-name> FROM <filename>
|
||||
COPY [ <conflict-clause> ] <table-name> FROM <filename>
|
||||
[ USING DELIMITERS <delim> ]
|
||||
}
|
||||
|
||||
|
||||
puts {
|
||||
<p>The COPY command is an extension used to load large amounts of
|
||||
data into a table. It is modeled after a similar command found
|
||||
@@ -163,7 +199,16 @@ the <b>STDIN</b> to read data from standard input.<p>
|
||||
in the table. Columns are separated by tabs. If a tab occurs as
|
||||
data within a column, then that tab is preceded by a baskslash "\"
|
||||
character. A baskslash in the data appears as two backslashes in
|
||||
a row.</p>
|
||||
a row. The optional USING DELIMITERS clause can specify a delimiter
|
||||
other than tab.</p>
|
||||
|
||||
<p>If a column consists of the character "\N", that column is filled
|
||||
with the value NULL.</p>
|
||||
|
||||
<p>The optional conflict-clause allows the specification of an alternative
|
||||
constraint conflict resolution algorithm to use for this one command.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
|
||||
<p>When the input data source is STDIN, the input can be terminated
|
||||
by a line that contains only a baskslash and a dot:}
|
||||
@@ -174,10 +219,12 @@ Section {CREATE INDEX} createindex
|
||||
Syntax {sql-statement} {
|
||||
CREATE [UNIQUE] INDEX <index-name>
|
||||
ON <table-name> ( <column-name> [, <column-name>]* )
|
||||
[ <conflict-clause> ]
|
||||
} {column-name} {
|
||||
<name> [ ASC | DESC ]
|
||||
}
|
||||
|
||||
|
||||
puts {
|
||||
<p>The CREATE INDEX command consists of the keywords "CREATE INDEX" followed
|
||||
by the name of the new index, the keyword "ON", the name of a previously
|
||||
@@ -194,6 +241,16 @@ attached to a single table, nor on the number of columns in an index.</p>
|
||||
index entries are not allowed. Any attempt to insert a duplicate entry
|
||||
will result in a rollback and an error message.</p>
|
||||
|
||||
<p>The optional conflict-clause allows the specification of al alternative
|
||||
default constraint conflict resolution algorithm for this index.
|
||||
This only makes sense if the UNIQUE keyword is used since otherwise
|
||||
there are not constraints on the index. The default algorithm is
|
||||
ABORT. If a COPY, INSERT, or UPDATE statement specifies a particular
|
||||
conflict resolution algorithm, that algorithm is used in place of
|
||||
the default algorithm specified here.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
|
||||
<p>The exact text
|
||||
of each CREATE INDEX statement is stored in the <b>sqlite_master</b>
|
||||
table. Everytime the database is opened, all CREATE INDEX statements
|
||||
@@ -216,15 +273,15 @@ CREATE [TEMP | TEMPORARY] TABLE <table-name> (
|
||||
<typename> ( <number> ) |
|
||||
<typename> ( <number> , <number> )
|
||||
} {column-constraint} {
|
||||
NOT NULL |
|
||||
PRIMARY KEY [<sort-order>] |
|
||||
UNIQUE |
|
||||
CHECK ( <expr> ) |
|
||||
NOT NULL [ <conflict-clause> ] |
|
||||
PRIMARY KEY [<sort-order>] [ <conflict-clause> ] |
|
||||
UNIQUE [ <conflict-clause> ] |
|
||||
CHECK ( <expr> ) [ <conflict-clause> ] |
|
||||
DEFAULT <value>
|
||||
} {constraint} {
|
||||
PRIMARY KEY ( <name> [, <name>]* ) |
|
||||
UNIQUE ( <name> [, <name>]* ) |
|
||||
CHECK ( <expr> )
|
||||
PRIMARY KEY ( <name> [, <name>]* ) [ <conflict-clause> ]|
|
||||
UNIQUE ( <name> [, <name>]* ) [ <conflict-clause> ] |
|
||||
CHECK ( <expr> ) [ <conflict-clause> ]
|
||||
}
|
||||
|
||||
puts {
|
||||
@@ -265,6 +322,17 @@ the database is closed. Any indices created on a temporary table
|
||||
are also temporary. Temporary tables and indices are stored in a
|
||||
separate file distinct from the main database file.</p>
|
||||
|
||||
<p>The optional conflict-clause following each constraint
|
||||
allows the specification of an alternative default
|
||||
constraint conflict resolution algorithm for that constraint.
|
||||
The default is abort ABORT. Different constraints within the same
|
||||
table may have different default conflict resolution algorithms.
|
||||
If an COPY, INSERT, or UPDATE command specifies a different conflict
|
||||
resolution algorithm, then that algorithm is used in place of the
|
||||
default algorithm specified in the CREATE TABLE statement.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
|
||||
<p>There are no arbitrary limits on the number
|
||||
of columns or on the number of constraints in a table.
|
||||
The total amount of data in a single row is limited to about
|
||||
@@ -363,7 +431,7 @@ LIKE | GLOB | NOT LIKE | NOT GLOB
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>This section is different from the others. Every other section of
|
||||
<p>This section is different from the others. Most other sections of
|
||||
this document talks about a particular SQL command. This section does
|
||||
not talk about a standalone command but about "expressions" which are
|
||||
subcomponent of most other commands.</p>
|
||||
@@ -490,8 +558,8 @@ The "<b>count(*)</b>" syntax is supported but
|
||||
Section INSERT insert
|
||||
|
||||
Syntax {sql-statement} {
|
||||
INSERT INTO <table-name> [( <column-list> )] VALUES ( <value-list> ) |
|
||||
INSERT INTO <table-name> [( <column-list> )] <select-statement>
|
||||
INSERT [ <conflict-clause> ] INTO <table-name> [( <column-list> )] VALUES ( <value-list> ) |
|
||||
INSERT [ <conflict-clause> ] INTO <table-name> [( <column-list> )] <select-statement>
|
||||
}
|
||||
|
||||
puts {
|
||||
@@ -513,6 +581,11 @@ name in the column list. A new entry is made in the table
|
||||
for every row of the SELECT result. The SELECT may be simple
|
||||
or compound. If the SELECT statement has an ORDER BY clause,
|
||||
the ORDER BY is ignored.</p>
|
||||
|
||||
<p>The optional conflict-clause allows the specification of an alternative
|
||||
constraint conflict resolution algorithm to use during this one command.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
}
|
||||
|
||||
Section SELECT select
|
||||
@@ -597,7 +670,9 @@ are connected into a compound, they group from left to right.</p>
|
||||
Section UPDATE update
|
||||
|
||||
Syntax {sql-statement} {
|
||||
UPDATE <table-name> SET <assignment> [, <assignment>] [WHERE <expression>]
|
||||
UPDATE [ <conflict-clause> ] <table-name>
|
||||
SET <assignment> [, <assignment>]
|
||||
[WHERE <expression>]
|
||||
} {assignment} {
|
||||
<column-name> = <expression>
|
||||
}
|
||||
@@ -608,7 +683,12 @@ selected rows of a table. Each assignment in an UPDATE specifies
|
||||
a column name to the left of the equals sign and an arbitrary expression
|
||||
to the right. The expressions may use the values of other columns.
|
||||
All expressions are evaluated before any assignments are made.
|
||||
A WHERE clause can be used to restrict which rows are updated.
|
||||
A WHERE clause can be used to restrict which rows are updated.</p>
|
||||
|
||||
<p>The optional conflict-clause allows the specification of an alternative
|
||||
constraint conflict resolution algorithm to use during this one command.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
}
|
||||
|
||||
Section VACUUM vacuum
|
||||
|
||||
Reference in New Issue
Block a user