T-SQL中的主/明细关系

时间:2011-10-31 17:59:05

标签: sql-server tsql

在一个专注于生成订单的普通t-sql数据库中,我注意到有几个表(想想订单头和订单行),它们没有在数据库中定义的真实约束。是否存在定义此约束的缺点?它似乎会阻止孤儿记录...

更新:我要问的一个原因是,在生成Order Header / Order Line结构的存储过程中,有一些代码如下:

SELECT  @sc_count = COUNT(*)
FROM    shopping_cart
WHERE   session_id = @sessionid 

INSERT  INTO log_table
        ( col1 ,
          col2 ,
          col3 ,
          col4 ,
          col5 ,
          col6 
        )
VALUES  ( 'load config' ,
          'count before' ,
          @sc_count ,
          @sessionid ,
          @quoteid ,
          @login_name 
        ) 

DECLARE @quote_product_id UNIQUEIDENTIFIER
DECLARE cart_cur CURSOR
FOR
    SELECT  quote_product_id
    FROM    quote_products
    WHERE   quote_id = @quoteid
OPEN cart_cur
FETCH NEXT FROM cart_cur INTO @quote_product_id

WHILE @@fetch_status = 0 
    BEGIN
        INSERT  INTO log_table
                ( col1 ,
                  col2 ,
                  col3 ,
                  col4 ,
                  col5
                )
        VALUES  ( 'load cart' ,
                  @sessionid ,
                  @quoteid ,
                  'checking product' ,
                  @quote_product_id
                )
        IF NOT EXISTS ( SELECT  session_product_id
                        FROM    shopping_cart
                        WHERE   session_product_id = @quote_product_id ) 
            BEGIN

                BEGIN TRY
                    INSERT  INTO shopping_cart
                            ( session_product_id ,
                              session_id ,
                              product_dim_id ,
                              quantity ,
                              price ,
                              picked_by_user ,
                              category_id ,
                              kit_id ,
                              price_list_id ,
                              configuration_id ,
                              origin_by ,
                              origin_date ,
                              changed_by ,
                              change_date ,
                              from_product ,
                              base_category_id ,
                              discount ,
                              discount_amount
                        )
                            SELECT  quote_product_id ,
                                    @sessionid ,
                                    product_dim_id ,
                                    quantity ,
                                    unit_price ,
                                    picked_by_user ,
                                    category_id ,
                                    kit_id ,
                                    price_list_id ,
                                    configuration_id ,
                                    origin_by ,
                                    origin_date ,
                                    changed_by ,
                                    change_date ,
                                    from_product ,
                                    NULL,
                                    discount ,
                                    discount_amount

                            FROM    quote_products
                            WHERE   quote_product_id = @quote_product_id
                END TRY
                BEGIN CATCH
                    DECLARE @error_number INT
                    DECLARE @error_message NVARCHAR(2048)
                    SELECT  @error_number = ERROR_NUMBER() ,
                            @error_message = ERROR_MESSAGE()

                    DELETE  FROM shopping_cart_header
                    WHERE   session_id = @sessionid
                    INSERT  INTO log_table
                            ( col1 ,
                              col2 ,
                              col3 ,
                              col4 ,
                              col_max
                            )
                    VALUES  ( 'dm load cart error - CATCH' ,
                              @sessionid ,
                              @quoteid ,
                              @error_number ,
                              @error_message
                            )

                    SELECT  @kitid AS kit_id ,
                            @pricelistid AS price_list_id ,
                            NEWID() AS configuration_id ,
                            0 AS cart_number_of_products ,
                            1 AS quote_number_of_products

                    RETURN 
                END CATCH

            END 
        ELSE 
            BEGIN
                UPDATE  shopping_cart
                SET     session_id = @sessionid
                WHERE   session_product_id = @quote_product_id
            END

        FETCH NEXT FROM cart_cur INTO @quote_product_id
    END

CLOSE cart_cur
DEALLOCATE cart_cur

SELECT  @sc_count = COUNT(*)
FROM    shopping_cart
WHERE   session_id = @sessionid 
INSERT  INTO log_table
        ( col1 ,
          col2 ,
          col3 ,
          col4 ,
          col5 ,
          col6 
        )
VALUES  ( 'load config' ,
          'count after' ,
          @sc_count ,
          @sessionid ,
          @quoteid ,
          @login_name 
        )

似乎存储过程正在尝试识别一个错误的状态,其中quote_product_id从某个WHERE子句条件返回更多行,然后是另一个。有一条评论基本上说报价可能会错误地保存,因此现在必须进行检查以确保所有报价产品(行)都存在并计算在内。

1 个答案:

答案 0 :(得分:2)

我可以想到两个可能的原因,但我相信还有更多原因:

  1. 参照完整性约束可能会影响性能。这并不意味着它们不应该被使用或启用(除非经过仔细的分析,否则你确定事实确实如此)。
  2. 插入顺序不允许保留约束。由于数据库有时可能处于无效状态,除非所有此类操作都在事务中得到谨慎维护,所以在每次事务结束时保持数据库有效。
  3. 没有出于这个原因的约束是一个冒险的命题,因为数据库有时可能处于无效状态。