Could this not be achieved by two indexes: one partial and one complete? CREATE UNIQUE INDEX idx_books1 ON Books(title, author);
CREATE UNIQUE INDEX idx_books2 ON Books(title) WHERE author ISNULL; To save space and (maybe) time, you could put a 'WHERE author NOTNULL' on the first index. Of course, I'm just talking about how to code it, the issues mentioned by R Smith is a different kettle of fish. Cheers, Barry > On 23 Aug 2015, at 3:05 am, "R.Smith" <rsmith at rsweb.co.za> wrote: > > > >> On 2015-08-21 11:23 PM, Will Parsons wrote: >>> On 21 Aug 2015, R.Smith wrote: >>> >>>> On 2015-08-21 04:47 AM, Will Parsons wrote: >>>> I'm working on a program that involves a catalogue of books. Part of >>>> the database schema looks like this: >>>> >>>> create table Books(id integer primary key, >>>> title text collate nocase not null, >>>> author references Authors(id), >>>> ... >>>> unique(title, author)); >>>> >>>> create table Authors(id integer primary key, >>>> name text unique not null check(name <> '')); >>>> >>>> The idea here is that the title+author of a book must be unique, but a >>>> book may not necessarily have an author associated with it. But, the >>>> schema fragment as I have presented it does not disallow entering the >>>> same title with a null author multiple times, which is clearly >>>> undesirable. >>>> >>>> In thinking about how to avoid this, one possibility that has occurred >>>> to me is to add an entry to the Authors table with id=0, name=NULL, and >>>> to modify the Books table to be: >>>> >>>> create table Books(id integer primary key, >>>> title text collate nocase not null, >>>> author references Authors(id) not null, >>>> ... >>>> unique(title, author)); >>>> >>>> With this, entries in the Books table that presently have the author >>>> field set to NUll would instead have author=0. >>>> >>>> What I would like to have is a trigger that when an attempt is made to >>>> enter a new record into the Books table with a NULL author field, is >>>> to force the author field to 0 instead. I can't see how to do this >>>> with a "before insert" trigger, though. Perhaps I'm approaching this >>>> the wrong way; in any case I'd appreciate advice. >>> Nothing wrong with your approach, simply declare the Author to be NOT >>> NULL and if it is possible to have non-Authors you could do what you >>> suggest, add a 0-Author to the parent table, or, you could use a partial >>> Index (available after SQLite 3.7 only I think) which would allow you to >>> have NULLS but still maintain a strict relation, something like this: >>> >>> create table Books(id integer primary key, >>> title text collate nocase not null, >>> author int not null references Authors(id), >>> ... >>> ); >>> >>> create unique index uBookAuth on Books(title,author) where author is not >>> null; >>> >>> create table Authors(id integer primary key, >>> name text unique not null check(name <> '')); >> I guess I don't understand how having a partial index where author is >> not null prevents adding two entries with the same title and a null >> author. How is this different from what I have now with the >> "unique(title, author)" specification? > > I think I may have misinterpreted slightly... > > To clarify: are the book titles unique or are they not? > > If they are Unique, i.e if no book title can ever appear twice, regardless > who authored it, then simply declare a unique index on title. > If they are NOT Unique, i.e. if a title can appear more than once, then why > is it not working for you? > > Essentially, if I interpret correctly, you are asking the DB to NOT limit the > number of same-titled books, except when you have supplied an author and the > same author has already such a titled book, but then when you don't supply an > author, it should know to now also limit the copies of no-author books? > > I assumed before that you only added NULL for author if you don't know the > author yet (which would make sense and can later be updated) but then you > can't force the unique constraint, there may be many books with coinciding > titles and not-yet-known authors. > > Reading again, I am now thinking that's not the case, you might add NULL > authors to books which simply don't have authors (well, all books have > authors, but the author might be unknown and accepted to be of unknown status > for time to come), in which case, there might be many same-titled > unknown-author books. > > If this is the case and you still want to limit unknown author books to just > 1 instance, I would suggest to use an explicit author name, maybe something > like "(by Unknown)" which would be happily subdued by the Unique constraint > if violated. Another reader suggested the empty string, which will also count > as a valid author and do the limiting you require. Your own suggestion of > using a zero ID in stead will also do the job just fine. In fact, this is the > only reason we'd ever put NULL into a field such as this, precisely so that > the Unique constraint is not forced, because for any valid value, it will be. > > A note on NULL and why: NULL + NULL != 2(NULL). > > NULL is not a valid value, in fact it isn't a value at all, it is not meant > to appear in anything data related barring to indicate a fault or voidness. > You can't have operations on non-values. If you want a constraint or perhaps > another sort of function to work on some data, make sure it is actual data > and not NULL. > > To put this philosophically: "Infinity" is a much more precise value than > "NULL". > > This also means that NULL is not equal to NULL, it equals nothing because it > cannot be compared, even to other NULLs - In DB theory anyway[1]. Sadly many > DB engines have kind of circled around this problem a bit by allowing NULL to > do all kinds of things it shouldn't. I'm happy though that for UNIQUE > constraints in some DBs (and SQLite at least) a NULL is not equal to any > other value, including other NULLs. > > > > Apologies for the ramble, hope some of it helps. > Ryan > > > [1] - I don't actually see the reason for 3-value logic, NULL is a construct > with origins in DB engine design, not relational theory. It's useful to have > a word to indicate "emptiness" or more mathematically correct: "The empty > set", but beyond that, any operational use of it is questionable. > > > _______________________________________________ > sqlite-users mailing list > sqlite-users at mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users