Kennt jemand eine Problemumgehung dafür? Im Wesentlichen erzwingt die gespeicherte Prozedur einen Einfügeoperator gegen die indizierte Ansicht, obwohl die Zeilen nicht qualifiziert sind. Infolgedessen liegt ein Umwandlungsfehler vor. Bei Ad-hocs entfernt SQL die Ansicht jedoch korrekt aus der Betrachtung.
Betrachten Sie das folgende Schema:
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
Diese alle funktionieren:
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;
Dies schlägt fehl:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Ein Vergleich der "geschätzten Ausführungspläne":
insert into testdata (kind, data) values ('noninteger', 'noninteger')
::
exec insert_testdata @kind = 'noninteger', @data = 'noninteger'
::
sql-server
Cocogorilla
quelle
quelle
option (recompile)
?Antworten:
Vielen Dank, dass Sie ein vollständiges Skript zur Neuerstellung des Problems bereitgestellt haben.
Ich habe es mit SQL Server 2014 Express getestet.
Wenn ich es hinzufüge
OPTION(RECOMPILE)
, funktioniert es:Wenn ich dies in SSMS ausführe:
Ich bekomme diese Nachricht:
und eine Zeile wird der Tabelle hinzugefügt.
Welche Version von SQL Server verwenden Sie? Ich erinnere mich vage, dass sich dies in Versionen vor 2008
OPTION(RECOMPILE)
etwas anders verhalten hat.In diesem Fall ist es möglicherweise besser, einen gefilterten Index anstelle einer indizierten Ansicht zu verwenden:
Das Optimierungsprogramm sollte diesen Index verwenden, wenn der
WHERE
Filter der Abfrage genau mit derWHERE
Klausel des Index übereinstimmt .Ja, hier befindet sich der Index in einer
nvarchar
Spalte, was möglicherweise nicht das Beste ist, insbesondere wenn Sie diese Tabelle mit einerint
Spalte einer anderen Tabelle verknüpfen oder versuchen, Werte in dieser Spalte mithilfe vonint
Werten zu filtern .Eine weitere Variante, die den Sinn kommt , ist beharrte berechnete Spalte , dass Konvertiten
nvarchar
zuint
. Im Wesentlichen ist es Ihrer Ansicht sehr ähnlich, aber die persistiertennvarchar
Werte, in die konvertiertint
wird, werden mit derselben Tabelle und nicht in einem separaten Objekt gespeichert.Mit dieser Einstellung habe ich versucht, Ihre ursprünglich gespeicherte Prozedur zum Einfügen von Zeilen zu verwenden, und es hat auch ohne funktioniert
OPTION(RECOMPILE)
.Tatsächlich scheint es, dass der Hauptgrund, warum die oben genannte Spalte funktioniert, darin besteht, dass ich sie verwende
CASE
. Wenn ichCASE
zur Definition Ihrer Ansicht hinzufüge , funktioniert die gespeicherte Prozedur ohneOPTION(RECOMPILE)
.quelle