【问题标题】:SQL Stored Procedure Comparing valuesSQL 存储过程比较值
【发布时间】:2009-04-17 03:37:53
【问题描述】:

假设我有下表

book
-----
id
name
genre
check_out_date
location_id

任何人都可以发布一个高效存储过程的示例,它只更新传入的值与表中的当前值不同的 book 表吗?

即如果我传入值(1,“屠宰场 V”,“小说”,2008 年 10 月 10 日,54) 表中的值为 (1, "Slaughterhouse V, "Fiction", 10/24/2009, 70), 它只会更新 check_out_date 和 location_id 列。

Update Book set check_out_date=@check_out_date (10/24/2009), location_id=@location_id (70).

提前致谢

【问题讨论】:

    标签: sql-server stored-procedures


    【解决方案1】:
    UPDATE book
    SET name = @name,
        genre = @genre,
        check_out_date = @check_out_date,
        location_id = @location_id
    FROM BOOK
    WHERE (id = @id) AND
         (((@name IS NULL AND name IS NOT NULL) OR
           (@name IS NOT NULL AND name IS NULL) OR
           (@name IS NOT NULL AND name IS NOT NULL AND name <> @name)) OR 
          ((@genre IS NULL AND genre IS NOT NULL) OR
           (@genre IS NOT NULL AND genre IS NULL) OR
           (@genre IS NOT NULL AND genre IS NOT NULL AND genre <> @genre)) OR 
         ((@check_out_date IS NULL AND check_out_date IS NOT NULL) OR
           (@check_out_date IS NOT NULL AND check_out_date IS NULL) OR
           (@check_out_date IS NOT NULL AND check_out_date IS NOT NULL AND
            check_out_date <> @check_out_date)) OR 
         ((@location_id IS NULL AND location_id IS NOT NULL) OR
           (@location_id IS NOT NULL AND location_id IS NULL) OR
           (@location_id IS NOT NULL AND location_id IS NOT NULL AND
            location_id <> @location_id)))
    

    【讨论】:

    • 您可能需要进行空值检查,但这可能是多余的。
    • 请注意,这不会更新任何列值为空或任何参数值为空的行(这意味着如果任何参数为空,则不会更新任何行)
    • @Charles 和@Adam:挑剔,挑剔... ;-)
    • 只是想让你诚实;)
    • 我不知道这意味着什么。但是假设它做了 AlteredConcept 想要的,那真的比仅仅更新整行更有效吗?我的意思是,是否有正当理由在更新前进行此类检查?
    【解决方案2】:

    您可能不想这样做,但您也可以先删除具有匹配 ID 的记录,然后再次插入。

    【讨论】:

      【解决方案3】:

      最有效的选择是在 BL 或可能的 DAL 中进行比较,并在那里做出是否更新的决定。

      如果您知道它是更新而不是插入,那么您可能正在阅读记录。并且可能还有其他验证。一站式处理。

      【讨论】:

      • 那么通过 sproc 执行此操作通常较慢吗?如果是这样,要慢多少?编写代码来比较每个对象在应用程序中的值当然是可行的,但我还有 20 个其他类可能也需要进行相同的比较。
      • 如果你在 SP 中测试,你必须为每一行执行 SP。您不调用 0 的 SP 的负载。您将不得不在其中一个或另一个中编写逻辑。我认为您可以看到使用 C# 等更具表现力的语言而不是 TSQL 会更容易。相同的差异 x 20。
      • 所以我可能需要将我的 BookDAL 方法 Update(Book b) 更改为 Update(Book updatedBook, Book originalBook),然后比较对象并仅更新该方法中的更改,对吗?对不起,如果我问了太多问题,但我是 oop 概念的新手。我习惯于只获取更新的值并将它们直接发送到 sp 而无需创建对象。谢谢
      • 通常,如果你有一个 Book 对象,你手头上已经有一个 BookDAL 对象,基于查询数据库以确定它是否存在;并且列值将分配给 Book 对象属性。这些将与 UI 或新字段值的来源进行比较。每当对象属性(名称、标题等)设置器看到与现有值不匹配的值时,设置“脏”属性并不罕见。
      • 您有任何关于如何为每个对象属性创建脏属性的示例吗?这肯定会让事情变得很多更容易,因为我可以在没有其他对象的情况下进行比较。
      【解决方案4】:

      您说的是存储过程,所以没有理由不保持简单并进行单独更新。

      UPDATE book SET name = @name WHERE id = @id and name <> coalesce(@name,name)
      UPDATE book SET genre = @genre WHERE id = @id and genre <> coalesce(@genre,genre)
      UPDATE book SET check_out_date = @check_out_date WHERE id = @id and check_out_date <> coalesce(@check_out_date,check_out_date)
      UPDATE book SET location_id WHERE id = @id and location_id <> coalesce(@location_id,location_id)
      

      【讨论】:

      • 这仍然不能正确处理 NULL。它会在它为 NULL 并且仍然为 NULL 时更新。而且是否在存储过程中与每列一条SQL语句的智慧无关。
      • 已更新以考虑空值,但与依赖应用程序相比,在同一存储过程中执行多次更新仍然是一个更好的答案。
      猜你喜欢
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多