Est-ce que quelqu'un connaît une solution de contournement pour cela? Essentiellement, la procédure stockée force un opérateur d'insertion contre la vue indexée, même si les lignes ne sont pas qualifiées. Il en résulte une erreur de transtypage. Cependant, pour les ad hocs, sql élimine correctement la vue de toute considération.
Considérez le schéma suivant:
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
Tout cela fonctionne:
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;
Cela échoue:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Une comparaison des "plans d'exécution estimés":
insert into testdata (kind, data) values ('noninteger', 'noninteger')
:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger'
:
sql-server
cocogorilla
la source
la source
option (recompile)
aides?Réponses:
Merci d'avoir fourni un script complet pour recréer le problème.
Je l'ai testé avec SQL Server 2014 Express.
Quand j'ajoute
OPTION(RECOMPILE)
ça marche:Lorsque je lance cela dans SSMS:
Je reçois ce message:
et une ligne est ajoutée au tableau.
Quelle version de SQL Server utilisez-vous? Je me souviens vaguement que dans les versions antérieures à 2008, cela
OPTION(RECOMPILE)
se comportait un peu différemment.Dans ce cas, il peut être préférable d'utiliser un index filtré au lieu d'une vue indexée:
L'optimiseur doit utiliser cet index lorsque le
WHERE
filtre de la requête correspond exactement à laWHERE
clause de l'index.Oui, ici l'index est sur une
nvarchar
colonne, ce qui n'est peut-être pas la meilleure chose, surtout si vous joignez cette table à uneint
colonne d'une autre table ou essayez de filtrer les valeurs de cette colonne à l'aide deint
valeurs.Une autre variante qui vient à l'esprit est la colonne calculée persistante qui se convertit
nvarchar
enint
. En substance, il est très similaire à votre vue, mais lesnvarchar
valeurs persistantes qui sont converties enint
sont stockées avec la même table, pas dans un objet séparé.Avec cette configuration, j'ai essayé d'utiliser votre procédure stockée d'origine pour insérer des lignes et cela a fonctionné même sans
OPTION(RECOMPILE)
.En fait, il semble que la principale raison pour laquelle la colonne persistante ci-dessus fonctionne est que j'utilise
CASE
. Si j'ajouteCASE
à la définition de votre vue, la procédure stockée fonctionne sansOPTION(RECOMPILE)
.la source