【问题标题】:SQL Server Insert Using ViewSQL Server 使用视图插入
【发布时间】:2016-08-30 18:15:44
【问题描述】:

这是我想做的一个简化示例。假设有一个名为contractor 的表,如下所示:

name | paid_adjustment_amount | adj_date
Bob  | 1000                   | 4/7/2016
Mary | 2000                   | 4/8/2016
Bill | 5000                   | 4/8/2016
Mary | 4000                   | 4/10/2016
Bill | (1000)                 | 4/12/2016
Ann  | 3000                   | 4/30/2016

有一个contractor 表的视图,我们称之为v_sum,它只是按名称分组的paid_adustment_amount 的SUM。所以它看起来像这样:

name | total_paid_amount
Bob  | 1000
Mary | 6000
Bill | 4000
Ann  | 3000

最后,还有一个名为 to_date_payment 的表,如下所示:

name | paid_to_date_amount
Bob  | 1000
Mary | 8000
Bill | 3000
Ann  | 3000
Joe  | 4000      

我想将 to_date_payment 表中的信息与 v_sum 视图进行比较,并在contractor 表中插入一个新行以显示调整。像这样的:

INSERT INTO contractor
SELECT to_date_payment.name, 
    to_date_payment.paid_to_date_amount - v_sum.total_paid_amount,
    GETDATE()
FROM to_date_payment
LEFT JOIN v_sum ON to_date_payment.name = v_sum.name
WHERE to_date_payment.paid_to_date_amount - v_sum.total_paid_amount <> 0
    OR v_sum.name IS NULL

为此使用视图有什么问题吗?我的理解是,如果我错了,请纠正我,视图只是查询的结果集。而且,由于视图是我正在向其中插入新记录的表,我担心可能存在数据完整性问题。

感谢您的帮助!

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    为了完全了解您在做什么,您还应该提供v_sum 的定义。一般来说,视图可能会提供一些优势,尤其是在索引时。更多详情请见herehere

    视图的简单使用不会带来性能优势,但它们非常适合提供对表的抽象。

    在您的特定情况下,我认为加入视图没有任何问题,但我会担心与以下相关的潜在问题:

    1) JOIN 使用 VARCHARs 而不是整数 - ON to_date_payment.name = v_sum.name - 如果可能,尝试在整数(ids 或外键 ids)值上JOIN,因为它是更快(应用于整数列的索引将具有更小的键,比较会稍微快一些)。

    2) 查询中的 OR - 通常会导致性能问题。要尝试的一件事是像这样更改 SELECT:

    SELECT to_date_payment.name, 
        to_date_payment.paid_to_date_amount - v_sum.total_paid_amount,
        GETDATE()
    FROM to_date_payment
    JOIN v_sum ON to_date_payment.name = v_sum.name
    WHERE to_date_payment.paid_to_date_amount - v_sum.total_paid_amount <> 0
    
    UNION ALL
    
    SELECT to_date_payment.name, 
        to_date_payment.paid_to_date_amount,    -- or NULL if this is really intended
        GETDATE()
    FROM to_date_payment
    -- NOT EXISTS is usually faster than LEFT JOIN ... IS NULL
    WHERE NOT EXISTS (SELECT 1 FROM v_sum V WHERE V.name = to_date_payment.name)
    

    3) 可能的不良结果 - 默认情况下,涉及 NULL 的算术返回 NULL。当 v_sum 中没有匹配项时,v_sum.total_paid_amount 为 NULL,to_date_payment.paid_to_date_amount - v_sum.total_paid_amount 将评估为 NULL。它是否正确?也许to_date_payment.paid_to_date_amount - ISNULL(v_sum.total_paid_amount, 0) 是有意的。

    【讨论】:

    • 谢谢! #1 不幸的是,我无法控制唯一标识符。它们不是名称,而是从需要 VARCHAR 的外部来源提供的字母数字组合(例如 AB123)。 #2 我以前用 UNION 代替 OR。但是,我应该避免所有 OR 和 IN 吗?我可以想到一个不相关的查询,其中我有一个在 IN 子句中有 6 个项目的条件。我应该改为用 5 个联合编写 6 个查询吗??? #3很好的收获。感谢您的帮助!
    • #2。这个要根据实际的执行计划来考虑。如果您没有大量记录,OR/IN 可能仍会获得合理的时间。此外,对于复杂的查询,您可以定义一个临时表并执行多个插入。除了可能的性能优化外,它还允许更轻松的调试(每次插入后临时检查)。
    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多