how to prevent duplicate records in database - primary-key

Question:
How do I prevent two different admin users of a website from creating a customer record with the same customer id.
Background information:
The website I'm working with autogenerates a number called "customer number" based on a routine/method that does the following:
checks the allowable range of numbers by using the cust_number_range table.
figures out the highest number in use from the customer table.
displays the next available number on the "create new customer" form.
when the submit button is clicked, before attempting to save the record, i double check the customer table again to make sure the number i have calculated as the next available one is not in use. if it's still ok, then i save to the database.
Here's what the database looks like:
customer table
=====================
id integer - primary key
custnumber integer
fname varchar(255)
lname varchar(255)
cust_number_range
====================
lower_range integer
upper_range integer
id integer - primary key
The problem I've run into is if two admins click on the "submit" new cust record at the exact same time, the system will create two records with the same custnumber.
Here are some questions that I have:
Is making the custnumber field a part of the pk optional? meaning, is that really the "proper" solution?
what other ways do i have to solve the problem?
thanks.

You should use unique columns for that. But I would also check from code, before adding user to the database, check if user does not exists, and if not, only then add.

Do you need the numbers to be in sequence?
You can create an "index" table.
index_table
====================
index_type integer (possible values - 1 for customers, 2 for orders, etc.)
last_index integer
Every time you create a new customer create an index for the user from the index table by advancing the last_index id field.
If the user does not save the record, you just skip an id.
Most databases though have a record_id which has a similar mechanism, so I would recommend using that.

Related

SQL Referencing a particular table chosen from a row value in another table

I've got a database called SimpleCredentials in which there is a table called dbo.Properties which has (PK) UserID and then some other attributes like Name, Date of Birth etc. There is another Primary Key attribute called ExtendedCredentials which is a string dbo.UserID. So, for example the user with UserID = S-1-5-21-2177 will have the string dbo.S15212177 in their ExtendedCredentials column.
I've got another database called ExtendedCredentials. For every User there is a unique table in that database. Using the previous example, there will be a table called dbo.S15212177.
So, if I have 100 users there will be 100 rows in the dbo.Properties table in the SimpleCredentials database, and there will be 100 unique tables incorporating their UserID in the ExtendedCredentials database.
I want to create an entity relationship diagram, and eventually a MS SQL schema, but how do I represent the multiplicity of dbo.UserIDs and their relationship to their dbo.UserID string attribute in dbo.Properties?
Am I getting something fundamentally wrong here?
You may ask why I don't have a single database called ExtendedProperties with a single table in which each row is the UserID PK and the various extended properties are contained in columns. The simple answer is that some properties are themselves tables. Not every user has the same attributes in those tables. And I can't know ahead of time (a priori) what the full set of user extended property attributes is. So each user gets a table of their own.
Is there a better way to do this?

Delete an item (row) from table but keep the unused ID number for a future insertion

I have a database with an "inventory" table which contains products from a shop. Each product is identified using an ID number set in the "ID" column of the table.
I want to be able to delete a product from the table, but keeping the deleted product's id number for future product insertions into the database.
As a demonstration I inserted 4 items and named all of them "test"
And just as an example I named the "deleted" product as "vacio" (empty in spanish) to show the one that i deleted.
Now, if want to add another product in the future, the id number 2 is unused and I want to add the product with that id number instead of 4 (following the given example).
The DELETE query is no good since it erases the id number as well so its a no go.
I thought about checking for the first row of the table that contains the value "vacio" and using the UPDATE query in all fields except id but this doesnt feel "classy" and is not very efficient as It should have to update values a lot of times.
Is there some nice way of doing this?
I would not actually recommend reusing old identifiers. For one, this prevents you from using the auto_increment feature, which mean that you need to manually handle the column for each and every insertion: this adds complexity and is not efficient. Also, it might cause integrity issues in your database if you have other tables referencing the product id.
But if you really want to go that way: I would go for the deletion option. If there are foreign keys referencing the column, make sure that they have the on delete cascade option enabled so data is properly purged from dependent tables when a product is dropped.
Then, you can fill the first available gap the next time your create a new product with the following query:
insert into products(id, categoria, producto)
select min(id) + 1, 'my new category', 'my new product'
from products p
where not exists (select 1 from products p1 where p1.id = p.id + 1)
You could have a new column ESTADO where you handle if a record is active (1) or inactive (0). Then, to obtain only "undeleted" records you just have to filter by the new column. That way, you also prevent changing the product name to "vacio", which might be useful in the future.

Many to many relationship and MySQL

If I wanted to make a database with subscribers (think YouTube), my thought is to have one table containing user information such as user id, email, etc. Then another table (subscriptIon table) containing 2 columns: one for the user id and one for a new subscriber's user id.
So if my user id is 101 and user 312 subscribes to me, my subscription table would be updated with a new row containing 101 in column 1 and 312 in column 2.
My issue with this is that every time 101 gets a new subscriber, it adds their id to the subscription table meaning I can't really set a primary key for the subscription table as a user id can be present many times for each of their subscribers and a primary key requires a unique value.
Also in the event that there's a lot of subscriptions going on, won't it be very slow to search for all of 101's followers as all the rows will have to be searched and be checked for every time 101 is in the first column and check the user id (the subscriber to 101) in the second column?
Is there's a more optimal solution to my problem?
Thanks!
In your case, the pairs (user_id, subscriber_id) are unique (a user can't have two subscriptions for another user, can they?). So make a compound primary key consisting of both fields if you need one.
Regarding the speed of querying your subscription table: think about the queries you'll run on the table, and add appropriate indexes. A common operation might be "give me a list of all my subscribers", which would translate to something like
SELECT subscriber_id FROM subscriptions WHERE user_id = 123;
(possibly as part of a join). If you have indexed the user_id column, this query can be run quite efficiently.
A Primary Key can be made of two columns, subscribe and subscriber in your case. And since search will only be on integer value, (no text search) it will be fast.
more informations here : https://stackoverflow.com/a/2642799/1338574

SQL Table Design - Identity Columns

SQL Server 2008 Database Question.
I have 2 tables, for arguments sake called Customers and Users where a single Customer can have 1 to n Users. The Customers table generates a CustomerId which is a seeded identity with a +1 increment on it. What I'm after in the Users table is a compound key comprising the CustomerId and a sequence number such that in all cases, the first user has a sequence of 1 and subsequent users are added at x+1.
So the table looks like this...
CustomerId (PK, FK)
UserId (PK)
Name
...and if for example, Customer 485 had three customers the data would look like...
CustomerId | UserId | Name
----------
485 | 1 | John
485 | 2 | Mark
485 | 3 | Luke
I appreciate that I can manually add the 1,2,3,...,n entry for UserId however I would like to get this to happen automatically on row insert in SQL, so that in the example shown I could effectively insert rows with the CustomerId and the Name with SQL Server protecting the Identity etc. Is there a way to do this through the database design itself - when I set UserId as an identity it runs 1 to infinity across all customers which isn't what I am looking for - have I got a setting wrong somewhere, or is this not an option?
Hope that makes sense - thanks for your help
I can think of no automatic way to do this without implementing a custom Stored Procedure that inserted the rows and checked to increment the Id appropriately, althouh others with more knowledge may have a better idea.
However, this smells to me of naturalising a surrogate key - which is not always a good idea.
More info here:
http://www.agiledata.org/essays/keys.html
That's not really an option with a regular identity column, but you could set up an insert trigger to auto populate the user id though.
The naive way to do this would be to have the trigger select the max user id from the users table for the customer id on the inserted record, then add one to that. However, you'll run into concurrency problems there if more than one person is creating a user record at the same time.
A better solution would be to have a NextUserID column on the customers table. In your trigger you would:
Start a transaction.
Increment the NextUserID for the customer (locking the row).
Select the updated next user id.
use that for the new User record.
commit the transaction.
This should ensure that simultaneous additions of users don't result in the same user id being used more than once.
All that said, I would recommend that you just don't do it. It's more trouble than it's worth and just smells like a bad idea to begin with.
So you want a generated user_id field that increments within the confines of a customer_id.
I can't think of one database where that concept exists.
You could implement it with a trigger. But my question is: WHY?
Surrogate keys are supposed to not have any kind of meaning. Why would you try to make a key that, simultaneously, is the surrogate and implies order?
My suggestions:
Create a date_created field, defaulting to getDate(). That will allow you to know the order (time based) in which each user_id was created.
Create an ordinal field - which can be updated by a trigger, to support that order.
Hope that helps.

How do create table with dynamic no. of columns for data entry

I'm currently working on a project where I need to save data depending upon the active no. of items.
Its like..
Stores can have n no of items which can be dynamically added or reduced from admin back-end. Each item can either be activated or deactivated. NO problem.
But I need to manage/save these dynamic n no. of items in a table for each store. I'm not able to decide on the table schema.
Any help will be highly appreciated.
I suggest a standard many-to-many relationship using a middle table. So you would use 3 tables:
StoresTable: the list of stores
ItemsTable: the list of items
StoreItemsTable: a list of items-in-stores, each row will have a foreign key to both the stores table and the items table
Hope that helps.
your problem is actually not that hard if you use a different approach.
A store can have a number of items. So basically Susi's store has 1 item, but suddenly she wants 2, and you would like to add a column. This is very difficult if she suddenly wants to add 2000 items.
The best approach would be to use a store table (which has the name of the store, the date it was created and a primary key) and a items table. You can then add items as entries to the table and link them to the store via the stores primary key.
An example:
Store table:
PK Name Owner
1 Sunshine Store Susi
2 Moonstore Harald
Item table:
PK Name Store_id Price
1 Candle 1 2.44
2 Table 1 51.44
3 Chair 2 6.55
This allows you to add as many items to any store you want. The Store_id is called a Foreign Key in this example, because it links the items to the store. You can then use SQL commands to select the items, e.g.
"Select * from ITEMS where Store_id = 1;"
and get all of Susi's items as an answer.
Good luck!
i think you use active column and use that active bit for every purpose because that's very good for future in other transaction too.