SQL 未创建 Server 2008 R2 记录集

SQL Server 2008 R2 Recordset apears not created

环境:SQL Server Express 2008 R2,EW4,Windows XP SP3

这里有一些来自 ASPX 页面的重要程序语句。

conn=Server.CreateObject("ADODB.Connection")
conn.Open (connString)  -->  conn.State = True
sql1 = USE [my_db]; SELECT * FROM [dbo].[CustomerTable];
rs=Server.CreateObject("ADODB.Recordset") --> rs(create).State = False
rs.Open (sql1,conn)  -->  rs(open).State = False
conn.State = True
do until (rs.EOF)  // produces fatal exception

来自我的日志文件 (C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\Log\ERRORLOG):

2017-01-02 12:31:06.33 Server The SQL Server Network Interface library could not register the Service Principal Name (SPN) for the SQL Server service. Error: 0x54b, state: 3. Failure to register an SPN may cause integrated authentication to fall back to NTLM instead of Kerberos. This is an informational message. Further action is only required if Kerberos authentication is required by authentication policies.

这些来自 Procmon.exe (SysInternalsSuite)

Date & Time: 1/2/2017 12:21:33 PM Event Class: File System Operation: DeviceIoControl Result: INVALID PARAMETER Path: C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\ MSSQL\DATA\my_db.mdf TID: 4972 Duration: 0.0000050 Control: IOCTL_MOUNTDEV_QUERY_DEVICE_NAME

Date & Time: 1/2/2017 12:21:33 PM Event Class: File System Operation: CreateFile Result: NAME INVALID Path: C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\ MSSQL\DATA\my_db.mdf TID: 4972 Duration: 0.0000107 Desired Access: Read Attributes, Synchronize Disposition: Open Options: Synchronous IO Non-Alert, Open Reparse Point Attributes: N ShareMode: Read, Write AllocationSize: n/a Impersonating: servername\mainuser


关于解决 SQL 服务器错误日志中提到的 SPN 问题的早期努力,我找到了以下参考资料:

https://msdn.microsoft.com/en-us/library/ms191153(v=sql.110).aspx#Defaults

因此 Kerberos 用于远程连接。在这种情况下只有本地连接。所以本地没有使用 Kerberos 在这种情况下可能无关紧要。本地使用 NTLM。

所以在这种情况下,SPN 的未注册可能不是问题。

一时间ERRORLOG中提到的无法注册SPN和Kerberos认证警告似乎是唯一可以跟进的项目。这是那里列出的唯一重大错误(警告),有一段时间似乎是唯一的线索。

最初,SPN 问题似乎是由某些权限设置不当引起的。此外,许多网页似乎将 SPN 问题和无法获取查询归因于 运行 权限设置不当。该用户开始认为权限不足是他想象的记录集创建对象失败的根本原因。

具体来说,有一段时间,该用户认为 sql 服务器启动帐户无法创建记录集对象,因为它没有足够的权限来完成任务。此外,MSDN 网络文章建议 g运行t Read 和 WriteServicePrincipalName 权限使用 Active Directory(以启用远程连接的 Kerberos 身份验证)进一步加深了用户的错误理解。最终,这种思路被证明是错误的,因为计算机是独立的(未联网),并且不是服务器 os 不能有 AD DC(本地),没有任何远程数据库连接并且是远程连接不需要 Kerberos 身份验证。

所以sql服务器ERRORLOG中的SPN和Kerberos警告在这种情况下最终判断为非问题。但是这部分调查耗时费力,非常混乱。

虽然,关于权限,将 sql 服务器启动帐户登录类型从本地服务设置(更改)为本地系统(更高特权帐户)似乎确实有所改善。


请接受我对您(和其他人)为我的计划所提供的帮助和努力的感谢。我怀疑您可能比我拥有更多 sql 服务器经验,因此值得尊重。但我的目标是不同的,让网站完全起来 运行。我正在认真听从您的建议。

总的来说,关于这个程序,很重要,因为在修复之前没有可用的数据库,没有可用的网站,工程公司也无法开门。

关于这个程序,我严重怀疑真的只有一个(主要)持久性问题(后来发现是格式错误的查询字符串)。最初看起来像是数据库连接或权限问题导致创建记录集对象失败 (rs.State=0),但事实证明这是不正确的。数据库连接被证明是足够的, rs.State=0 (对于创建 rs 对象)不是错误,更像是一条天生的零记录消息。最初的 rs.State=0(对于 rs 创建对象)被误解并证明非常混乱。

更令人困惑的是,rs.State实际上returns一个枚举值(本质上是一个整数)而不是布尔值(例如代码片段视图中显示的False window)。此处显示了意外的数据类型不匹配(意外的非法转换)。因此,原始代码片段视图 window 在这方面并不完全正确。

当程序最终 运行 正确 rs(create).State=0 和 rs(open).State=1 时,这不是预期的结果。事实上,最初期望 rs(create).State 和 rs(open).State 应该都等于 1,事实证明这是不正确的。这位用户仔细观察了rs(create).State 方法对象属性 的值,结果证明是一个无用的占用。 (它并没有真正帮助。)

当 "USE [my_db]; " 部分从 sql 查询字符串中删除后,数据库开始被正确查询并且 RS.State=1(对于 rs.Open) .到那时,"USE [my_db]; " 终止了所有查询。事情开始明朗起来,然后很明显存在(或曾经存在)通常(或总是)有害的三重数据库连接规范。连接字符串中的两个,带有 AttachDBFilename 参数和 Database 参数。第三个在 sql 查询字符串中带有 "USE [my_db]; "。三个数据库连接无疑导致了一些软件问题(因为过度指定),即使所有三个条目都是相同且正确的(对人类而言)。使用 Procmon.exe (SysInternalsSuite) 的进一步测试显示与 AttachDBFilename 参数相关的错误和单独使用时(连接字符串)数据库参数的零错误。因此,数据库参数是 chosen,仅在连接字符串中使用。

关于多活动结果集 (MARS) 属性连接字符串参数,下面的 MSDN 网络文章说它最初默认是禁用的。显然这是一个高级数据库功能,涉及几个高级问题、同步、异步、缓存、多个批处理命令会话。虽然 MARS 功能很有价值,但人们认为它应该被禁用,直到用户变得足够高级以在代码中正确处理它。所以这个MARS连接参数不推荐db初学者使用。 https://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.110).aspx

通常与 MARS 一起使用,"DataTypeCompatibility=80; " 参数将数据库数据类型限制为 2005 集。这似乎是不必要和不利的。除非使用 MARS,否则不建议使用此参数。 https://msdn.microsoft.com/en-us/library/ms131002(v=sql.110).aspx

最后一个等价键值对:"Integrated Security=SSPI" 等于 "Trusted_Connection=yes"。
所以 chose 一个以避免冗余。

一条评论说:"Take a look here for info on how to create the correct connection string: https://social.technet.microsoft.com/wiki/contents/articles/1409.how-to-create-a-sql-connection-string-for-an-application-udl-file.aspx ."我确实觉得这个 UDL 过程很有用,因为它提供了系统确认正确的提供者(以及其他一些东西)应该是什么。尽管如此,我最终还是使用了自定义连接字符串。

关于确认连接字符串,确切的结果是:

[oledb] ;此行之后的所有内容都是 OLE DB initstring
Provider=SQLNCLI10.1;Integrated Security=SSPI;Persist Security Info=False;User ID="";Initial Catalog=my_db;Data Source=serverName\SQLEXPRESS;Initial File Name= "";服务器 SPN=""


我要特别感谢尼克。他费了很大的力气,一直陪着我,直到这件事圆满解决。他关于删除 "USE [my_db]; " 的评论直接导致了修复。完成最简单的测试 sql 查询后,实际上 运行 正确。所有其他错误都像纸牌屋一样消失了(一件好事)。所以我猜他找到了我问题的根源。衷心感谢 Nick。

这是部分理论,可能不完全正确,但这是我的理解。

似乎当 Recordset.Open return 没有记录时,它 return 带有 state=0

当你运行这个查询时:

USE [my_db]; SELECT * FROM [dbo].[CustomerTable];

它return是第一个语句的第一个记录集。在这种情况下,第一个语句是

USE [my_db];

其中return没有记录

所以打开部分不会抛出任何错误,因为它运行完美

检查 rs.EOF 时会抛出错误,因为记录集已关闭(因为该语句没有 return 任何记录或列)

如果深入了解致命异常,您会看到类似这样的错误。

我怀疑如果您从一个空的 table 中选择,结果会有点不同,即没有记录的打开记录集。

这与写存储过程时的SET NOCOUNT ON要求非常相似