2013-12-17 78 views
0

这个问题似乎有点愚蠢,但我问,因为我的SQL已经变得相当生疏。使用SQL更新现有记录

我想在Microsoft SQL数据库中做一个简单的更新。我有一个我自己创建的数据库表项的对象表示。

它得到了所有的数据库表具有字段和现在我需要做的就是用新的数据,我从一个客户端应用程序得到了更新数据库中的原始记录。我从客户那里得到每一个领域,甚至是没有改变的领域。我需要以某种方式发出SQL语句:

  1. 查找数据库中的现有记录。
  2. 只更新数据中字段不同的记录。

我甚至不确定是否可以在SQL语句中检查它,或者只是简单地覆盖数据,而不管它是否与原始数据相同。

+0

出于好奇,你为什么不使用像NHibernate的或实体框架的ORM,因为他们会解决这些问题给你。 – Dai

+0

@Dai因为我有6个星期的时间来编写一个相当庞大的数据应用程序,并且在记录所有内容时编写一份报告来启动。所以我没有考虑过。这是一个原型,所以我可以随时切换到实体或nHibernate^_^ – OmniOwl

回答

0

所以这里是一个方法:

 
1.) Do a equi join 
Table1 
FirstName LastName PrimaryKey 
Jay  Donner 1 
Steven Woods  2 
Bruce  Beard  3 
Table2 
Firstname LastName PrimaryKey 
Jay  Donner 1 
Steven Wood  2 
Bruce  Bears  3 

所以内连接

Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
On A.FirstName = B.FirstName 
AND A.LastName = B.LastName 

现在的结果集将匹配字段 杰伊·唐纳1

既然你想找到与 不匹配的字段可以使用'not in'命令使用子查询,如下所示:

Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
ON A.PrimaryKey =B.PrimaryKey 
Where A.PrimaryKey NOT IN (
    Select A.PrimaryKey 
    From Table1 A INNER JOIN Table2 B 
    On A.FirstName = B.FirstName 
    AND A.LastName = B.LastName 
) 

因此,上面的查询指出:找到主键匹配并且属性与名字和姓氏字段中的值不匹配的东西。

 
Steven Woods  2 
Bruce  Bear  3 

现在您知道需要更新的主键。接下来,用update语句遍历表。光标是一块蛋糕,但我想有人告诉你在这里使用CTE递归。祝你好运......这就是我讨厌SQL的原因。 这是一个使用游标递归的例子...因此,我个人将使用Entity Framework的c#执行此任务,并将其作为可执行命令与SSIS包一起包装在我的SQL Server中。 反正!下面是迭代。

这里的示例代码没有评论。

申报@fname如为nvarchar(50)

Declare @LName as nvarchar(100) 

声明@PrimaryKeyas诠释

Declare PersonCursor CURSOR FAST_FORWARD FOR 


Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
ON A.PrimaryKey =B.PrimaryKey 
Where A.PrimaryKey NOT IN (
    Select A.PrimaryKey 
    From Table1 A INNER JOIN Table2 B 
    On A.FirstName = B.FirstName 
    AND A.LastName = B.LastName 
) 


OPEN PersonCursor 

FETCH NEXT FROM PersonCursor 

INTO @FName, @LName, @Email 


WHILE @@FETCH_STATUS = 0 

BEGIN 

-- do row specific stuff here 



    UPDATE table2 
    SET [EmployeeIdentification]= @Fname, [email protected] 
    WHERE [email protected] 


FETCH NEXT FROM PersonCursor 

INTO @FName, @LName, @Email 

END 


CLOSE PersonCursor 

DEALLOCATE PersonCursor 
+0

对不起,如果答案不完整,但它应该给你非常好的主意。让我知道,如果我漏了一个主要的漏洞。 – hidden

+0

你是对的,这确实给了我一个很好的主意。相当不错的答案,我会继续接受:) – OmniOwl

+0

如果你有SQL服务器2008或以上使用合并命令,而不是我的光标会很大,如下所示。我忘了那个。 – hidden

1

所以我猜你正在使用ADO.NET ...

当你加载你的对象,你会在对象上填充主键等效场。假设它是一个int标识或者不是,如果你正在创建一个新的对象,它将会是0。否则,它将是您从数据库中加载它时得到的值。

当然,你必须确保你所做的任何绑定都具有价值。

因此,当你坚持对象到数据库,检查对象的主键值,并呼吁无论是插入或相应的更新方法。

正如戴秉国说,不过,你的里程将强烈的更好,如果你选择一个ORM。实体框架有一点学习曲线。虽然我不是PetaPoco的粉丝,但对于非常小规模的项目来说,这是相当不错的。

0

Finds an existing record in the Database

我把它放在一个存储过程。

or if I simply have to just overwrite data regardless of it being the same as the original or not.

我个人使用的方法在这一切每一次更新。只要确保你没有更新那些不属于主键的列。例如:UPDATE table set firstname = @firstname, @lastname = lastname where userid = @userid。只要确保你不更新UserID

基于你的问题还没有明确,你是否需要看实际的代码?

+0

如果可能的话肯定。我不会乞求代码,这是粗鲁的^^。问题是我有很多的领域。 24确切地说。 – OmniOwl

0

你可以做到这一点,但它会非常长篇大论的速度非常快,如果有一个可为空领域涉及它变得可怕。长期以来,标准方法只是覆盖所有领域。 如果您想避免重复其他人的编辑,我建议您使用时间戳字段,并检查单个列值在更新时未更改。

+0

这就是假设在他的特定用例中,多个用户将同时更新相同的记录,否则你甚至不必使用TimeStamp,对吧? – logixologist

+0

更新将由服务器管理,以便它们按顺序进入。两个客户端不可能同时连接到数据库。 – OmniOwl