我的团队成员遇到了一些奇怪的行为,可以在开发环境和系统测试环境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
但是,如果他在视图中放置相同的查询,则错误地返回 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
,正确创建一个 517行的表格。但是,如果他在存储过程中放入相同的SQL,则会错误地返回 311行。
似乎一旦查询被封装在数据库对象中,它就会返回太少的行。
如上所述,他也在其他数据库系统上重新创建了错误。
任何想法会导致这种奇怪的行为?
他也试过以下内容但没有取得任何成功:
nolock
更新
我不确定是否使用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
这是其中一个使用的表,不幸的是,数据库非常庞大,有数百个表和视图,所以我不能在这里发布所有内容。
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]
答案 0 :(得分:1)
尝试在SP和/或函数中填充查询并比较返回的记录数。
您看到的内容可能会受到连接ANSI设置的影响。 SSMS和SQL Server默认在每个连接上设置一些,而像视图这样的对象在创建时设置它们并在执行时保持不变。
检查当前为会话启用的选项:
https://www.mssqltips.com/sqlservertip/1415/determining-set-options-for-a-current-session-in-sql-server/
检查视图中保留的选项:
SELECT * FROM sys.sql_modules
答案 1 :(得分: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
答案 2 :(得分:0)
我建议您尝试完成以下语法。我的猜测是在创建存储过程时以某种方式使用中断的旧ANSI JOIN语法。
SELECT
p.package_id
,la.CODE_KID
FROM package AS p
JOIN Strength AS s ON p.Strength_ID = s.Strength_ID
JOIN ProductCODE AS la ON la.Product_ID = s.Product_ID
JOIN CODE AS a ON la.CODE_KID = a.CODE_ID
EXCEPT
SELECT p.package_ID, p.CODE_KID from package p
答案 3 :(得分:0)
真正的问题是,如果将查询封装到视图中,哪些recods会被过滤掉?
所以,正如@Alex之前建议的那样,您应该比较查询中的结果和视图中的相同查询。
SSMS中的尝试类似:
SELECT *
FROM (
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
) AS DIRECT_Q
FULL JOIN
(
SELECT *
FROM YOUR_VIEW_CREATED_FROM_QUERY /* <-- THE NAME OF YOUR VIEW */
) AS VIEWED_Q
ON DIRECT_Q.package_id=VIEWED_Q.package_id
AND DIRECT_Q.CODE_KID=VIEWED_Q.CODE_KID
通过这种方式,您将看到哪些记录丢失并尝试了解原因(空值,重音符号,特定字符ecc ecc)
我还会检查package.CODE_KID和ProductCODE.CODE_KID的数据类型和排序规则是否相同。