DBAs and ad hoc queries sometimes go together like oil and water. While we may prefer to avoid the ad hoc queries, sometimes it is the best method to achieve a task.
What exactly is an ad hoc query though? An ad hoc query is a query that should serve a single use purpose (not always the case), is routinely unplanned and quite possibly was untested (again, not always the case). Sometimes, however, the definitions of ad hoc don’t fully apply to queries in SQL Server. One such case is through the use of dynamic type queries and queries issued to linked servers via openrowset.
In my experience, queries used against a linked server and using the openrowset functionality is typically more of a prepared statement. However, it is treated as an ad hoc query. As such, you may encounter an error you may not have been expecting.
Msg 15281, Level 16, State 1, Line 161
SQL Server blocked access to STATEMENT ‘OpenRowset/OpenDatasource’ of component ‘Ad Hoc Distributed Queries’ because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of ‘Ad Hoc Distributed Queries’ by using sp_configure. For more information about enabling ‘Ad Hoc Distributed Queries’, search for ‘Ad Hoc Distributed Queries’ in SQL Server Books Online.
This article will help show how to resolve for this error so your queries may go on as intended.
Let’s first take a look at a pretty typical type of query I use routinely to check various things on my lab servers.
SELECT a.* FROM OPENROWSET('SQLNCLI', 'server=.DIXNEUFLATIN1;Trusted_Connection=yes;', 'DECLARE @ServerMajorVersion DECIMAL(4, 2) SELECT @ServerMajorVersion = CONVERT(DECIMAL(4, 2), PARSENAME(dt.fqn, 4) + ''.'' + PARSENAME(dt.fqn, 3)) FROM ( SELECT CONVERT(VARCHAR(20), SERVERPROPERTY(''ProductVersion'')) ) dt ( fqn ); select Case when @ServerMajorVersion = 14.00 then ''SQL Server 2017'' when @ServerMajorVersion = 13.00 then ''SQL Server 2016'' when @ServerMajorVersion = 12.00 then ''SQL Server 2014'' when @ServerMajorVersion = 11.00 then ''SQL Server 2012'' when @ServerMajorVersion = 15.00 then ''SQL Server 2019'' end as SQLVer , @ServerMajorVersion as ServerMajorVersion , xl.name, xl.description from master.sys.dm_xe_objects xl where xl.object_type = ''target''') AS a
This is a query that I use (or something like it) to retrieve various Extended Events data from different lab servers. Notice, I use the openrowset method in order to query my linked server. If I do not have the server configured for ad hoc distributed queries then I will receive the error previously noted. The solution for that error is to enable the setting. We can do that via the following query.
sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; GO sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE WITH OVERRIDE; GO
Once enabled, then the openrowset queries will work across linked servers. This needs to be enabled on the server that is local in order to send the ad hoc query across to the remote server. With the setting now enabled, running the query that threw the error (from above) now returns the follow results.
This article took a look at an error that may occur depending on your use of linked servers and the use of openrowset. Documentation states that this is something that should be done infrequently and alludes to the issue being resolved through the use of linked servers. In my case, this crops up when using openrowset to query my linked servers. I find that using openrowset to query the linked server is far more reliable, efficient, and better performing. YMMV.