使用查询通知
适用于: SQL Server Azure SQL 托管实例
重要
SQL Server Native Client (SNAC) 未随附:
- SQL Server 2022 (16.x) 及更高版本
- SQL Server Management Studio 19 及更高版本
不建议使用 SQL Server Native Client(SQLNCLI 或 SQLNCLI11)和旧的 Microsoft OLE DB Provider for SQL Server (SQLOLEDB)进行新的应用程序开发。
对于新项目,请使用以下驱动程序之一:
对于作为 SQL Server 数据库引擎组件(版本 2012 到 2019)随附的 SQLNCLI,请参阅此支持生命周期特例。
SQL Server 2005 (9.x) 和 SQL Server Native Client 中引入了查询通知。 查询通知基于 SQL Server 2005(9.x)中引入的 Service Broker 基础结构构建,允许在数据发生更改时通知应用程序。 对提供数据库信息的缓存且需要在源数据发生更改时收到通知的应用程序(如 Web 应用程序)而言,以上功能特别有用。
查询通知使您可以在查询的基础数据发生更改时请求在指定的超时期限内发送通知。 通知请求指定通知选项,其中包括服务名称、消息正文和服务器的超时值。 通知是通过 Service Broker 队列传递的,应用程序可以轮询该队列以获取可用通知。
查询通知选项字符串的语法为:
service=<service-name>[;(local database=<database> | broker instance=<broker instance>)]
例如:
service=mySSBService;local database=mydb
由于应用程序可能在创建通知订阅后终止,因此,通知订阅的生存期比启动它们的进程的生存期长。 订阅将保持有效,如果数据发生更改,则将在创建该订阅时指定的超时期限内发送通知。 通知是通过执行的查询、通知选项和消息正文标识的,将通知的超时值设置为零可以取消该通知。
只发送一次通知。 对于数据更改的持续通知,必须在处理每个通知之后重新执行查询来创建新的订阅。
SQL Server Native Client 应用程序通常通过使用 Transact-SQL RECEIVE 命令从与通知选项中指定的服务关联的队列读取通知来接收通知。
注意
对于需要通知的查询,必须限定其中的表名,例如 dbo.myTable
。 表名必须用包含两个部分的名称进行限定。 如果使用的名称由三个或四个部分组成,则订阅无效。
通知基础结构构建在 SQL Server 2005 (9.x) 中引入的队列功能之上。 通常,在服务器上生成的通知是通过这些队列发送的,以便在稍后进行处理。
若要使用查询通知,服务器上必须存在队列和服务。 可以使用 Transact-SQL 创建这些项,如下所示:
CREATE QUEUE myQueue
CREATE SERVICE myService ON QUEUE myQueue
([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
注意
服务必须使用预定义约定 http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification
,如上所示。
SQL Server Native Client OLE DB 访问接口
SQL Server Native Client OLE DB 访问接口支持行集修改的使用者通知。 使用者在行集修改的每个阶段以及在尝试执行任何更改时接收通知。
注意
使用 ICommand::Execute 将通知查询传递给服务器是使用 SQL Server Native Client OLE DB 访问接口订阅查询通知的唯一有效方法。
DBPROPSET_SQLSERVERROWSET 属性集
为了支持通过 OLE DB 的查询通知,SQL Server Native Client 将以下新属性添加到DBPROPSET_SQLSERVERROWSET属性集。
名称 | Type | 说明 |
---|---|---|
SSPROP_QP_NOTIFICATION_TIMEOUT | VT_UI4 | 查询通知保持为活动状态的秒数。 默认为 432000 秒(5 天)。 最小值为 1 秒,最大值为 2^31-1 秒。 |
SSPROP_QP_NOTIFICATION_MSGTEXT | VT_BSTR | 通知的消息正文。 消息正文是用户定义的,没有预定义格式。 默认情况下,该字符串为空。 您可以使用 1 至 2000 个字符指定消息。 |
SSPROP_QP_NOTIFICATION_OPTIONS | VT_BSTR | 查询通知选项。 采用 name=value 语法以字符串形式指定这些内容。 用户负责创建服务并从队列中读取通知。 默认值为空字符串。 |
无论语句是在用户事务中运行还是以自动提交模式运行,或者无论是提交还是回滚运行语句的事务,将始终提交通知订阅。 根据以下任一无效通知条件激发服务器通知:更改基础数据或架构,或者当达到超时期限时(以先发生者为准)。 激发通知后将立即删除通知注册。 因此,在接收通知时,应用程序必须再次订阅通知,以备进一步更新之用。
其他连接或线程可以检查通知的目标队列。 例如:
WAITFOR (RECEIVE * FROM MyQueue); // Where MyQueue is the queue name.
请注意,SELECT * 不会从队列中删除条目,但 RECEIVE * FROM 会删除条目。 如果队列为空,该语句将停止服务器线程。 如果调用时存在队列项,则会立即返回这些队列项;否则调用将一直等待,直到生成队列项为止。
RECEIVE * FROM MyQueue
如果队列为空,该语句将立即返回空的结果集;否则会返回所有队列通知。
如果 SSPROP_QP_NOTIFICATION_MSGTEXT 和 SSPROP_QP_NOTIFICATION_OPTIONS 为非 NULL 和非空,当执行其中的每个命令时,将向服务器发送包含上面定义的三个属性的查询通知 TDS 头。 如果其中任一属性为 Null(或空),则不会发送头,并引发 DB_E_ERRORSOCCURRED(或者如果两个属性均标记为可选,则引发 DB_S_ERRORSOCCURRED),同时将状态值设置为 DBPROPSTATUS_BADVALUE。 在执行/准备期间进行验证。 同样,当为连接到 SQL Server 2005(9.x)之前的 SQL Server 版本设置查询通知属性时,将引发DB_S_ERRORSOCCURED。 在这种情况下,状态值为 DBPROPSTATUS_NOTSUPPORTED。
启动订阅不能保证将成功传递后续消息。 此外,不会检查指定服务名称的有效性。
注意
准备语句永远不会启动订阅;只有执行语句才能实现此目的,并且 OLE DB 核心服务的使用不会影响查询通知。
有关DBPROPSET_SQLSERVERROWSET属性集的详细信息,请参阅 行集属性和行为。
SQL Server Native Client ODBC 驱动程序
SQL Server Native Client ODBC 驱动程序通过向 SQLGetStmtAttr 和 SQLSetStmtAttr 函数添加三个新属性支持查询通知:
SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT
SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS
SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT
如果 SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT 和 SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS 不为 NULL,每次执行命令时,则不会向服务器发送包含上面定义的三个属性的查询通知 TDS 头。 如果上述两个属性中的任一属性为 Null,则不会发送标头,并返回 SQL_SUCCESS_WITH_INFO。 验证发生在 SQLPrepare 函数、 SqlExecDirect 和 SqlExecute 上,如果属性无效,则所有验证都会失败。 同样,如果为 SQL Server 2005(9.x)之前的 SQL Server 版本设置了这些查询通知属性,则执行会失败并SQL_SUCCESS_WITH_INFO。
注意
准备语句永远不会启动订阅;可以通过执行语句启动订阅。
特殊事例和限制
通知不支持以下数据类型:
text
ntext
image
如果针对返回以上任一类型的查询执行通知请求,则立即激发通知,并指明不可能实现通知订阅。
如果发出批处理或存储过程订阅请求,则会针对批处理或存储过程内执行的每个语句发出单独的订阅请求。 EXECUTE 语句不会注册通知,但是会将通知请求发送到已执行的命令。 如果为批处理,则上下文将适用于已执行的语句,并且应用上述相同规则。
提交同一数据库上下文下同一用户提交的通知查询,并具有相同模板、相同参数值、相同通知 ID 和现有活动订阅的相同传递位置,将续订现有订阅,重置新的指定超时。这意味着,如果为相同的查询请求通知,则只会发送一个通知。 这将适用于批处理中的重复查询,也适用于存储过程中调用多次的查询。