Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
How can an algorithm is written to find Primary Keys and Foreign Keys of a relation ?
Given parameters are name of relation, degree of relation and an array of the attributes(a primary key may include more than one attribute)
I think if an attribute is referenced than it is primary key. and the attirbute that references is FK
I would make a list of columns that contain no redundancies and no null cells as possible primary keys. I suppose one fast way to detect them would be to attempt to declare the column as a PK and see if there are errors. Another approach would be a group by:
select column_name, count(*) c from table_name
where column_name is not null
group by c
having c <> 1
If column_name of table_name is plausibly a primary key, the query above should produce no rows.
As for foreign keys, try this:
select column_name from table_name
except
select other_column from other_table
This should return an empty set if other_column of other_table has column_name of table_name as a foreign key.
As for automating the above tests over all the tables and each of their columns, I can't help there as my SQL vocabulary doesn't include Microsoft.
Note that passing the tests above is a necessary but not sufficient condition for a column to be a key. Determining which columns should be keys is as much a matter of intuition as algorithms, and if your starting point is taming a messy collection of raw data there may be columns that fail the tests but should nevertheless be keys.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have some studentIDs that are missing some characters from the end. I need to find the closest match (correct ID number) from the Student table.
My script below is taking time to do as I have many students.
Please advise on a better way. I would like to add all incomplete IDs and get the correct one like
if studentID like ('JG853102%','SE686104%','SE686104%')
then get the closest match from my table.
SELECT First Name, Surname, StudentID
FROM StudentTable
WHERE StudentID like 'JG853102%'
OR StudentID like 'SE686104%'
OR StudentID like 'SE686104%'
The query you have is SARGable, however, as I mentioned in the comments the WHERE can never be true. You are checking that the value of StudentID starts with both 'JG853102' and 'SE686104'. This is obviously impossible as a string cannot start with two completely different sets of characters. You therefore most likely want an OR.
The reason the query is slow, however, is likely due to a lack any type of indexing. On a table with the name StudentTable and a column with the name StudentID one would assume that this is your PRIMARY KEY, which means it would be indexed already. This strongly suggests it is not. Based on the value though it doesn't look like it's an always ascending value, meaning that it could likely not be a good candidate for a CLUSTERED INDEX. If it is always ascending, then creating your PRIMARY KEY as a CLUSTERED one would likely make the query far better:
ALTER TABLE dbo.StudentTable ADD CONSTRAINT PK_StudentTable PRIMARY KEY CLUSTERED (StudentID);
As the CLUSTERED INDEX automatically includes all columns in the table, then it'll be a covering index for your columns First and Surname as well.
If the value isn't always ascending, then you want to create a separate index. For what we have, that would minimally be the following:
ALTER TABLE dbo.StudentTable ADD CONSTRAINT PK_StudentTable PRIMARY KEY NONCLUSTERED (StudentID);
CREATE INDEX IX_StudentTable_StudentID ON dbo.StudentTable (StudentID) INCLUDE (First, Surname);
If you have more columns in your table StudentTable then I would INCLUDE all of those if you can.
Finally, you might find that a Table Variable or VALUES construct with an EXISTS might be more performant than an OR. That would look like the following:
--VALUES
SELECT First AS [Name],
Surname,
StudentID
FROM dbo.StudentTable ST
WHERE EXISTS (SELECT 1
FROM (VALUES('JG853102%'),
('SE686104%'))V(StudentID)
WHERE ST.StudentID LIKE V.StudentID);
--Variable
DECLARE #IDs table (StudentID varchar(10));
INSERT INTO #IDs
VALUES('JG853102%'),
('SE686104%');
SELECT First AS [Name],
Surname,
StudentID
FROM dbo.StudentTable ST
WHERE EXISTS (SELECT 1
FROM #IDS I
WHERE ST.StudentID LIKE I.StudentID);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
A patient can select many tests, and a test can be selected by many patient.
Then what would be the structure of these tables and how the relationship can be established between them?
your table structure should be below
PatientTable
PatientId int Primary Key,
PatientName varchar(50),
EmailId varchar(50)
Password varchar(50)
TestTable
TestId int Primary key,
TestName varchar(50)
PatientTestTable
PatientId int FK(PatientTable)
TestId int FK (TestTable)
This way you can give relationship to two tables. you need to understand funamental of RDBMS.
You will probably need 3 tables, Patient table, Test Table and PatientTest Table
with PatientID as foreign key fro Patient table and TestId as foreign key from Test table and you can add any other column ( like TestDatetime, TestResult ...)
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I tried to create a table which has got 2 primary key and both of them supposed to be auto incremental by changing the Identity specification but in the property window the option (I just mentioned) is disable and I cannot change that.
The column I want to change to auto increment is the primary key of the table and type of it is INT.
What's wrong ? or What I'm wrong ?
As mentioned by TT, you can only have a single identity column and only a single primary key in a table.
For SQL Server 2012 and above, You can however use a SEQUENCE if you need 2 or more auto increment columns. You can then create a PRIMARY KEY on IDENTITY column and a UNIQUE constraint on the column with sequence as default
CREATE SEQUENCE mainseq START WITH 1 INCREMENT BY 1 ;
GO
create table table1 (
id1 int IDENTITY(1,1) NOT NULL PRIMARY KEY,
id2 bigint not null constraint DF_table1_id2 default next value for mainseq,
data varchar(20) not null
)
GO
INSERT INTO table1(data) VALUES('row 1');
INSERT INTO table1(data) VALUES('row 2');
SELECT * FROM table1;
Note that the column with sequence default behaves in differently than an identity. you cannot directly insert into an identity column (except when identity_insert is on) however you can manually insert / update the column being defaulted by a sequence.
From the definition of IDENTITY in SQL Server, you can read that a table can only have one IDENTITY column. See remarks, quote:
Only one identity column can be created per table.
I also wonder how you get two primary keys on a table, as that is not possible. See the following article on creating primary keys, quote from Limitations and Restrictions:
A table can contain only one PRIMARY KEY constraint.
If you need an additional auto incrementing column you could add a trigger to the table FOR INSERT. Something that would find the current maximum value and then add one to it.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I have a table in SQL Server 2008 - let's call the table MyTable. The table has a column named Status, which is not a computed column, and is defined as varchar(40) and it allows NULLs; however, there is also a DEFAULT CONSTRAINT on this column, with the default value = 'POOL'. I just added a computed column to the table, using the following:
ALTER TABLE MyTable
ADD PrimaryStatus AS
CASE
WHEN Status LIKE '%/%' THEN LEFT(Status,CHARINDEX('/', Status) - 1)
ELSE Status
END PERSISTED
If I insert records into the table one by one (and let Status default to 'POOL' using the constraint) it works just fine; for instance, this SQL statement has no problem:
INSERT INTO MyTable (Name) VALUES ('Foo')
With the above SQL, I end up with a new record in the table with Name = 'Foo' and Status = 'POOL' and PrimaryStatus = 'POOL'
But if I execute a multi-row INSERT like the following:
INSERT INTO MyTable (Name) VALUES ('Foo'),('Bar')
then it throws an error:
Msg 537, Level 16, State 2, Line 1
Invalid length parameter passed to the LEFT or SUBSTRING function.
If I drop either the default constraint or the computed column (or both), the multi-row INSERT works fine; but for some reason having both the constraint and the computed column are causing the multi-row INSERT to fail. I have tried tweaking the computed column in a variety of ways to account for NULLs (even though I don't think it should matter given the order of evaluation), but nothing seems to remedy the problem.
Anybody ever seen something like this before?
I tried to replicate the error. But, I don't get any error. I could have added this as a comment, but don't have enough points yet. Anyway, this is what i did -
CREATE TABLE [dbo].[MyTable](
[Name] [varchar](50) NULL,
[Status] [varchar](50) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_MyTable_Status]
DEFAULT ('POOL') FOR [Status]
GO
Then i removed an extra ) in your code and did -
ALTER TABLE MyTable ADD PrimaryStatus AS
CASE WHEN Status LIKE '%/%' THEN LEFT(Status,CHARINDEX('/',Status)-1)
ELSE Status END PERSISTED
Followed by -
INSERT INTO MyTable (Name) VALUES ('Foo')
INSERT INTO MyTable (Name) VALUES ('Foo'),('Bar')
It works. Am I missing something ?
Observe the following table model:
CREATE TABLE [site].[Permissions] (
[ID] INT REFERENCES [site].[Accounts]( [ID] ) NOT NULL,
[Type] SMALLINT NOT NULL,
[Value] INT NULL
);
The site.Accounts->site.Permissions is a one-to-many relationship so 'ID' cannot be made a primary key due to the uniqueness that a PK imposes.
The rows are selected using a WHERE [ID] = ? clause, so adding a phoney IDENTITY column and making it the PK yields no benefit at the cost of additional disk space.
Its my understanding that the targeted platform - SQL Server (2008) - does not support composite PKs. These all add up to my question: If a Primary Key is not used, so something wrong? Or could something be more right?
Your understanding is not correct, SQL Server does support composite primary keys!
The syntax to add one would be
ALTER TABLE [site].[Permissions]
ADD CONSTRAINT PK_Permissions PRIMARY KEY CLUSTERED (id,[Type])
Regarding the question in the comments "What is the benefit of placing a PK on the entire table?"
I'm not sure from your description though what the PK would need to be on. Is it all 3 columns or just 2 of them? If it's on id,[Type] then presumably you wouldn't want the possibility that the same id,[Type] combo could appear multiple times with conflicting values.
If it is on all 3 columns then to turn the question around why wouldn't you want a primary key?
If you are going to have a clustered index on your table you could just make that the primary key. If say you made a clustered index on the id column only SQL Server would add in uniqueifiers anyway to make it unique and your columns are so narrow (int,smallint,int) this just seems a pointless addition.
Additionally the query optimiser can use unique constraints to improve its query plans (though might not apply if the only queries on that table really are WHERE [ID] = ?) and it would be pretty wasteful to allow duplicates that you then have to both store and filter out with DISTINCT.