Кто-нибудь знает обходной путь для этого? По сути, хранимая процедура заставляет оператор вставки использовать индексированное представление, даже если строки не соответствуют требованиям. В результате возникает ошибка приведения. Однако для ad hocs sql правильно исключает представление из рассмотрения.
Рассмотрим следующую схему:
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
Это все работает:
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;
Это не удается:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Сравнение «сметных планов выполнения»:
insert into testdata (kind, data) values ('noninteger', 'noninteger')
:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger'
:
sql-server
cocogorilla
источник
источник
option (recompile)
?Ответы:
Спасибо за предоставление полного сценария для воссоздания проблемы.
Я проверил это с SQL Server 2014 Express.
Когда я добавляю
OPTION(RECOMPILE)
это работает:Когда я запускаю это в SSMS:
Я получаю это сообщение:
и строка добавляется в таблицу.
Какую версию SQL Server вы используете? Я смутно помню, что в версиях до 2008 года он
OPTION(RECOMPILE)
вел себя немного иначе.В этом случае может быть лучше использовать отфильтрованный индекс вместо индексированного представления:
Оптимизатор должен использовать этот индекс, когда
WHERE
фильтр запроса точно соответствуетWHERE
предложению индекса.Да, здесь индекс находится по
nvarchar
столбцу, что может быть не лучшим решением, особенно если вы объединяете эту таблицу соint
столбцом другой таблицы или пытаетесь отфильтровать значения в этом столбце, используяint
значения.Еще один вариант, который приходит на ум, - это постоянный вычисляемый столбец, который преобразуется
nvarchar
вint
. По сути это очень похоже на ваше представление, но сохраненныеnvarchar
значения, которые преобразуются вint
, хранятся в одной таблице, а не в отдельном объекте.С этой настройкой я попытался использовать вашу оригинальную хранимую процедуру для вставки строк, и она работала даже без
OPTION(RECOMPILE)
.На самом деле, кажется, что основная причина, почему вышеупомянутый постоянный столбец работает, заключается в том, что я использую
CASE
. Если я добавлюCASE
к определению ваше мнение, хранимая процедура работает безOPTION(RECOMPILE)
.источник