我正在尝试对远程 2000 服务器运行查询;但是本地服务器正在生成的查询不正确,导致远程服务器返回错误:
列前缀“Tbl1002”与查询中使用的表名或别名不匹配。
当你跟踪远程服务器时,你可以看到该sp_cursorprepexec
批处理实际上是无效的 SQL;它引用了一个Tbl1002
不存在的派生表。
我在本地服务器上运行的查询是:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(*)
FROM Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM Positions P
WHERE P.PositionID = '{D1B0912D-B1A5-11D4-BBDD-0004ACC5B8A7}'
WhereEmployees
和Positions
are 视图只是从链接服务器中选择的。为了消除这种混淆,我们将消除视图 - 并直接使用四部分命名:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(*)
FROM WCLHR.CasinoHR.dbo.Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM WCLHR.CasinoHR.dbo.Positions P
WHERE P.PositionID = '{D1B0912D-B1A5-11D4-BBDD-0004ACC5B8A7}'
查询仍然失败:
列前缀“Tbl1002”与查询中使用的表名或别名不匹配。
为了消除对子句中 guid 的任何混淆WHERE
,我们将删除该WHERE
子句:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(*)
FROM WCLHR.CasinoHR.dbo.Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM WCLHR.CasinoHR.dbo.Positions P
它仍然失败:
列前缀“Tbl1002”与查询中使用的表名或别名不匹配。
为了消除对*
in使用的任何混淆COUNT
,我们将消除它,而只计算一个常量:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(1)
FROM WCLHR.CasinoHR.dbo.Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM WCLHR.CasinoHR.dbo.Positions P
它仍然失败:
列前缀“Tbl1002”与查询中使用的表名或别名不匹配。
再往下,我们甚至会消除链接服务器,并在 2000 机器上本地运行查询。
如果您在远程服务器本身上运行它会怎样?
如果我对远程服务器本身运行此查询:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(*)
FROM Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM Positions P
它工作正常。
生成的查询是什么,你怎么知道它是坏的?
使用 Profiler,我们可以看到进入远程服务器的查询。这是一个巨大的可怕的混乱,但它绝对是无效的。它尝试引用不在范围内的派生表。任何在 SQL Server 中使用过远程服务器的人都会熟悉整个批次:
declare @P1 int
set @P1=NULL
declare @P2 int
set @P2=NULL
declare @P3 int
set @P3=557064
declare @P4 int
set @P4=98305
declare @P5 int
set @P5=0
exec sp_cursorprepexec @P1 output, @P2 output, NULL, N'SELECT "Tbl1002"."PositionID", .....
select @P1, @P2, @P3, @P4, @P5
真正的问题是另一个 SQL Server 要求服务器准备的 SQL 语句。修剪下来,它说:
SELECT
"Tbl1002"."PositionID" "Col1010", ...
( SELECT "Expr1007"
FROM (
SELECT "Expr1006","Expr1006" "Expr1007"
FROM (
SELECT COUNT(*) "Expr1006"
FROM (
SELECT
"Tbl1005"."EmployeeID" "Col1043", ...
FROM "CasinoHR"."dbo"."Employees" "Tbl1005"
WHERE "Tbl1005"."PositionID"="Tbl1002"."PositionID"
) Qry1103
) Qry1104
) "Subquery_Source_Tbl"
) "Expr1008"
FROM "CasinoHR"."dbo"."Positions" "Tbl1002"
WHERE "Tbl1002"."PositionID"={guid'D1B0912D-B1A5-11D4-BBDD-0004ACC5B8A7'}'
这是一个混乱的阅读,但你可以看到问题,它Tbl1002
在一些嵌套的派生表中引用:
WHERE "Tbl1005"."PositionID"="Tbl1002"."PositionID"
但只在外面声明;在最后:
FROM "CasinoHR"."dbo"."Positions" "Tbl1002"
我们在这里讨论的是什么版本的 SQL Server?
我们试图查询的“远程”服务器(“wclhr”)是带有 SP4 的 SQL Server 2000:
Microsoft SQL Server 2000 - 8.00.2066(英特尔 X86)2012 年 5 月 11 日 18:41:14
发出查询时,我们尝试了 SQL Server 2005 和 SQL Server 2008 R2。当两台服务器都是 SQL Server 2000 时,它曾经可以工作。
从 SQL Server 2005 开始,一直到 2008 R2,它正在生成无效的SQL!
我们尝试过的其他事情
令人惊讶的是,一个可怕的 hack 是运行:
SELECT TOP 99.999999 PERCENT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(1)
FROM WCLHR.CasinoHR.dbo.Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM WCLHR.CasinoHR.dbo.Positions P
这会阻止本地 SQL Server 2008 R2 为 2000 机器生成无效的 sql。
本地服务器不是 64 位的,但我们还是升级了 SQL Server 2000 上的目录。它没有解决它。
您的原始查询不是同样错误吗?
@Damien the Unbeliever 不相信范围界定可能是问题所在。放心,是的。我的原始查询针对 SQL Sever 2000 正确运行:
SELECT
P.Code, P.Name AS PositionName, P.CompCommitteeMember,
( SELECT COUNT(*)
FROM Employees E
WHERE E.PositionID = P.PositionID
) AS EmployeeCount
FROM Positions P
WHERE P.PositionID = '{D1B0912D-B1A5-11D4-BBDD-0004ACC5B8A7}'
不幸的是,SQL Server 2005/2008/2008R2 优化器将该查询转换为等效查询 - 但不幸的是 SQL Server 2000 无法执行的查询:
SELECT
Tbl1002.PositionID,
Tbl1002.Name AS PositionName,
Tbl1002.CompCommitteeMember,
( SELECT RecordCount
FROM (
SELECT COUNT(*) AS RecordCount
FROM (
SELECT
Employees.EmployeeID
FROM Employees
WHERE Employees.PositionID=Tbl1002.PositionID
) Qry1103
) Qry1104
) AS EmployeeCount
FROM Positions Tbl1002
WHERE Tbl1002.PositionID= 'D1B0912D-B1A5-11D4-BBDD-0004ACC5B8A7'
在 SQL Server 2000 上,它给出:
Msg 107, Level 16, State 2, Line 12
The column prefix 'Tbl1002' does not match with a table name or alias name used in the query.
SQL Server 2000 似乎存在关联子查询的范围问题;在 SQL Server 2005中得到“改进” 。