views:

59

answers:

3

Hi! Wondering if anyone knows an easy way to do this. I have a couple of tables with data, this data is "static" in that way that users don't change it, it's only me that gets to insert/update rows. And I wonder if there's an easy way to insert rows that don't exists and update rows that are different.

The way that I figured would work would be to do like this:

IF((SELECT COUNT(*) FROM myTable WHERE myId = x) = 0)
   INSERT myTable() values()
ELSE
   UPDATE myTable SET data = updatedData WHERE myId = 0

But since I have quite many rows that I want to update, I wonder if there's an easier way to do this. There's a Data comparer in VS Database, is it possible to use it in some way from a query script or some other way? I want these updates to be done when deploying a database project with VS.

Thanks.

+1  A: 

You can make a trigger on datbase which automatically update/insert rows.

Rahul Malhotra
do you mean that the trigger checks if the record exists, and if so updates and if not inserts?
Markus
ya exactly i mean this
Rahul Malhotra
This seems to do exactly what I want. Thank you very much!
Markus
+1  A: 

You can remove the if statement easily, like so:

insert into myTable
select
   <values>
where
   not exists(select * from myTable where myId = @x)

Then, you could check the @@rowcount value. If it is non-zero, then you can exit that section of logic, knowing the record was entered into the database.

If @@rowcount is zero, it means that the record with that id exists in the database and you can issue the update:

update 
    myTable 
set 
    <values>
where 
    myId = @x

Note that you want to make sure this runs within a transaction, as you could have race conditions that occur if you are trying to update this code from two separate clients.

casperOne
Hmm...that is a nicer looking query. :)But it doesn't solve my real problem, I still have to write these two queries for every record. I was hoping for a more "automatic" solution. :)
Markus
+1. Of course, you could fire the update first, then the insert. If the row doesn't exist, nothing will be updated. The insert will only then happen if the the row doesn't exist. You are probably going to take a very small performance hit as a trade off for writing slightly less code, but probably worth it (if the column you're comparing on is properly indexed of course!)
MPritch
@Markus: That's really the best you are going to get. If you were on SQL Server 2008, you could use the MERGE command, as @MPritch indicates in his answer: http://stackoverflow.com/questions/2340020/doing-a-data-compare-with-t-sql-in-a-query/2340112#2340112 but it doesn't seem like that's an option for you. While I don't like the two-query option either, it's the cleanest way (without embedding in an if statement). Note of course, you want to do this within a transaction so that you don't have race conditions.
casperOne
A: 

What you're after is the SQL Server 2008 'MERGE' command. Here's the MS documentation page http://technet.microsoft.com/en-us/library/bb510625.aspx.

Snippet:

MERGE INTO dbo.myTable AS Target
USING (VALUES   ('something 1','other 1'), 
                ('something 2', 'other 2'), 
                ('something 3', 'other 3'))
       AS Source (Field1, Field2)
ON Target.myId = Source.myId
WHEN MATCHED THEN
    UPDATE SET Field1 = Source.Field1,
               Field2 = Source.Field2
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Field1, Field2) 
    VALUES (Field1, Field2)

I'm guessing from the SQL2005 tag that this isn't going to help you much (sorry!), so casperOne's answer is probably the most suitable.

MPritch
@MPritch: Unfortunately he is on SQL Server 2005, as indicated by the tags.
casperOne
Thanks. I made that observation in my answer and recommended your answer for SQL 2005 (as well as upvoting yours...). My answer was added for the community who may be using SQL 2008
MPritch
@casperOne - I presume this is your downvote. Unwarranted IMHO. StackOverflow is a long-term resource, so while this answer is not directly useful to the OP, as observed by MPritch, it's one that people Googling in months and years to come may well find useful. +1 from me to counter.
David M
@David M: With all due respect, your opinion runs contrary to practice on SO, as the discussion on Meta SO about downvoting points out: http://meta.stackoverflow.com/questions/2451/why-do-you-cast-downvotes-on-answers - Specifically, the answer is wrong for the context that the question was presented in. If it was SQL Server 2005, then the downvote wouldn't have been cast, but then again, the answer wouldn't be posted.
casperOne
@David M: Additionally, the vote can't be changed until an edit is made to the answer so I couldn't remove the downvote even with the further clarification. Also, note the tooltip when you hover over the upvote arrow, it says "This answer is useful". Your reasoning for the upvote flies in defiance of that, and you are using it as a tool for *retribution* which doesn't benefit anyone and is technically, an abuse of the voting system.
casperOne
@David M: Finally, I've updated the title of the post to properly reflect the context of the question, so as to remove ambiguity about the question.
casperOne