Olá pessoal,
Boa noite!
No post de hoje vou falar sobre um erro não muito comum que ocorre no SQL Server ao tentar executar queries utilizando Linked Server ou instruções entre servidores (Ex: OPENROWSET, OPENQUERY, etc) e o SQL Server nos retorna a seguinte mensagem:
Msg 7405, Level 16, State 1, Line 45
Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection. This ensures consistent query semantics. Enable these options and then reissue your query.
A primeira vez que vi esse erro, foi quando meu colega Henrique Mauri, o cara que mais está me dando ideias de posts ultimamente, tentou criar uma sequence e utilizá-la em uma função escalar que era chamada a partir de uma stored procedure dentro de uma aplicação escrita em C# e se deparou com essa mensagem de erro.
Esse problema ocorre especialmente quando se desativa manualmente as instruções ANSI_NULLS e ANSI_WARNINGS antes de utilizar um linked server no SQL Server. Vamos entender o porque isso acontece e como resolver.
Por quê utilizar ANSI_NULLS e ANSI_WARNINGS?
Antes de mais nada, preciso deixar claro que o problema relatado neste post só ocorre quando pelo menos uma dessas duas configurações está desabilitada (OFF). Já falei sobre as duas no meu post Os comandos SET do SQL Server. O padrão do SQL Server é que elas esteja ativadas (ON), mas muita gente acaba desabilitando para evitar alertas ao utilizar de forma ERRADA algumas queries no banco de dados.
Eu recomendo fortemente que você NÃO desative o ANSI_NULLS e ANSI_WARNINGS nas suas rotinas. Na verdade, nem me lembro quando foi a última vez precisei alterar o comportamento padrão de uma query utilizando comandos SET (a não ser utilizando SET LANGUAGE e SET DATEFORMAT).
Segundo o próprio site da Microsoft, em uma versão futura do SQL Server, ANSI_NULLS sempre estará ON e quaisquer aplicativos que definam explicitamente a opção como OFF gerarão um erro. Evite usar esse recurso em novos trabalhos de desenvolvimento e planeje modificar os aplicativos que o utilizam atualmente.
Simulando o problema
Para simular esse problema, vou disponibilizar abaixo um script que vai mostrar exatamente essa mensagem de erro. Lembrem de trocar o nome do LinkedServer pro nome da sua instância SQL Server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
---------------------------------- -- CRIAÇÃO DO LINKED SERVER ---------------------------------- USE [master] GO DECLARE @instancia NVARCHAR(200) = N'127.0.0.1\SQL2014' IF ((SELECT COUNT(*) FROM sys.servers WHERE name = @instancia) > 0) EXEC master.dbo.sp_dropserver @server=@instancia, @droplogins='droplogins' EXEC master.dbo.sp_addlinkedserver @server = @instancia, @srvproduct=N'SQL Server' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=@instancia,@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL ---------------------------------- -- CRIAÇÃO DA TABELA DE TESTES ---------------------------------- IF (OBJECT_ID('Testes.dbo.Teste') IS NOT NULL) DROP TABLE Testes.dbo.Teste SELECT 12456.74 AS Valor, 'Teste 1' AS Tipo INTO Testes.dbo.Teste UNION SELECT 1314.00, 'Teste 2' UNION SELECT 745.99, 'Teste 2' UNION SELECT 1587.90, 'Teste 1' UNION SELECT 100, NULL UNION SELECT NULL, NULL ---------------------------------- -- SIMULAÇÃO DO ERRO ---------------------------------- SET ANSI_NULLS OFF GO SELECT SUM(Valor), Tipo FROM [127.0.0.1\SQL2014].Testes.dbo.Teste GROUP BY Tipo |
Resolvendo o problema
Pessoal, a solução desse problema é extremamente simples e já está claro pela mensagem de erro e por tudo o que eu já falei no post. Basta ativar os parâmetros SET ANSI_WARNINGS E SET ANSI_NULLS.
Se você já fez isso e continua recebendo essa mensagem de erro, procure todo o seu código-fonte, porque com certeza o problema é esse. Veja se não tem nenhuma SP sendo executada e que esteja desativando uma das duas opções ou algum código ad-hoc na sua aplicação ou na sua camada de acesso a banco de dados. Verifique também o comando de criação das Stored Procedures envolvidas, pois pode ser que no comando de CREATE/ALTER PROCEDURE essas opções tenham sido desativadas.
Espero que tenham gostado do post.
Até a próxima!
Muito boa essa dica