【问题标题】:SQL Server Conditional InsertSQL Server 条件插入
【发布时间】:2013-04-03 06:03:21
【问题描述】:

我有一个表格,其中包含有关零件供应商的信息

背景:这张表是

的join
  • 部件主记录,其中包含
    • 部件号、部件名称和默认供应商。
  • 另一个表是供应商信息表,其中包含
    • 零件编号与供应商的记录及其对零件的报价(我在此示例中省略了额外信息)

在此表中某些零件的默认供应商为 NULL。 对于这些记录,我想插入一条新记录作为占位符 即下面的#3

有些零件有默认供应商,但没有可能供应商的记录(带报价)。 对于这些记录,我还想插入一条新记录作为占位符。 即下面的#1

当前表

+-------+-----------+-------------------+-------------------+------------+------------+
|PART   |PART NAME  |Default Supplier   |Possible Suppliers |Quote       |InfoComplete|
+-------+-----------+-------------------+-------------------+------------+------------+
|#1     |Part 1     |Supplier 5         |Supplier 1         |25.0        |0           |
|#1     |Part 1     |Supplier 5         |Supplier 2         |20.5        |0           |
|#2     |Part 2     |Supplier 10        |Supplier 10        |10.4        |1           |
|#3     |Part 3     |NULL               |Supplier 3         |9.5         |0           |
|#3     |Part 3     |NULL               |Supplier 4         |11.5        |0           |
+-------+-----------+-------------------+-------------------+------------+------------+

所需的输出(为清楚起见显示空间)

+-------+-----------+-------------------+-------------------+------------+------------+
|PART   |PART NAME  |Default Supplier   |Possible Suppliers |Quote       |InfoComplete|
+-------+-----------+-------------------+-------------------+------------+------------+
|#1     |Part 1     |Supplier 5         |Supplier 1         |25.0        |0           |
|#1     |Part 1     |Supplier 5         |Supplier 2         |20.5        |0           |
|#2     |Part 2     |Supplier 10        |Supplier 10        |10.4        |1           |
|#3     |Part 3     |NULL               |Supplier 3         |9.5         |0           |
|#3     |Part 3     |NULL               |Supplier 4         |11.5        |0           |
|       |           |                   |                   |            |            |     
|#1     |Part 1     |Supplier 5         |**MISSING**        |NA          |0           |
|#3     |Part 3     |**MISSING**        |**MISSING**        |NA          |0           |
+-------+-----------+-------------------+-------------------+------------+------------+

从我阅读的内容来看,合并语句可能是一个解决方案,但我根本无法让它工作。

编辑:

抱歉,我在最初的帖子中应该更清楚一点,正在导出信息以供用户查看缺失的数据。 没有计划替换数据库中的 NULL 值。

我只是想对数据进行操作,让用户更清楚地理解数据。

根据反馈,我正在寻找更好的方式向用户显示信息。

【问题讨论】:

  • 为什么要浪费额外的空间来存储 `**MISSING** 在这些记录中,而 NULL 将是一种更有效和更典型的数据排列方式?此外,采用这种方法会降低默认供应商为空的零件的搜索效率。
  • 我无法从示例中看到第 1 部分(以及第 3 部分)如何从可能的供应商那里获得MISSING

标签: sql sql-server-2008 tsql insert


【解决方案1】:

考虑使用触发器

CREATE TRIGGER NULL_DEFAULTSUPP
AFTER INSERT ON TABLE-NAME
FOR EACH ROW BEGIN
WHERE NEW.Default Supplier IS NULL
BEGIN
INSERT INTO TABLE-NAME VALUES(NEW.PART, NEW.PART-NAME, "**MISSING**", ....);
END;

【讨论】:

    【解决方案2】:

    我决定不再等待听听您想用magic strings 替换 Nulls 的理由。我只能假设您想要这样做,因为您希望您的查询简单,并在默认供应商为 NULL 时输出短语**MISSING**。有更好的方法以非重复方式完成该任务,而不是将您的供应商外键(假设您甚至有一个)转换为从不包含 null 的可为空的 varchar 字段。

    如果是这样的话,我建议你使用视图来访问这些数据:

    IF ( OBJECT_ID('dbo.vw_PartsSuppliers') IS NOT NULL ) 
       DROP VIEW dbo.vw_PartsSuppliers
    GO
    
    CREATE VIEW dbo.vw_PartsSuppliers
    AS
      SELECT 
             p.PartId,
             p.PartName,
             ISNULL(s.SupplierName, '**MISSING**'),
             ISNULL(s.Quote, 'NA'),
             s.InfoComplete
      FROM
             dbo.Part p
             LEFT JOIN dbo.Supplier s ON p.DefaultSupplierId = s.SupplierId            
    GO  
    

    这种方法灵活且可重复使用,并为您提供所需的格式。此外,一旦查询出现,您需要在没有默认供应商的情况下识别零件(您可能会这样做),您将不会遭受性能损失,因为您不是在搜索 **MISSING** 魔术字符串,而是在搜索 NULL。

    【讨论】:

    • 感谢您的帮助。我编辑了我最初的帖子来解释我的疯狂!
    【解决方案3】:

    在这种情况下,SupplierId 用作表 dbo.Supplier 的 PRIMARY KEY,表 dbo.SupplierInfo 的 Id PRIMARY KEY 与 FOREIGN KEY DefSupplierId 上的表 dbo.Supplier 关联

    DECLARE @SupplierId TABLE(SupplierId int)
    
    INSERT dbo.Supplier(Part, PartName, DefaultSupplier)
    OUTPUT inserted.SupplierId INTO @SupplierId(SupplierId) 
    SELECT DISTINCT s.Part, s.PartName, ISNULL(s.DefaultSupplier, '**MISSING**')       
    FROM dbo.Supplier s LEFT JOIN dbo.SupplierInfo i ON s.SupplierId = i.DefSupplierId
    WHERE s.DefaultSupplier IS NULL OR i.PossibleSuppliers IS NULL
    
    INSERT dbo.SupplierInfo
    SELECT SupplierId, '**MISSING**', 0, 0
    FROm @SupplierId
    

    SQLFisddle上的演示

    【讨论】:

      【解决方案4】:

      这是一个稍微简化的示例,您可以如何使用 MERGE 来实现所需的输出。只有一张表PartsSuppliersInfo 包含有关零件和供应商的数据,如上例所示。

      SQLFiddle DEMO

      ;WITH trgtCTE AS 
      (
          SELECT Part, PartName, DefaultSupplier, PossibleSuppliers, Quote, InfoComplete FROM PartsSuppliersInfo
          WHERE DefaultSupplier = '**MISSING**' OR [PossibleSuppliers] = '**MISSING**'
      )
      MERGE trgtCTE AS trgt
      USING
      (
          SELECT DISTINCT Part, PartName, '**MISSING**' AS DefaultSupplier,'**MISSING**' AS PossibleSuppliers, NULL AS Quote, 0 AS InfoComplete  FROM PartsSuppliersInfo
          WHERE DefaultSupplier IS NULL
          UNION 
          SELECT DISTINCT p.Part, PartName, DefaultSupplier,'**MISSING**' AS PossibleSuppliers, NULL AS Quote, 0 AS InfoComplete FROM PartsSuppliersInfo p
          WHERE DefaultSupplier IS NOT NULL AND InfoComplete = 0  
      ) src
      ON src.part = trgt.part AND src.DefaultSupplier = trgt.DefaultSupplier AND src.PossibleSuppliers = trgt.PossibleSuppliers
      WHEN NOT MATCHED BY TARGET THEN
          INSERT (Part, PartName, DefaultSupplier, PossibleSuppliers, Quote, InfoComplete)
          VALUES (Part, PartName, DefaultSupplier, PossibleSuppliers, Quote, InfoComplete)
      WHEN NOT MATCHED BY SOURCE THEN
          DELETE;
      

      MERGE 的目标部分是 CTE,只有行具有 **MISSING** 关键字。第一次它是空的,但每次下一次运行语句,它都会有上一次运行的结果。

      源部分是带有逻辑的子查询,如何计算应该存在哪些**MISSING** 行。

      最后两部分删除不再需要的行(如果部分不再丢失),然后插入新行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-02
        • 1970-01-01
        • 2018-03-30
        相关资源
        最近更新 更多