टीएसक्यूएल वेरिएबल को स्थिर बनाने का कोई तरीका है?


जवाबों:


60

नहीं, लेकिन आप एक फंक्शन बना सकते हैं और इसे वहां पर हार्डकोड कर सकते हैं और इसका उपयोग कर सकते हैं।

यहाँ एक उदाहरण है:

CREATE FUNCTION fnConstant()
RETURNS INT
AS
BEGIN
    RETURN 2
END
GO

SELECT dbo.fnConstant()

13
WITH SCHEMABINDING इसे 'वास्तविक' स्थिरांक में बदलना चाहिए (यूडीएफ के लिए एक आवश्यकता को SQL में निर्धारक के रूप में देखा जाना चाहिए)। यानी इसे कैश किया जाना चाहिए। फिर भी, +1।
जोनाथन डिकिंसन

यह उत्तर अच्छा है, बस जिज्ञासु एक डिफ़ॉल्ट मान के रूप में एक फ़ंक्शन को sqlserver संदर्भ में तालिका स्तंभ कर सकता है। मुझे यह काम करने के लिए नहीं मिला
Ab Bennett

1
@JonathanDickinson स्पष्ट होने के लिए, आपका सुझाव कथन WITH SCHEMABINDINGमें उपयोग करने के लिए है CREATE FUNCTION(जैसा कि संग्रहित प्रक्रिया में विरोध किया जा सकता है जो फ़ंक्शन को कॉल कर सकता है) - क्या यह सही है?
डेवलपर

1
हां, फंक्शन में। SCHEMABINDING के साथ SQL "इनलाइन टेबल-वैल्यूड फंक्शंस" में SQL इनलाइन की अनुमति देता है - इसलिए इसे इस रूप में भी होना चाहिए: gist.github.com/jcdickinson/61a38dedb84b35251da301bb8535ceb । क्वेरी विश्लेषक SCHEMABINDING या BEGIN के साथ कुछ भी बिना इनलाइन नहीं करेगा।
जोनाथन डिकिंसन

गैर नियतात्मक यूडीएफ का उपयोग करने के निहितार्थ: docs.microsoft.com/es-es/archive/blogs/sqlprogrammability/…
Ochoto

28

जेरेड को द्वारा प्रस्तुत एक समाधान, छद्म स्थिरांक का उपयोग करना है

एसक्यूएल सर्वर में बताया गया है : चर, पैरामीटर या साहित्य? या… लगातार? :

छद्म-स्थिरांक चर या पैरामीटर नहीं हैं। इसके बजाय, वे केवल एक पंक्ति के साथ विचार कर रहे हैं, और आपके स्थिरांक का समर्थन करने के लिए पर्याप्त कॉलम। इन सरल नियमों के साथ, SQL इंजन दृश्य के मूल्य को पूरी तरह से अनदेखा करता है, लेकिन फिर भी इसके मूल्य के आधार पर एक निष्पादन योजना बनाता है। निष्पादन योजना भी दृश्य में शामिल नहीं होती है!

इस तरह बनाएं:

CREATE SCHEMA ShipMethod
GO
-- Each view can only have one row.
-- Create one column for each desired constant.
-- Each column is restricted to a single value.
CREATE VIEW ShipMethod.ShipMethodID 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]

तो इस तरह का उपयोग करें:

SELECT h.*
FROM Sales.SalesOrderHeader h
JOIN ShipMethod.ShipMethodID const
    ON h.ShipMethodID = const.[OVERNIGHT J-FAST]

या इस तरह:

SELECT h.*
FROM Sales.SalesOrderHeader h
WHERE h.ShipMethodID = (SELECT TOP 1 [OVERNIGHT J-FAST] FROM ShipMethod.ShipMethodID)

1
यह स्वीकृत उत्तर की तुलना में बेहतर समाधान है। प्रारंभ में हम स्केलर फंक्शन मार्ग से नीचे गए और इसका भयानक प्रदर्शन हुआ। बहुत बेहतर है यह उत्तर और जेरेड को के लेख के ऊपर लिंक।
डेविड कोस्टर

हालांकि, एक स्केलर फ़ंक्शन में SCHEMABINDING के साथ जोड़ने से इसके प्रदर्शन में उल्लेखनीय सुधार होता है।
डेविड कॉस्टर

लिंक अब मृत है।
मथिउ कॉर्मियर

1
@MatthieuCormier: मैंने लिंक को अपडेट कर दिया है, हालांकि ऐसा लगता है कि MSDN ने पुराने URL से नए को वैसे भी पुनर्निर्देशित कर दिया था।
इल्मरी करोनन

23

लापता स्थिरांक के लिए मेरा काम है, आशावादी को मूल्य के बारे में संकेत देना।

DECLARE @Constant INT = 123;

SELECT * 
FROM [some_relation] 
WHERE [some_attribute] = @Constant
OPTION( OPTIMIZE FOR (@Constant = 123))

यह क्वेरी कंपाइलर को चर का इलाज करने के लिए कहता है जैसे कि निष्पादन योजना बनाते समय यह एक स्थिर था। नीचे की ओर यह है कि आपको दो बार मान को परिभाषित करना होगा।


3
यह मदद करता है लेकिन यह एकल परिभाषा के उद्देश्य को भी पराजित करता है।
मिकराजमासी 56

9

नहीं, लेकिन अच्छे पुराने नामकरण सम्मेलनों का उपयोग किया जाना चाहिए।

declare @MY_VALUE as int

@VictorYarema क्योंकि कभी-कभी आपको सभी की ज़रूरत होती है। और क्योंकि कभी-कभी आपके पास कोई और अच्छा विकल्प नहीं होता है। अब, एक तरफ, SQLMenace का जवाब बेहतर लग रहा है, मैं आपसे सहमत हूँ। फिर भी, फ़ंक्शन नाम को स्थिरांक, IMO के लिए सम्मेलन का पालन करना चाहिए। इसका नामकरण होना चाहिए FN_CONSTANT()। इस तरह यह स्पष्ट है कि यह क्या कर रहा है।
tfrascaroli

जब आप प्रदर्शन लाभ चाहते हैं तो यह अकेले मदद नहीं करेगा। प्रदर्शन को बढ़ावा देने के लिए मिशल डी। और जॉन निल्सन के उत्तरों को भी आज़माएं।
वंडरवर्कर

8

टी-एसक्यूएल में स्थिरांक के लिए कोई अंतर्निहित समर्थन नहीं है। आप इसे अनुकरण करने के लिए SQLMenace के दृष्टिकोण का उपयोग कर सकते हैं (हालांकि आप यह कभी सुनिश्चित नहीं कर सकते हैं कि किसी और ने कुछ और वापस करने के लिए फ़ंक्शन को ओवरराइट किया है ...), या संभवत: एक तालिका लिखी है जिसमें स्थिरांक है, जैसा कि यहां पर सुझाव दिया गया है । शायद एक ट्रिगर लिखें जो ConstantValueकॉलम में किसी भी परिवर्तन को वापस करता है?


7

SQL फ़ंक्शन का उपयोग करने से पहले प्रदर्शन में अंतर देखने के लिए निम्न स्क्रिप्ट चलाएँ:

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

4
यह काफी पुराना है, लेकिन मेरे सर्वर पर निष्पादित होने पर यहाँ संदर्भ के लिए: | 2760ms elapsed, using function| 2300ms elapsed, using local variable| 2286ms elapsed, using hard coded values|
z00l

2
एक देव लैपटॉप पर, स्कीमा बंधन के बिना दो अतिरिक्त कार्यों के साथ। 5570 elapsed, using function | 406 elapsed, using local variable| 383 elapsed, using hard coded values| 3893 elapsed, using function without schemabinding
बंदरगृह

तुलना के लिए, एक सरल चयन विवरण 4110ms लिया गया था, जहां चयनित कथनों के बीच वैकल्पिक रूप से दिया गया था select top 1 @m = cv_val from code_values where cv_id = 'C101' और ... 'C201' जहाँ कोड_वल्यूस 250 संस्करण के साथ डिक्शनरी टेबल है, SQL Server-2016 पर सभी थे
मंकीहाउस

6

यदि आप चर में एक मूल्य के लिए इष्टतम निष्पादन योजना प्राप्त करने में रुचि रखते हैं, तो आप एक गतिशील sql कोड का उपयोग कर सकते हैं। यह चर को स्थिर बनाता है।

DECLARE @var varchar(100) = 'some text'
DECLARE @sql varchar(MAX)
SET @sql = 'SELECT * FROM table WHERE col = '''+@var+''''
EXEC (@sql)

1
यह है कि मैं इसे कैसे करता हूं और यह उन प्रश्नों को एक विशाल प्रदर्शन को बढ़ावा देता है जिसमें निरंतरता शामिल है।
वंडरवर्कर

5

Enums या सरल स्थिरांक के लिए, एक पंक्ति के साथ एक दृश्य में बहुत अच्छा प्रदर्शन होता है और समय की जाँच / निर्भरता ट्रैकिंग (इसके स्तंभ पर कारण) का संकलन होता है

Jared Ko का ब्लॉग पोस्ट देखें https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/

दृश्य बनाएँ

 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]

दृश्य का उपयोग करें

SELECT h.*
FROM Sales.SalesOrderHeader 
WHERE ShipMethodID = ( select [OVERNIGHT J-FAST] from ShipMethods  )

3

ठीक है, देखते हैं

लगातार अपरिवर्तनीय मूल्य हैं जो संकलन समय पर ज्ञात हैं और कार्यक्रम के जीवन के लिए नहीं बदलते हैं

इसका मतलब है कि आप SQL सर्वर में एक स्थिर नहीं रख सकते

declare @myvalue as int
set @myvalue = 5
set @myvalue = 10--oops we just changed it

मूल्य बस बदल गया


1

चूंकि स्थिरांक के समर्थन में कोई निर्माण नहीं है, इसलिए मेरा समाधान बहुत सरल है।

चूंकि यह समर्थित नहीं है:

Declare Constant @supplement int = 240
SELECT price + @supplement
FROM   what_does_it_cost

मैं बस इसे परिवर्तित कर दूंगा

SELECT price + 240/*CONSTANT:supplement*/
FROM   what_does_it_cost

जाहिर है, यह पूरी बात पर निर्भर करता है (अंतरिक्ष और टिप्पणी के बिना पीछे मूल्य) अद्वितीय होने के लिए। इसे बदलना वैश्विक खोज और प्रतिस्थापन के साथ संभव है।


एक समस्या यह है कि यह केवल स्थानीय रूप से उपलब्ध है
बर्नार्डो दाल कॉर्नो

0

डेटाबेस साहित्य में "एक स्थिर बनाने" जैसी कोई चीज नहीं है। स्थिरांक के रूप में वे मौजूद हैं और जिन्हें अक्सर मूल्य कहा जाता है। कोई एक चर घोषित कर सकता है और इसे एक मान (स्थिर) दे सकता है। एक विद्वान दृष्टिकोण से:

DECLARE @two INT
SET @two = 2

यहाँ @two एक चर है और 2 एक मान / स्थिरांक है।


प्रदर्शन को बढ़ावा देने के लिए मिशल डी। और जॉन निल्सन के उत्तर भी आजमाएँ।
वंडरवर्कर

साहित्य परिभाषा से स्थिर होता है। एससी / यूनिकोड (संपादक के आधार पर) चरित्र 2को "संकलन समय" में असाइन किए जाने पर एक द्विआधारी मूल्य में अनुवादित किया जाता है। एन्कोड किया गया वास्तविक मान उस डेटा प्रकार पर निर्भर करता है जिसे उसे (int, char, ...) को सौंपा जा रहा है।
samis

-1

सबसे अच्छा उत्तर SQLMenace से है आवश्यकता के अनुसार यदि स्क्रिप्ट के भीतर उपयोग के लिए एक अस्थायी स्थिरांक बनाना है, अर्थात कई GO स्टेटमेंट्स / बैचों में।

बस tempdb में प्रक्रिया बनाएँ, फिर आप लक्ष्य डेटाबेस पर कोई प्रभाव नहीं है।

इसका एक व्यावहारिक उदाहरण एक डेटाबेस क्रिएट स्क्रिप्ट है, जो तार्किक स्कीमा संस्करण वाले स्क्रिप्ट के अंत में एक नियंत्रण मूल्य लिखता है। फ़ाइल के शीर्ष पर परिवर्तन इतिहास आदि के साथ कुछ टिप्पणियां हैं ... लेकिन व्यवहार में अधिकांश डेवलपर्स फ़ाइल के नीचे स्क्रॉल करना और स्कीमा संस्करण को अपडेट करना भूल जाएंगे।

उपरोक्त कोड का उपयोग डेटाबेस स्क्रिप्ट (SSMS के उत्पन्न स्क्रिप्ट सुविधा से कॉपी किया गया) डेटाबेस बनाने से पहले सबसे ऊपर दिखाई दे रहे निरंतर स्कीमा संस्करण की अनुमति देता है, लेकिन अंत में उपयोग किया जाता है। यह परिवर्तन इतिहास और अन्य टिप्पणियों के आगे डेवलपर के सामने सही है, इसलिए वे इसे अपडेट करने की बहुत संभावना रखते हैं।

उदाहरण के लिए:

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.