Alguém sabe uma solução alternativa para isso? Essencialmente, o procedimento armazenado força um operador de inserção contra a exibição indexada, mesmo que as linhas não se qualifiquem. Como resultado, há um erro de conversão. No entanto, para ad hocs, o sql elimina corretamente a exibição da consideração.
Considere o seguinte esquema:
create table testdata (
testid int identity(1,1) primary key
, kind varchar(50)
, data nvarchar(4000))
go
create view integer_testdata with schemabinding
as
select cast(a.data as int) data, a.kind, a.testid
from dbo.testdata a
where a.kind = 'integer'
go
create unique clustered index cl_intdata on integer_testdata(data)
go
create procedure insert_testdata
(
@kind varchar(50)
, @data nvarchar(4000)
)
as
begin
insert into testdata (kind, data) values (@kind, @data)
end
go
Tudo isso funciona:
insert into testdata (kind, data) values ('integer', '1234');
insert into testdata (kind, data) values ('integer', 12345);
insert into testdata (kind, data) values ('noninteger', 'noninteger');
exec insert_testdata @kind = 'integer', @data = '123456';
exec insert_testdata @kind = 'integer', @data = 1234567;
Isso falha:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Uma comparação dos "planos de execução estimados":
insert into testdata (kind, data) values ('noninteger', 'noninteger')
:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger'
:
sql-server
cocogorilla
fonte
fonte
option (recompile)
ajuda?Respostas:
Obrigado por fornecer um script completo para recriar o problema.
Eu testei com o SQL Server 2014 Express.
Quando adiciono
OPTION(RECOMPILE)
, funciona:Quando eu executo isso no SSMS:
Eu recebo esta mensagem:
e uma linha é adicionada à tabela.
Qual versão do SQL Server você está usando? Lembro-me vagamente de que nas versões anteriores a 2008 isso se
OPTION(RECOMPILE)
comportava um pouco diferente.Nesse caso, pode ser melhor usar o índice filtrado em vez da exibição indexada:
O otimizador deve usar esse índice quando o
WHERE
filtro da consulta corresponder exatamente àWHERE
cláusula do índice.Sim, aqui o índice está na
nvarchar
coluna que pode não ser a melhor coisa, especialmente se você ingressar nesta tabela com umaint
coluna de outra tabela ou tentar filtrar valores nessa coluna usandoint
valores.Outra variante que vem à mente é a coluna computada persistente que se converte
nvarchar
emint
. Em essência, é muito semelhante à sua exibição, mas osnvarchar
valores persistentes convertidosint
são armazenados com a mesma tabela, não em um objeto separado.Com essa configuração, tentei usar o procedimento armazenado original para inserir linhas e funcionou mesmo sem
OPTION(RECOMPILE)
.Na verdade, parece que a principal razão pela qual a coluna persistida acima funciona é que eu uso
CASE
. Se eu adicionarCASE
à definição da sua exibição, o procedimento armazenado funcionará semOPTION(RECOMPILE)
.fonte