MS-Access 与 .NET 的相同查询的排序顺序不同
本文关键字:排序 顺序 查询 NET MS-Access | 更新日期: 2023-09-27 18:32:31
我正在将遗留的 Access 应用程序移植到 .NET Framework,并且需要保持相同的数据排序顺序。连接到同一数据库时,ACCESS 应用程序使用按如下方式配置的 ODBC 连接:
Microsoft SQL Server 本机客户端版本 11.00.2100
数据源名称:中央主机集数据库
数据源说明:
服务器:本地主机''sqlexpress
使用集成安全性:是
数据库:中央SQL15
语言:(默认(
数据加密:否
信任服务器证书:否
多个活动结果集 (MARS(:否
镜像服务器:
翻译字符数据:是
日志长时间运行的查询:否
日志驱动程序统计信息:否
使用区域设置:否
使用 ANSI 引号标识符:是
使用 ANSI 空值、填充和警告:是
在.NET应用程序中,我最初使用SqlClient和SQL Server的连接字符串,但是我也尝试使用OdbcConnection/OdbcCommand/OdbcDataReader,使用与Access完全相同的ODBC连接。但是,ACCESS 和 .NET 之间的排序顺序始终不同。
例如,对于查询:
SELECT sessionstn3270.sessionid,
sessionnames.sessionname,
sessionstn3270.sessiontypeid,
sessionstn3270.usernameid,
sessionnames.host,
sessionnames.port,
lus.lu,
sessionnames.lastmodifiedsn,
templates.template,
templates.templatetype,
sessionnames.sessiontype
FROM (sessionnames
LEFT JOIN templates
ON sessionnames.template = templates.templateid)
INNER JOIN (sessionstn3270
LEFT JOIN lus
ON sessionstn3270.sessionid = lus.sessionid)
ON sessionnames.sessionnameid = sessionstn3270.sessionnameid
WHERE usernameid = 3978
ORDER BY templates.templatetype,
sessionnames.sessiontype;
对于 SQL Management Studio 和 .NET 应用,会话 ID 按以下顺序返回:
17797
17798
17799
17800
17801
105372
使用MS Access,它们按以下顺序返回:
17801
17800
17999
17998
17797
105372
95% 的情况下,我可以通过添加 SessionID DESC 来复制相同的搜索结果ORDER BY
但这不是 100%,我已经尝试了不同字段的不同排序顺序,但没有一个 100% 有效。
有谁知道还有什么可能影响 Access 和 .NET 之间的返回结果顺序?
我从 http://expressprofiler.codeplex.com/下载了ExpressProfiler,发现以下内容:
当 Access 将 SQL 查询发送到 ACCESS 数据库时,将发生以下事务:
SELECT "dbo"."SessionsTN3270"."SessionID" ,"dbo"."SessionsTN3270"."SessionID","dbo"."SessionNames"."SessionType" ,"dbo"."SessionNames"."SessionNameID","dbo"."Templates"."TemplateType" ,"dbo"."Templates"."TemplateID" FROM "dbo"."SessionsTN3270",'oj "dbo"."SessionNames" LEFT OUTER JOIN "dbo"."Templates" ON ("dbo"."SessionNames"."Template" = "dbo"."Templates"."TemplateID" ) ' WHERE (("dbo"."SessionsTN3270"."UserNameID" = 3978 ) AND ("dbo"."SessionNames"."SessionNameID" = "dbo"."SessionsTN3270"."SessionNameID" ) )
go
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 int',N'SELECT "SessionID" ,"dbo"."LUs"."LUID" FROM "dbo"."LUs" WHERE ("SessionID" = @P1)',17797
select @p1
go
exec sp_execute 1,17798
go
exec sp_execute 1,17799
go
exec sp_execute 1,17800
go
exec sp_execute 1,17801
go
exec sp_execute 1,105372
go
SELECT CASE DATABASEPROPERTYEX( DB_NAME(), 'Updateability') WHEN 'READ_ONLY' THEN 'Y' ELSE 'N' END
go
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "TemplateID","Template","TemplateType" FROM "dbo"."Templates" WHERE "TemplateID" = @P1 OR "TemplateID" = @P2 OR "TemplateID" = @P3 OR "TemplateID" = @P4 OR "TemplateID" = @P5 OR "TemplateID" = @P6 OR "TemplateID" = @P7 OR "TemplateID" = @P8 OR "TemplateID" = @P9 OR "TemplateID" = @P10',15,15,15,15,15,33,33,33,33,33
select @p1
go
declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "SessionNameID","SessionName","Host","Template","SessionType","Port","LastModifiedSN","SSMA_TimeStamp" FROM "dbo"."SessionNames" WHERE "SessionNameID" = @P1 OR "SessionNameID" = @P2 OR "SessionNameID" = @P3 OR "SessionNameID" = @P4 OR "SessionNameID" = @P5 OR "SessionNameID" = @P6 OR "SessionNameID" = @P7 OR "SessionNameID" = @P8 OR "SessionNameID" = @P9 OR "SessionNameID" = @P10',204,203,202,201,200,272,272,272,272,272
select @p1
go
declare @p1 int
set @p1=3
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "SessionID","SessionTypeID","UserNameID","SessionNameID" FROM "dbo"."SessionsTN3270" WHERE "SessionID" = @P1 OR "SessionID" = @P2 OR "SessionID" = @P3 OR "SessionID" = @P4 OR "SessionID" = @P5 OR "SessionID" = @P6 OR "SessionID" = @P7 OR "SessionID" = @P8 OR "SessionID" = @P9 OR "SessionID" = @P10',17801,17800,17799,17798,17797,105372,105372,105372,105372,105372
select @p1
go
declare @p1 int
set @p1=4
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "LUID","SessionID","LU" FROM "dbo"."LUs" WHERE "LUID" = @P1 OR "LUID" = @P2 OR "LUID" = @P3 OR "LUID" = @P4 OR "LUID" = @P5 OR "LUID" = @P6 OR "LUID" = @P7 OR "LUID" = @P8 OR "LUID" = @P9 OR "LUID" = @P10',18539,18539,18539,18539,18539,18539,18539,18539,18539,18539
select @p1
go
SELECT "SessionTypeID" ,"SessionType" FROM "dbo"."SessionTypes" WHERE ("HostTypeID" = 200 )
go
SELECT "UserNameID" ,"WSUserName" ,"RecordType" ,"Role" ,"SecurityLevel" ,"BuildingCode" ,"FloorLevel" ,"ServerID" ,"Airline" ,"Description" ,"LastModified" FROM "dbo"."WSUsers"
go
但是,当 SQL Server 运行查询时,它要简单得多:
SELECT SessionsTN3270.SessionID, SessionNames.SessionName, SessionsTN3270.SessionTypeID, SessionsTN3270.UserNameID, SessionNames.Host, SessionNames.Port, LUs.LU, SessionNames.LastModifiedSN, Templates.Template, Templates.TemplateType, SessionNames.SessionType
FROM (SessionNames LEFT JOIN Templates ON SessionNames.Template = Templates.TemplateID) INNER JOIN (SessionsTN3270 LEFT JOIN LUs ON SessionsTN3270.SessionID = LUs.SessionID) ON SessionNames.SessionNameID = SessionsTN3270.SessionNameID WHERE UserNameID = 3978 ORDER BY Templates.TemplateType, SessionNames.SessionType;
go
从这个SQL跟踪中,我发现我可以使用查询从SQL服务器复制相同的顺序,如下所示:
SELECT "dbo"."SessionsTN3270"."SessionID" ,"dbo"."SessionsTN3270"."SessionID","dbo"."SessionNames"."SessionType" ,"dbo"."SessionNames"."SessionNameID","dbo"."Templates"."TemplateType" ,"dbo"."Templates"."TemplateID" FROM "dbo"."SessionsTN3270", "dbo"."SessionNames" LEFT OUTER JOIN "dbo"."Templates" ON ("dbo"."SessionNames"."Template" = "dbo"."Templates"."TemplateID" )
WHERE (("dbo"."SessionsTN3270"."UserNameID" = 3978 ) AND ("dbo"."SessionNames"."SessionNameID" = "dbo"."SessionsTN3270"."SessionNameID" ) )
解决方案是使用 ExpressProfiler (http://expressprofiler.codeplex.com/( 如果您有完整的 SQL,请使用 SQL 附带的 SQL 配置文件。通过使用 ExpressProfiler 跟踪查询,我能够匹配 ACCESS 使用的查询,因为它在发送到 SQL 服务器之前修改了 SQL 查询,然后我可以按相同的顺序获得结果。我在这篇博文中提供的全部细节:http://chentiangemalc.wordpress.com/2013/09/23/case-of-the-sql-vs-access-sort-order/