I am trying to populate some tables using data that I extracted from Google BigQuery. For that purpose I essentially normalized a flattened table into multiple tables that include the primary key of each row in the multiple tables. The important point is that I need to load those primary keys in order to satisfy foreign key references.
Having inserted this data into tables, I then try to add new rows to these tables. I don't specify the primary key, presuming that Postgres will auto-generate those key values.
However, I always get a 'duplicate key value violates unique constraint "xxx_pkey" ' type error, e.g.
"..duplicate key value violates unique constraint "collection_pkey" DETAIL: Key (id)=(1) already exists.
It seems this is triggered by including the primary key in the data when initializing table. That is, explicitly setting primary keys, somehow seems to disable or reset the expected autogeneration of the primary key. I.E. I was expecting that new rows would be assigned primary keys starting from the highest value already in a table.
Interestingly I get the same error whether I try to add a row via SQLAlchemy or from the psql console.
So, is this as expected? And if so, is there some way to get the system to again auto-generate keys? There must be some hidden psql state that controls this...the schema is unchanged by directly inserting keys, but psql behavior is changed by that action.
I am happy to provide additional information.
Thanks
TL;DR
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side, specifically, in Postgres and, generally, in relational database systems?
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
How I got there
I had earlier on created a table with a column username on which I imposed a unique constraint. I then created another table with a column bearer_name having a FOREIGN KEY referencing the previous table's column username; the one which had a UNIQUE CONSTRAINT.
Now, I want to drop the UNIQUE CONSTRAINT on the username column from the database because I have later on created a UNIQUE INDEX on the same column and intuitively I feel that they serve the same purpose, or don't they? But the database is complaining that the UNIQUE INDEX has some dependent objects and so it can't be dropped unless I provide CASCADE as an option in order to drop even the dependent object. It's identifying the FOREIGN KEY on bearer_name column in the second table as the dependent object.
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side
No it does not require only UNIQUE CONSTRAINT. It could be PRIMARY KEY or UNIQUE INDEX.
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
CREATE TABLE tab_a(a_id INT, b_id INT);
CREATE TABLE tab_b(b_id INT);
ALTER TABLE tab_a ADD CONSTRAINT fk_tab_a_tab_b FOREIGN KEY (b_id)
REFERENCES tab_b(b_id);
ERROR: there is no unique constraint matching given keys
for referenced table "tab_b"
DBFiddle Demo
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
Yes, it is possible.
CREATE UNIQUE INDEX tab_b_i ON tab_b(b_id);
DBFiddle Demo2
I am using a tool called apgdiff 'https://www.apgdiff.com/' for finding the DDL diff between 2 postgres database. It parses 2 postgres dumps and generate the diff between the 2 dumps in terms of alter queries .
The tool actually doesn't mind the order of creating or dropping foreign key constraints while generating the diff. i.e. foreign key constraints should be created after primary key , or to be dropped before dropping the primary key . But still, what makes me curious is a line of code in their sourcecode, which says that all the primary keys should be dropped first and then all other non-primary keys should be dropped . Do we have any such constraint in Postgres that the primary keys should be dropped first and then the remaining constraints ..
If anything, other constraints should be dropped first, because foreign key constraints depend on primary key (or unique) constraints. It doesn't matter, though, if you use the CASCADE keyword when dropping the constraints.
I can't see a reason why dropping primary key constraints first should make a difference.
I am trying to generate foreign key constraint in Greenplum (Postgres). Its shows warning as below,
WARNING: Referential integrity (FOREIGN KEY) constraints are not supported in Greenplum Database, will not be enforced.
can anyone help me with this and explain how to add a foreign key.
Greenplum Doesnt support foriegn key constraint, if you try to create one, it will be created but not enforced
Also triggers are very limited, DML operation cant be performed using triggers
I am looking at multi-tenancy database schema design for an SaaS concept. It will be ASP.NET MVC -> EF, but that isn't so important.
Below you can see an example database schema (the Tenant being the Company). The CompanyId is replicated throughout the schema and the primary key has been placed on both the natural key, plus the tenant Id.
Plugging this schema into the Entity Framework gives the following errors when I add the tables into the Entity Model file (Model1.edmx):
The relationship 'FK_Order_Customer' uses the set of foreign keys '{CustomerId, CompanyId}' that are partially contained in the set of primary keys '{OrderId, CompanyId}' of the table 'Order'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_OrderLine_Customer' uses the set of foreign keys '{CustomerId, CompanyId}' that are partially contained in the set of primary keys '{OrderLineId, CompanyId}' of the table 'OrderLine'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_OrderLine_Order' uses the set of foreign keys '{OrderId, CompanyId}' that are partially contained in the set of primary keys '{OrderLineId, CompanyId}' of the table 'OrderLine'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_Order_Customer' uses the set of foreign keys '{CustomerId, CompanyId}' that are partially contained in the set of primary keys '{OrderId, CompanyId}' of the table 'Order'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_OrderLine_Customer' uses the set of foreign keys '{CustomerId, CompanyId}' that are partially contained in the set of primary keys '{OrderLineId, CompanyId}' of the table 'OrderLine'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_OrderLine_Order' uses the set of foreign keys '{OrderId, CompanyId}' that are partially contained in the set of primary keys '{OrderLineId, CompanyId}' of the table 'OrderLine'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The relationship 'FK_OrderLine_Product' uses the set of foreign keys '{ProductId, CompanyId}' that are partially contained in the set of primary keys '{OrderLineId, CompanyId}' of the table 'OrderLine'. The set of foreign keys must be fully contained in the set of primary keys, or fully not contained in the set of primary keys to be mapped to a model.
The question is in two parts:
Is my database design incorrect? Should I refrain from these compound primary keys? I'm questioning my sanity regarding the fundamental schema design (frazzled brain syndrome). Please feel free to suggest the 'idealized' schema.
Alternatively, if the database design is correct, then is EF unable to match the keys because it perceives these foreign keys as a potential mis-configured 1:1 relationships (incorrectly)? In which case, is this an EF bug and how can I work around it?
On a quick scan of EF's error messages, it clearly doesn't like the way you're setting up compound keys, and I think it's probably nudging you in the right direction. Give some thought again to what makes your primary keys unique. Is the OrderID alone not unique, without a CompanyID? Is a ProductID not unique, without a CompanyID? An OrderLine certainly should be unique without a CompanyID, since an OrderLine should be associated only with a single Order.
If you truly need the CompanyID for all of these, which probably means that the company in question is supplying you with ProductID and OrderID, then you might want to go a different direction, and generate your own primary keys that are not intrinsic to the data. Simply set up an auto-increment column for your primary key, and let these be the internal OrderID, OrderLineID, ProductID, CompanyID, etc. At that point, the OrderLine won't need the customer's OrderID or CompanyID; the foreign key reference to the Order would be its starting point. (And the CustomerID should never be an attribute of an order line; it's an attribute of the order, not the order line.)
Compound keys are just messy. Try designing the model without them, and see if it simplifies things.
I think that the error is not in the design.
Is not in the EF.
Is in Sql Server relations.
Read the EF message:
The relationship 'FK_Order_Customer'
uses the set of foreign keys
'{CustomerId, CompanyId}' that are
partially contained in the set of
primary keys '{OrderId, CompanyId}' of
the table 'Order'. The set of foreign
keys must be fully contained in the
set of primary keys, or fully not
contained in the set of primary keys
to be mapped to a model.
ERROR
Actualy the relation betwen Order and Customer use only one field (probably you dragged with the mouse the field "CustomerId" from teh Order table to the "Id" of the Customer table)
SOLUTION
Right click on the wire that connect Order and Customer and in the relation add also the CompanyId
PS: The design is correct.
Putting the CompanyId in each table is rith solution in multi-tenant architecture because help to scale (usualy always want to select only records from the loggedIn company).
I think storing the company number in each of the tables is hurting you more than helping. I can understand why you want to do this (as the programmer/dba you can just go into any table and 'see' what data belongs to who which is comforting), but it is getting in the way of you setting up the database the way it should be.
Avoid the compound keys and your design gets a whole lot simpler.
If you have to absolutely add CompanyID column to each table, add it as a regular column and not a composite Key. Composite key is mostly used when you have to implement many to many relationship.
As someone mentioned also create a Non-clustered Index on CompanyID so joins to the Company table are benefitted.
Thanks!
First: like others said, when referencing a foreign key, use the whole primary key in the other table (ie. both fields).
Second, I cannot imagine not using a CompanyID column in most tables in a serious application. Orderdetail might perhaps be an exception in this case (also global lookup tables perhaps, unless they are tenant dependant). Thing is, you cannot do any safe sort of free form search on a table without either adding the CompanyID, or doing JOINs up until the point you reach a table which has that column. The latter one obviously costs performance. Perhaps in this case you could make an exception for orderdetail and only search in the joined version (only two tables). Then again, its not really consistent.
Also regarding making a it a compound key or not: its possible, but opens up the possibility that a bug writes information incorrectly (into non existent, or other people's administrations) for the duration of the bug. Try to fix that in production, not to mention explain it to customers why there are seeing their competitors orders in their system.