Adakah yang tahu solusi untuk ini? Pada dasarnya, prosedur yang disimpan memaksa operator memasukkan terhadap tampilan yang diindeks, meskipun baris tidak memenuhi syarat. Akibatnya, ada kesalahan pemeran. Namun, untuk ad hocs, sql dengan benar menghilangkan tampilan dari pertimbangan.
Pertimbangkan skema berikut:
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
Ini semua bekerja:
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;
Ini gagal:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger';
Perbandingan "perkiraan rencana eksekusi":
insert into testdata (kind, data) values ('noninteger', 'noninteger')
:
exec insert_testdata @kind = 'noninteger', @data = 'noninteger'
:
sql-server
cocogorilla
sumber
sumber
option (recompile)
bantuan?Jawaban:
Terima kasih telah menyediakan skrip lengkap untuk menciptakan kembali masalah.
Saya mengujinya dengan SQL Server 2014 Express.
Ketika saya menambahkannya
OPTION(RECOMPILE)
berfungsi:Ketika saya menjalankan ini di SSMS:
Saya menerima pesan ini:
dan satu baris ditambahkan ke tabel.
Apa versi SQL Server yang Anda gunakan? Samar-samar saya ingat bahwa dalam versi sebelum 2008 ini
OPTION(RECOMPILE)
berperilaku sedikit berbeda.Dalam hal ini mungkin lebih baik menggunakan indeks yang disaring daripada tampilan yang diindeks:
Pengoptimal harus menggunakan indeks ini ketika
WHERE
filter kueri sama persis denganWHERE
klausa indeks.Ya, indeks di sini ada pada
nvarchar
kolom yang mungkin bukan yang terbaik, terutama jika Anda bergabung dengan tabel ini denganint
kolom dari tabel lain, atau mencoba memfilter nilai dalam kolom ini menggunakanint
nilai.Varian lain yang terlintas dalam pikiran adalah kolom komputasi tetap yang dikonversi
nvarchar
menjadiint
. Pada dasarnya itu sangat mirip dengan pandangan Anda, tetapinvarchar
nilai-nilai tetap yang dikonversi menjadiint
disimpan dengan tabel yang sama, bukan dalam objek yang terpisah.Dengan pengaturan ini saya mencoba menggunakan prosedur tersimpan asli Anda untuk menyisipkan baris dan itu berhasil bahkan tanpa
OPTION(RECOMPILE)
.Sebenarnya, sepertinya alasan utama mengapa kolom bertahan di atas berfungsi adalah yang saya gunakan
CASE
. Jika saya menambahCASE
definisi tampilan Anda, prosedur tersimpan berfungsi tanpaOPTION(RECOMPILE)
.sumber