How to add Foreign key constraint on array in PostgreSQL? - arrays

How to add Foreign key constraint on array in PostgreSQL?
look_up table for roles
CREATE TABLE party_role_cd
(
party_role_cd bigint NOT NULL,
code character varying(80) NOT NULL,
CONSTRAINT party_role_cd PRIMARY KEY (party_role_cd)
);
Party can have zero or many roles [ 0-N relationship ]
CREATE TABLE party
(
party_id biging NOT NULL,
party_role_cd bigint[] NOT NULL,
CONSTRAINT party_id PRIMARY KEY (party_id)
);
How to add the foreign key constraint for party_role_cd array in party table?

That's not implemented in PostgreSQL. Currently, FK constraints only operate on equality between whole column values. No array-to-element references. There is an open TODO item that has been added in 2010. See:
https://wiki.postgresql.org/wiki/Todo#Referential_Integrity
https://www.postgresql.org/message-id/1288033876.6278.6.camel#vanquo.pezone.net
There were even attempts to implement it, but never to completion.

Related

Creating Primary Keys

I would like to know which column should I put in the PK first, [ID_CHECK] or [ID_CONTROL].
CREATE TABLE QUALITY_CONTROL
(
[ID_CHECK] [int] NULL,
[ID_CONTROL] [int] NOT NULL
)
ALTER TABLE QUALITY_CONTROL ADD CONSTRAINT QUALITY_CONTROL_P01 PRIMARY KEY ([ID_CHECK], [ID_CONTROL])
or
ALTER TABLE QUALITY_CONTROL
ADD CONSTRAINT QUALITY_CONTROL_P01 PRIMARY KEY ([ID_CONTROL], [ID_CHECK])
The [ID_CHECK] column has more repeated data, I don't know if that means anything.
Thanks.

Entity Framework appears to skip mapping a table with a multi-column primary key set through a constraint

I've created an ADO.NET model via the database first approach.
One of my tables which is listed when creating the model doesn't actually get added to it.
The table has a multi-column primary key, composed of two foreign keys.
CREATE TABLE ForumAccess
(
UserID INT FOREIGN KEY REFERENCES Users(UserID) NOT NULL,
ForumID INT FOREIGN KEY REFERENCES Forums(ForumID) NOT NULL,
CONSTRAINT ForumAccessID PRIMARY KEY (UserID, ForumID),
);
It does show up when I have to select which tables to add, but then it seems to be skipped. No class is generated for it, and it's not shown in the .edmx file.
Part of my application depends on the existence of this table. I have another table which has a multi-column primary key, and another DateTime type column. That table does get added.
That table is:
CREATE TABLE Moderators
(
UserID INT FOREIGN KEY REFERENCES Users(UserID) NOT NULL,
ForumID INT FOREIGN KEY REFERENCES Forums(ForumID) NOT NULL,
TimeOfAddition DateTime NOT NULL, -- When the mod was added as a mod.
CONSTRAINT ModeratorID PRIMARY KEY (UserID, ForumID),
);
Why does the Moderators table get added, but the ForumAccess table doesn't?
There is no error, or any warning that I can see.
What am I missing?

Proper Database Design with Foreign Keys

Because I've never designed a database, I wanted to make sure that the design I'm using, while simple, follows general idiomatic design patterns.
Essentially, a friend is making a discord bot that allows you to submit photos and have others rate them. Putting the obvious trolling opportunities aside, here are the data fields that are needed:
Discord ID (unique ID for every person using discord)
List of URLs (each URL is tied to a certain discord member)
List of Votes (each vote has a score, the voter ID, and the URL)
What I don't particularly like about this design is that it maintains two scores: a running total that will be divided by the total number of votes of that user, and each vote in particular.
My questions are:
Is this design proper?
Using this design, how can I ensure that each person can only vote for each url once?
https://dbdesigner.net output:
CREATE TABLE "Members" (
"id" serial NOT NULL,
"discord_id" bigint NOT NULL,
"total_score" bigint NOT NULL,
"total_votes" bigint NOT NULL,
CONSTRAINT Members_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "Images" (
"id" serial NOT NULL,
"url" TEXT(64) NOT NULL,
"member_id" bigint NOT NULL,
CONSTRAINT Images_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "Votes" (
"id" serial NOT NULL,
"voter_id" serial NOT NULL,
"target_id" serial NOT NULL,
"score" serial NOT NULL,
"image_id" serial NOT NULL,
CONSTRAINT Votes_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
ALTER TABLE "Images" ADD CONSTRAINT "Images_fk0" FOREIGN KEY ("member_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk0" FOREIGN KEY ("voter_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk1" FOREIGN KEY ("target_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk2" FOREIGN KEY ("image_id") REFERENCES "Images"("id");
Since I cannot see your foreign key references and I don't see your code (i.e., SQL statements), I cannot know for sure if your synthetic keys are a good idea. But at first glance, it appears as though your real key for VOTES is (VOTER_ID, IMAGE_URL).
If we assume that you are not going to change the relations, their keys, and their non-key attributes, then all you need to do to satisfy #2 is to put a unique constraint on VOTES (VOTER_ID, IMAGE_URL).
Responding to the first part of the question, "Is this design proper", the short answer is "no".
If discord_ids are unique, you do not need another ID column in members. The discord_id is the primary key of the members table.
If Image URLs are unique, that could be the primary key of the Images table. That's really up to you; some people don't like using long text strings as keys. I'll assume you're one of them.
The Votes table shouldn't have an ID column at all. It's a many-to-many join table. Your key there is (voter_id, image_id). This also has the effect of preventing members from voting more than once.
The target_id column in votes is completely redundant, as that information already exists in the images table.
Neither voter_id nor image_id in Votes should be Serial. Instead, they should be INT. Score, which is presumably a numeric score, should be NUMERIC or INT (I'll use INT since total_score is bigint).
using mixed-case identifiers is generally a bad idea in SQL, as identifier (table) names are case-sensitive in strange ways.
Limiting URLs to 64 characters seems shortsighted; do you have an application constraint here you need to match?
You should add CASCADE to all of your foriegn keys, so that you can easily delete members or images.
As such, below is your revised schema:
CREATE TABLE "members" (
"discord_id" bigint NOT NULL,
"total_score" bigint NOT NULL,
"total_votes" bigint NOT NULL,
CONSTRAINT members_pk PRIMARY KEY ("discord_id")
);
CREATE TABLE "images" (
"id" serial NOT NULL,
"url" VARCHAR(64) NOT NULL,
"discord_id" BIGINT NOT NULL,
CONSTRAINT images_pk PRIMARY KEY ("id"),
CONSTRAINT images_url UNIQUE ("url")
);
CREATE TABLE "votes" (
"voter_id" INT NOT NULL,
"image_id" INT NOT NULL,
"score" INT NOT NULL,
CONSTRAINT votes_pk PRIMARY KEY (voter_id, image_id)
);
ALTER TABLE "images" ADD CONSTRAINT "images_fk0"
FOREIGN KEY ("discord_id") REFERENCES "members"("discord_id")
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "votes" ADD CONSTRAINT "votes_fk0"
FOREIGN KEY ("voter_id") REFERENCES "members"("discord_id")
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "votes" ADD CONSTRAINT "votes_fk2"
FOREIGN KEY ("image_id") REFERENCES "images"("id")
ON DELETE CASCADE ON UPDATE CASCADE;

SQL Server foreign relationship on two-column primary key

I have the following three sample tables (simplified demo for purpose of question):
CREATE TABLE Teams
(
Id int IDENTITY(1,1) NOT NULL,
Name varchar(50) NOT NULL,
PRIMARY KEY (Id)
)
CREATE TABLE TeamGroups
(
Id int NOT NULL,
TeamId int NOT NULL,
PRIMARY KEY (Id,TeamId)
)
CREATE TABLE RoomBookings
(
Id int NOT NULL,
TeamGroupId int NOT NULL,
RoomId int NOT NULL,
PRIMARY KEY (Id)
)
and I have the following foreign key already set up:
ALTER TABLE TeamGroups WITH CHECK
ADD CONSTRAINT [FK_TeamGroups_Teams]
FOREIGN KEY (TeamId) REFERENCES Teams(Id)
The idea is that each Team can be in zero or more TeamGroups, and each TeamGroup can have zero or more RoomBookings
To reflect that, I want to add a foreign key from the RoomBookings table into the TeamGroups table.
I tried using the Relationships GUI in Management Studio to create the foreign key (primary key table: TeamGroups.ID, foreign key table: RoomBookings.TeamGroupId) but I get an error:
The columns in table 'TeamGroups' do not match an existing primary key
or UNIQUE constraint
I'm assuming it's because the TeamGroups table has a two-column primary key?
I don't really want to make a foreign key constraint from the TeamGroups table (eg, the key is present in the TeamGroups table), as the table will eventually be used by other tables (such as EquipmentBookings, GroupManagers, etc).
Any help?
If your primary key is made up from more than one columns, then all foregin keys also must have all those columns - there's no way around this.
But I don't understand why you'd get this error trying to link TeamGroups to Team based on the Team.Id column.... that should work just fine.
Try using this:
ALTER TABLE TeamGroups WITH CHECK
ADD CONSTRAINT [FK_TeamGroups_Teams]
FOREIGN KEY (TeamId) REFERENCES Teams(Id);
You had Teams (which is not a valid column in TeamGroups at all), and you had REFERENCES Teams.id which is wrong - it needs to be REFERNCES Teams(Id); (column in parenthesis - not the "dot" notation)
Update: from TeamGroups to RoomBookings - yes.... either use both columns from TeamGroups in your RoomBookings table - or what would stop you from making the TeamGroups.Id column an INT IDENTITY and then have the PK on just this one column?? Any good reason for that??
CREATE TABLE TeamGroups
(
TeamGroupId int NOT NULL,
TeamId int NOT NULL,
PRIMARY KEY (TeamGroupId)
)
ALTER TABLE dbo.RoomBookings
ADD CONSTRAINT FK_RoomBookings_TeamGroup
FOREIGN KEY TeamGroupId REFERENCES TeamGroups(TeamGroupId)

Can I have a foreign key in my table be null?

I have this DDL:
CREATE TABLE [dbo].[Test] (
[TestId] VARCHAR (20) NOT NULL,
[Title] NVARCHAR (100) NOT NULL,
[TopicId] INT NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([TestId] ASC),
CONSTRAINT [FK_TestTopic] FOREIGN KEY ([TopicId]) REFERENCES [dbo].[Topic] ([TopicId])
);
I would like the allowed values of the TopicId to be null or one that matches the TopicId in the Topic table.
Can someone tell me how I can describe the foreign key for this?
Yes, foreign key constraint columns may allow NULLs. Simply change the foreign key column to allow NULL values. Referential integrity of NULL values are not checked. This is a common practice for optional (zero-or-more) relationships.
Well.. You could do that very easily just by making the field to allow null.. But, keep this in your mind, 'you are breaking data modelling'.

Resources