MySQL - Storing Default Values for System - mysql

I have a few tables storing their corresponding records for my system. For example, there could be a table called templates and logos. But for each table, one of the rows will be a default in the system. I would have normally added a is_default column for each table, but all of the rows except for 1 would have been 0.
Another colleague of mine sees another route, in which there is a system_defaults table. And that table has a column for each table. For example, this table would have a template_id column and a logo_id column. Then that column stores the corresponding default.
Is one way more correct than the other generally? The first way, there are many columns with the same value, except for 1. And the second, I suppose I just have to do a join to get the details, and the table grows sideways whenever I add a new table that has a default.

The solutions mainly differ in the ways to make sure that no more than one default value is assigned for each table.
is_default solution: Here it may happen that more than one record of a table has the value 1. It depends on the SQL dialect of your database whether this can be excluded by a constraint. As far as I understand MySQL, this kind of constraint can't be expressed there.
Separate table solution: Here you can easily make sure by your table design that at most one default is present per table. By assigning not null constraints, you can also force defaults for specific tables, or not. When you introduce a new table, you are extending your database (and the software working on it) anyway, so the additional attribute on the default table won't hurt.
A middle course might be the following: Have a table
Defaults
id
table_name
row_id
with one record per table, identified by the table name. Technically, the problem of more than one default per table may also occur here. But if you only insert records into this table when a new table gets introduced, then your operative software will only need to perform updates on this table, never inserts. You can easily check this via code inspection.

Related

Convert Access table to SharePoint list with auto increment ID starting from the same number

I need to move a table from within an ms access database to a SharePoint list. The table I need to move has had old records removed that has ID's auto increment. I need the SharePoint list to start from the same auto increment number as in the table.
I have tried using the ms access export to SharePoint list functionality but when I re-import the table back into access as a linked table to a SharePoint list the ID has started back at 1 (not 81 like in the table I uploaded to SharePoint).
I need the table to upload to the SharePoint list with the auto increment ID starting at 81 as it is in the table initially.
I understand Albert's logic, but somewhat disagree. I worked with one client that had been using an original Auto-numbered field as the Customer's ID in their access database for years, so their work orders, invoices, etc..., all have the Customer's ID there. If you use the newly-created autonumber field, then all customer id's would change to new numbers. Worse yet, if you use a 2nd, non-autonumber field as Albert recommends, then anytime you add a new customer, you would need to use a sql statement (or query) to determine the last used number from this 2nd field and increment it 1 so that it is unique. Kind of a pain.
So, the workaround is still a pain, but for a solution that does what you actually asked, you can do this. Create a new list in SharePoint with an auto-numbered field. link that list in the access database. then, look at the highest ID number (eg highest customer id) from the table with your original data... because you need to create that many rows in the SharePoint list. You can either create code to loop through creating x number of records, or if you're not comfortable with that, create an excel sheet with that many rows. then, import that excel file into the linked table. next, create a delete query which deletes all records in the linked table that doesn't have the matching ID (eg customer ID) in your access table. this leaves you with a linked list with only the IDs you are using, and it's still auto-numbering so new records are automatically assigned new numbers.
Like I said, it's a bit of a work-around. But this actually does what you are asking for, instead of being forced into a different solution.
If the column in question is a autonumber column, then during a upload or migration then those autonumbers can change. Since such numbers have NO meaning, then this should not matter. If you have several related tables then you MUST ensure that your relations are setup correctly before you move the data to sharepoint (because SharePooint will re-number these values, then the child tables and FK keys ALSO will be correctly updated). However, if you don't set the relationships, then you WILL break the related data since SharePoint does and can and will re-number the PK's used.
You are limited to ONLY using autonumber PK's if you wish to keep related tables intact. You cannot control this re-numbering, but as noted the number ONE rule in databases is that such numbers do NOT matter anyway.
If you MUST and WANT to stop the re-numbering of that column, then change the data type to a long number, and NOT autonumber type. And then of course simply add another autonumber column. So to STOP or PREVENT the numbers being changed, you have to convert the column from being autonumber to a standard long number column. (edit: you ALSO thus have to ensure that the column is NOT marked as PK).
Keep in mind that any other table as part of the related data will ALSO see those standard long number columns re-numbered and changed if that column is part of a defined relationships to some PK. So Access during a up-size WILL re-number the PK (autonumber) and will ALSO automatic for you re-number the FK columns used in child tables. If you as noted do NOT want such re-numbering to occur, then the PK and FK columns can NOT be part of a defined relationship.
So dropping the autonumber column is the only way to prevent such re-numbering. Since autonumbers don't have any real meaning, then if they are changed during a up-load, then this should not matter.

what is the best practice - a new column or a new table?

I have a users table, that contains many attributes like email, username, password, phone, etc.
I would like to save a new type of data (integer), let's call it "superpower", but only very few users will have it. the users table contains 10K+ records, while fewer than 10 users will have a superpower (for all others it will be null).
So my question is which of the following options is more correct and better in terms of performance:
add another column in the users table called "superpower", which will be null for almost all users
have a new table calles users_superpower, which will at most contains 10 records and will map users to superpowers.
some things i have thought about:
a. the first option seems wasteful of space, but it really just an ingeger...
b. the second option will require a left join every time i query the users...
c. will the answer change if "superpower" data was 5 columns, for example?
note: i'm using hibenate and mysql, if it changes the answer
This might be a matter of opinion. My viewpoint on this follows:
If superpower is an attribute of users and you are not in the habit of adding attributes, then you should add it as a column. 10,000*4 additional bytes is not very much overhead.
If superpower is just one attribute and you might add others, then I would suggest using JSON or another EAV table to store the value.
If superpower is really a new type of user with other attributes and dates and so on, then create another table. In this table, the primary key can be the user_id, making the joins between the tables even more efficient.
I would go with just adding a new boolean field in your user entity which keeps track of whether or not that user has superpowers.
Appreciate that adding a new table and linking it requires the creation of a foreign key in your current users table, and this key will be another column taking up space. So it doesn't really get around avoiding storage. If you just want a really small column to store whether a user has superpowers, you can use a boolean variable, which would map to a MySQL BIT(1) column. Because this is a fixed width column, NULL values would still take up a single bit of space, but this not a big storage concern most likely as compared to the rest of your table.

MySQL Trigger to update corresponding column in another table

I'm trying to write a MySQL trigger for a table update (and a similar one for insert) that will take the updated columns and update corresponding columns in another table.
My set-up is this: I have one table (A) with several columns of numerical values and a record number Primary Key. I have another table (B) with identical column names but with short text descriptors that relate to each numerical value and also a record number as a Foreign Key referring to table A. Both of these tables may grow over time to include more columns - always matching each other - each with a simple predictable name (sticking with integers for now). All records are 1:1.
My hope was that I could write triggers for both update and insert on table A that would look at the numbers and, based on some simple logic, assign a descriptor to the corresponding record in table B (inserting that record in the case of the insert trigger). It got rather complicated quickly because I had to query INFORMATION_SCHEMA.COLUMNS to identify all current column names in table A, check each OLD vs NEW to verify that column was updated (for the update trigger anyway), do some logic to determine the appropriate descriptor, then INSERT/UPDATE the corresponding column in table B. I can't figure out how to set up a procedure/trigger that doesn't require storing column names in a variable to dynamically build an SQL statement. This is, of course, not allowed in a trigger and I have made some attempts at getting around this by moving the dynamic SQL statement into a separate stored procedure. None of this has worked and I've run into so many roadblocks, I'm coming to the conclusion that I'm going about this in entirely the wrong way.
Since I'm very new to database design, I just don't know what question to ask at this point other than, is there a better way or alternatively, is there a fix to my approach outlined above?
As always, I've searched thoroughly and not found any questions that answer mine but, if you see one that does, please point me that way!

MySql Soft delete

I have an existing application (with MySQL DB).
I just got a new requirement where I need to delete some records from one of main entity. I dont want to apply hard delete here as its risky for whole application. If I use soft delete I have to add another field is_deleted and because of that i have to update all my queries (like where is_deleted = '0').
Please let me know if there is any smarter way to handle this situation. I have to make changes in half of the queries if I introduce a new flag to handle deletes.
Your application can run without any changes. MySQL is ANSI-SPARC Architecture compliant . With external schema you achieve codd's rule 9 "Logical data independence":
Changes to the logical level (tables, columns, rows, and so on) must
not require a change to an application based on the structure. Logical
data independence is more difficult to achieve than physical data
independence.
You can rename your tables and create views with original table names. A sample:
Let's supose a table named my_data:
REMAME TABLE my_data TO my_data_flagged
ALTER TABLE my_data_flagged
ADD COLUMN is_deleted boolean NOT NULL default 0;
CREATE VIEW my_data AS
SELECT *
FROM my_data_flagged
WHERE is_deleted = '0'
Another way is create a trigger and make a copy of erased rows in independent table.
Four suggestions:
Instead of using a bit called is_deleted, use a dateTime called something like deleted_Date... have this value be NULL if it is still active, and be a timestamp for the deletion date otherwise. This way you also know when a particular record was deleted.
Instead of updating half of your queries to exclude deleted records, create a view that does this filtering, and then update your queries to use this view instead of applying the filtering everywhere.
If the soft deleted records are involved in any type of relationships, you may have to create triggers to ensure that active records can't have a parent that is flagged as deleted.
Think ahead to how you want to eventually hard-delete these soft-deleted records, and make sure that you have the appropriate integrity checks in place before performing the hard-delete.

Access VBA avoiding a conflict with primary key when adding a record to a linked table

So the root of this problem may lie in poor database design, some of the way this is set up is inherited from older versions. I just couldn't figure out a better way to do this.
I have four tables linked by the same field: [OBJECTID]. Each table is linked to an Access Form that controls the data. It is important that these tables be separate as the data is georeferenced and needs to be mapped separately, however they inherit several fields from one another by default.
Most of the time, the tables are in a one-to-one-to-one-to-one relationship, however occasionally, there is only data for the first table, and occasionally, there is only data for the second, third and fourth form.
Right now, the [OBJECTID] field in the first table is set to datatype autonumber, so that all subsequent linked records in the other tables can inherit that number. For the cases where the record in Tbl1 are not entered via Form1, it is easy enough to just assign a number that does not conflict with any current number, but how do I avoid assigning a number that could conflict with some future [OBJECTID] generated by the autonumber field in Tbl1?
Sorry if that is confusing! Thanks in advance for helping me think this through....
If the design is correct, there should be a relationship with referential integrity between tbl1 and table 2/3/4. Since you mention that occasionally, there is only data for the second, third and fourth form that means we have no referential integrity here :-/.
I would identify the fields that are common to all 4 tables, and create a "main" table with those, meaning that the main table MUST be filled. Then you create a 1 to 0,1 relationship to the other 4 tables, with an outer join, their PK beeing then a Long Integer.
For the source of your forms 1 to 4, use an outer join between MainTable and T1/2/3/4. The "subtables" will then inherit the PK of the main table.
Hope I am not too obscure.