数据库对象中的封装查询返回的行太少

12 sql sql-server

我的团队成员已经获得了一些奇怪的行为,可以在开发环境和系统测试环境MS SQL数据库中重新创建.

如果他直接运行此查询,则返回517行,这是正确的预期结果:

SELECT 
        p.package_id, la.CODE_KID
    FROM package p with (nolock), Strength s with (nolock),
    ProductCODE la  with (nolock), CODE  a with (nolock)
    where p.Strength_ID = s.Strength_ID
    and la.Product_ID = s.Product_ID
    AND la.CODE_KID = a.CODE_ID
    except 
    select p.package_ID, p.CODE_KID from package p
Run Code Online (Sandbox Code Playgroud)

但是,如果他在视图中放置相同的查询,则错误地返回311行 - 比直接运行查询时少206行.

如果我们为直接查询和视图查询运行查询分析器,我们会看到两个查询计划完全不同,但我们不明白为什么.

他还试图将查询转储到临时表中:

insert into MyDB.CODE_PACKAGE
    SELECT 
            p.package_id, la.CODE_KID
        FROM package p with (nolock), Strength s with (nolock),
        ProductCODE la  with (nolock), CODE  a with (nolock)
        where p.Strength_ID = s.Strength_ID
        and la.Product_ID = s.Product_ID
        AND la.CODE_KID = a.CODE_ID
        except 
        select p.package_ID, p.CODE_KID from package p
Run Code Online (Sandbox Code Playgroud)

,正确创建一个包含517行的表.但是,如果他将相同的SQL放在存储过程中,则会错误地返回311行.

似乎一旦查询被封装在数据库对象中,它就会返回太少的行.

如上所述,他也在其他数据库系统上重新创建了错误.

什么想法会导致这种奇怪的行为?

他也尝试过以下方面但没有取得任何成功:

  • 除掉 nolock
  • 将事务隔离级别设置为read uncommitted

更新

我不确定是否使用SSMS向导或模板来创建视图,但如果我选择"脚本视图为 - >创建到 - >新查询编辑器窗口",那么这是输出:

USE [TestUtv]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE view [MyDBviews].[CODE_PACKAGE]
as

    SELECT 
            p.package_id, la.CODE_KID
        FROM package p with (nolock), Strength s with (nolock),
        ProductCODE la  with (nolock), CODE  a with (nolock)
        where p.Strength_ID = s.Strength_ID
        and la.Product_ID = s.Product_ID
        AND la.CODE_KID = a.CODE_ID
        except 
        select p.package_ID, p.CODE_KID from package p

GO
Run Code Online (Sandbox Code Playgroud)

这是使用的表之一,遗憾的是数据库非常庞大,有数百个表和视图,所以我不能在这里发布所有内容.

CREATE TABLE [dbo].[Package](
    [Package_ID] [uniqueidentifier] NOT NULL,
    [Multiple] [int] NULL,
    [Multiple2] [int] NULL,
    [OutProdnum] [varchar](6) NULL,
    [OutProdnumDate] [datetime] NULL,
    [zzzPackage_KID] [uniqueidentifier] NULL,
    [Strength_ID] [uniqueidentifier] NULL,
    [Indi] [varchar](4096) NULL,
    [CreatedDate] [datetime] NULL,
    [CreatedBy] [varchar](255) NULL,
    [LastChangedDate] [datetime] NULL,
    [LastChangedBy] [varchar](255) NULL,
    [CODE_KID] [uniqueidentifier] NULL,
    [MarkDate] [datetime] NULL,
    [Amount] [int] NULL,
    [KIPackage_ID] [uniqueidentifier] NULL,
    [xyz] [bit] NULL,
    [Ean] [varchar](255) NULL,
    [D_ID] [uniqueidentifier] NULL,
    [abc_ID] [uniqueidentifier] NULL,
    [DDD] [decimal](18, 4) NULL,
    [era_KID] [uniqueidentifier] NULL,
    [uuu] [decimal](18, 4) NULL,
    [ueer_KID] [uniqueidentifier] NULL,
    [abcIdString] [varchar](4095) NULL,
    [ExternalId] [varchar](255) NULL,
    [Dpack_KID] [uniqueidentifier] NULL,
    [tttpacks_KID] [uniqueidentifier] NULL,
 CONSTRAINT [Package_PK] PRIMARY KEY CLUSTERED 
(
    [Package_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

Lau*_*gil 0

使用 JOIN 语句尝试相同的查询。对于使用这种旧连接技术的查询,您可能会从不同的查询计划中得到不同的结果。

SELECT 
    p.package_id, 
    la.CODE_KID
FROM package p with (nolock)
INNER JOIN Strength s with (nolock)
    ON p.Strength_ID = s.Strength_ID
INNER JOIN ProductCODE la with (nolock)
    ON la.Product_ID = s.Product_ID
INNER JOIN CODE a with (nolock)
    ON la.CODE_KID = a.CODE_ID
EXCEPT
SELECT 
    p.package_ID, 
    p.CODE_KID 
FROM package p
Run Code Online (Sandbox Code Playgroud)