Eu tenho uma tabela com 2 colunas de nome:
CREATE TABLE Test
(
TestID int identity primary key clustered
, Name_Eng nvarchar(50)
, Name_Nat nvarchar(50)
)
Agora preciso de uma query para pegar essa Name
coluna separada por ,
, assim:
DECLARE @NameColumns NVARCHAR(1024)
SET @NameColumns = STUFF(
(SELECT ',' + 'Test.' + name AS [text()]
FROM ( SELECT c.name
FROM sys.columns c
INNER JOIN sys.tables t ON t.object_id = c.object_id
WHERE t.name = 'Test'
AND c.name LIKE 'Name_%'
) AS D
FOR XML PATH('') ,
TYPE).value('.[1]', 'VARCHAR(MAX)'), 1, 1,
N'')
select @NameColumns
Mas esta consulta tem um aviso no plano de execução:
Existe alguma maneira de remover esse aviso?
O aviso existe por causa da função XML
value()
. O segundo parâmetrovalue()
é o que você deseja que o valor armazenado no XML seja convertido. Você poderia argumentar que esta não é de fato uma conversão implícita, mas uma conversão muito explícita, já que você está pedindo que isso aconteça. Talvez algo para um item de conexão sugerir à Microsoft.Maneira mais simples de reproduzir o que você vê.
Dá esses dois avisos.
Como você pode ver, você também obtém int's e obtém dois deles para cada invocação de
value()
.A conversão é feita no operador Stream Aggregate que calcula o valor desta forma.
O resultado da função Table Valued é retornado na coluna
lvalue
ou .value
A expressão verifica usandodatalength
para descobrir de onde deve ser buscada e, em seguida, converte-a no tipo de dados desejado.Sim existe. Você remove a
TYPE
diretiva daFOR XML PATH
instrução e remove a chamada para avalue()
função. Um efeito colateral de fazer isso é que os valores que você concatena que contêm caracteres que precisam ser codificados no XML como&<>
serão codificados em seu resultado.Embora eu concorde com @Kin sobre os tipos de dados, não acho que esse aviso seja tão problemático quanto você pensa. Você está executando a concatenação agrupada, que será muito mais cara do que qualquer conversão de qualquer maneira (e, como disse Daniel, a menos que suas visualizações de catálogo sejam massivas - como em maior que a memória física - é improvável que afete qualquer coisa em termos de estimativa também).
Eu escreveria a consulta dessa maneira, tomando cuidado para nunca usar strings varchar (o que também significa parar de deixar de fora o
N
prefixo em strings literais) e também garantir que você use terminadores de instrução :Mesmo assim, não acredito que haja alguma maneira de evitar a conversão implícita sem alterar a saída evitando
TYPE
/value()
como Mikael sugeriu . Eu diria que se preocupe com isso quando você puder provar que isso tem algum impacto material no desempenho da consulta. Em meus testes, as duas formas diferentes tiveram o mesmo desempenho (estamos falando de sub-10ms todas as vezes), mas é claro que se eu tiver uma tabela nomeadaSales & Stuff
, ela ficaráSales & Stuff
sem a conversão implícita.O aviso no plano de consulta significa que, como você tem uma conversão implícita de tipo de dados, o SQL Server não poderá adivinhar com precisão o número correto de linhas retornadas, o que, por sua vez, pode levar a um plano abaixo do ideal.
Isso é importante em consultas que precisam ter um bom desempenho, normalmente porque trabalham com muitos dados, mas na sua situação, não parece ser o caso, pois você está apenas consultando
sys.tables
esys.columns
.A resposta curta para sua pergunta é: não importa, a menos que você tenha milhões e milhões de tabelas e colunas em seu banco de dados.