I have table named 'Dictionary' with columns as follow:
ID bigint
TYPE varchar (200)
ITEM varchar (200)
Table is used by various tables as simple dictionary / lookup.
Eg it stores countries, titles, business type lists.
TYPE column keeps info about type of dictionary , ITEM is dictionary string value.
All works well but I have problem to set up relationship between dictionary and foreigin tables.
When I'm using 'Foreign Key Relationship' I can not make it depended of 'TYPE" column.
(Please note same item with same type - eg 'countries' can be linked to several tables, when item with another type can be linked to different)
Currently I'm using USPs to manage that but I'd like to switch to standard relationship mechanism.
Any advice how to get that?
It looks to me that you could consider an alternative design
Dictionary table
ID (pk)
DICTIONARY_TYPE_ID (fk to dictionaryType)
ITEM
DictionaryType table
ID (pk)
DESCRIPTION
and then make links to the ID of DictionaryType table in places where you currently want to reference Type field from your original design
From the context of the question, I'm guessing you'll need to do one of two things:
Make your Type column the primary key
or have the foreign keys depend on the ID field here.
Foreign keys need to refer to a primary key, and it looks like your Type column isn't a PK.
what you have here is an EAV db design which is bad for number of reasons one being your problem. there is no solution for this in the real sense. you might try using sql_variant as a column type for the item and try to to a PK-FK relationship on that.
there's another way you could try to do this with the xml datatype and schemas like i describe here. however you'll have to test this to see if it applies to your problem.
Related
In SQL I have a table setup
RegisterTable
----
DocId int
status int
docType int
CarDocument Table
----
carDocId int (PK, FK -> RegisterTable)
name string
carMake varchar
EmployeeDocument
----
emplyeeDocId int (PK, FK -> RegisterTable)
name varchar
age int
This is a database about documents. Tables design have no relevance to the question.
So I have different documents Cars/Emplyees/etc... -- they all have completely different set of fields, unrelated.
I need to have metadata for these documents, which is represented in RegisterTable. This metadata is similar across documents. So it's a bit like inheritance.
Which is the DB design for this case? Currently I made three separate tables and created one-to-one relation from CarDocument/EmployeeDpcument to RegisterTable.
When I create a document, I first create it's metadata in RegisterTable, then I take the key and use it to create a document in corresponding CarDocument or EmployeeDocument table.
This works but looks cumbersome to me.
Extra info: I have 10-20 different document tables.
I use typeorm as my ORM solution.
Research:
Has similarities with Table has one to one relationship with many tables
My design works but RegisterTable is kinda fake since it holds all the docIds.
Which is the best DB design for this case?
Postgres actually does inheritance - see https://www.postgresql.org/docs/current/tutorial-inheritance.html
Aside from that, if you have metadata that is always the same across various types of documents, your approach to have a metadata table with a relation to the document tables is the right one, in principle (see below).
The metadata table itself does not need to know about the tables that reference it. Your query logic can derive the correct secondary document from the docType and the docId.
For your specific case, as you've posted it above, if a single "status" field is the only actual metadata you hold in that table, I think you would be better off to simply add that field to the document tables. Only if you have a fixed set of metadata that you don't want to replicate over many different tables does it make sense to split it into its own table.
I see nothing wrong with your design. One key point, anyway, is deciding if you'll share the IDs for all your entities/tables (as you're doing) or have separate IDs. The second choice may be the more tidy and flexible. You'll have something like this:
RegisterTable
----
docId int
status int
docType int
CarDocument
----
carDocId int (PK)
docId int (FK-> RegisterTable)
name string
carMake varchar
EmployeeDocument
----
emplyeeDocId int (PK)
docId int (FK-> RegisterTable)
name varchar
age int
Of course, you can also have just ONE big table with a lot of fields, filling each field (or not) depending on the docType, and maybe with different semantics for each different docType (no, I'm joking, don't do that).
There's a more flexible and scalable approach that can be used.
A single table would store all document metadata and then another separate table for each document type that stores specific details for that type of doc.
RegisterTable can be renamed to DocumentMetadata and contains DocId, status, docType etc.
CarDocument and EmployeeDocument tables contain columns that are specific to each type such as carMake and age.
Can bind the tables via Foreign Key from DocumentMetadata table to document-specific tables
It's not only more flexible because you can keep adding new types of docs, but also avoids creation of a meaningless table that doesn't have any real info (RegisterTable)
Need to identify the best way to contemplate this scenario :
The User can enter the system which fields he wants and what type of field
Example:
ID;Key;Type;
01;Name;Varchar;
02;Date;DateTime;
03;Gender;byte;
Then a 'tbRegister' table must store the information of the document registered by the user using the fields that it created.
Exemple:
Guid;DocumentID;Fild_Name;Fild_Date;Fild_Gender;CreateOn; CreateBy;
das215sa-15d1a-2d56as1;1;João;21/01/2001;1;30/11/2013 10:00:00; msantiago;
I also see a relationship between these tables. Something like:
FildByDocument:
idFild;DocumentID;
01;1;
02;1;
03;1;
01;2;
How would this in practice?
Like to meet a good structure. For such systems may contain very different types of documents
Got an exact example of what I wanted:
Thank you
I would do something like
Table_One_User
User_ID;INT; IDENTITY(1,1); --<-- Primary Key
01;Name;Varchar;
02;Date;DateTime;
03;Gender;byte;
Table_Two_File
DocumentID; --<-- Use INT not GUID (GUID is Not a good choice for Primary Key)
Fild_Name;
Fild_Date;
CreateOn;
CreateBy; Foreign Key --<-- Referencing to User_ID column in Table_One
-- You dont need to record Gender here you have
-- this information in Table one
Let's say I have an entity CLIENT, which can be either PERSON or ORGANIZATION. Depending on which type it is, I have to choose attributes (address, name for organization, date_of_birth,first_name,last_name for person). I have created all three entities, but how can I make the attributes type-dependent?
Seen Database design: objects with different attributes, didn't help...
One typical choice is a 1:1 extension table:
create table client (id int primary key);
create table person (id int foreign key references client(id), ...columns...);
create table organization (id int foreign key references client(id), ...columns...);
However, my preferred choice is to include all columns in the client table. You can have a column for type that is either person or organization. Columns that are not relevant for the row's type can be null. Your queries will be much simpler that way.
Either you use 3 tables or you use 1 table and leave the not needed columns null. Which design is superior depends on the use case. Using only 1 table gives simpler queries but requires to change the table for each new subclass. Using multiple tables allows to add more types easily but gives more complicated queries. In doubt I would start with only 1 table but your mileage may vary.
How do I store custom values in place of data types for the column.
I have a Table named as 'Orders' in which a column named as 'OrderStatus' and it's purpose will be to store the Status of the Order. For example R=Rejected, S=Sent, T=Returned.
I am very new to databases and design...
The 'correct' answer is to use Standard SQL-92's CREATE DOMAIN. Sadly, SQL Server doesn't support it yet. If you would like to see support you can vote for it here.
SQL Server has its own CREATE TYPE syntax but when I last looked I declared them not fit for purpose. If anyone disagrees, please post an answer to my question :)
This leaves two viable choices: a table with a foreign keys or CHECK constraints. The rule of thumb is that if the set of domain values is small and stable (e.g. the ISO 5218 sex codes) then use CHECK constraints, otherwise prefer a table with foreign keys.
In this case you don't really need a custom data type, you just need a foreign key to a table with all of your statuses in it.
Your OrderStatus table would look like:
id int PK NOT NULL, IDENTITY
code char(1) NOT NULL
description varchar(100) NOT NULL
(edit: note, as Martin pointed out in a comment on another answer, the surrogate id key isn't entirely necessary, but it allows flexibility for easily changing the code without having to update the data that refers to it)
Your Order table would then have a foreign key to this table:
order_status_id int FK NOT NULL
You can do that.
OrderStatus OrderStatusCode
----------- ---------------
Rejected R
Sent S
Returned T
Later, when you've got more 'design' under your belt, you go with a lookup table.
Best practice is to normalize, which means creating a table called ORDER_STATUS with the approved values in there, minimally with a schema like:
ORDER_STATUS(id number auto increment, code character, meaning varchar)
and then relate ORDERS to that table in a column called order_status_id, which would be a foreign key that would not be null.
I'm defining a database for a customer/ order system where there are two highly distinct types of customers. Because they are so different having a single customer table would be very ugly (it'd be full of null columns as they are pointless for one type).
Their orders though are in the same format. Is it possible to have a CustomerId column in my Order table which has a foreign key to both the Customer Types? I have set it up in SQL server and it's given me no problems creating the relationships, but I'm yet to try inserting any data.
Also, I'm planning on using nHibernate as the ORM, could there be any problems introduced by doing the relationships like this?
No, you can't have a single field as a foreign key to two different tables. How would you tell where to look for the key?
You would at least need a field that tells what kind of user it is, or two separate foreign keys.
You could also put the information that is common for all users in one table and have separate tables for the information that is specific for the user types, so that you have a single table with user id as primary key.
A foreign key can only reference a single primary key, so no. However, you could use a bridge table:
CustomerA <---- CustomerA_Orders ----> Order
CustomerB <---- CustomerB_Orders ----> Order
So Order doesn't even have a foreign key; whether this is desirable, though...
I inherited a SQL Server database where this was done (a single column used in four foreign key relationships with four unrelated tables), so yes, it's possible. My predecessor is gone, though, so I can't ask why he thought it was a good idea.
He used a GUID column ("uniqueidentifier" type) to avoid the ambiguity problem, and he turned off constraint checking on the foreign keys, since it's guaranteed that only one will match. But I can think of lots of reasons that you shouldn't, and I haven't thought of any reasons you should.
Yours does sound like the classical "specialization" problem, typically solved by creating a parent table with the shared customer data, then two child tables that contain the data unique to each class of customer. Your foreign key would then be against the parent customer table, and your determination of which type of customer would be based on which child table had a matching entry.
You can create a foreign key referencing multiple tables. This feature is to allow vertical partioining of your table and still maintain referential integrity. In your case however, this is not applicable.
Your best bet would be to have a CustomerType table with possible columns - CustomerTypeID, CustomerID, where CustomerID is the PK and then refernce your OrderID table to CustomerID.
Raj
I know this is a very old question; however if other people are finding this question through the googles, and you don't mind adding some columns to your table, a technique I've used (using the original question as a hypothetical problem to solve) is:
Add a [CustomerType] column. The purpose of storing a value here is to indicate which table holds the PK for your (assumed) [CustomerId] FK column. Optional - addition of a check constraint (to ensure CustomerType is in CustomerA or CustomerB) will help you sleep better at night.
Add a computed column for each [CustomerType], eg:
[CustomerTypeAId] as case when [CustomerType] = 'CustomerA' then [CustomerId] end persisted
[CustomerTypeBId] as case when [CustomerType] = 'CustomerB' then [CustomerId] end persisted
Add your foreign keys to the calculated (and persisted) columns.
Caveat: I'm primarily in a MSSQL environment; so I don't know how well this translates to other DBMS (ie: Postgres, ORACLE, etc).
As noted, if the key is, say, 12345, how would you know which table to look it up in? You could, I suppose, do something to insure that the key values for the two tables never overlapped, but this is too ugly and painful to contemplate. You could have a second field that says which customer type it is. But if you're going to have two fields, why not have one field for customer type 1 id and another for customer type 2 id.
Without knowing more about your app, my first thought is that you really should have a general customer table with the data that is common to both, and then have two additional tables with the data specific to each customer type. I would think that there must be a lot of data common to the two -- basic stuff like name and address and customer number at the least -- and repeating columns across tables sucks big time. The additional tables could then refer back to the base table. As there is then a single key for the base table, the issue of foreign keys having to know which table to refer to evaporates.
Two distinct types of customer is a classic case of types and subtypes or, if you prefer, classes and subclasses. Here is an answer from another question.
Essentially, the class-table-inheritance technique is like Arnand's answer. The use of the shared-primary-key technique is what allows you to get around the problems created by two types of foreign key in one column. The foreign key will be customer-id. That will identify one row in the customer table, and also one row in the appropriate kind of customer type table, as the case may be.
Create a "customer" table include all the columns that have same data for both types of customer.
Than create table "customer_a" and "customer_b"
Use "customer_id" from "consumer" table as foreign key in "customer_a" and "customer_b"
customer
|
---------------------------------
| |
cusomter_a customer_b