How to update a one-to-many relationship from a CheckBoxList, ListBox, etc? - multi-select

Given 2 tables:
Person
PersonsFavoriteColors
A person can have one or more favorite colors. These colors are updated with a multi-select control (CheckBoxList, ListBox w/ multi-select enabled).
In the past, if I am updating the person's colors, I'd:
Start Transaction
Delete all color records for the person
Insert records for each selected color
Commit Transaction
Is this the standard and best practice for handling multi-select controls that add / update / delete records in "to-many" child tables?
Thanks!

I normally wouldn't delete all the old colours but rather just the ones that were no longer favourites and then I'd only add the ones that were actually new.

If you're not locked in to two tables, a relatively simple way to store values the way you've described is to use an array as the data type of favorite colors instead of a separate table.
http://www.postgresql.org/docs/8.0/interactive/arrays.html
If that is an acceptable option, your updating instructions would simply be:
Start Transaction
Update Row
Commit Transaction

Related

Database to keep track of inventory/ live stock

I am looking for help with database design for a small project I am working on.
In short what I am trying to achieve is to have say the following tables:
Paddocks
Paddock ID
Paddock Name
Paddock Size
etc.
Cattle
Herd ID
Herd Name
Number of cows
Current Paddock
Cattle_Movements
Herd Name
Current Paddock
New Paddock
Date
etc.
I was hoping to have the 'Cattle_Movements' table be like a summary of all movements of a herd of cattle. And when a herd is moved from one paddock to another it would update the 'Current Paddock' field in the 'Cattle' table.
At this stage I am trying to workout the relationships, queries and high level process that I will need to implement.
Any help will be greatly appreciated.
Start by setting up a normalized table structure. make the tables below and hook them together with the relationships tool on the ribbon under database tools-relationships. To create a relationship drag the primary key from one table to the corresponding and same named foreign key in the table that will be the many side of the relationship. In the pop up make sure to check the enforce referential integrity, cascade update, and cascade delete checkboxes.
I've highlighted the two "Many to Many Relationships" in this normalization. HerdsPaddocks is a more generic name for the CattleMovements Table. There are other possible normalized table structures, but the subtle differences are beyond the scope of this answer. When you are ready, look up table normalization and Many to Many Relationships.
Next, Close the Relationships tool, select a table from the sidebar and on the ribbon under Create hit create form. Do this for all the tables. Now we have a working database but you need to learn how to use it. So play!
Below I gave some play suggestions, but just play with everything until you figure out how to use the forms to (add, search, edit) cows, herds, and paddocks. Also learn why you should delete the primary keys from all the forms and how to replace the foreign keys like CattleType in the Cattle Table with the user friendly CattleTypeDesscription from the CattleTypes Table.
Start with the Herds table and enter some random herds. (pro tip: never add data to the table directly except when playing the error rate is too high). Then Open the herds form where you can browse and edit the herds.
Play tips: In the Table Herds HerdID is both an autonumber and a primary key. It behaves differently from the other columns. Check it out. after that delete the HerdID textbox from the form and see what happens(a good thing). How do you add herds using the Herds Form?
Moving on to playing with the Cattle form, first make sure to add a few CattleTypes to the CattleTypes table. Then at some point, try replacing the CattleTypeID in the Cattle Form with the CattleTypeDescription: https://btabdevelopment.com/how-to-change-a-text-box-to-a-combo-box-wont-work-with-data-access-page/
Also, note the Cattle Form has a subform allowing you to simultaneously assign/edit cattle assignments to herds.
Once you are comfortable adding and editing data, play with the query editor. For instance, to get how many cows are currently in Paddock holds10cattle (my dummy data).
query 1 showing the relevant data
results from query1:
Query 2 getting really close:
Query 3: which gives the number 2:
'Query 3 SQL from SQL pane of query designer
SELECT Count(Cattle.CowName) AS CountOfCowName
FROM Paddocks INNER JOIN ((Herds INNER JOIN (Cattle INNER JOIN CattleHerds ON Cattle.CattleID = CattleHerds.CattleID) ON Herds.HerdID = CattleHerds.HerdID) INNER JOIN HerdsPaddocks ON Herds.HerdID = HerdsPaddocks.HerdID) ON Paddocks.PaddockID = HerdsPaddocks.PaddockID
GROUP BY Herds.HerdName, Paddocks.PaddockName, HerdsPaddocks.HerdPaddockEndDate, HerdsPaddocks.HerdPaddockStartDate
HAVING (((Paddocks.PaddockName)="holds10cattle") AND ((HerdsPaddocks.HerdPaddockEndDate) Is Null) AND ((HerdsPaddocks.HerdPaddockStartDate)<Now()))
ORDER BY HerdsPaddocks.HerdPaddockStartDate;
Next Steps could include the specific paddock with a parameter and using the query in a report.

.NET Storing "Checked" items into the database

Wondering if someone could assist with the best way to handle storing "checked" items in a MSSQL database.
On my form, i have a list of fields (name, address ect) and then a listbox the user can check for e.g. favourite colors.
In my database I would have a table for user details (tbl_userdetails - [UserID, Address...]) and a table for colors (tbl_colors, [ColorID, ColorName, ColorCode]). I would also need a table for user colors (tbl_userColors - [userID, ColorID])Theses would be linked via a "userID"
Normally, to save the user details, I have a sql string "UPDATE tbl_userdetails SET... WHERE userID = #userID". What is the best way to save the changed checked items into the next table?
My thoughts are:
Delete all the colors for UserID in the tbl_userColors and then loop the checked items into a "INSERT" statment.
Loop though each item that exists in the list create a datatable and then "merge" the data (on match, insert. on not matched delete)
Any other thoughts? What is the best way to build the INSERT statment?
Cheers
The DELETE and INSERT strategy works well as long as nothing is tied to those records. If you ever have any tables that reference tbl_userColors on the "one" side of the relationship, then you will have headaches.
The MERGE strategy is decent, usually. One possibly unfortunate consequence would be that a MISSING record is the same as a FALSE record. For instance, you Have your list of colors, {red, green, blue}, and your users are making their selections. Six months later you get crazy and add orange. Now you have no idea who didn't select orange vs. those that simply weren't presented with orange as an option.
A third option is to place an Enabled BIT field on the tbl_userColors table. This allows you to determine if a user was presented with a color option and they declined it vs. if the user never saw a particular color option.
Speaking of Enabled BITs. Your tbl_colors table should really have an Enabled BIT as well - or some other mechanism of removing a color from the UI without removing its database record. You realize at some point you no longer want to offer blue to your users, but you also don't want to loose the historical data.
And a small aside: Your tables names are horrific. You should really consider dropping the Hungarian notation. I'm a big fan of camel-case table names: Users, Colors, and UserColors.
Simple really. When an item is checked it returns a boolean. Whenever you get ready to save to the database you just want to loop through the colors and if it is checked (AKA is check is true) then you add it to a list that you can later loop through to save all of the values.

Visual studio Lightswitch

I have a two database tables, on light switch the first one called product and the second one called invoice line items.
The Product table has one column called Bought Quantity.
The Invoice line items has one column called sold Quantity.
Now I need to have a search screen with the both tables on it, but here come my question.
When I made the relationship between the two tables, then the screen will show the grid with two columns, one called the "quantity I bought" and another column "quantity I sold".
I need to make subtraction and the result will show on another column called "available".
So I have a local property called Available. Now I need code to write to make the subtraction process and then will show on the available.
That is my question.
Lightswitch screens will only show data for an entity within your project. If you want to shape your table using joins to merge tables then you'll either need to create a view in your datasource and import it into your project or use WCF RIA to shape your data accordingly.
Michael Washington has created loads of examples on how to do this, you can find them here:
http://lightswitchhelpwebsite.com/Blog/tabid/61/tagid/21/WCF-RIA-Service.aspx
Good luck.
Paul.

Many to many relations and history tables

Suppose I have Item and Tag, each of which have an id and name column only, and an Item_Tag_Map table that has a composite Item.id, Tag.id primary key.
If I want to implement a history table for Item and Tag, this seems relatively straightforward - I can add a third column revision and a trigger to copy into an ItemHistory or TagHistory table with id, revision as primary key and operation ("INSERT","UPDATE",etc). Since I may want to "delete" items, I can go about this one of two ways:
Add another column on Item or Tag for is_active, and do not actually delete any rows ever
Delete rows, but record the deletion in the history table as a delete operation, and on an Item or Tag insert, make sure to get the latest revision number from the ItemHistory or TagHistory table with that item, and set it to be that
The second option leaves a bad taste in my mouth, so I am fine with using the first. After all, why should I really ever need to delete an item when I can just modify it or change its active status?
Now, I've run into the same problem for the history table on the Item_Tag_Map table, but this time, neither option seems all that attractive. If I choose to add an is_active for the Item_Tag_Map, the logic of finding out whether a tag is mapped to an item changes from:
Get ALL tag_mapping for THESE items
to
Get ALL tag_mapping for THESE items WHERE is_active
The implicit idea that the presence of a mapping means that the mapping exists goes away. The set of unmapped item-tags not only includes all the ones that are not present in the table, but also the ones where is_active is false.
On the other hand, if I choose the second option, it's still rather ugly.
I'm sure people have run into this problem many times before, and I am interested in learning how you have dealt with it.
My answer depends on a few things, so I'll try to state my assumptions.
No matter what I think is_active on Item and Tag are ok. If the record size grows very fast on those two entities, then consider running a nightly job to move the inactive records to an archived version of the tables. This can be used for reporting or auditing of things later. You can also write a script to restore records if you need, but the idea is that your real time tables are fast and without deleted data.
If you allow the user to add/update/delete mappings, then I would consider the table the same as Item and Tag. Add the flag and use it in your queries. It doesn't seem ugly to me - I've seen it before.
If the mapping table isn't under user control, then I would guess you would use the is_active flag on either Item or Tag to determine whether or not a query could be run.
Just know that once you add that flag, people will forget to use it. I know I've done it many times, ("Why did I get so many records, what am I missing? Oh yeah, is_active...)

Cascading Choices in FileMaker 11 Pro Advance

Working with cascading choices in the new(er) FMP seems to be a little weird. My intention is to create a bunch of drop-down lists / pop ups that rely on the previous choice. If a user clicks on a Customer drop-down, the next drop-down (address field) will ONLY have related data for that customer street address. Once you click the certain address, the other state, city, zip, etc fields will be automatically keyed in.
This is done by creating two tables (shipping, customer) along with a table occurrence of shipping and one unique value as a relationship in both the customer and shipping table...yeah. All of this is very doable, if not a little convoluted; however, I was wondering if there was a way to clean up these relationships? Sorry, calling all FileMaker pros out there, thanks!
I'm afraid the answer is no. Setting up cascaded value lists is rather tedious and, to my knowledge, there's no silver bullet. You're lucky to have just two levels :)
If I were going to take a stab at this, I'd try to build the next level of popup contents by deriving the necessary value list from the records of a related table. Since the selection of one value triggers the next popup, you're finding entries in a predefined database made of multiple tables where the values are all the possible dropdown list/popups. It's a cascade engineered through layouts, find and sort.

Resources