Is it well designed relational database just with one table? - database

I have MySQL database containing just one table, having 100 rows and 12 columns: ID (primary key), NAME, LATITUDE, LONGITUDE, TYPE, COUNTRY, CONTINENT, DESCRIPTION_PATH, STORY_PATH, PICTURE_PATH, ICON_PATH and VIDEO_PATH. Do you think it is OK to keep all the data in one table or should data be distributed within more tables?

This is a perfectly fine table design as long as your Name rows only need at most one description, one story, one picture, one icon, and one video.
As soon as you want someone to have two pictures, you'll need to create another table for pictures and store one picture per row, each one referencing your first table.
For example:
CREATE TABLE Pictures (
picture_id INT,
name_id INT,
picture_path VARCHAR(100),
PRIMARY KEY (picture_id, name_id)
FOREIGN KEY (name_id) REFERENCES Names (id)
);
And you'd remove the picture_path column from first table of course.

Related

Is there is a constraint to make sure one column has and only matched column

I have a problem to set correct constraint to make sure one column has and only has one matched column within the table.
For example, company Apple has Bloomberg ticker AAPL:US and only has this ticker. Otherwise, SQL Server will notice there is a error.
I try to use constraint with unique, but it does not work.
I imagine that your schema might be a standard one using a junction table. That is, your tables might look something like:
company (id, name)
ticker (id, name)
company_ticker (id_company, id_ticker)
That is, the company_ticker table is a junction table which stores the relationships between companies and tickers. Normally, this table would by default be many-to-many. But if you want to restrict a company to having only one ticker, then you may place a unique constraint on the id_company column:
CREATE TABLE company_ticker (
id_company INT NOT NULL,
id_ticker INT NOT NULL,
PRIMARY KEY (id_company, id_ticker),
CONSTRAINT cnstr UNIQUE (id_company)
);
With the above unique constraint in place, your schema will only allow a given company to have one relationship with some ticker.

SQL Server Database Design - multiple columns in one table reference single column is another table

I'm designing my first SQL Server database and wonder if there's a better way to accomplish what I'm trying to do.
The goal is to be able to create one of 14 documents based on 200+ different document sections (titles, headings, paragraphs, lists, etc). Each document section is part of 1 or more documents.
My application does a single database lookup for a particular document and retrieves the data stored in the 50 text fields.
To do this, I first stored each unique document section in a "sections" table, giving each section a unique identifier (sectionID) and made the identifier a primary key, for example:
dbo.sections
sectionID(pk) sectionText
iv1 this is the text for the first section
AHv1 this text is for another section
APv2 more text to include
.
.
.
EFv3 another text section
GHv2 this is the last section text in the table
I then created a second table called "documents" to store each document name and the sections that belong to it. There are 51 columns in this table. The first column is the document name and the other 50 columns store the id's of the sections (they're named section1, section2, ...) that make up that particular document. Each of the section columns are foreign keys that reference the primary key in the "sections" table, for example:
dbo.documents
docID section1(fk) section2(fk) ... section50(fk)
option1 iv1 AHv1 ... GHv2
option2 iv1 APv2 ... EFv3
All of this seems straightforward to me. However, in order to get the text for each document to be part of a given record, I have to create a view that does 50 joins of the sections table. By doing that, each document id and its text are stored in one row of a table.
Is there a better way to get the same end result? Or a better design? It seems like there may be a lot of overhead to join the data between tables.
Any input would be greatly appreciated!
Let's say you have one table, document, with a one-to-many relationship with a second table, documentSection. Document has a PK field documentID, documentSection's PK is compound, documentID and sectionID, so when the two tables are joined, it's only on the documentID field. Then you won't need one column for each section.
Actually, it sounds like you have all of the document section text stored in your section table, which can be used in multiple documents. Maintenance nightmares aside, you can have Section be your primary table and sectionDocument have the one-to-many relationship, but you may need to introduce a sectionSequence field to keep the sections of your document in sequence. You'll actually need the sequence field regardless of which table is primary.
regarding your comment, let's say you have a section table with a PK field sectionID. Then you can have a sectionDocument table with a compound PK, sectionID and documentID, which will probably need to include a sequence number. You're currently using the ordinal position of the column to identify the sequence of the section in the document, but as you say, you don't want 50 relationships to the section table. The way to handle that is to have the sections defined vertically instead of horizontally. In rows instead of columns. You can also have a document table with PK documentID and the document name.
Building on (and maybe clarifying) what Beth is talking about, you might consider a three-table approach. The lords-of-data generally refer to normalization rules or normal forms to describe patterns in your data that result in great flexibility and performance.
At first blush, these rules seem to spread your data out, but it's very worthwhile learning about these patterns. You don't have to worry about your database "joining a lot" as this is what relational databases are really good at - and normalized database are really easy to join up.
For example, in order to select all the section texts in order for a given document, you would do something like this:
select
s.SectionText
from
Documents d
inner join
DocumentSections ds
on
d.DocumentId=ds.DocumentId
inner join
Sections s
on
ds.SectionId = s.SectionId
where
d.DocumentId = 'MyDoc'
order by
ds.Position
Basically, this converts your 50 columns in documents to an unlimited number of rows in DocumentSections.
Here's how you'd define such a system in SQL Server:
create table dbo.Sections
(
SectionId
nvarchar(8) not null
constraint [Sections.SectionId.PrimaryKey]
primary key clustered,
SectionText
nvarchar( max ) not null
)
create table dbo.Documents
(
DocumentId
nvarchar(8) not null
constraint [Documents.DocumentId.PrimaryKey]
primary key clustered,
Name
nvarchar( 255 ) not null
constraint [Documents.Name.Unique]
unique nonclustered
)
create table dbo.DocumentSections
(
DocumentId
nvarchar(8) not null
constraint [DocumentSections.to.Documents]
foreign key references dbo.Documents( DocumentId )
on delete cascade,
SectionId
nvarchar(8) not null
constraint [DocumentSections.to.Sections]
foreign key references dbo.Sections( SectionId )
on delete cascade,
Position
int not null,
constraint [DocumentSections.DocumentId.SectionId.PrimaryKey]
primary key clustered( DocumentId, SectionId ),
constraint [DocumentSections.DocumentId.Position.Unique]
unique ( DocumentId, Position )
)
There are a couple of things worth noting:
In this code, if you delete a row from Documents, the DocumentSections rows also go away (but not the Sections that were used in the Documents row). Likewise, if you delete a Sections row, the DocumentSections rows for that deleted Sections row go away, leaving the Documents unmolested. This is done with the on delete cascade clauses in the foreign key constraints. They're totally optional, but I showed it just for fun. This is often very handy.
I added a restriction (again optional) that prevents a Section from being used more than once in a Document. If that's not what you want, you can just remove that whole constraint.
I picked nvarchar(8) for the size of the key fields - for no particular reason. If you make these bigger, be sure to increase the width in the referring tables, too.

Change ID of row and reflect this change to all related tables

Old version
I have a Person table and the table Company.
both tables have a column Id (Identity)
Table Company have Ids of 1 to 165
In the table Person have Ids 1 until 2029
New Version
In the new version of the system, was created a table Entity.
This table contains the records of the Companies and People
The Company and Person tables will be maintained, referring to the Entity table.
The Id in table Entity will be the same in Company or Person table
Question
Both tables have multiple relationships with other tables.
Table Entity (as well as others) has a column ID (identity).
The problem is that the Id were repeated when the two tables together (It was to be expected).
How to import without losing relationships?
Attempts
I thought of changing the value of Ids in Company table, starts from 2030.
Thus the Ids would not duplicate when joining the two tables.
But this creates another questions.
How to do this without losing existing relationships?
How to change the Id of a row in the table and this is reflected in all tables which it relates?
I would like to do this using only DDL (SQL Server)
I thought of changing the value of Ids in Company table, starts from 2030. Thus the Ids would not duplicate when joining the two tables.
Create foreign key constraints on the Person table to all related tables (or alter the existing foreign key constraints) with ON UPDATE CASCADE. Then update the Person table and change the values if the id columns - these changes will cascade to the related tables.
To stop further problems, maybe change the identity columns in Person and Company to something like identity( 1000, 3 ) and identity (1001, 3) respectively.
However, I think the best idea is to have a different EntityID column in the Entity table, unrelated to PersonID and CompanyID. The Entity table would also have a column called AltEntityID or BusinessKey that contains the id from the other table and that does not have a unique constraint or a foreign key constraint.
And if you make small modification to your attempt - add new column, say newId, to Company and to Person to manage relation with Entity and leave id columns as is. Why this is the simpliest way? Because new columns shouldnot be identity columns, from one side. From the other side, you can leave all logic of relating other tables with Company and Person intact.

SQL Server primary / foreign keys

I am developing a system in which I have a table Employees with multiple columns related to employees. I have a column for the JobTitle and another column for Department.
In my current design, the JobTitle & the Department columns are compound foreign keys in the Employees table and they are linked with the Groups table which has 2 columns compound primary key (JobTitle & Department) and an extra column for the job description.
I am not happy about this design because I think that linking 2 tables using 2 compound varchar columns is not good for the performance, and I think it would be better to have an Integer column (autonumber) JobTitleID used as the primary key in the Groups table and as a foreign key in the Employees table instead of the the textual JobTitle & the Department columns.
But I had to do this because when I import the employees list (Excel) into my Employees table it can just be directly mapped (JobTitle --> JobTitle & Department --> Department). Otherwise if I am using an integer index as primary key I would have then to manually rename the textual JobTitle column in the excel sheet to a number based on the generated keys from the Groups table in order to import.
Is it fine to keep my database design like this (textual compound primary key linked with textual compound foreign key)? If not, then if I used an integer column in the Groups table as primary key and the same as a foreign key in the Employees table then how can I import the employees list from excel directly to Employees table?
Is it possible to import the list from Excel to SQL Server in a way that the textual JobTitle from the excel sheet will be automatically translated to the corespondent JobTitleID from the Groups table? This would be the best solution, I can then add JobTitleID column in the Groups table as a primary key and as a foreign key in the Employees table.
Thank you,
It sounds like you are trying to make the database table design fit the import of the excel file which is not such a good idea. Forget the excel file and design your db tables first with correct primary keys and relationships. This means either int, bigint or guids for primary keys. This will keep you out of trouble unless you absolutely know the key is unique such as in a SSN. The when you import, then populate the departments and job titles into their respective tables creating their primary keys. Now that they are populated, add those keys to the excel file that can be imported into the employees table.
This is just an example of how I would solve this problem. It is not wrong to use multiple columns as the key but it will definitely keep you out of harms way if you stick with int, bigint or guids for your primary keys.
Look at the answer in this post: how-to-use-bulk-insert...
I would create a simple Stored Procedure that imports your excel data into a temporary unrestricted STAGING table and then do the INSERT into your real table by doing the corresponding table joins to get the right foreign keys and dump the rows that failed to import into an IMPORT FAIL table. Just some thoughts...

SQL Server how to maintain GUID across tables in same DB

I want to create a DB , where each table's PK will be GUID and which will be unique across the DB,
Example: my DB name is 'LOCATION'. And I have 3 table as 'CITY' , 'STATE' and 'COUNTRY'.
I want that all the 3 tables have same PK field as GUID ,and that value will be unique across DB.
How to do this in SQL Server, any idea? I have never used SQL Server before, so it will be helpful if briefly explained.
create table CITY (
ID uniqueidentifier not null primary key default newid(),
.
.
.
)
Repeat for the other tables.
What do you mean exactly ?
Just create the table, add an Id field to each table, set the data type of the Id field to 'uniqueidentifier', and you're good to go.
Next, add a primary constraint on those columns, and make sure that, when inserting a new record you assign a new guid to that column (for instance, by using the newid() function).
I can't think of any good reason to have a unique number shared by 3 tables, why not just give each table a unique index with a foreign key reference? Indexed fields are queried quicker than random numbers would be.
I would create a 'Location' table with foreign keys CityId, StateId & CountryId to link them logically.
edit:
If you are adding a unique id across the City, State and Country tables then why not just have them as fields in the same table? I would have thought that your reason for splitting them into 3 tables was to reduce duplication in the database.

Resources