Apakah ada cara untuk membuat variabel TSQL konstan?
sql-server
tsql
TheEmirOfGroofunkistan
sumber
sumber
WITH SCHEMABINDING
harus mengubahnya menjadi konstanta 'nyata' (persyaratan untuk UDF untuk dilihat sebagai deterministik dalam SQL). Yaitu harus mendarat di cache. Tetap saja, +1.WITH SCHEMABINDING
dalamCREATE FUNCTION
pernyataan (sebagai lawan dalam prosedur tersimpan yang mungkin memanggil fungsi) - apakah itu benar?Salah satu solusi yang ditawarkan Jared Ko adalah dengan menggunakan konstanta semu .
Seperti yang dijelaskan di SQL Server: Variabel, Parameter, atau Literal? Atau… Konstanta? :
sumber
Solusi saya untuk kehilangan konstanta adalah memberikan petunjuk tentang nilai kepada pengoptimal.
DECLARE @Constant INT = 123; SELECT * FROM [some_relation] WHERE [some_attribute] = @Constant OPTION( OPTIMIZE FOR (@Constant = 123))
Ini memberi tahu compiler kueri untuk memperlakukan variabel seolah-olah itu adalah konstanta saat membuat rencana eksekusi. Sisi negatifnya adalah Anda harus mendefinisikan nilainya dua kali.
sumber
Tidak, tapi konvensi penamaan lama yang baik harus digunakan.
declare @MY_VALUE as int
sumber
FN_CONSTANT()
. Dengan begitu, jelas apa yang dilakukannya.Tidak ada dukungan bawaan untuk konstanta di T-SQL. Anda bisa menggunakan pendekatan SQLMenace untuk mensimulasikannya (meskipun Anda tidak pernah bisa yakin apakah orang lain telah menimpa fungsi untuk mengembalikan sesuatu yang lain…), atau mungkin menulis tabel yang berisi konstanta, seperti yang disarankan di sini . Mungkin menulis pemicu yang mengembalikan setiap perubahan ke
ConstantValue
kolom?sumber
Sebelum menggunakan fungsi SQL, jalankan skrip berikut untuk melihat perbedaan kinerja:
IF OBJECT_ID('fnFalse') IS NOT NULL DROP FUNCTION fnFalse GO IF OBJECT_ID('fnTrue') IS NOT NULL DROP FUNCTION fnTrue GO CREATE FUNCTION fnTrue() RETURNS INT WITH SCHEMABINDING AS BEGIN RETURN 1 END GO CREATE FUNCTION fnFalse() RETURNS INT WITH SCHEMABINDING AS BEGIN RETURN ~ dbo.fnTrue() END GO DECLARE @TimeStart DATETIME = GETDATE() DECLARE @Count INT = 100000 WHILE @Count > 0 BEGIN SET @Count -= 1 DECLARE @Value BIT SELECT @Value = dbo.fnTrue() IF @Value = 1 SELECT @Value = dbo.fnFalse() END DECLARE @TimeEnd DATETIME = GETDATE() PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using function' GO DECLARE @TimeStart DATETIME = GETDATE() DECLARE @Count INT = 100000 DECLARE @FALSE AS BIT = 0 DECLARE @TRUE AS BIT = ~ @FALSE WHILE @Count > 0 BEGIN SET @Count -= 1 DECLARE @Value BIT SELECT @Value = @TRUE IF @Value = 1 SELECT @Value = @FALSE END DECLARE @TimeEnd DATETIME = GETDATE() PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using local variable' GO DECLARE @TimeStart DATETIME = GETDATE() DECLARE @Count INT = 100000 WHILE @Count > 0 BEGIN SET @Count -= 1 DECLARE @Value BIT SELECT @Value = 1 IF @Value = 1 SELECT @Value = 0 END DECLARE @TimeEnd DATETIME = GETDATE() PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using hard coded values' GO
sumber
2760ms elapsed, using function
|2300ms elapsed, using local variable
|2286ms elapsed, using hard coded values
|5570 elapsed, using function
|406 elapsed, using local variable
|383 elapsed, using hard coded values
|3893 elapsed, using function without schemabinding
select top 1 @m = cv_val from code_values where cv_id = 'C101'
dan sama di... 'C201'
mana code_values adalah tabel kamus dengan 250 vars, semuanya ada di SQL-Server 2016Jika Anda tertarik untuk mendapatkan rencana eksekusi yang optimal untuk nilai dalam variabel, Anda dapat menggunakan kode sql dinamis. Itu membuat variabel konstan.
DECLARE @var varchar(100) = 'some text' DECLARE @sql varchar(MAX) SET @sql = 'SELECT * FROM table WHERE col = '''+@var+'''' EXEC (@sql)
sumber
Untuk enum atau konstanta sederhana, tampilan dengan satu baris memiliki performa yang bagus dan pemeriksaan waktu kompilasi / pelacakan ketergantungan (karena itu adalah nama kolom)
Lihat entri blog Jared Ko https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/
buat tampilan
CREATE VIEW ShipMethods AS SELECT CAST(1 AS INT) AS [XRQ - TRUCK GROUND] ,CAST(2 AS INT) AS [ZY - EXPRESS] ,CAST(3 AS INT) AS [OVERSEAS - DELUXE] , CAST(4 AS INT) AS [OVERNIGHT J-FAST] ,CAST(5 AS INT) AS [CARGO TRANSPORT 5]
gunakan tampilan
SELECT h.* FROM Sales.SalesOrderHeader WHERE ShipMethodID = ( select [OVERNIGHT J-FAST] from ShipMethods )
sumber
Oke, mari kita lihat
Konstanta adalah nilai yang tidak dapat diubah yang diketahui pada waktu kompilasi dan tidak berubah selama masa pakai program
itu berarti Anda tidak akan pernah memiliki konstanta di SQL Server
declare @myvalue as int set @myvalue = 5 set @myvalue = 10--oops we just changed it
nilainya baru saja berubah
sumber
Karena tidak ada build yang mendukung konstanta, solusi saya sangat sederhana.
Karena ini tidak didukung:
Declare Constant @supplement int = 240 SELECT price + @supplement FROM what_does_it_cost
Saya hanya akan mengubahnya menjadi
SELECT price + 240/*CONSTANT:supplement*/ FROM what_does_it_cost
Jelas, ini bergantung pada semuanya (nilai tanpa spasi dan komentar) agar unik. Mengubahnya dimungkinkan dengan pencarian dan penggantian global.
sumber
Tidak ada hal seperti "membuat konstanta" dalam literatur database. Konstanta ada sebagaimana adanya dan sering disebut nilai. Seseorang dapat mendeklarasikan sebuah variabel dan menetapkan nilai (konstanta) padanya. Dari pandangan skolastik:
DECLARE @two INT SET @two = 2
Di sini @two adalah variabel dan 2 adalah nilai / konstanta.
sumber
2
diterjemahkan ke dalam nilai biner saat ditetapkan pada "waktu kompilasi". Nilai sebenarnya yang dikodekan bergantung pada tipe data yang ditugaskan (int, char, ...).Jawaban terbaik adalah dari SQLMenace sesuai dengan persyaratan jika itu adalah untuk membuat konstanta sementara untuk digunakan dalam skrip, yaitu di beberapa pernyataan / batch GO.
Buat saja prosedur di tempdb maka Anda tidak berdampak pada database target.
Salah satu contoh praktisnya adalah skrip buat basis data yang menulis nilai kontrol di akhir skrip yang berisi versi skema logis. Di bagian atas file terdapat beberapa komentar dengan riwayat perubahan, dll. Tetapi dalam praktiknya sebagian besar pengembang akan lupa untuk menggulir ke bawah dan memperbarui versi skema di bagian bawah file.
Menggunakan kode di atas memungkinkan konstanta versi skema yang terlihat untuk didefinisikan di atas sebelum skrip database (disalin dari fitur skrip pembuatan SSMS) membuat database tetapi digunakan di bagian akhir. Ini tepat di hadapan pengembang di samping riwayat perubahan dan komentar lain, jadi mereka sangat mungkin untuk memperbaruinya.
Sebagai contoh:
use tempdb go create function dbo.MySchemaVersion() returns int as begin return 123 end go use master go -- Big long database create script with multiple batches... print 'Creating database schema version ' + CAST(tempdb.dbo.MySchemaVersion() as NVARCHAR) + '...' go -- ... go -- ... go use MyDatabase go -- Update schema version with constant at end (not normally possible as GO puts -- local @variables out of scope) insert MyConfigTable values ('SchemaVersion', tempdb.dbo.MySchemaVersion()) go -- Clean-up use tempdb drop function MySchemaVersion go
sumber