Should I add the primary key in my sql server index? - sql-server-2008-r2

I know any non clustered index contains the primary key. But I wonder if it contains it in a specific order or not.
I have a query which retrieve for every "MemberTee" its most recent (highest ID) "MemberTeeHist"'s teeID value.
SELECT
MT.ID
, MTH.teeID
FROM Favorite.tMemberTee AS MT
INNER JOIN (
SELECT
MTH.memberTeeID
, MTH.teeID
, ROW_NUMBER() OVER (PARTITION BY MTH.memberTeeID ORDER BY MTH.ID DESC) AS RNK
FROM Favorite.tMemberTeeHist AS MTH
) AS MTH ON (
MTH.memberTeeID = MT.ID
AND
MTH.RNK = 1
)
In order for this query to perform the best, I need an index on tMemberTeeHist ordered by memberTeeID and ID (primary key).
Here are the tables DDL :
CREATE SCHEMA Favorite
GO
CREATE TABLE Favorite.tMemberTee (
ID INT NOT NULL IDENTITY
, CONSTRAINT PK_tMemberTee PRIMARY KEY (ID)
, memberID BIGINT NOT NULL
, CONSTRAINT FK_tMemberTee_memberID FOREIGN KEY (memberID) REFERENCES dbo.tMembers(ID)
, courseID INT NOT NULL
, CONSTRAINT FK_tMemberTee_courseID FOREIGN KEY (courseID) REFERENCES dbo.tCourseBases(ID) ON DELETE CASCADE
, CONSTRAINT UQ_tMemberTee_01 UNIQUE (courseID, memberID)
)
GO
CREATE TABLE Favorite.tMemberTeeHist (
ID INT NOT NULL IDENTITY
, CONSTRAINT PK_tMemberTeeHist PRIMARY KEY (ID)
, memberTeeID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_memberTeeID FOREIGN KEY (memberTeeID) REFERENCES Favorite.tMemberTee(ID) ON DELETE CASCADE
, teeID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_teeID FOREIGN KEY (teeID) REFERENCES dbo.tTees(ID)
, [date] DATETIME NOT NULL CONSTRAINT DF_tMemberTeeHist_date DEFAULT GETDATE()
, originatorID INT NOT NULL
, CONSTRAINT FK_tMemberTeeHist_originatorID FOREIGN KEY (originatorID) REFERENCES dbo.tClubMembers(ID)
)
GO
Now, should I create the index this way (because SQL SERVER would already internally have ID ordered inside the index) :
CREATE NONCLUSTERED INDEX IDX_tMemberTeeHist_memberTeeID ON Favorite.tMemberTeeHist (memberTeeID ASC)
GO
Or should I have it like this :
CREATE NONCLUSTERED INDEX IDX_tMemberTeeHist_memberTeeID ON Favorite.tMemberTeeHist (memberTeeID ASC, ID ASC)
GO

Since the constraint
CONSTRAINT PK_tMemberTee PRIMARY KEY (ID)
creates a default, clustered primary key (and thus a clustered index), that clustering column ID is already part of every nonclustered index (at the leaf level) anyway
There's no point or no benefit in adding it in separately again.

Related

DB2 referential constraint cannot created

I can not add a referential constraint, both tables has the two columns id and version as primary key. I will only check the integrity that the row is existing without checking version.
CREATE TABLE TABLEE
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION);
CREATE TABLE CHAIR
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION);
ALTER Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT
Got this error
[Code: -573, SQL State: 42890] A column list specified in the references clause of constraint "MYC " does not identify a unique constraint of the parent table or nickname "TABLEE".. SQLCODE=-573, SQLSTATE=42890, DRIVER=4.28.11
The problem here is that Tablee its primary key consists of two columns id and version. But the integrity check should only be made on the referenced id, not version.
To establish a foreign key on a table the referenced column needs to:
Be a primary key on the other table.
...or at least act as one.
Since you already have a primary key on the referenced table, you can use the second approach and add a UNIQUE and NOT NULL constraints on ID.
For example:
CREATE TABLE TABLEE (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION),
constraint uq1 unique (id) -- added UNIQUE constraint on ID
);
CREATE TABLE CHAIR (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION)
);
ALTER table Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT;
See running example at db<>fiddle.
Note: If you want ID to have repeated values over the table, then ID is not a key, and cannot be referenced as one.

Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'questions_ibfk_1' in the referenced table 'category'

cannot add foreign key constraint to table
create table users
(
user_id int auto_increment primary key not null,
username varchar(50) unique null ,
email varchar(50) unique ,
passwords varchar(50) not null,
login_status boolean not null
);
create table category (
category_id int primary key not null,
category_name varchar(50) not null
);
create table answers (
id_answer int auto_increment primary key not null,
answer boolean not null
);
create table questions (
question_id int primary key not null,
category_name varchar(50) not null,
content varchar(50) not null ,
foreign key (category_name) references category (category_name)
);
You get this error because there's no index on category_name in the category table. Change that CREATE statement as follows:
create table category (
category_id int primary key not null,
category_name varchar(50) not null,
KEY category_name_index (category_name)
);
From the docs (8.0 version, but the statement is true for older versions):
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Also, you're using a varchar(50) as your foreign key, which is not usually a great idea for a variety of reasons. You probably want to use a numeric value, such as category_id, instead.

update order column based on groupby postgresql

I have created an order-column and i want to update the current values that is in that table.
CREATE TABLE public.publishroomcontacts
(
id integer NOT NULL DEFAULT nextval('publishroomcontacts_id_seq'::regclass),
publishroomid integer NOT NULL,
contactorder integer NOT NULL,
CONSTRAINT publishroomcontacts_pkey PRIMARY KEY (id),
CONSTRAINT fk_publishroomcontacts_publishroom_id FOREIGN KEY (publishroomid)
REFERENCES public.publishrooms (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
)
WITH (
OIDS = FALSE
);
What i want to do is to go through all rows, group by publishroomid and add a contactorder.
So if there is 4 contacts with the same publishroomid whey will have contact order 1, 2, 3 and 4.
How do i do this?
EDIT:

One to one relation not setting primary key

I have a schema where Table1 had a primary auto increment identity key and Table2 has a primary key with a FK constraint that it equals the Table1 primary key.
Schema is:
CREATE TABLE [dbo].[Table1](
[Key] [bigint] IDENTITY(1,1) NOT NULL,
[Value] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
(
[Key] ASC
)
CREATE TABLE [dbo].[Table2](
[Key] [bigint] NOT NULL,
[Value] [nchar](10) NOT NULL,
CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED
(
[Key] ASC
)
ALTER TABLE [dbo].[Table2] WITH CHECK ADD CONSTRAINT [FK_Table2_Table1] FOREIGN KEY([Key])
REFERENCES [dbo].[Table1] ([Key])
Code is:
void Main()
{
var table1 = new Table1
{
Value = "table1",
Table2 = new Table2
{
Value = "table2",
}
};
Table1.InsertOnSubmit(table1);
SubmitChanges();
}
Then do an insert and save it complains that the Table2 can't insert duplicate foreign key.
I'm guessing that it's not setting the primary key value in Table2 with the return from the Table1 insert and I can't figure out how to do this without making it two separate calls.

How to add a foreign key constraint to same table using ALTER TABLE in PostgreSQL

To create table I use:
CREATE TABLE category
(
cat_id serial NOT NULL,
cat_name character varying NOT NULL,
parent_id integer NOT NULL,
CONSTRAINT cat_id PRIMARY KEY (cat_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE category
OWNER TO pgsql;
parent_id is a id to another category. Now I have a problem: how to cascade delete record with its children? I need to set parent_id as foreign key to cat_id.
I try this:
ALTER TABLE category
ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
REFERENCES category (cat_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
But it falls with:
ERROR: insert or update on table "category" violates foreign key constraint "cat_cat_id_fkey"
DETAIL: Key (parent_id)=(0) is not present in table "category".
The problem you have - what would be the parent_id of a category at the top of the hierarchy?
If it will be null - it will break the NOT NULL constratint.
If it will be some arbitrary number like 0 - it will break the foreign key (like in your example).
The common solution - drop the NOT NULL constratint on the parent_id and set parent_id to null for top categories.
-- create some fake data for testing
--
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE category
(
cat_id serial NOT NULL,
cat_name character varying NOT NULL,
parent_id integer NOT NULL,
CONSTRAINT cat_id PRIMARY KEY (cat_id)
);
INSERT INTO category(cat_name,parent_id)
SELECT 'Name_' || gs::text
, gs % 3
FROM generate_series(0,9) gs
;
-- find the records with the non-existing parents
SELECT ca.parent_id , COUNT(*)
FROM category ca
WHERE NOT EXISTS (
SELECT *
FROM category nx
WHERE nx.cat_id = ca.parent_id
)
GROUP BY ca.parent_id
;
-- if all is well: proceed
-- make parent pointer nullable
ALTER TABLE category
ALTER COLUMN parent_id DROP NOT NULL
;
-- set non-existing parent pointers to NULL
UPDATE category ca
SET parent_id = NULL
WHERE NOT EXISTS (
SELECT *
FROM category nx
WHERE nx.cat_id = ca.parent_id
)
;
-- Finally, add the FK constraint
ALTER TABLE category
ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
REFERENCES category (cat_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
;
This is quite simple.
Here the foreign key parent_id refers to cat_id.
Here a record with parent_id=0 exists but not a record with cat_id=0.