I would like to ask a for an advice for a good database design to log user activity.
Currently I am implementing such approach for a simple website where user can post/edit/delete an article on the website.
Table Logbook
- log_id
- log_change[Enum: new/edit/remove]
- log_date
- member_id
- post_id
Table Post
- post_id
- post_title
- etc....
Table Member
- member_id
- member_username
- member_pwd
- etc..
Using this table, everytime user makes a new post (or edit/remove) of an article it will be logged on the Logbook (along with the time when it happens).
However, what if I am dealing with a larger system where not only user can post an article but do other things such as login/logout (from the system), make a purchase (transaction).
Should I go for different table for each module?. For example, if the system has modules like Posting article, E-commerce, etc.. hence I would have log tables for:
Article Log
E-Commerce Log
Where each table will log activity in each corresponding module.
You could use an entity sub-typing design approach, where common log attributes, like who and when are tracked in a single table for all types of changes. For changes that have additional attributes you can have additional tables, one for each type.
Each of the sub-type log tables reference the common table using a foreign key. Typically the foreign key from the sub-type table to the common table is also the primary key of the sub-type table, i.e. the relationship is 1:1.
In such a design, the common table often includes a column (partitioning attribute) which indicates which sub-type is applicable to each record in the common table.
This approach reduces the amount of code you need to build and maintain your logging system while allowing you to keep your log tables normalized.
Related
Folks,
Quick Version:
How should I model HUBs, SATs and LINKs when I have multiple domain lookup references in my HUB_SAT?
If you are were to generically model these from the source schema, how would you differentiate between FKs that should be LINKs and FKs that should be References?
Long Version:
I am building out a generic solution for generating DV models from an existing 3NF MSSQL schema. In my source database I have one huge Domain reference table which holds the majority of the business lookup keys
Key INT (Unique)
TypeID INT
Description VARCHAR
Posting Code
... some other fields that are not relevant to the discussion
As I see it there are four basic choices for linking to this table
Create it as a HUB and then produce LINK tables for each business HUB that refers to it
Create it as a single ReferenceLookup table and include the R_ReferenceIDs in the SAT table
Create a separate ReferenceLookup table for each TypeID and link from the SAT using the R_ReferenceID
Create Separate HUBs for each TypeID and generate LINK tables
Create a single LINK table with a LINK_SAT table to hold details of which reference value is mapped by the LINK
and of these #3 feels like the best design (but also the hardest to model correctly - especially as in my case the lookup table has a FK to the Type table)
From the Wikipedia for DataVault,
Reference tables are referenced from Satellites, but never bound with physical foreign keys.
My generic code is based on the design pattern as explained in the BIML DataVault walkthrough
I am looking at all tables in the source schema to determine whether they are a HUB (Have PK and multiple FKs plus fields that are not FKs), SAT (Have PK and only one FK) or LINK (Have PK, more than one FK and all fields are in PK/FK)
I then build:
HUBs with the a HUB_ID and the source PK
SATs with the non FK fields of the HUB source table
SATs for the source SAT tables
LINKs from the source LINK tables
LINKs from the HUB FK relationships
This is all working up to a point (i.e. I have tables for all of the above) however there are some pretty wide tables where a significant number of the fields are simply R_RefID fields all looking up on the same HUB and they are all bound with FKs on the entity table referencing the reference table
E.G. source Asset table has reference fields for
- Asset Type
- Asset Purpose
- Asset Manager
- Asset Funder
- ...
so in the preliminary model I have:
ASSET_HUB (HubID, Asset_ID)
ASSET_SAT (SAT_ID, BuildDate, DisposalDate, ....)
Lookup_HUB (Hub_ID, LookupID)
ASSET_Lookup_1_LINK) (Link_ID,ASSET_HUB_ID,Lookup_HUB_ID)
ASSET_Lookup_2_LINK) (Link_ID,ASSET_HUB_ID,Lookup_HUB_ID)
ASSET_Lookup_3_LINK) (Link_ID,ASSET_HUB_ID,Lookup_HUB_ID)
ASSET_Lookup_4_LINK) (Link_ID,ASSET_HUB_ID,Lookup_HUB_ID)
but there is no way of identifying what each of the LINK tables respresents in the domain model
How would you go about interrogating the schema to determine whether the table is a genuine HUB candidate or whether it should be a REF table instead and how would you determine whether an FK should be treated as a LINK or a SAT.R_RefID. I am after strategy rather than code (but I ;m not going to turn down code if it is on offer :) ) My source DB is SQL2008R2 and my development environment i SQL2016_Dev
In Response to tobi6:
In the source system The business entity has a number of attribute fields which are just XXX_ID types that look up their descriptors from the domain reference table. If you model this domain reference table as a HUB then you either have to have separate link tables for each lookup (LINK tables are automatically generated because there is an FK on the business entity), or multiple active LINK records with a LINK_SAT to identify which attribute you are tracking (actually this creates a 5th design pattern option). If I tag the domain reference table as a REFerence then the XXX_IDs stay in the HUB_SAT which feels like a better solution but is harder to model generically. I.e. how do I determine whether the business entity FK should create a LINK, LINK and LINK_SAT or SAT.R_RefID
I'm creating a rather large APEX application which allows managers to go in and record statistics for associates in the company. Currently we have a database in oracle with data from AD which hold all the associates information. Name, Manager, Employee ID, etc.
Now I'm responsible for creating and modeling a table that will house all their stats for each employee. The table I have created has over 90+ columns in it. Some contain data such as:
Documents Processed
Calls Received
Amount of Doc 1 Processed
Amount of Doc 2 Processed
and the list goes on for well over 90 attributes. So here is my question:
When creating this table in my application with so many different columns how would I go about choosing a primary key that's appropriate? Should I link it to our employee table using the employees identification which is unique (each have a associate number)?
Secondly, how can I create these tables (and possibly form) to allow me to associate the statistic I am entering for an individual to the actual individual?
I have ordered two books from amazon on data modeling since I am new to APEX and DBA design. Not a fresh chicken, but new enough to need some guidance. An additional problem I am running into is that each form can have only 60 fields to it. So I had thought about creating tables for different functions out of my 90+ I have.
Thanks
4.2 allows for 200 items per page.
oracle apex component limits
A couple of questions come to mind:
Are you sure that the employee Ids are not recyclable? If these ids are unique and not recycled.. you've found yourself a good primary key.
What do you plan on doing when you decide to add a new metric? Seems like you might have to add a new column to your rather large and likely not normalized table.
I'd recommend a vertical table for your metrics.. you can use oracle's pivot function to make your data appear more like a horizontal table.
If you went this route you would store your employee Id in one column, your metric key in another, and value...
I'd recommend that you create a metric table consisting of a primary key, a metric label, an active indicator, creation timestamp, creation user id, modified timestamp, modified user id.
This metric table will allow you to add new metrics, change the name of the metric, deactivate a metric, and determine who changed what and when.
This would be a much more flexible approach in my opinion. You may also want to think about audit logs.
I started building a database to manage things like vehicles, finances, bills, work history, residence history....etc.
I'm mostly doing this as a learning exercise to teach myself different methods of schema design and ground up development. I've been a database developer for 4 years, but I've only ever worked on the same system/schema. Even my ground up development of new features still have to abide by the existing Schema.
Anyways, I have tables for things like Vehicle Registration, Vehicle Loans/Purchases, Bills, etc. But rather than storing their billing info (payment amount, occurrence, etc), I thought maybe I could put a GUID column on every table, and then store the billing info by the GUID, and then have some sort of view or function that lets me look up the object_id (table) for a particular GUID.
Is this design method a good way to do things?
How would I go about designing the function/view to return the objectid / tablename for specific GUID's?
EDIT: I guess this is a poor explanation, so here's a quick example:
Table: VehicleRegistration
This table would have information like license plate, when the registration is good for, etc.
Table: VehicleLoan
This table would have loan information about each vehicle (amount financed, term, apr, date of purchase, etc).
Both of those tables would also have information like Billing Date, Occurence, Estimated Amount, etc. But instead of storing that data in the two tables, I would store it in another table called BillingInfo or something like that. Obviously I could add a FK on the two tables that point to the PK on the BillingInfo table. But that would mean every table that requires billing information would require that FK on it. Rather than creating that FK on every table...what if instead, every row in VehicleRegistration and VehicleLoan had a unique ID. And I would store the billing info by unique ID instead.
And since it's unque across tables, I would have a function or view to tell me which table that GUID is in. (keep in mind, this is a very small personal database, so for now, speed and optimization is not a concern).
If I applied this method to all common info, like billing information, then I could avoid having to put a FK on every table that needs it. I could just create the table and use the Unique ID's instead?
As a personal project, I essentially want to create a web application that allows users to submit amplifier settings for specific tones, which will render images and create an archive of guitar tones for specific amps.
I know that I first should design a database to support this web application. After reading about relational databases and normalization, I have started to draft a database, but I've confused myself in the process.
So far, I've created the following tables:
tbl_Makes (list of amplifier brands):
tbl_Models (list of amplifier models, linked to their brand by the MakeID field):
But I am at a bit of a loss on how to design the remaining table(s). I assume I will need a tbl_Settings table which contains both MakeID, and ModelID as foreign keys, but also some sort of column(s) to hold the amplifier settings. The issue I'm currently facing is that most amplifiers have different settings, so I'm not sure how I'd handle that. Would I need an additional table for each amplifier model to hold its specific settings?
Any suggestions? Is my current database design ok, or does it need to be modified?
You may be breaking it down too far. A table with Make and Model may be good enough. However with your current design, you would make the MakeID a Foreign Key to the Make table's Primary Key (ID).
Then you'd have an "settings" table which has a ModelID, attribute, and value - since each AMP may have different attributes. You may want to have an attribute table and use attributeID if you want to control the attribute types (with a PK and FK relationship).
Oh, and for the love of God, please don't prefix tables with tbl_
I am building a database as a simple exercise, it could be hosted on any database server, so I am trying to keep things as much standard as possible. Basically what I would like to do is a 'code' table that get referenced by other entities. I explain:
xcode
id code
r role
p property
code
r admin
r staff
p title
....
then I would like to have some view like:
role (select * from code where xcode='r')
r admin
r staff
property (select * from code where xcode='p')
p title
then, suppose we have an entity
myentity
id - 1
role - admin (foreign key to role)
title - title (foreign key to property)
Obviously I cannot create foreign key to a view, but this is to tell the idea I have in mind. How can I reflect such behaviour using whenever possible, standard sql syntax, then as a second option, database additional features like trigger ecc... ?
Because if I tell that role and title in myentity are foreign key to 'code', instead of the views, nothing would stop me to insert a role in title field.
I have worked on systems with a single table for all codes and others with one table per code. I definitely prefer the latter approach.
The advantages of a table per code are:
Foreign keys. As you have already spotted it is not possible to enforce compliance to permitted values through foreign keys with a single table. Using check constraints is an alternative approach but it has a higher maintenance cost.
Performance. Code lookups are not normally a performance bottle neck, but it undoubtedly helps the optimizer to make sensible decisions about execution paths if it knows it is retrieving records from a table with four rows rather than four hundred.
Code groups. Sometimes we want to organise a code into sub-divisions, usually to make it easier to render complex lists of values. If we have a table per code we have more flexibility when it comes to structure.
In addition I notice that you want to be able to deploy "on any database server". In that case avoid triggers. Triggers are usually bad news in most scenarios, but they have product-specific syntax.
What you are trying to do is in most cases an anti pattern and design mistake. Just create the different tables instead of views.
There are some rare cases where this kind of design makes sense. In this kind include the xcode field in the primary key/ foreign key. So your entity will look like this:
myentity
id - 1
role_xcode
role - admin (foreign key to role)
title_xcode
title - title (foreign key to property)
You then can create check constraints to enforce role_xcode='r' and title_xcode='p'
(sorry I don't know if they are standard, they do exist in oracle and are so simple that I'd expect them on other rdbms's as well)