SQLMetal - Foreign Key Constraint with multiple fields - Error - sql

When I try to run SQLMetal on a sqlite database which defines a foreign key constraint on multiple fields, i get an error.
The table is as follows:
CREATE TABLE A (
a1 INTEGER,
a2 INTEGER,
PRIMARY KEY (a1,a2)
);
CREATE TABLE B (
b1 INTEGER,
b2 INTEGER,
b3 INTEGER,
b4 TEXT,
PRIMARY KEY (b1,b2,b3),
FOREIGN KEY (b1,b2) REFERENCES A (a1,a2)
);
The error message is:
"sqlmetal: Sequence contains more than one matching element"
Anybody knows how to resolve that problem?

I think the issue is that you can only have one primary key per table. Here's the blurb from the sqlite documentation:
"Each table in SQLite may have at most one PRIMARY KEY. If the keywords PRIMARY KEY are added to a column definition, then the primary key for the table consists of that single column. Or, if a PRIMARY KEY clause is specified as a table-constraint, then the primary key of the table consists of the list of columns specified as part of the PRIMARY KEY clause. If there is more than one PRIMARY KEY clause in a single CREATE TABLE statement, it is an error."

Related

How to manage postgresql foreign keys?

I need some advice on SQL structure on Postgresql.
I have those two tables :
DROP TABLE IF EXISTS "public"."attribute_value";
CREATE TABLE "public"."attribute_value"
(
"id" INTEGER NOT NULL,
"attribute_id" INTEGER NOT NULL,
"value" CHARACTER VARYING(100) NULL
);
--*****************************************************
DROP TABLE IF EXISTS "public"."product_attribute";
CREATE TABLE "public"."product_attribute"
(
"product_id" INTEGER NOT NULL,
"attribute_value_id" INTEGER NOT NULL,
"attribute_id" INTEGER NOT NULL
);
I added no constraints on purpose.
I need a foreign key on the child table product_attribute.attribute_value_id referencing the parent table attribute_value.id. The best practice is to create a primary key on the field attribute_value.id (maybe with a sequence), or to CREATE UNIQUE INDEX on attribute_value.id ?
I first thought indexes were only special lookup tables that the database search engine can use to speed up data retrieval. But when I played with foreign keys, I found that creating an unique index allowed me to avoid error "there is no unique constraint matching given keys for referenced table blablabla" because a foreign key is not supposed to point to a non unique value. Should indexes be used to create foreign keys then ?
I also need a foreign key on the child table product_attribute.attribute_id referencing parent table attribute_value.attribute_id. The problem is that attribute_value.attribute_id is not unique. But all the rows in product_attribute.attribute_id must not take any value out of attribute_value.attribute_id's possible values. How should I do ?
Every table should have a primary key. Don't join the legion of people who complain about duplicate rows in their tables.
So make id the primary key of attribute_value, then you can create a foreign key constraint.
Constraints are implemented by unique indexes, so technically they are almost the same. Still you need a constraint and not just a unique index as the target of a foreign key constraint.
About attribute_id: that should not be a foreign key constraint between the two tables from your question, but both tables should have a foreign key referencing yet another table (attribute?).

How to reference a postgres table with multiple primary keys

How could I create a xref table with a reference to this table?
CREATE TABLE reviewer (
screen_name integer,
identity_provider text
CONSTRAINT identity PRIMARY KEY (screen_name, identity_provider)
);
This is what I've tried so far:
CREATE TABLE business_reviewer_xref (
reviewer_screen_name integer,
reviewer_identity_provider text,
CONSTRAINT reviewer_identity UNIQUE (reviewer_screen_name, reviewer_identity_provider),
reviewer_identity REFERENCES reviewer(identity)
);
CREATE TABLE business_reviewer_xref (
reviewer_screen_name integer,
reviewer_identity constraint REFERENCES reviewer(identity)
);
CREATE TABLE business_reviewer_xref (
reviewer_screen_name integer,
reviewer_identity REFERENCES reviewer(identity)
);
A table cannot have multiple primary keys. It can only have one or none. But a primary key can of course consist of more than one column (but at least of one of course). To reference such a multi column primary key, you need a corresponding column in the referencing table for each column in the primary key of the referenced column.
To define a foreign key constraint, list the corresponding columns in the referencing table in the same order as their counterparts occur in the primary key constraint in the referenced table in the defining tuple of the foreign key. Also keep the order in the definition of the referenced columns' tuple.
In your case:
CREATE TABLE business_reviewer_xref
(reviewer_screen_name integer,
reviewer_identity text,
FOREIGN KEY (reviewer_screen_name,
reviewer_identity)
REFERENCES reviewer
(screen_name,
identity));
Note that a foreign key constraint, in contrast to a primary key constraint, doesn't implicitly set a unique constraint. If you want uniqueness too, you'd have to define another constraint for that.

Foreign key referencing primary key of multiple values

Im using ms sql server. I get this msg when I reference a primary key that is a composite key of 3 values in the foreign key.
"number of referencing columns in foreign key differs from the number of reference columns". The problem lies in second last line of code in member booking. Any ideas? Thanks in advance.
CREATE TABLE room
(
Block CHAR (1),
Lvl INT,
rNum INT,
RmType VARCHAR (15),
Condition VARCHAR (15),
CONSTRAINT room_PK PRIMARY KEY (Block, Lvl, rNum),
)
CREATE TABLE booking
(
BookingID INT,
BStartDate DATE,
BEndDate DATE,
Fee DECIMAL (8,2) NOT NULL CHECK (fee >= 0),
Memberbooking INT NOT NULL,
MemberID INT NOT NULL,
CONSTRAINT booking_pk PRIMARY KEY (BookingID),
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum),
CONSTRAINT FK_MemberID FOREIGN KEY (MemberID) references member (ID)
)
You are getting an error because you are trying to map 1 column (FOREIGN KEY (Memberbooking)) with 3 columns room (Block, Lvl, rNum)
it's possible to create a foreign key relationship to a compound (more
than one column) primary key, make sure to specify the same number of columns in your FOREIGN KEY
You define this constraint in the table booking:
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum)
meaning that you want the column Memberbooking to reference 3 columns (!!) in the table room.
Each column from a table can reference one column from another table, not multiple ones.
You can define the same column to reference more than 1 columns in another table, but with different constraints, and always 1 to 1.
Read more here: Create Foreign Key Relationships
Since I see from the comments you are intent to implement this type of check, I would propose a check constraint:
CONSTRAINT CK_MemberID CHECK (EXISTS(SELECT 1 FROM room where Memberbooking=room.Block+convert(nchar,room.Lvl)+convert(nchar,room.rNum)))
However, this design is not very good. The lack of seperators in the Membermooking field might cause collisions.
Eg, consider you have a Memberbooking: 'A1101'
Is that Block A, Lvl 11, rNum 01? Or is it Block A, Lvl 1, rNum 101?
On table "room", you currently have a compound natural key. This is a valid design decision. The alternative would be to add a single column artificial id, such as an int Identity. That would lead to two keys on the same table (one of them Primary Key, the other one Unique constraint).
In a foreign key constraint, you can reference any Unique constraint or Primary Key. If you want to keep the "room" table the way it is, then you need to mirror those key fields in the referencing table. So that would mean your "booking" table would need a Block char(1), Lvl int and rNum int column.
That is why an artificial key (on room) can be useful, because then your foreign key constraint (on booking) can be single column and reference that Unique constaint.

Cannot find primary key column in table

I added a constraint primary key to my table and the query ran successfully. The dilemma I am facing is I cannot locate the primary key column in my table.
ALTER TABLE salesdata
ADD CONSTRAINT pk_salesdata PRIMARY KEY( "Address_of_New_Home","Sq_Ft","Build_Spec", "Realtor_Sale","Can","Actual_Sale_Date")
When I do:
select * from salesdata
It shows all the columns from before and no primary key column (pk_salesdata).
And even more baffling is when:
select pk_salesdata from salesdata
Database shows:
ERROR: column "pk_salesdata" does not exist
I want to add primary key column to the table. I humbly request assistance of databasers.
You create PRIMARY KEY, but...
you create composed primary key from columns "Address_of_New_Home", "Sq_Ft", "Build_Spec", "Realtor_Sale", "Can", "Actual_Sale_Date" - it is not good idea
your primary key have an alias name pk_salesdata, but it's only constraint name
you didn't create new column
If you would like new synthetic primary key column you have to use command:
ALTER TABLE salesdata ADD COLUMN mynewautoincrementid SERIAL PRIMARY KEY;
Primary Kay it's constraint in table when you add a primary key to any column you can select column name to show data
It looks like you've wrapped the columns you want to include in your primary keys in double quotes. That's not how this command works. Drop the quotes re-run the command and see what happens.
ALTER TABLE salesdata
ADD CONSTRAINT pk_salesdata PRIMARY KEY( Address_of_New_Home,Sq_Ft,Build_Spec, Realtor_Sale,Can,Actual_Sale_Date)
It might be easier to add a primary index through the SQL GUI.
Here's the MS documentation page for creating a primary key.
https://msdn.microsoft.com/en-us/library/ms189039.aspx
Note: Since your adding a primary key don't expect it to be available as a column.

Self Referencing table : UNIQUE constraint failed (SQL)

Architecture
I have the following self referencing table. Every Entity has a relation with 1 to many entities.
Tables
Since it's a 1 to many relationship I representation Relation by a table.
CREATE TABLE ENTITY (ID TEXT PRIMARY KEY NOT NULL, VALUE TEXT);
CREATE TABLE RELATION (ID_SOURCE TEXT NOT NULL, ID_DESTINATION TEXT NOT NULL, PREDICAT TEXT, PRIMARY KEY(ID_SOURCE, ID_DESTINATION), FOREIGN KEY(ID_SOURCE) REFERENCES ENTITE(ID), FOREIGN KEY(ID_DESTINATION) REFERENCES ENTITE(ID));
Problem
When I am inserting the values I am getting the following error:
UNIQUE constraint failed: RELATION_ENTITY.ID,
RELATION_ENTITY.ID_DESTINATION
I know why I am getting this error. I am inserting the same Ids in the table Relation But the value is different. THE entity m.06y3r references the entity m.02jvmvm with two different values. How can I fix this design error?
ID_SOURCE ID_DESTINATION VALUE
m.06y3r m.02jvmvm adopted_child.adoptive
m.06y3r m.02jvmvm people.person.parents
It is all because in Relation table you have PRIMARY KEY(ID_SOURCE, ID_DESTINATION) so this both values have to create unique set. If you change it to PRIMARY KEY(ID_SOURCE, ID_DESTINATION, VALUE), then it should work just fine.
EDIT
example of solution mentioned in comment below:
CREATE TABLE RELATION (
ID INT NOT NULL,
ID_SOURCE TEXT NOT NULL,
ID_DESTINATION TEXT NOT NULL,
VALUE TEXT,
PRIMARY KEY(ID),
UNIQUE (ID_SOURCE, ID_DESTINATION, VALUE)
FOREIGN KEY(ID_SOURCE) REFERENCES ENTITE(ID),
FOREIGN KEY(ID_DESTINATION) REFERENCES ENTITE(ID));
If you want rows with duplicate values for id_source and id_destination you can either use a surrogate primary key (like an autonumber int), maybe id_relation, together with a unique constraint for the three other columns or extend the primary key to include the value column too so that it would be PRIMARY KEY(ID_SOURCE, ID_DESTINATION, VALUE).
If you want to reference this table in joins, using a surrogate key might make your life easier.