Uhmm.. Interesting. Thanks for your help.

Jay A. Kreibich wrote:
> On Fri, Feb 05, 2010 at 06:42:34PM -0500, German Escallon scratched on the 
> wall:
>
>   
>> create table X(xid integer primary key);
>> create table Y(yid integer primary key, y_xid references X(xid) );
>> create table Z(zid integer primary key, z_xid references X(xid) );
>>
>> create table Y_Z
>>    (
>>    yzid integer primary key autoincrement,
>>    yz_yid references Y(yid),  /*references primary key in y */
>>    yz_zid references Z(zid),  /* references primary key in z */
>>    CHECK
>>       (
>>          (select y_xid from Y where yid= yz_yid ) =  (select z_xid from 
>> Z where zid= yz_zid )
>>       )
>>    );
>>     
>
>
>   OK, this is a tad on the ugly side, but it might work.  Basically I'm
>   having rows in y_z carry around a copy of the xid from the two
>   tables.  The CHECK constraint then becomes simple.   I've fiddled
>   with the names a bit to keep things straight in my head.
>
>   Yes, some of the UNIQUEs are redundant, but they're required for the
>   FKs to work correctly.
>
> ----------------------------------------------------------------------
> PRAGMA foreign_keys = 1;
>
> CREATE TABLE x ( xid  INTEGER   PRIMARY KEY ); 
> CREATE TABLE y ( yid  INTEGER   PRIMARY KEY,
>                  xid  INTEGER   REFERENCES x ( xid ),
>                  UNIQUE ( yid, xid ) );
> CREATE TABLE z ( zid  INTEGER   PRIMARY KEY,
>                  xid  INTEGER   REFERENCES x ( xid ),
>                  UNIQUE ( zid, xid ) );
>
> CREATE TABLE y_z ( yzid     INTEGER   PRIMARY KEY   AUTOINCREMENT,
>                     yid     INTEGER,
>                     y_xid   INTEGER,
>                     zid     INTEGER,
>                     z_xid   INTEGER,
>
>                     FOREIGN KEY ( yid, y_xid ) REFERENCES y ( yid, xid ),
>                     FOREIGN KEY ( zid, z_xid ) REFERENCES z ( zid, xid ),
>                     CHECK ( y_xid == z_xid )
> );
>
> INSERT INTO x ( xid ) VALUES ( 1 );
> INSERT INTO x ( xid ) VALUES ( 2 );
>
> INSERT INTO y ( yid, xid ) VALUES ( 111, 1 );
> INSERT INTO y ( yid, xid ) VALUES ( 112, 1 );
> INSERT INTO y ( yid, xid ) VALUES ( 121, 2 );
> INSERT INTO y ( yid, xid ) VALUES ( 122, 2 );
>
> INSERT INTO z ( zid, xid ) VALUES ( 211, 1 );
> INSERT INTO z ( zid, xid ) VALUES ( 212, 1 );
> INSERT INTO z ( zid, xid ) VALUES ( 221, 2 );
> INSERT INTO z ( zid, xid ) VALUES ( 222, 2 );
>
> -- this should work:
> INSERT INTO y_z ( yid, y_xid, zid, z_xid ) VALUES ( 111, 1, 211, 1 );
>
> -- fails check constraint:
> INSERT INTO y_z ( yid, y_xid, zid, z_xid ) VALUES ( 111, 1, 221, 2 );
>
> -- fails foreign key constraint ( there is no y(221,1) )
> INSERT INTO y_z ( yid, y_xid, zid, z_xid ) VALUES ( 111, 1, 221, 1 );
> ----------------------------------------------------------------------
>
>   Of course, the INSERT on y_z gets... interesting.  There are ways to
>   reduce that, however.  Maybe something like:
>
> INSERT INTO y_z ( yid, y_xid, zid, z_xid )
>     VALUES ( ?1, ( SELECT xid FROM y WHERE yid = ?1 ),
>              ?2, ( SELECT xid FROM z WHERE zid = ?2 ) );
>
>   You might even be able to work that into a trigger so you can just
>   insert yid and zid and the trigger fills in the y_xid and z_xid.
>
>   Actually... come to think of it, you might just build a trigger into
>   your original schema.  You can't put a sub-select into a CHECK, but
>   you can put one in a trigger.  Try an INSERT/UPDATE trigger that
>   makes sure all the references line up and throws an error if they
>   do not.
>
>    -j
>
>
>   
>> Jusding by this diagram 
>> <http://www.sqlite.org/syntaxdiagrams.html#table-constraint> I thought 
>> my last create table statement was syntactically correct.  But I got the 
>> following message:
>> "Error: subqueries prohibited in CHECK constraints"..  Uhmm..  Bummer.
>>
>> Here's some background to my problem.
>>
>> Table (X) is referenced by two other tables (Y & Z).  This are 
>> one-to-many relationships (for every record in X there are 0 or more 
>> records in both Y, and in Z).
>> Now..  I also have a many-to-many relationship between Y & Z (for every 
>> record in Y there are 0 or more records in Z, and for every record in Z 
>> there are 0 or more records in Y).  
>> So, I created a table Y_Z to keep track of this relationship.  If I 
>> remove the check constraint that is causing the error, how can I ensure 
>> that all Y_Z entries associate entries that reference the same record in 
>> X?  In other words, say I have..
>>
>> insert into X (xid) values(1);
>> insert into X (xid) values(2);
>> insert into Y (yid, y_xid) values (1, 1); /* references entry 1 in X */
>> insert into Z (zid, z_xid) values (1, 2); /* references entry 2 in X */
>>
>> I need a constraint that would fail the following statement, and 
>> maintain my data integrity.
>>
>> insert into Y_Z( yz_yid, yz_xid) values (1, 1).
>>
>> Is there any alternative you can suggest?  Thank you in advance.
>>
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users@sqlite.org
>> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
>>     
>
>   
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to