How to prevent adding new row, to prevent overloading in sql - mysql

Let's say I'm trying to create sample db schema for cinema reservation.
I have a Table "auditorium" with int capacity and i wish to be able to create as much 'bookings' record, but i want to be unable to create booking when the auditorium is fill.
So for example, lets say Auditiorium A has 100 seats. Then i wish to be able to insert 100 bookings that has FK to Auditorium A, and when i try to create 101'st booking i will have error or something like this.

This would normally be handled by a trigger -- in either MySQL or SQL Server.
One method is to have an Auditoria table that has a maximum capacity (or perhaps a maximum per event, if the configuration could change).
The Bookings table would have a trigger. When records are inserted, the number of records for the event would be compared to the capacity for the auditorium, and inserts that exceed the capacity would fail.
If the Auditoria have a fixed capacity and layout, you can also have a table with one row per seat. The booking would then be for a particular seat -- and the capacity issue is automatically taken care of (because no seats would be available).

Related

Using a MySQL View to Retrieve Running Total

We're building an e-commerce system and we need some help in deciding on what's the best way to determine how many stocks are available per product.
Say we have the tables "products", "products_in", and "products_out". "products_in" records all our transactions that increase the quantities of our products (e.g. when we buy the products from our wholesale suppliers). While "products_out" records all our transactions that decrease the quantities of our products (e.g. when our customers buy the products).
In our apps, retrieving the quantities available for our products is more common than writing/updating records in the "products_in" and "products_out" tables. Given this, will the use of a MySQL view that depends on "products_in" and "products_out" and computes the available stock be more efficient than computing it on the fly every time we query it? Will the value on the view be recomputed every time there's a new record in "products_in" or "products_out"? Or will the view recompute the value every time we query it (which can be quite expensive in our case)?
will the use of a MySQL view that depends on "products_in" and "products_out" and computes the available stock be more efficient than computing it on the fly every time we query it? Will the value on the view be recomputed every time there's a new record in "products_in" or "products_out"? Or will the view recompute the value every time we query it (which can be quite expensive in our case)?
Let's think of the db steps in each case:
Case 1 If you compute available_stock every time a product comes in or goes out and store it in say product table
If product comes in, Insert queries in product_in table or if product goes out, Insert queries in product_out table
In either case, Update queries in available_stock column of product. (Assume here if 10 products come or 10 products go, there will be 10 individual queries that will be fired) - Expensive?
Case 2 If you compute available_stock in view everytime and not store it in database
Fetch records from product_in and product_out tables (only for few products for which you want available_stock), do some math, and display the estimated stock - Expensive?
I personally would go with case 2, because it involves less db transactions overall then case 1 which involves tons of transactions to keep the stock in sync.
Footnote In the sidelines, I'd definitely say that if you are hardcore 'Object Oriented Programmer' then your db mappings definitely violates the fundamentals. Products_in, Products_out are both the same entities (objects) that records the inventory/stock transactions (like Father,Mother entities are Persons), therefore you should make them encapsulated into one general table ProductInOutData.
In ProductInOutData, you can then add an enum having either in value or out value. Having both in and out records in one table will not only improve the readability and accessibility but also will help in easy calculation of the products coming in or going out making the case 2 more lightweight.

Ms access : calculated field from other table

I've been searching for this for a while and I can't seem to find anything!
Here's my problem:
I have a ms access database for the maintenance of the trucks of a company.
I've built a form in which you can see a VEHICLE and the amount of money spent on it. This information is available by a subform that takes information in the MAINTENANCE table
I would like to have the same exact information in the VEHICLE table so I could build charts (histograms)
basically I want a calculated field in my VEHICLE table that reads the MAINTENANCE table and sums up every maintenance for this vehicle.
I hope this is not impossible.
Its not impossible. However, you may need to rethink how you want to do this.
You could do this in C# or VBA, etc, but since I'm not an expert at those, I'll give you a simple solution.
Create the maintenace_total field in your vehicle table.
Create a new table (tbl_VehicleMaintenanceAmt) that only contains the fields for your unique vehicle identifier and maintenance total.
Create a new query (qry_AppendVehicleMaintenanceAmt) based on your maintenance table that groups by vehicle unique identifier and sums the maintenance amounts.
Change your new query (qry_AppendVehicleMaintenanceAmt) to append to your new table (tbl_VehicleMaintenanceAmt). This will give you a clean one row per vehicle with maintenance total.
Create a new update query that links your new table (tbl_VehicleMaintenanceAmt) with your Vehicle table by vehicle identifier, and update the maintenance_total in your Vehicle table with the Maintenance amount from tbl_VehicleMaintenanceAmt.
You'd want to clear out the tbl_VehicleMaintenanceAmt and re-append your maintenance total data to it every time you want to get accurate numbers.
You could also do this with Form and Subform grouping with Sums and Totals, but the explanation is a pain so I went as far as I'm willing. :)

Working out users points - update vs select

I have users who earn points by taking parts in various activities on the website and then the user can spend these points on whatever they like, the way I have it set up the at the minute is I have a table -
tbl_users_achievements and tbl_users_purchased_items
I have these two tables to track what the users have done and what they have bought (Obviously!)
But instead of having a column in my user tables called 'user_points', I have decided to display their points by doing a SELECT on all achievements and getting a sum of the points they have earnt, I am then doing another select on how many points they have spent.
I thought it might of been better to have a column to store their points and when they buy something and win stuff I do an UPDATE on the column for that user, but that seemed like multiple areas I have to manage, I have to insert a new row for the transaction and then update their column where if I use a query to work out their total won - spent I only have to insert the row and do no update. But the problem is then comes to performance of running and doing a calculation with the query.
So which solution would you go with and why?
Have a column to store their points and do an update
Use a query to work out the users points they can spend and have no column
Your current model is logically the right one - a key aspect for RDBMS normalization is not to repeat any information, and keeping an explicit "this customer has x points" column repeats data.
The benefits of this are obvious - you have less data manipulation code to write, and don't have to worry about what happens when you insert the transaction but can't update the users table.
The downsides are that you're running additional queries every time you show the customer profile; this can create a performance problem. The traditional response to that performance problem is to de-normalize, for instance by keeping a calculated total against the user table.
Only do that if that's absolutely, provably necessary.
myself, I would put the user points into a separate table PK'd by user ID or whatever and store them there and do updates to increment or decrement as achievements are attained or points spent.

Database data inconsistency

I have three tables on my database the BILL,RECHARGE AND SENT.The BILL table has a column named UNITBALS and the RECHARGE table has a column named UNITS also the SENT table has a column named VOLUME.What normally should happen is that when a customer recharge his account his new UNITS will be sum with his old UNITS on the RECHARGE table and the sum of the VOLUME of the total sent message on the SENT table will be subtracted from the sum of the UNITS on RECHARGE table and the result will be used to update the UNITBALS on the BILL table.But the problem now is that when customer recharge their account the UNITBALS on the BILL table is updated with the new balance or sometimes the UNITBALS is being updated with higher values than it ought to be.There is a kind of inconsistency in my database now and the customers are complaining.
So from what I gather you are storing the results of a aggregate calculation on BILL.UNITBALS
Specifically
BILL.UNITBALS = SUM(RECHARGE.UNITS) - SUM(SENT.VOLUME)
Unless you made a serious error, what's likely going on is due to a pending transaction and the transaction isolation level you're missing a value that you should be taken into account.
Because of this issue I try and do whatever I can to avoid storing the results of a calculation in the DB
Typically this means that I do the calculation every time I retrieve the data. This may (or may not be) a performance issue but at least you get more opportunities to get the correct information.
If the perf penalty is too high then I recommend that you do a reconcilation only once every 24 hours and add a disclaimer like "payments made will not appear on your account for X business days"

How should I lock to avoid duplicate numbers

I have a table A (SQL Server 2008) that contains sets of min and max numbers. In one of my stored procedures I use this table joined with a product table B to find an available product number that's between min and max and then insert a new product with this product number. So I want the next free number that's between min/max.
Between finding out the next available number and inserting the product row I want a lock to prevent anyone of finding the same number (and giving a duplicate).
How should I think in this situation? Should I get an update lock on the A table even though I never modify it? The lock should be released after I do the insert into table B and the transaction finishes? Will this update lock prevent other transactions from reading table A?
Edit: The min/max table is a table for different product series. Depending on which serie you want i want to try and find an available number in this sequence. The productnr is not unique, it would be possible to make it unique in combination with a second column though. Simplified sp:
CREATE PROCEDURE [dbo].[InsertProduct]
(
#Param1 int,
#Param2 bit,
...
#Param20 int) AS
BEGIN
DECLARE #ProductNr int
--Here I do a query to determine which ProductNr I should have. Checking that the number is between max/min in the series and that no other product has this productnr.
--Now insert the row
INSERT INTO Products VALUES (#Param1, #ProductNr, ...., #Param2
END
Your question is kind of obscure, it would help if you included some sample data.
Regardless, a tactic that I have used in the past is to try and wrap everything withing a single statement -- here, it would be an INSERT. Every SQL statement is de-facto wrapped in its own implicit transaction (that's atomicity, what the "A" in the ACID of relational database properties fame stands for). In psuedo-code, it'd look something like:
INSERT MyTable (Id, Plus, Other, Columns)
select CalcForNewId, Plus, Other, Columns
from [what may be a pertty convoluted query to determine the "next" valid Id]
This only works if you can write your business logic as a single reasonable query (where "reasonable" means it doesn't lock, block, or deadlock either the current or any other user for an unreasonable length of time). That can be a pretty tall order, but I'd take that over having to write complex BEGIN TRANSACTION/COMMIT/ROLLBACK code intermixed with TRY...CATCH blocks any day. (That will of course work, and I've upvoted #Scott Bruns accordingly.)
Just insert the next number into table B. If it commits it is yours to use. If you get a Key Violation it means that a different process has just entered the new number. In that case increment the new number and try again.
The database will automatically handle the concerency for you. No manual locking is required.