Having two tables for capturing data at a specific moment - sql

I'm creating an application which will hold curriculum vitaes
the user should be able to:
create different work information for using with different CV's
Name of work, Start date, End Date, ...
CV will have many WorkInformations
Workinformation belongs to many CV's
though when a user changes workinformation outside the scope of the CV I don't want it to change within the current CV's.
Is it correct to have an extra table with the same information?
Its supposed to create a new "workinformation" from a copy of a "workinformation_that_shouldent.."
or any other approach I should look into, open for all suggestions, new to designing relational databases.

No, I don't think you should have a different workinformation table.
Instead, you should have the CV point to a work information record. When the work information record changes outside the CV world, then create a new version of the record. That way, all work information records are in the same table. The ones that CVs refer to remain the same.
You can keep track of different versions of the same record in more than one way. A simple way is to have versions refer back to the base work information record, with another field having the version number.
By the way, I find it unusual that a work information record would be referred to by multiple CVs.

Related

Access 365 - No duplicates based on a forgein key

I have an issue/problem that I'm looking for a solution for. If I find a solution for this, it could fix two issues I'm facing in a database tool I'm creating for my school's admin office.
The gist of it is, I'm looking for a way in Access 365 (or Access 2019) either through a form/query/vba... to limit data to not have duplicates. Now, of course I know that you can set the field in your table to not have duplicates. But, here is the thing, I wouldn't mind a duplicate in that column in certain cases.
So, let me explain the issue/problem by giving an example.
Image that you have two tables. One table is filled with the name of a school bus and the yearly price that the parents have to pay for it. Another table has all the stops that the school busses take.
Now, here comes the problem. I would love to have a system where I can let the user decide the order of those stops.
What I'm currently doing is, I let the user fill in a number. In another column, I have a calculated field that adds the primary key of the schoolbus table "." the number of the order.
So, that would look like this for the first school bus and the first five stops.
1.1, 1.2, 1.3, 1.4, 1.5
And I have a duplicate control that column. Since that way, I can make sure that it doesn't block the number 1 for the next bus.
Something that might work as well, if that's possible in access is that for each school bus you create, you add a column in the stops table to check for duplicates. But how do you make sure then to filter which stops belongs to which schoolbus?
I hope my issue is a bit clear. If it's not, feel free to ask.
I have a similar style problem in another part of the tool with a book fair system.
Where you have an order table where the order number, the student number, the creation and pickup dates are stored. It also has a field to lock the form to avoid any edits for the bookkeeping folks. I also have an orderline form where all the actual bought books are stored. Now, I would love it if a system exists to avoid users adding the same book twice on an order in the orderline table since I do have an amount column for that. So, in a way, it's almost similar to the above described problem.

Custom user defined database fields, what is the best solution?

To keep this as short as possible I'm going to use and example.
So let's say I have a simple database that has the following tables:
company - ( "idcompany", "name", "createdOn" )
user - ( "iduser", "idcompany", "name", "dob", "createdOn" )
event - ( "idevent", "idcompany", "name", "description", "date", "createdOn" )
Many users can be linked to a single company as well as multiple events and many events can be linked to a single company. All companies, users and events have columns as show above in common. However, what if I wanted to give my customers the ability to add custom fields to both their users and their events for any unique extra information they wish to store. These extra fields would be on a company wide basis, not on a per record basis ( so a company adding a custom field to their users would add it to all of their users not just one specific user ). The custom fields also need to be sesrchable and have the ability to be reported on, ideally automatically with some sort of report wizard. Considering the database is expected to have lots of traffic as well as lots of custom fields, what is the best solution for this?
My current research and findings in possible solutions:
To have generic placeholder columns such as "custom1", "custom2" etc.
** This is not viable as there will eventually be too many custom columns and there will be too many NULL values stored in the database
To have 3x tables per current table. eg: user, user-custom-field, user-custom-field-value. The user table being the same. The user-custom-field table containing the information about the new field such as name, data type etc. And the user-custom-field-value table containing the value for the custom field
** This one is more of a contender if it were not for its complexity and table size implications. I think it will be impossible to avoid a user-custom-field table if I want to automatically report on these fields as I will have to store the information on how to report on these fields here. However, In order to pull almost any data you would have to do a million joins on the user-custom-field-value table as well as the fact that your now storing column data as rows which in a database expected to have a lot of traffic as well as a lot of custom fields would soon cause a problem.
Create a new user and event table for each new company that is added to the system removing the company id from within those tables and instead using it in the table name ( eg user56, 56 being the company id ). Then allowing the user to trigger DB commands that add the new custom columns to the tables giving them the power to decide if it has a default value or auto increments etc.
** Everytime I have seen this solution it has always instantly been shut down by people saying it would be unmanageable as you would eventually get thousands of tables. However nobody really explains what they mean by unmanageable. Firstly as far as my understanding goes, more tables is actually more efficient and produces faster search times as the tables are much smaller. Secondly, yes I understand that making any common table changes would be difficult but all you would have to do is run a script that changes all your tables for each company. Finally I actually see benefits using this method as it would seperate company data making it impossible for one to accidentally access another's data via a potential bug, plus it would potentially give the ability to back up and restore company data individually. If someone could elaborate on why this is perceived as a bad idea It would be appreciated.
Convert fully or partially to a NoSQL database.
** Honestly I have no experience with schemaless databases and don't really know how dynamic user defined fields on a per record basis would work ( although I know it's possible ). If someone could explain the implications of the switch or differences in queries and potential benefits that would be appreciated.
Create a JSON column in each table that requires extra fields. Then add the extra fields into that JSON object.
** The issue I have with this solution is that it is nearly impossible to filter data via the custom columns. You would not be able to report on these columns and until you have received and processed them you don't really know what is in them.
Finally if anyone has a solution not mentioned above or any thoughts or disagreements on any of my notes please tell me as this is all I have been able to find or figure out for myself.
A typical solution is to have a JSON (or XML) column that contains the user-defined fields. This would be an additional column in each table.
This is the most flexible. It allows:
New fields to be created at any time.
No modification to the existing table to do so.
Supports any reasonable type of field, including types not readily available in SQL (i.e. array).
On the downside,
There is no validation of the fields.
Some databases support JSON but do not support indexes on them.
JSON is not "known" to the database for things like foreign key constraints and table definitions.

How to identify a user with a not changeable number on IBM Notes

We have a few IBM Notes databases here, at least one hundred I think, and if we have to identify a user we are using the given Name at the moment. We are also connecting this with a database of all the employees here, using it to do time-management and administrative stuff.
Therefore we need to determine which user is which, as I said we are doing that by the name at the moment. But names change, so now we would like to change to a not changing ID. I thought we could use the key identifier, or one of them at least. So my question is, is there a way to get it through Lotus Script? If not, is there another way to identify the user of a certain key-file?
Lotus Notes and Domino do not have any builtin unique key identifier for users. It was never part of the design. You can't use the noteid of the Person document because that varies from one replica of the Domino Directory to another, and you should not use the unid, because although that's stable across replicas it can still change if you have to recreate the Person document, which you might have to do if the employee leaves your company and then comes back, or if the Person document is damaged.
The way most large organizations deal with this is to set the EmployeeID field in the Person document and use that as the unique identifier. Some organizations might also create unique identifiers and use them for the ShortName.
Whilst I don't diasagree with Richards answer in general, it is possible to 'capture' a Document-ID (UNID) in a separate 'created when composed' field. This will then hold a static 'unique' 32 character reference. Once this has been set, it should not change unless you have a process to change it. A UNID is based on/derived from a time-stamp so they are extremely unlikely to be reused or clash with future system generated unids, even after many years or many millions of docs being used. This captured value may or may not agree with the actual system assigned unid, but this generally doesn't matter.
If you are unhappy with a copy of an system unid, then this could be used on a temporary basis until it can be overridden with an external ID reference. Alternatively, use a proven external 'guid' reference and assign that to the records you want to track.
If the raw unid creates side issues for you, use #password to hash it to another unique value. This generates a quick/old MD5 style hash, but good enough for reference-IDs.
One other point to mention is that keeping previous names in a list is also feasible, so that matching an 'old name' is still viable. Either create an additional field in the person doc (admins may hate you for doing this) or add older names to the 'fullname' field list. This usually contains a list of name variations. If you add the older name to the bottom of the list (ie: append) the you and the system can match against this name (for logins and routing) but Notes only ever uses the first name in the list as the users 'official' name (for reader/author fields etc), which should be the current name. To find the name, just lookup the name in the ($Users) view if using the FullName field or create a new view in using your own field (again Admins may hate you more).

Required an expert suggestion in TSQL

I have a scenarios where Table A has reference to Table B , Table B has a reference on Table C column ...etc.
To implement an update task in my project I ought to implement it in two phase logic
i.e. delete the row first and add the latest again.
But unfortunately , when I try to delete a row in table A it has reference which in turn has reference to other table and so on. Hence my logic of delete and add does not work in a proper way all the time. Even if it is deleted and added again , the sequence at which it is being added is last i.e. as a new record. Hence I am losing all the earlier references track in the same order as old one.
Hence I would like to delete a row from a table without effecting the references i.e. for time being it should allow to ignore reference , once i added it again i.e update record then i need to re-enforce/enable back the reference.
Is it possible to do in such a way ? or there any other logic works in similar fashion or replace the original intention ? could anyone please provide your expertise advice on this ?
How general logic of windows service pack works ? can any one elaborate on that? or share some info or doc or blog regarding the same?
Thank you so much.
Regards,
Shyam
What you want to do is a bad practice, I would rethink your design. It doesn't let you delete the parent record because there are child records. That is what the database ii supposed to and to try to circumvent it is a 100% guarantee of bad data.
If what you are trying to accomplish is to move the child records to a new parent, that can be done but you add the new record first and then make updates. It is best if you have some field to be able to define what old record it used to be associated with or a mapping table to use to make many changes. Then you would need to run updates for every child table. This kind of thing shoudl be a one time change, not a regular practice. It certainly shoudl virtually never happen from the application and shoudl only be done by a qualified databse developer.
If what you are trying to accomplish is to inactivate the parent so it can no longer be used for some purposes(such as creating new orders) and leave the details for reporting (wouldn't want to lose the finacials for old orders), then you should put an active flag on the table and use that to filter records instead. Often this means creating a view of only active records and pointing the code to the view insted of directly to the table.

What is the best method of logging data changes and user activity in an SQL database?

I'm starting a new application and was wondering what the best method of logging is. Some tables in the database will need to have every change recorded, and the user that made the change. Other tables may just need to have the last modified time recorded.
In previous applications I've used different methods to do this but want to hear what others have done.
I've tried the following:
Add a "modified" date-time field to the table to record the last time it was edited.
Add a secondary table just for recording changes in a primary table. Each row in the secondary table represents a changed field in the primary table. So one record update in the primary could create several records in the secondary table.
Add a table similar to no.2 but it records edits across three or fours tables, reference the table it relates to in an additional field.
what methods do you use and would recommend?
Also what is the best way to record deleted data? I never like the idea that a user can permanently delete a record from the DB, so usually I have a boolean field 'deleted' which is changed to true when its deleted, and then it'll be filtered out of all queries at model level. Any other suggestions on this?
Last one.. What is the best method for recording user activity? At the moment I have a table which records logins/logouts/password changes etc, and depending what the action is, gives it a code either 1,2, 3 etc.
Hope I haven't crammed too much into this question. thanks.
I know it's a very old question, but I'd wanted to add more detailed answer as this is the first link I got googling about db logging.
There are basically two ways to log data changes:
on application server layer
on database layer.
If you can, just use logging on server side. It is much more clear and flexible.
If you need to log on database layer you can use triggers, as #StanislavL said. But triggers can slow down your database performance and limit you to store change log in the same database.
Also, you can look at the transaction log monitoring.
For example, in PostgreSQL you can use mechanism of logical replication to stream changes in json format from your database to anywhere.
In the separate service you can receive, handle and log changes in any form and in any database (for example just put json you got to Mongo)
You can add triggers to any tracked table to olisten insert/update/delete. In the triggers just check NEW and OLD values and write them in a special table with columns
table_name
entity_id
modification_time
previous_value
new_value
user
It's hard to figure out user who makes changes but possible if you add changed_by column in the table you listen.