我有这个重度嵌套的sql语句,在我的sql server 2008 express中运行良好 [下面的代码块]
但是,当我将它移到我们的初步测试服务器(sql server 2000)时,除非我在每个语句的from子句中使用完全解析的表引用,否则它不起作用。我不能这样做,因为数据库名称因现场安装而异。
它给了我这个错误信息:
Msg 913,Level 16,State 8,Line 14 找不到数据库ID 102.数据库可能尚未激活或可能正在转换。
我在这个[sql newsgroups]论坛中找到了一个主题;这表明未修补的sql server设置导致错误。
Microsoft支持链接: This will work for ~10 minutes or until microsoft changes its website document locations.
从链接:
You may receive a 913 error message when you run a query that meets the following conditions:
文章指出您可以通过修补sql server安装来解决此问题。 (这很容易。而且,不可能,因为我们不能强制客户端更新。)或者通过简化sql语句;在我的情况下,这可能意味着减少派生表的数量。具体来说,看起来最后一个带有GROUP BY
子句的问题就是问题。 (也许,一个派生表太过分了。)
那么,如何在不破坏查询的情况下简化此查询呢?
由于
使用[mydatabase]
SELECT [Desc],
[Series],
[Manufacturer],
[Distributer],
MAX(LastOrdr) AS LastOrdr,
[Minimum],
SUM(Qty) AS Qty
FROM (SELECT [pptype].[Desc],
COALESCE(cStock.Serial,' ') AS Serial,
COALESCE([misccode].Descript,' ') AS Series,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Mfg),' ') AS Manufacturer,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Distrib),' ') AS Distributer,
[ppType].Minimum,
COALESCE(cQty.Qty,0) AS Qty,
COALESCE(cStock.Recvd,0) AS LastOrdr,
[pptype].Trkser
FROM (SELECT [Typeid], [Serial], [Series], MAX([Recvd]) AS Recvd FROM [dbo].[ppstock] WHERE [Invoice] != 'SETUP' GROUP BY [Typeid], [Serial], [Series]) cStock
LEFT OUTER JOIN [dbo].[pptype] ON
cStock.[Typeid] = [pptype].Typeid
LEFT OUTER JOIN (SELECT [Typeid], [Serial], SUM([Qty]) AS Qty FROM [dbo].[pplocatn] GROUP BY [Typeid], [Serial]) cQty ON
cStock.[Typeid] = cQty.[Typeid] AND cStock.Serial = CASE
WHEN [dbo].EMPTY(cStock.Serial) = 1 THEN 'Do not match.' ELSE cQty.[Serial] END
LEFT OUTER JOIN [dbo].[misccode] ON
cStock.[Series] = [misccode].[Code] AND [misccode].[type] = 'SERIES'
WHERE [dbo].EMPTY([pptype].Inactive) = 1 and
(COALESCE(cQty.Qty,0) < [pptype].Minimum)) cData
GROUP BY [Desc],[Series],[Manufacturer],[Distributer],[Minimum]
答案 0 :(得分:1)
您可以将其中一个内部派生表分解为临时表吗? IE:
SELECT [Typeid], [Serial], [Series], MAX([Recvd]) AS Recvd
INTO #InnerTable1
FROM [dbo].[ppstock] WHERE
[Invoice] != 'SETUP' GROUP BY [Typeid], [Serial], [Series]) cStock
LEFT OUTER JOIN [dbo].[pptype] ON
cStock.[Typeid] = [pptype].Typeid
LEFT OUTER JOIN (SELECT [Typeid], [Serial], SUM([Qty]) AS Qty FROM [dbo].[pplocatn] GROUP BY [Typeid], [Serial]) cQty ON
cStock.[Typeid] = cQty.[Typeid] AND cStock.Serial = CASE
WHEN [dbo].EMPTY(cStock.Serial) = 1 THEN 'Do not match.' ELSE cQty.[Serial] END
LEFT OUTER JOIN [dbo].[misccode] ON
cStock.[Series] = [misccode].[Code] AND [misccode].[type] = 'SERIES'
WHERE [dbo].EMPTY([pptype].Inactive) = 1 and
(COALESCE(cQty.Qty,0) < [pptype].Minimum
SELECT [Desc],
[Series],
[Manufacturer],
[Distributer],
MAX(LastOrdr) AS LastOrdr,
[Minimum],
SUM(Qty) AS Qty
FROM (SELECT [pptype].[Desc],
COALESCE(cStock.Serial,' ') AS Serial,
COALESCE([misccode].Descript,' ') AS Series,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Mfg),' ') AS Manufacturer,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Distrib),' ') AS Distributer,
[ppType].Minimum,
COALESCE(cQty.Qty,0) AS Qty,
COALESCE(cStock.Recvd,0) AS LastOrdr,
[pptype].Trkser
FROM #InnerTable1) cData
GROUP BY [Desc],[Series],[Manufacturer],[Distributer],[Minimum]
这应该有效,因为内部表是你的外部查询的基础。如果涉及到连接,并且您是根据内部数据从其他表中进行选择,那么我会担心这两个查询之间发生数据更改的可能性,但是因为您从最里面的连接中选择了所有数据,使用临时表不应该有任何问题。
如果由于某种原因这不起作用,请回复,我会尝试进一步调整它,以便它。
答案 1 :(得分:1)
所以,这就是我最终要做的事情。我拆分了内部sql语句,并使用DECLARE @foo TABLE
语法创建了一个临时表,我填充了INSERT INTO
。然后我使用临时表进行最终选择。
此过程在我的SQL Server 2000测试环境中编译;虽然我还没有开始我的alpha测试。如果它没有结束,我会回复。
感谢。
DECLARE @cData TABLE (
[Desc] VARCHAR(25),
[Series] VARCHAR(40),
[Manufacturer] VARCHAR(30),
[Distributer] VARCHAR(30),
[LastOrdr] CHAR(8),
[Minimum] SMALLINT,
[Qty] INT
)
INSERT INTO @cData (
[Desc],
[Series],
[Manufacturer],
[Distributer],
[LastOrdr],
[Minimum],
[Qty]
)
SELECT [pptype].[Desc],
COALESCE([misccode].Descript,' ') AS Series,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Mfg),' ') AS Manufacturer,
COALESCE((SELECT vendors.vn_Name FROM [dbo].vendors WHERE vendors.Vn_id = [pptype].Distrib),' ') AS Distributer,
COALESCE(cStock.Recvd,0) AS LastOrdr,
[ppType].Minimum,
COALESCE(cQty.Qty,0) AS Qty
FROM (SELECT [Typeid], [Serial], [Series], MAX([Recvd]) AS Recvd FROM [dbo].[ppstock] WHERE [Invoice] != 'SETUP' GROUP BY [Typeid], [Serial], [Series]) cStock
LEFT OUTER JOIN [dbo].[pptype] ON
cStock.[Typeid] = [pptype].Typeid
LEFT OUTER JOIN (SELECT [Typeid], [Serial], SUM([Qty]) AS Qty FROM [dbo].[pplocatn] GROUP BY [Typeid], [Serial]) cQty ON
cStock.[Typeid] = cQty.[Typeid] AND cStock.Serial = CASE
WHEN [dbo].EMPTY(cStock.Serial) = 1 THEN 'Do not match.' ELSE cQty.[Serial] END
LEFT OUTER JOIN [dbo].[misccode] ON
cStock.[Series] = [misccode].[Code] AND [misccode].[type] = 'SERIES'
WHERE [dbo].EMPTY([pptype].Inactive) = 1 and
(COALESCE(cQty.Qty,0) < [pptype].Minimum)
ORDER BY [Desc],[Series],[Manufacturer],[Distributer],[Minimum]
SELECT [Desc],
[Series],
[Manufacturer],
[Distributer],
MAX(LastOrdr) AS LastOrdr,
[Minimum],
SUM(Qty) AS Qty
FROM @cData
GROUP BY [Desc],[Series],[Manufacturer],[Distributer],[Minimum]
ORDER BY [Desc],[Series],[Manufacturer],[Distributer],[Minimum]
答案 2 :(得分:0)
您可能知道,但我建议在表调用上使用(NOLOCK)提示,因为您的查询涉及许多表,可能存在表锁。如果这有帮助,请告诉我。
另外我认为您可以CTE查询。试一下。