¿Sabe alguien una solución para esto? Esencialmente, el procedimiento almacenado fuerza a un operador de inserción contra la vista indexada, aunque las filas no califican. Como resultado, hay un error de lanzamiento. Sin embargo, para ad hocs, sql elimina correctamente la vista de la consideración.
Considere el siguiente 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
Todo esto 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;
Esto falla:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Una comparación de los "planes de ejecución estimados":
insert into testdata (kind, data) values ('noninteger', 'noninteger'):

exec insert_testdata @kind = 'noninteger', @data = 'noninteger':

sql-server
cocogorilla
fuente
fuente

option (recompile)ayuda?Respuestas:
Gracias por proporcionar un script completo para recrear el problema.
Lo probé con SQL Server 2014 Express.
Cuando agrego
OPTION(RECOMPILE)funciona:Cuando ejecuto esto en SSMS:
Recibo este mensaje:
y se agrega una fila a la tabla.
¿Qué versión de SQL Server estás usando? Recuerdo vagamente que en versiones anteriores a 2008 esto se
OPTION(RECOMPILE)comportó de manera un poco diferente.En este caso, puede ser mejor usar el índice filtrado en lugar de la vista indizada:
El optimizador debe usar este índice cuando el
WHEREfiltro de la consulta coincida exactamente con laWHEREcláusula del índice.Sí, aquí el índice está en la
nvarcharcolumna, lo que puede no ser lo mejor, especialmente si une esta tabla con unaintcolumna de otra tabla, o intenta filtrar valores en esta columna usandointvalores.Otra variante que viene a la mente es la columna computada persistente que se convierte
nvarcharaint. En esencia, es muy similar a su vista, pero losnvarcharvalores persistentes que se conviertenintse almacenan con la misma tabla, no en un objeto separado.Con esta configuración, intenté usar su procedimiento almacenado original para insertar filas y funcionó incluso sin él
OPTION(RECOMPILE).En realidad, parece que la razón principal por la que funciona la columna persistente anterior es que yo uso
CASE. Si agregoCASEa la definición de su vista, el procedimiento almacenado funciona sin élOPTION(RECOMPILE).fuente