On Sat, 11 Dec 2010 12:39:39 +0100, TP <paratribulati...@free.fr> wrote:
>Hello, > >I have a question about referential integrity when there is no explicitly >defined primary key in the table on the one side. Look at this example: > >-------------------------- >PRAGMA foreign_keys = ON; > >CREATE TABLE foo( bar ); >INSERT INTO foo values( "bar1" ); > >CREATE TABLE fox( dog > , foo_id > , FOREIGN KEY ( foo_id ) REFERENCES foo ON UPDATE CASCADE ON DELETE >CASCADE ); >INSERT INTO fox values( "dog1", 1 ); >Error: foreign key mismatch Side note: string literals should be quoted with single quotes, so INSERT INTO foo VALUES (1, "bar1"); should be INSERT INTO foo VALUES (1, 'bar1'); http://www.sqlite.org/lang_expr.html#litvalue >SELECT *, rowid from foo; >bar rowid >-------------------- -------------------- >bar1 1 >--------------------------- > >So, we obtain a "foreign key mismatch", whereas there is the suitable value >of rowid in the table. > >If we modify the previous example by including an explicit primary key in >table foo, it works: > >-------------------------- >PRAGMA foreign_keys = ON; > >CREATE TABLE foo( > foo_id INTEGER PRIMARY KEY > , bar ); >INSERT INTO foo values( 1, "bar1" ); > >CREATE TABLE fox( dog > , foo_id > , FOREIGN KEY ( foo_id ) REFERENCES foo ON UPDATE CASCADE ON DELETE >CASCADE ); >INSERT INTO fox values( "dog1", 1 ); > >select * from fox; >dog1|1 >-------------------------- > >What is the explanation for this behavior? It is by design. At the bottom of http://www.sqlite.org/lang_createtable.html it says: The parent key of a foreign key constraint is not allowed to use the rowid. The parent key must used named columns only. This means you have to alias the rowid to be able to refer to it in a foreign key clause. In your case, the foreign key clause does not explicitly refer to a specific column in the parent table, foo. SQLite probably tries to find the primary key of the parent table, but there isn't one. In general it is a bad idea to depend on the implicit existence of rowid. Make it a habit to alias rowid to an explicit integer primary key. It makes your code more portable and more readible. For readibility, I would also explicitly name the column in the foreign key clause. So your example would become: CREATE TABLE foo ( id INTEGER PRIMARY KEY NOT NULL , bar TEXT ); CREATE TABLE fox ( dog TEXT , foo_id INTEGER , CONSTRAINT fk_foo_id FOREIGN KEY ( foo_id ) REFERENCES foo (id) ON UPDATE CASCADE ON DELETE CASCADE ); BEGIN; INSERT INTO foo (id,bar) VALUES (1,'bar1'); INSERT INTO fox (dog,foo_id) VALUES ('dog1',last_insert_rowid() ) COMMIT; -- ( Kees Nuyt ) c[_] _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users