¿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
WHERE
filtro de la consulta coincida exactamente con laWHERE
cláusula del índice.Sí, aquí el índice está en la
nvarchar
columna, lo que puede no ser lo mejor, especialmente si une esta tabla con unaint
columna de otra tabla, o intenta filtrar valores en esta columna usandoint
valores.Otra variante que viene a la mente es la columna computada persistente que se convierte
nvarchar
aint
. En esencia, es muy similar a su vista, pero losnvarchar
valores persistentes que se conviertenint
se 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 agregoCASE
a la definición de su vista, el procedimiento almacenado funciona sin élOPTION(RECOMPILE)
.fuente