views:

184

answers:

7

I'm having an issue with duplicates being inserted on refresh. Our team here decided using 'if exists' in sql is the best way to stop duplicate inserts. However, what if a parameter is set to null?

string cmdText = " if (not exists(select * from table where field1 = @field1 and field2 = @field2 and field3 = @field3)) Insert into table(field1,field2,field3) Values(@field1,@field2,@field3)";

if (txtfield1.text != "")
    cmd.Parameters.Add(new SqlParameter("@field1", txtfield1.text));
else
    cmd.Parameters.Add(new SqlParameter("@ field1", DBNull.Value));

    cmd.Parameters.Add(new SqlParameter("@field2", txtfield2));
    cmd.Parameters.Add(new SqlParameter("@field3", txtfield3));

This does not work when there is a null value in field1.

+1  A: 

Well you would have to use IS instead of = if you are going to set @field1 to NULL. NULL is not gonig to work with the equality operator. You need to use an equivalence type 'IS' for that.

string cmdText = " if (not exists(select * from table where field1 = @field1 and field2 = @field2 and field3 = @field3)) Insert into table(field1,field2,field3) Values(@field1,@field2,@field3)";

goes to

string cmdText = "";
if (txtfield1.text != "") 
cmdText = " if (not exists(select * from table where field1 = @field1 and field2 = @field2 and field3 = @field3)) Insert into table(field1,field2,field3) Values(@field1,@field2,@field3)";
else
cmdText = " if (not exists(select * from table where field1 IS @field1 and field2 = @field2 and field3 = @field3)) Insert into table(field1,field2,field3) Values(@field1,@field2,@field3)";
end if

Rinse and repeat and refactor :)

Shaun F
+7  A: 

You could wrap your fields around isnull's or something to take into account for the nulls

isnull(field1, '') = isnull(@field1, '') and 
isnull(field2, '') = isnull(@field2, '') and 
isnull(field3, '') = isnull(@field, '')
Joseph
There's a problem with these kinds code solutions. Every time you write an sql query to that table you have to use this testing. You can do it with constraints and it's cleaner and easier.
egon
@egon that's true for the fields, and I was assuming they weren't going to modify the db schema. However, you'd still need the logic for the parameters.
Joseph
@joseph you can use triggers for that. If they can't modify schema then your solution is ok. But I still think these checks should be in database.
egon
+1  A: 
where field1 IS @field1

is not valid syntax

Use isnull()

So:

string cmdText = " if (not exists(select * from table where isnull(field1, '') = isnull(@field1, '') ...
ElHombre
+1  A: 

If you don't want duplicates in your table, maybe your table should have a primary key or at least a unique clustered index on your field1, field2 and field3.

That way, you could just try ton insert and catch the error if the row already exists.

Danielle
+3  A: 

Would it not be a better idea to reduce the load on the database and attack the problem at the source?

Usually this kind of error occurs when you have a page that handles its own submission, ie the form action property points back to itself, so when someone hits refresh after they posted something, the POST data is still 'live' and gets posted back to the page.

A better way is to have the data submitted to a second object which deals with insertion and then redirects back to where it came from, the redirection clears the POST data and you save yourself a LOT of unnecessary queries.

Just my 2c

MalphasWats
I would use this in conjunction with eliminating duplicates in the table with restrictions.
Jeff O
+2  A: 

following condition will help.

field1 is null or @field1 = field1

Saar
+1  A: 

In field definition you can use NOT NULL constraint so that null element's wouldn't be able to be there.

http://www.w3schools.com/SQl/sql%5Fnotnull.asp

And use sql UNIQUE constraint so they have to be unique.

http://www.w3schools.com/SQl/sql%5Funique.asp

 CREATE TABLE YourTable
 (
   Field1 varchar(255),
   Field2 varchar(255),
   Field3 varchar(255),
   CONSTRAINT uc_fields UNIQUE (Field1, Field2, Field3)
 )

 CREATE TRIGGER table_null_convert
   ON YourTable
   FOR INSERT, UPDATE 
   REFERENCING NEW ROW AS n
   FOR EACH ROW
     SET n.Field1 = ISNULL(n.Field1, '')
     SET n.Field2 = ISNULL(n.Field2, '')
     SET n.Field3 = ISNULL(n.Field3, '');

And you'll be allowed to insert if these conditions are met.

Hope I got the trigger right. :)

egon
What does the user enter if they don't know one of the values? Sounds like these values have not been required in their business rules.
Jeff O
Sorry I misunderstood. I thought they didn't want the NULL-s at all. I think I would use still a trigger. (Not sure if I got the trigger totally right, haven't done triggers a while).
egon