Hi I'm creating a notification system which consists of only 3 data inputs
1. email - to which the notification should be sent
2. the notification message - varchar
3. status - sent or not (y or N)
--Note the final goal is club all notification to be sent to an email and send it as one email by a batch job
Help me choosing which design is better
Design -1
create table Notifications(
notification_id integer auto_increment primary key,
message varchar(100) not null
);
create table Emails(
email_id integer not null auto_increment primary key,
email varchar(40) not null
);
create table Email_notifications(
email_id integer not null,
notification_id integer ,
status varchar(5) not null,
foreign key(email_id) references Emails(email_id),
foreign key(notification_id) references Notifications(notification_id),
primary key(email_id, notification_id)
);
Design-2:
create table batchnotifications(
id integer not null auto_increment primary key,
email varchar(40) not null,
message varchar(100) not null,
status varchar(5) not null default 'N'
);
Since i'm going to use JDBC in it let me know in that perspective in terms of ease of api creation.
You should use Design 1 Its better to implement.
you can use Design-2 also but if you have to send status to multiple people with different emails and notifications,then it is possible only with Design-1
Let's assume one condition :
If you have to send email with id 2 and notification with id 4 then in that case, you need two different tables for email and notification. which you are doing in Design-1.
AND
Let's assume another condition :
If you have to send unique email and notification with same id then use Design-2
Design 1 is future proof.
Design 2 is still correct with respect of normalization rules, assuming that:
you will not add later content like "Name", "Reputation", etc to the email. In that moment, usage of Design 1 is mandatory.
the relative large key of "email" is not a space/performance problem, as compared to the integer key.
The driver you use to connect (JDBC, DAO, ODBC, OLEDB or native) is irrelevant with respect of the data structure.
Related
I want to introduce a queue functionality in an existing application built on Access VBA with an SQL Server 2012 backend. It should allow the application to store open tasks with 1:n parameters in a queue table and process them later on. It deserves mentioning that for some tasks, it might take several process steps until all information needed for their processing is available.
Some more information on my current situation:
The data needs to be persisted in the database for compliance reasons
No more than 1500 tasks will be processed each day
The application will be rebuild (except for the backend), the new application will make much more heavy use of this queue functionality
The total number of different tasks to be queued, as well as the no. of parameters they might need, is unknown
My currently best approach - however in EAV schema - would consist of three tables:
1. Table "tblQueueItemType"
It contains definitions for each type (or category) of task.
It contains an id, a name and an attribute count. This attribute count defines the number of attributes for this task. I want to use it later on to ensure data consistency for all tasks with status "READY".
Example for an entry in this table:
"1", "Generate Book Database Entry", "5"
2. Table "tblQueueItemHeader"
It which represents the instantiated tasks defined in the tblQeueItemType. They have a task id, their corresponding task type defined in tblQeueItemType, a status as well as a timestamp.
The status is either OPEN (not all information available), READY (all information available to process task), and DONE (when processed).
Example for an entry in this table:
"2", "1", "OPEN"
3. Table "tblQueueItemAttribute"
It contains all the information the tasks need to be processed. It contains an id, the id of the header, an attribute type and an attribute value.
Example entries for this table:
"1","2", "Author", "H.G. Wells"
"1","2", "No. Pages", "1234"
My table definitions so far:
CREATE TABLE [dbo].[tblQueueItemType](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
Name NVARCHAR(20) NOT NULL,
AttributeCount INT NOT NULL
)
CREATE TABLE [dbo].[tblQueueItemHeader](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
QueueItemTypeId INT NOT NULL,
Status NVARCHAR(5) NOT NULL,
Timestamp DATETIME NOT NULL
CONSTRAINT QueueTypeHeader
FOREIGN KEY (QueueItemTypeId)
REFERENCES tblQueueItemType (id)
)
CREATE TABLE [dbo].[tblQueueItemAttribute](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
QueueItemHeaderId INT NOT NULL,
Attribute NVARCHAR(5) NOT NULL,
Value NVARCHAR(50) NOT NULL,
Timestamp DATETIME NOT NULL
CONSTRAINT QueueHeaderAttribute
FOREIGN KEY (QueueItemHeaderId)
REFERENCES tblQueueItemHeader (id)
)
ALTER TABLE tblQueueItemHeader
ADD CONSTRAINT QueueItemHeaderStatus
CHECK (Status IN ('OPEN', 'READY', 'DONE'));
Obviously the current design is suboptimal. What would be best schema for this kind of use-case? How feasible is my current approach?
Thank you very much!
I am writing an application in which application users can add friends with whom they can later share things inside the app. The thing is that they can add friends who are already using the application (easy case) but they can also add people who are not yet using the application but might start doing it one day (the tricky part). In the latter case they can simply add a record in the app and then share it via email but the record still needs to be stored in a database. An important thing to mention is that whenever a user adds a record for a friend a record is added for him/her as well (because they are sharing stuff I need to add information about user's part as well).
If friends could only be application users, then I would simply have a User table and a junction table defining the many-to-many relationship between users. Then, the record table could look somewhat like this:
CREATE TABLE IF NOT EXISTS Record (
record_id INT NOT NULL, -- primary key
record_col VARCHAR(45) NULL, -- some column describing the record
added_by_id VARCHAR(45) NOT NULL, -- references user_id from the User table
added_for_id VARCHAR(45) NOT NULL -- references user_id from the User table
);
However, since one can add friends who are not application users and can then add records for them I think I need an additional table to store information about friends:
CREATE TABLE IF NOT EXISTS Friend (
friend_id INT NOT NULL, -- primary key
friend_col VARCHAR(45) NULL, -- some column describing the friend
friend_of_user_id VARCHAR(45) NOT NULL, -- id of the user who added this friend
is_user BIT(1) NOT NULL, -- boolean indicating if this friend has already created an account
friend_user_id INT NULL -- if above is true, user_id of this friend would go here
);
But then how do I handle this in the Record table? I could have some records added for application users and some for non-users so for some of them the foreign key would reference user_id and for the rest friend_id. This doesn't seem right to me...
I could also try putting everyone (both application users and non-users) in a single table but then for the same physical person (let it be John Smith) I would have potentially multiple records added by different people who are friends with John and a record representing the actual John Smith being application user. This seems nasty.
What am I missing here? This doesn't seem like an unusual thing to do and yet I cannot figure out a proper solution.
Is the following DB-schema ok?
REQUEST-TABLE
REQUEST-ID | TYPE | META-1 | META-2 |
This table stores all the requests each of which has a unique REQUEST-ID. The TYPE is either A, B or C. This will tell us which table contains the specific request parameters. Other than that we have the tables for the respective types. These tables store the parameters for the respective requests. META-1 are just some additional info like timestamps and stuff.
TYPE-A-TABLE
REQUEST-ID | PARAM_X | PARAM_Y | PARAM_Z
TYPE-B-TABLE
REQUEST-ID | PARAM_I | PARAM_J
TYPE-C-TABLE
REQUEST-ID | PARAM_L | PARAM_M | PARAM_N | PARAM_O | PARAM_P | PARAM_Q
The REQUEST-ID is the foreign key into the REQUEST-TABLE.
Is this design normal/best-practice? Or is there a better/smarter way? What are the alternatives?
It somehow feels strange to me, having to do a query on the REQUEST-TABLE to find out which TYPE-TABLE contains the information I need, to then do the actual query I'm interested in.
For instance imagine a method which given an ID should retrieve the parameters. This method would need to do 2 db-access.
- Find correct table to query
- Query table to get the parameters
Note: In reality we have like 10 types of requests, i.e. 10 TYPE tables. Moreover there are many entries in each of the tables.
Meta-Note: I find it hard to come up with a proper title for this question (one that is not overly broad). Please feel free to make suggestions or edit the title.
For exclusive types, you just need to make sure rows in one type table can't reference rows in any other type table.
create table requests (
request_id integer primary key,
request_type char(1) not null
-- You could also use a table to constrain valid types.
check (request_type in ('A', 'B', 'C', 'D')),
meta_1 char(1) not null,
meta_2 char(1) not null,
-- Foreign key constraints don't reference request_id alone. If they
-- did, they might reference the wrong type.
unique (request_id, request_type)
);
You need that apparently redundant unique constraint so the pair of columns can be the target of a foreign key constraint.
create table type_a (
request_id integer not null,
request_type char(1) not null default 'A'
check (request_type = 'A'),
primary key (request_id),
foreign key (request_id, request_type)
references requests (request_id, request_type) on delete cascade,
param_x char(1) not null,
param_y char(1) not null,
param_z char(1) not null
);
The check() constraint guarantees that only 'A' can be stored in the request_type column. The foreign key constraint guarantees that each row will reference an 'A' row in the table "requests". Other type tables are similar.
create table type_b (
request_id integer not null,
request_type char(1) not null default 'B'
check (request_type = 'B'),
primary key (request_id),
foreign key (request_id, request_type)
references requests (request_id, request_type) on delete cascade,
param_i char(1) not null,
param_j char(1) not null
);
Repeat for each type table.
I usually create one updatable view for each type. The views join the table "requests" with one type table. Application code uses the views instead of the base tables. When I do that, it usually makes sense to revoke privileges on the base tables. (Not shown.)
If you don't know which type something is, then there's no alternative to running one query to get the type, and another query to select or update.
select request_type from requests where request_id = 42;
-- Say it returns 'A'. I'd use the view type_a_only.
update type_a_only
set param_x = '!' where request_id = 42;
In my own work, it's pretty rare to not know the type, but it does happen sometimes.
The phrase you may be looking for is "how do I model inheritance in a relational schema". It's been asked before. Whilst this is a reference to object oriented software design, the basic question is the same: how do I deal with data where there is a "x is a type of y" relationship.
In your case, "request" is the abstract class, and typeA, TypeB etc. are the subclasses.
Your solution is one of the classic answers - "table per subclass". It's clean and easy to maintain, but does mean you can have multiple database access requests to retrieve the data.
Based on Constraint for only one record marked as default would the same approach of a view and unique clustered index apply if I wanted to achieve the same result at a table scope?
I have a table called Accounts. There can be only one System account, however there can be many Partner and Client accounts. Each type of account does not vary in terms of the columns but instead with just the Type column.
ID | Type | Name
1 System Contoso
2 Partner Wingtip
3 Partner Northwind
4 Client Adventure Works
5 Client Fabrikam
In the above I want to prevent adding another System account, but allow many partner and client accounts. It feels like a concern that belongs in the database as opposed to the domain (maybe I'm wrong)?
If you know that the system account will always have ID number 1, you can implement this with a CHECK constraint. Something along these lines . . .
create table accounts (
id integer primary key,
type varchar(15) not null,
name varchar(15) not null,
unique (type, name),
check (
(id = 1 and type = 'System') or
(id <> 1 and type <> 'System')
)
);
In fact, if this is your database, the system account can have any id number. Just change the CHECK() constraint to match.
If you're building for deployment to a client site, you can add the system account before deployment. (And you probably should, regardless of how you handle the constraints.)
Think about about what to do when a user tries to delete rows from this table. (Especially that system account row.) Then think about what to do when a database admin tries to delete rows from that table.
You can probably use a foreign key constraint (no cascade) or a trigger to prevent a database admin from accidentally deleting the system account. The admin can probably get around those restrictions, but you'd hope she knows what she's doing if she's willing to go that far to delete a row.
I am creating a communication module with email and onsite messaging. 4 questions:
1) When storing the messages, it can belong to folders (Spam, trash, inbox, outbox, etc). Are these separate tables or 1 table with just a column for "folder" which is FK to a "folder lookup table"?
2) Like on hotmail, a user can create x number of custom folders so how to represent that in the data model? I can say inbox = id 1, outbox = id 2, etc but for the custom folders like "vacation email", "work email", etc i am not sure how to show that in the Data model if a message resides in that folder.
3) One email goes to multiple people. Does this mean i need to have 1 row per user sent to?
4) Lastly, messages have attachments. i assume that means a separate attachments table which FK links to which ever table (s) are used for storing messages?
1&2: Folders need to be an entity, relationship MessageFolder one to many to Message
3: MessageUser entity with UserID, MessageID, Type (Sender,Recipient)
4: Seperate table for attachments (MessageAttachments).
CREATE TABLE `message`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`author` INTEGER NOT NULL,
`contents` TEXT NOT NULL,
`subject` TEXT NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `messagefolder`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`id_message` INTEGER NOT NULL,
`id_folder` INTEGER NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `folder`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `messageattachment`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`fk_message` INTEGER NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `messageuser`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`fk_message` INTEGER NOT NULL,
`type` INTEGER NOT NULL,
PRIMARY KEY (`id`)
);;
ALTER TABLE `message` ADD FOREIGN KEY (author) REFERENCES `user` (`id`);
ALTER TABLE `messagefolder` ADD FOREIGN KEY (id_message) REFERENCES `message` (`id`);
ALTER TABLE `messagefolder` ADD FOREIGN KEY (id_folder) REFERENCES `folder` (`id`);
ALTER TABLE `messageattachment` ADD FOREIGN KEY (fk_message) REFERENCES `message` (`id`);
ALTER TABLE `messageuser` ADD FOREIGN KEY (fk_message) REFERENCES `message` (`id`);
1) When storing the messages, it can belong to folders (Spam, trash,
inbox, outbox, etc). Are these separate tables or 1 table with just a
column for "folder" which is FK to a "folder lookup table"?
One folder can have many messages. If a message can reside in one folder only, then the relations is one (folder) to many (messages), so yes to the 2nd choice.
First choice is leads to a not normalized database.
2) Like on hotmail, a user can create x number of custom folders so
how to represent that in the data model? I can say inbox = id 1,
outbox = id 2, etc but for the custom folders like "vacation email",
"work email", etc i am not sure how to show that in the Data model if
a message resides in that folder.
Standars folders could be like like you said ... , sent = id 3, spam = id 4, trash = id 5.
After that, any custom folder will have: vacation mail = id 6, etc...
No need for any change in the Data model.
3) One email goes to multiple people. Does this mean i need to have 1
row per user sent to?
One email, many recipients. So, yes, if you have a table for email-recipients relationship.
4) Lastly, messages have attachments. i assume that means a separate
attachments table which FK links to which ever table (s) are used for
storing messages?
Yes, like answer 3. (one email, many attachments).
If however, an attachment can be in many emails (like if one forwards an email and the attachment), and you want that in your model, the relationship will be many-to-many.