pgsql how to enforce uniqueness for some keys - sql

I have two tables. table1 has attributes unique or not
attribute_id uniqueness
1 no
2 yes
3 yes
Table 2 has below data, there is unique constraint on combined columns object_id and attribute_id .
Now I need another unique constraint on value column for some attribute_id has uniqueness=yes.
Like, attribute_id 2 and 3 has unique=yes in table1. they can't have duplicate values in table2.
auto_id object_id attribute_id value
1 1 1 a
2 2 1 a
3 1 2 b
4 2 2 d
We can't insert (attribute_id,value)=(2,b) or (2,d) and it should through error duplicate key value violates unique constraint if we try to insert dup values.
I hope we can do this by trigger but it will be very slow.
Looking for better approach, any possible solution pls ?

The only way to do that with a constraint that I can think of is this:
add the uniqueness column to table2 too and fill it with the proper value
define a UNIQUE constraint on table1(attribute_id, uniqueness)
define a foreign key constraint on table2:
ALTER TABLE table2 ADD FOREIGN KEY (attribute_id, uniqueness)
REFERENCES table1 (attribute_id, uniqueness);
define a partial unique index on table2:
CREATE UNIQUE INDEX ON table2 (attribute_id, value) WHERE uniqueness;
Of course this will lead to data duplication, but the foreign key will guarantee that no inconsistencies can occur.

Related

Prevent row insertion if foreign_key is not null in the referenced row

Simple table with primary key as the first column and foreign key referencing the same table as the second column.
1 | null
2 | 1
I want to prevent insertion of a row whose fk would reference a row whose fk is not null. E.g. insertion of the row below should be prevented:
3 | 2
How can it be achieved? I'v tried the following
ALTER TABLE t
ADD CONSTRAINT t_check
CHECK (
fk not in (select t.pk from t1 t where t.pk = fk and t.fk is not null)
);
but got
ERROR: cannot use subquery in check constraint
as expected.

Allowing only unique combination in sql table

I'm trying to create a sql table in net frame work in VS that has room and user id ,but I want that only one of each combination can exist in the table:
Want:
room --- user id
1 2
1 3
3 2
2 1
1 1
3 1
Dont want:
room --- user id
1 2
1 2
how can I make it so that only unique combination can be entered?
You can enforce uniqueness using a unique constraint or index:
create unique index unq_t_room_userid on t(room, user_id);
or:
alter table t add constraint unq_t_room_userid
unique (room, user_id);
Looks like you want Room, UserId to be the PRIMARY KEY on that table.
CREATE TABLE Occupancy
(
RoomId INT NOT NULL
,UserId INT NOT NULL
,CONSTRAINT PK_Occupancy PRIMARY KEY CLUSTERED (RoomId,UserId)
)
When you try to insert a duplicate value:
INSERT dbo.Occupancy (RoomId,UserId)
VALUES
(1,1)
,(1,2)
,(1,1)
GO
You will get a message like this:
Violation of PRIMARY KEY constraint 'PK_Occupancy'. Cannot insert
duplicate key in object 'dbo.Occupancy'. The duplicate key value is
(1, 1).

How to create SQL constraint on primary key to make sure it could only be referenced once?

How do I add constraint to guard that a primary key could only be referenced once?(It could be referenced in two tables)
Each reference should have a unique value out of the primary key.
Table A
----------------------
id
1
2
3
4
Table B
----------------------
id a_id (foreign key to table A.id)
1 2
2 3
Table C
----------------------
id a_id (foreign key to table A.id)
1 1
I want something to happen to give error when try to insert a_id = 2 into table C as its used in table B already.
You can use an INSERT, UPDATE trigger on each of the child tables to ensure that the PK of the parent table that is about to be inserted or updated does not already exist in the other child table.
What you are trying to do requires another table D, that will help unify the references to A.
Table D will contain its own primary key ( Id ), a reference to table A with a UNIQUE constraint on it (call it AId ), and a third column (called "RowType") to indicate to which of the child tables (B or C) the row corresponds. You can make this column to be of type int, and assign value "0" for B and "1" for C, for example.
Then in table B you add a foreign key to D.Id, AND another column "BRowType" as foreign key to D.RowType; then you define a constraint on this column, so it can only have the value '0' ( or whatever value you have decided to correspond to this table).
For table C your constraint will limit the values to '1'.
Or course, in order to insert a record into B or C you first need to create a record in D. But once you have a record in B that references a record in D, which in turn links to a record in A, you will no longer be able to create a record in C for the same line in A - because of the UNIQUE constraint on D.AId AND the constraint on C.BRowType.
If I understand the question correctly, it sounds like you need to add a unique constraint on the column of each table that references your primary key.
For example:
Table A
----------------------
id (primary key)
1
2
3
Table B
----------------------
id a_id (foreign key to table A.id)
1 2
2 3
Set the a_id column to be UNIQUE and that way you can ensure that the primary key from Table A is not used twice. You would do that in each table which references A.id
If you want to avoid using triggers, you could create a table X with id and a unique constraint on it.
In each transaction in which you insert a record into B or C you have to insert into X as well. Both insertions will only be possible if not yet in the other table.

Foreign Keys to Composite Key

If I have a table where AId is the primary key and BId and CId are foreign keys referencing their tables. I need to make the combination of BId and CId unique.
How would I alter the table to make the combination unique?
Thanks
AId BId CId Notes Date
=== === === ===== ====
1 200 1 Random 2/2/2005
2 201 2 ETC 2/8/2007
3 202 3 ETC 2/12/2012
You need to create a unique index or a unique constraint.
I generally prefer unique indexes as they are more flexible (can add included columns if desired) and they don't have to be uniquely named in the schema.
Example syntax for a unique index
CREATE UNIQUE NONCLUSTERED INDEX SomeIndex ON YourTable(BId, CId)
The order of BId, CId makes no difference to the uniqueness guarantee but does affect the queries the index can efficiently support (that way round supports looking up by Bid or BId, CId but not CId)
Try this:
ALTER TABLE myTable
ADD CONSTRAINT myConstraint
UNIQUE NONCLUSTERED
(
BId, CId
)
You can create unique indexes that are not the primary key. This will force the combination of BId and CId unique.
CREATE UNIQUE INDEX ix_ATable_AltUniqueIndex ON ATable(BId,CId)
Or you can create a unique constraint
ALTER TABLE ATable ADD CONSTRAINT uni_ATable UNIQUE (BId,CId)
Create a unique constraint appears to create a unique index also.

how to keep combination of cells unique

i have table A and table B. I have a bridge table called tableC
in table C i have:
ID
tableA_ID
tableB_ID
ID is the primary key.
i also want to enforce the combination of tableA_ID and tableB_ID to be unique so there are no duplicate records.
how do i enforce this?
create unique index myIdx on tableC(tableA_ID, tableB_ID)
or whatever the syntax for your particular database system is.
Make the PRIMARY KEY tableA_ID and tableB_ID, EXCLUDING ID
lets say we have a table TABLEA with values
tableAID
1
2
3
and table TABLEB with values
tableBID
4
5
6
making the primary key (ID, tableA_ID, tableB_ID) will not work eg.
ID | tableAID | tableBID
1 | 1 | 4
2 | 1 | 4
will work fine with the above pk, but you need PRIMARY KEY (tableA_ID, tableB_ID)
Drop the ID column then make the other two columns the primary key and their uniqueness will be enforced by the database server.
It's not really necessary to have the ID column - even though it serves as a handy way of referencing a particular record - as the uniqueness of the other two columns will mean that they are sufficient to reference a particular record.
You may also want to put an index on this table, that includes bothe columns, to make access faster.