How to handle duplicates in SQL Server - c#

I have a table in SQL Server called Test_Table with two columns: ID and Name
The table looks something like this:
ID NAME
--------
1 John
2 Jane
Now I have a stored procedure which inserts records into this.
INSERT INTO Test_Table
VALUES (#Id,#Name)
And I'm passing this values from my c# code. Now I want to modify this so that the table does not have duplicates. Where should I check this, In the code or the DB? I'm very weak in DB side stuff. So how can I handle duplicates before inserting values in my table

The "right" way to do that is in DB because:
Don't need to read all DB
Need to pass all data to C# which increase the IO
Concurrency - if you have more than 1 C# application you will need to sync them vs in DB it would be simpler
You can define the column as unique or key, which will prevent duplicate values ,DB will take care of it
If you use MSSQL use UNIQUE Constraints
Read this good answer about avoid duplicates

You should do this check in the database. Always, if you want it to be true of the data.
I'm not sure what you consider a duplicate. Normally, an id column would be an identity column that is automatically incremented for each value. This would prevent duplicates. You would define it as:
create table test_table (
id int not null identity(1, 1),
. . .
Then, you would insert into it using:
insert into test_table(name)
values (#Name);
The id would be assigned automatically.
If you want no duplicates just for name, then create a unique index or unique constraint (really the same thing). You can do this in the table definition just by adding unique to the column:
create table test_table (
id int not null identity(1, 1),
name varchar(255) unique
. . .
Or by creating a unique index after you have created the table:
create index test_table_name on test_table(name)
(Or by explicitly creating a constraint, which is another method.)

In either case ,you will have to access to database to check wheteher values exist already.
IF NOT EXISTS (SELECT * FROM Test_Table WHERE ID= #ID AND Name=#Name)
BEGIN
INSERT INTO Test_Table
VALUES (#Id,#Name)
END
If it is possible to make ID column as unique you can avoid checking as insertion would.t be allowed for repeating ID values , in that case you will have to handle error.
See this thread how to handle violation of Unique key constraint.

If you don't want repeating IDs you'll have to set the ID as the Primary Key, which is pretty much obligatory.
If you don't want the Name to repeat, you could populate a list with the Names the table contains, and then you would only insert whatever name is not in that List.
Here is an example, instead of using a list I used a dictionary:
Dictionary<int, string> Names = new Dictionary<int, string> ();
using (SqlCommand command = new SqlCommand ("SELECT * FROM TestTable", con))
using (SqlDataReader reader = command.ExecuteReader ()) {
while (reader.Read ()) {
Names.Add (reader["ID"], reader["NAME"]);
}
}
if (!Names.ContainsValue ("ValueYouWantToInsert")) {
//do stuff
}

You should check it in DB, Also you can make ID as Primary Key
Which is mostly used, because people can have duplicate name.

You can modify your Id with the Unique key constraint or you can also make it Primary key.
Try like this:
alter table Test_Table add primary key (ID)
and
alter table Test_Table add unique key (Name)

IF NOT EXISTS (SELECT * FROM Test_Table WHERE ID= #ID AND Name=#Name)
BEGIN
INSERT INTO Test_Table
VALUES (#Id,#Name)
END
ELSE
BEGIN
UPDATE Test_Table
SET ID= #ID,NAME = #Name
WHERE ID= #ID AND Name=#Name
END

Related

Adding SQL Server ID Increment upon registration

How would I retrieve an Id from my SQL Server table, add +1 to it, and register that number to the next Id when someone registers into my program?
This is my code so far. The ?? means I don't know what would go there for this to work.
SqlCommand hi = new SqlCommand("SELECT MAX(Id) FROM Table");
hi.CommandType = CommandType.Text;
hi.Connection = connection;
hi.Parameters.AddWithValue("#Id", ??);
For example, last Id was 14. Now someone is registering and I want it to say 15 in the SQL Server table under Id.
I'm not sure what your full table structure is like, but the functionality you're describing is available natively in a SQL Server databases, and it's called an identity column. The way you would implement it is like this:
CREATE TABLE MyTable
(
Id int not null identity(1,1),
Name nvarchar(255) not null
# other columns go here...
)
You should be able to alter an existing table to make an Id column use identity, the only catch is you can only have one identity column per table.
When you want to insert a new record into the table, you can leave the identity column out of your insert statement, as SQL Server will fill it with the appropriate value:
INSERT INTO MyTable (Name)
VALUES ('My Name')
I would suggest to handle it at database level by making ID column auto increment.
If you want to do it from your code then you have to make additional hit to database to get last ID before you make your insert call to add data.

Sql or linq to sql Unique Constraint based on two columns value

I don't know is it possible or not.
I have a table that keeps records for a book issue return.There are two columns in this one is [status] and other [bookid] .I want to add a constraint in sql that will restrict user to insert duplicate record for status="issue" with same bookid.
For example if there is already a record with status='issue' and bookid=1 then it must not allow to insert other record with status="issue" and bookid=1 but there can me multipule records with other status like staus='return' and bookid=1 may occur a number of times.
Or there may be solution using linq to sql in c#
You do not need a user defined function, in general. In SQL Server (and many other databases) you can just use a filtered index:
create unique index unq_bookissue
where status = 'issued' ;
In earlier versions of SQL Server you can do this with a computed column, assuming that you have a table with columns such as:
BookId, which is repeated across rows.
Status, which should be unique when the value is issue.
BookIssueId, which uniquely identifies each row.
Then, add a computed column to keep track of status = 'issue':
alter table t add computed_bookissueid as (case when status = 'issue' then -1 else BookIssueId end);
Now add a unique index on this column and BookId:
create unique index unq_bookid_issue on (BookId, computed_bookissueid);
You have a complex condition here, so a UNIQUEconstraint won't help you. You will need a CHECKconstraint.
You first need a function to to do your check:
CREATE FUNCTION dbo.IsReturnDuplicate
(
#id INT,
#bookid INT,
#status VARCHAR(MAX)
)
RETURNS BIT
AS
BEGIN
RETURN (SELECT TOP 1 COUNT (*) FROM bookreturns WHERE (id <> #id) AND (status = #status) AND (bookid = #bookid) AND (status = 'issue')
END
This will return 1 if there is already a row in the table that has status 'issue' and has a different id
You can then create a CHECK constraint using this function
CREATE TABLE bookreturns (
--...
CONSTRAINT CK_bookreturns_status CHECK (dbo.IsReturnDuplicate(id, bookid, status) == 0)
)
Using Gordon answer
create unique index unq_bookissuedReference
on Books(Book_id) where [status] = 'issued'
Works for me

Insert values in both related tables MySQL

I have two tables:
create table `db_csms`.`tbl_item_requester`
(
`id` int not null,
`item_id` int not null,
`requester_id` int not null,
foreign key(`item_id`) references `db_csms`.`tbl_items`(`item_id`),
foreign key(`requester_id`) references `db_csms`.`tbl_user_details`(`user_id`),
primary key (`id`)
);
create table `db_csms`.`tbl_item_requests`
(
`id` int not null,
`item_requester_id` int not null,
`quantity` int(5) not null default 0,
foreign key(`item_requester_id`) references `db_csms`.`tbl_item_requester`(`id`),
primary key (`id`)
);
tbl_items and tbl_user_details are already populated with values. My problem is when a new row is added into table 1 because the table 2 uses the id of that new row inserted in table 1.
My issues are:
How to get the newly inserted row id of table 1 which is needed for inserting in table 2.
Strategy to solve this issue(my thinking):
Remove auto_increment and then generate a random value (using C# code) and use that value in both tables.
Are there any workaround to this problem? Do i have to change my strategy? Is the Database design incorrect?
Since you're using MySQL as your database, there is the specific function LAST_INSERT_ID()
which only works on the current connection that did the insert.
In case of SQL Server you could write:
Insert .... Values(....); Select Scope_Identity()
and use SqlCommand.ExecuteScalar() that returns the first value of the first row, which would be the ID of newly inserted row. In MySql, you should be able to write last_insert_id() instead of Scope_identity().

Good practice to avoid duplicate records

I have a application where users can add update and delete a record, I wanted to know the best ways to avoid duplicate records. In this application to avoid duplicate records i created a index on the table, is it a good practice or there are others?
There are a few ways to do this. If you have a unique index on a field and you try to insert a duplicate value SQL Server with throw an error. My preferred way is to test for existence before the insert by using
IF NOT EXISTS (SELECT ID FROM MyTable WHERE MyField = #ValueToBeInserted)
BEGIN
INSERT INTO MyTable (Field1, Field2) Values (#Value1, #Value2)
END
You can also return a value to let you know if the INSERT took place using an ELSE on the above code.
If you choose to index a field you can set IGNORE_DUP_KEY to simply ignore any duplicate inserts. If you were inserting multiple rows any duplicates would be ignored and the non duplicates would continue to be inserted.
You can use UNIQUE constraints on columns or on a set of columns that you don't want to be duplicated; see also http://www.w3schools.com/sql/sql_unique.asp.
Here is an example for both a single-column and a multi-column unique constraint:
CREATE TABLE [Person]
(
…
[SSN] VARCHAR(…) UNIQUE, -- only works for single-column UNIQUE constraint
…
[Name] NVARCHAR(…),
[DateOfBirth] DATE,
…
UNIQUE ([Name], [DateOfBirth]) -- works for any number of columns
)
An id for a table is almost compulsory according to me. To avoid duplicates when inserting a row, you can simply use :
INSERT IGNORE INTO Table(id, name) VALUES (null, "blah")
This works in MySQL, i'm not sure about SQL Server.

Updating column from one table based on changes in another table

Forgive me as I'm new to databases. I have a recipe form that the user can enter several ingredients and the recipe name into. With this form I have the following tables: Recipe{recipeID, recipeName} RecipeIngredient{recipeID,ingredientID,measurement} Ingredient{ingredientID, ingredientName}
RecipeIngredients acts as an intermediate table for the one to many relationship (one recipe to many ingredients). I assigned recipeID as a foreign key inside that table to the primary key recipeID in the recipe table. I thought a foreign key would update based on the primary key updating, but if I insert into the Recipe table the RecipeIngredients table does nothing.
The recipe and the ingredients are assigned ID's automatically.I'm trying to link the ID of one recipe to the auto assigned ID's of each ingredient. For example if the user enters in 8 ingredients, a unique ID is assigned to each of those ingredients. I need the RecipeIngredients table to duplicate those ID's and associate them with the auto-assigned Recipe ID.
I've tried several solutions for updating a column based on changes in other tables. I've tried modifying this MySQL update statement and also modifying this SQL server but I can't seem to get either of them to work.
Suggestions?
In general, you will need to get the new recipeID from the first insert, then use that when you insert into the ingredients table.
Do you have access to the newly inserted recipeID from the insert into the recipe table? How are you doing this insert?
Here is an example Stored Procedure which goes into the database to do the insert / update and return the id:
CREATE PROCEDURE [dbo].[spAlertCategoryInsUpd]
#AlertCategoryID int,
#AlertID int,
#CategoryID int,
#ScreenSortOrder int
AS
SET NOCOUNT ON
IF EXISTS(SELECT [AlertCategoryID] FROM [dbo].[AlertCategories] WHERE [AlertCategoryID] = #AlertCategoryID)
BEGIN
UPDATE [dbo].[AlertCategories] SET
[AlertID] = #AlertID,
[CategoryID] = #CategoryID,
[ScreenSortOrder] = #ScreenSortOrder
WHERE
[AlertCategoryID] = #AlertCategoryID
SELECT #AlertCategoryID as AlertCategoryID;
END
ELSE
BEGIN
INSERT INTO [dbo].[AlertCategories] (
[AlertID],
[CategoryID],
[ScreenSortOrder]
)
OUTPUT INSERTED.AlertCategoryID AS AlertCategoryID
VALUES (
#AlertID,
#CategoryID,
#ScreenSortOrder
)
;
END

Categories

Resources