संगतता स्तर 80 का वास्तविक व्यवहार क्या है?


47

क्या कोई मुझे संगतता मोड सुविधा के बारे में बेहतर जानकारी प्रदान कर सकता है? यह मेरी अपेक्षा से भिन्न व्यवहार कर रहा है।

जहाँ तक मुझे संगतता मोड की समझ है, यह SQL सर्वर के विभिन्न संस्करणों के बीच कुछ भाषा संरचनाओं की उपलब्धता और समर्थन के बारे में है।

यह डेटाबेस इंजन संस्करण के आंतरिक कामकाज को प्रभावित नहीं करता है। यह उन सुविधाओं और निर्माणों के उपयोग को रोकने की कोशिश करेगा जो पहले के संस्करणों में अभी तक उपलब्ध नहीं थे।

मैंने अभी SQL Server 2008 R2 में कॉम्पिटिटर स्तर 80 के साथ एक नया डेटाबेस बनाया है। एकल इंट कॉलम के साथ एक तालिका बनाई और कुछ पंक्तियों के साथ इसे आबाद किया।

फिर एक row_number()फ़ंक्शन के साथ एक चयनित स्टेटमेंट निष्पादित किया गया ।

मेरा विचार था, चूंकि row_number फ़ंक्शन केवल 2005 में शुरू किया गया था, इसलिए यह 80 मोड में कॉम्पिटिटर में एक त्रुटि फेंक देगा।

लेकिन मेरे आश्चर्य के लिए यह ठीक काम किया। फिर, निश्चित रूप से, जब आप 'कुछ बचाते हैं' तो हम केवल नियमों का मूल्यांकन करते हैं। इसलिए मैंने अपने row_number स्टेटमेंट के लिए एक संग्रहित proc बनाया।

संग्रहीत खरीद निर्माण ठीक हो गया और मैं इसे पूरी तरह से निष्पादित कर सकता हूं और परिणाम प्राप्त कर सकता हूं।

क्या कोई मुझे संगतता मोड के काम को बेहतर ढंग से समझने में मदद कर सकता है? मेरी समझ स्पष्ट रूप से त्रुटिपूर्ण है।

जवाबों:


66

से डॉक्स :

SQL सर्वर के निर्दिष्ट संस्करण के साथ संगत होने के लिए कुछ डेटाबेस व्यवहार सेट करता है।
...
संगतता स्तर SQL सर्वर के पुराने संस्करणों के साथ केवल आंशिक पिछड़े संगतता प्रदान करता है। संगत संगतता-स्तर सेटिंग द्वारा नियंत्रित किए गए व्यवहारों में संस्करण अंतरों के आसपास काम करने के लिए एक अंतरिम माइग्रेशन सहायता के रूप में संगतता स्तर का उपयोग करें।

मेरी व्याख्या में, संगतता मोड व्यवहार और वाक्यविन्यास के पार्सिंग के बारे में है, न कि पार्सर जैसी चीजों के लिए, "अरे, आप उपयोग नहीं कर सकते हैं ROW_NUMBER()!" कभी-कभी कम अनुकूलता स्तर आपको सिंटैक्स के साथ दूर रहना जारी रखने की अनुमति देता है, और कभी-कभी यह आपको नए सिंटैक्स निर्माण का उपयोग करने से रोकता है। प्रलेखन कई स्पष्ट उदाहरणों को सूचीबद्ध करता है, लेकिन यहां कुछ प्रदर्शन हैं:


फ़ंक्शन तर्कों के रूप में अंतर्निहित कार्य पास करना

यह कोड संगतता स्तर 90+ में काम करता है:

SELECT *
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL);

लेकिन 80 में इसकी पैदावार होती है:

एमएसजी 102, स्तर 15, राज्य 1
गलत सिंटैक्स पास '(')।

यहाँ विशिष्ट समस्या यह है कि 80 में आपको किसी फ़ंक्शन में अंतर्निहित फ़ंक्शन को पारित करने की अनुमति नहीं है। यदि आप 80 संगतता मोड में रहना चाहते हैं, तो आप यह कहकर काम कर सकते हैं:

DECLARE @db_id INT = DB_ID();

SELECT * 
FROM sys.dm_db_index_physical_stats(@db_id, NULL, NULL, NULL, NULL);

तालिका प्रकार को टेबल-वैल्यू फ़ंक्शन में पास करना

उपरोक्त के समान, आप एक टीवीपी का उपयोग करते समय एक सिंटैक्स त्रुटि प्राप्त कर सकते हैं और इसे टेबल-वैल्यू फ़ंक्शन में पास करने की कोशिश कर सकते हैं। यह आधुनिक कम्प्रेसर स्तरों में काम करता है:

CREATE TYPE dbo.foo AS TABLE(bar INT);
GO
CREATE FUNCTION dbo.whatever
(
  @foo dbo.foo READONLY
)
RETURNS TABLE
AS 
  RETURN (SELECT bar FROM @foo);
GO

DECLARE @foo dbo.foo;
INSERT @foo(bar) SELECT 1;
SELECT * FROM dbo.whatever(@foo);

हालाँकि, संगतता स्तर को 80 में बदलें, और अंतिम तीन पंक्तियों को फिर से चलाएं; आपको यह त्रुटि संदेश मिलता है:

Msg 137, Level 16, State 1, Line 19
को स्केलर वैरिएबल "@foo" घोषित करना चाहिए।

वास्तव में मेरे सिर के ऊपर से कोई अच्छा वर्कअराउंड नहीं है, कॉम्पेटिटर स्तर को अपग्रेड करने या परिणामों को अलग तरीके से प्राप्त करने के अलावा।


APPLY में योग्य स्तंभ नामों का उपयोग करना

90 संगतता मोड और अप में, आप समस्या के बिना यह कर सकते हैं:

SELECT * FROM sys.dm_exec_cached_plans AS p
  CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t;

हालांकि, 80 संगतता मोड में, फ़ंक्शन को सौंपे गए योग्य कॉलम में एक सामान्य वाक्यविन्यास त्रुटि होती है:

एमएसजी 102, स्तर 15, राज्य 1
'के पास गलत सिंटैक्स।'।


आदेश एक स्तंभ नाम से मेल खाने वाले उपनाम से होता है

इस प्रश्न पर विचार करें:

SELECT name = REVERSE(name), realname = name 
FROM sys.all_objects AS o
ORDER BY o.name;

80 संगतता मोड में, परिणाम इस प्रकार हैं:

001_ofni_epytatad_ps   sp_datatype_info_100
001_scitsitats_ps      sp_statistics_100
001_snmuloc_corps_ps   sp_sproc_columns_100
...

90 संगतता मोड में, परिणाम काफी अलग हैं:

snmuloc_lla      all_columns
stcejbo_lla      all_objects
sretemarap_lla   all_parameters
...

कारण? 80 संगतता मोड में, तालिका उपसर्ग को पूरी तरह से अनदेखा किया जाता है, इसलिए यह SELECTसूची में उपनाम द्वारा परिभाषित अभिव्यक्ति द्वारा आदेश दे रहा है । नए संगतता स्तरों में, तालिका उपसर्ग को माना जाता है, इसलिए SQL सर्वर वास्तव में तालिका में स्तंभ का उपयोग करेगा (यदि यह पाया जाता है)। यदि ORDER BYतालिका में उपनाम नहीं मिला है, तो नए संगतता स्तर अस्पष्टता के बारे में क्षमा नहीं कर रहे हैं। इस उदाहरण पर विचार करें:

SELECT myname = REVERSE(name), realname = name 
FROM sys.all_objects AS o
ORDER BY o.myname;

myname80 में अभिव्यक्ति द्वारा परिणाम का आदेश दिया जाता है , क्योंकि फिर से तालिका उपसर्ग को अनदेखा किया जाता है, लेकिन 90 में यह त्रुटि संदेश उत्पन्न करता है:

Msg 207, स्तर 16, राज्य 1, पंक्ति 3
अमान्य स्तंभ नाम 'myname'।

यह सब प्रलेखन में भी समझाया गया है :

ORDER BYसूची में स्तंभ संदर्भों को सूची में परिभाषित किए गए स्तंभों से SELECTबांधते समय, स्तंभ अस्पष्टताओं को अनदेखा किया जाता है और स्तंभ उपसर्गों को आमतौर पर अनदेखा किया जाता है। यह एक अप्रत्याशित क्रम में लौटने के लिए सेट परिणाम का कारण बन सकता है।

उदाहरण के लिए, ORDER BYएक एकल दो-भाग कॉलम ( <table_alias>.<column>) के साथ एक खंड जो एक SELECT सूची में एक स्तंभ के संदर्भ के रूप में उपयोग किया जाता है, को स्वीकार किया जाता है, लेकिन तालिका उपनाम को अनदेखा किया जाता है। निम्नलिखित प्रश्न पर विचार करें।

SELECT c1 = -c1 FROM t_table AS x ORDER BY x.c1

निष्पादित होने पर, स्तंभ उपसर्ग को अनदेखा किया जाता है ORDER BY। सॉर्ट ऑपरेशन निर्दिष्ट स्रोत कॉलम ( x.c1) पर अपेक्षित रूप से नहीं होता है; इसके बजाय यह व्युत्पन्न पर होता हैc1स्तंभ जिसे क्वेरी में परिभाषित किया गया है। इस क्वेरी के लिए निष्पादन योजना से पता चलता है कि व्युत्पन्न कॉलम के लिए मूल्यों की गणना पहले की जाती है और फिर गणना किए गए मानों को क्रमबद्ध किया जाता है।


आदेश सूची में कुछ नहीं द्वारा आदेश

90 संगतता मोड में आप ऐसा नहीं कर सकते:

SELECT name = COALESCE(a.name, '') FROM sys.objects AS a
UNION ALL
SELECT name = COALESCE(a.name, '') FROM sys.objects AS a
ORDER BY a.name;

नतीजा:


यदि कथन में UNION, INTERSECT या EXCEPT ऑपरेटर हो तो Msg 104, Level 16, State 1 ORDER BY आइटम का चयन सूची में होना चाहिए।

80 में, हालांकि, आप अभी भी इस सिंटैक्स का उपयोग कर सकते हैं।


पुराना, icky बाहरी जुड़ता है

80 मोड भी आपको पुराने, पदावनत बाहरी सम्मिलित वाक्यविन्यास ( *=/=*) का उपयोग करने की अनुमति देता है :

SELECT o.name, c.name
FROM sys.objects AS o, sys.columns AS c
WHERE o.[object_id] *= c.[object_id];

SQL Server 2008/2008 R2 में, यदि आप 90 या उससे अधिक उम्र के हैं, तो आपको यह क्रिया संदेश मिलता है:

एमएसजी 4147, स्तर 15, राज्य 1
क्वेरी गैर-एएनएसआई बाहरी जुड़ने वाले ऑपरेटरों (" *=" या " =*") का उपयोग करती है। संशोधन के बिना इस क्वेरी को चलाने के लिए, कृपया वर्तमान डेटाबेस के लिए संगतता स्तर सेट करें, ALAT DATABASE के SET COMPATIBILITY_LEVEL विकल्प का उपयोग करके। यह ANSI बाहरी जॉइन ऑपरेटरों (LEFT OUTER JOIN, RIGHT OUTER JOIN) का उपयोग करके क्वेरी को फिर से लिखने की दृढ़ता से अनुशंसा की जाती है। SQL सर्वर के भविष्य के संस्करणों में, गैर-एएनएसआई शामिल होने वाले ऑपरेटरों को पिछड़े-संगतता मोड में भी समर्थित नहीं किया जाएगा।

SQL Server 2012 में, यह अब बिल्कुल भी सिंटैक्स नहीं है, और निम्न प्राप्त करता है:

एमएसजी 102, स्तर 15, राज्य 1, लाइन 3
'* =' के पास गलत सिंटैक्स।

बेशक SQL Server 2012 में आप संगतता स्तर का उपयोग करके इस समस्या के आसपास काम नहीं कर सकते, क्योंकि 80 अब समर्थित नहीं है। यदि आप किसी डेटाबेस को 80 कंप्रेशर मोड (इन-प्लेस अपग्रेड, डिटैच / अटैच, बैकअप / रिस्टोर, लॉग शिपिंग, मिररिंग इत्यादि) से अपग्रेड करते हैं, तो यह आपके लिए अपने आप 90 पर अपग्रेड हो जाएगा।


टेबल संकेत के बिना

80 कॉम्पिटिटर मोड में, आप निम्न का उपयोग कर सकते हैं और तालिका संकेत देखे जाएंगे:

SELECT * FROM dbo.whatever NOLOCK; 

90+ में, यह NOLOCKअब एक टेबल संकेत नहीं है, यह एक उपनाम है। अन्यथा, यह काम करेगा:

SELECT * FROM dbo.whatever AS w NOLOCK;

लेकिन यह नहीं है:

Msg 1018, स्तर 15, राज्य 1
'NOLOCK' के पास गलत सिंटैक्स। यदि यह तालिका संकेत के एक भाग के रूप में अभिप्रेत है, तो A कीवर्ड और कोष्ठक के साथ अब आवश्यक है। उचित सिंटैक्स के लिए SQL सर्वर पुस्तकें ऑनलाइन देखें।

अब, यह साबित करने के लिए कि व्यवहार को पहले उदाहरण में नहीं देखा गया है जब 90 कॉम्पिटिटर मोड में, एडवेंचरवर्क्स का उपयोग करें (यह सुनिश्चित करें कि यह उच्चतर स्तर में है) और निम्नलिखित रन करें:

BEGIN TRANSACTION;
SELECT TOP (1) * FROM Sales.SalesOrderHeader UPDLOCK;
SELECT * FROM sys.dm_tran_locks 
  WHERE request_session_id = @@SPID
  AND resource_type IN ('KEY', 'OBJECT'); -- how many rows here? 0
COMMIT TRANSACTION;

BEGIN TRANSACTION;
SELECT TOP (1) * FROM Sales.SalesOrderHeader WITH (UPDLOCK);
SELECT * FROM sys.dm_tran_locks
  WHERE request_session_id = @@SPID
  AND resource_type IN ('KEY', 'OBJECT'); -- how many rows here? 2
COMMIT TRANSACTION;

यह एक विशेष रूप से समस्याग्रस्त है क्योंकि व्यवहार त्रुटि संदेश या यहां तक ​​कि त्रुटि के बिना बदलता है। और यह भी कुछ है कि उन्नयन सलाहकार और अन्य उपकरण भी हाजिर नहीं हो सकते हैं, क्योंकि यह सब जानता है, यह एक तालिका उपनाम है।


नई तिथि / समय प्रकार शामिल करने वाले वार्तालाप

SQL Server 2008 (जैसे dateऔर datetime2) में पेश की गई नई तिथि / समय प्रकार मूल datetimeऔर की तुलना में बहुत बड़ी रेंज का समर्थन करते हैं smalldatetime। समर्थित सीमा के बाहर मूल्यों के स्पष्ट रूपांतरण कोई भी बात नहीं करेंगे, उदाहरण के लिए संगतता स्तर:

SELECT CONVERT(SMALLDATETIME, '00010101');

पैदावार:

Msg 242, Level 16, State 3
एक varchar डेटा टाइप को एक स्मालडलटाइम डेटा टाइप में बदलने के परिणामस्वरूप आउट-ऑफ-द-रेंज मान होता है।

हालाँकि, अंतर्निहित रूपांतरण नए संगतता स्तरों में खुद को काम करेंगे। उदाहरण के लिए यह 100+ में काम करेगा:

SELECT DATEDIFF(DAY, CONVERT(SMALLDATETIME, SYSDATETIME()), '00010101');

लेकिन 80 में (और 90 में भी), यह ऊपर के समान त्रुटि देता है:

Msg 242, Level 16, State 3
एक varchar डेटा टाइप को डेटाइम टाइम टाइप करने के लिए आउट-ऑफ-रेंज मान दिया गया।


ट्रिगर में खंड के लिए निरर्थक

यह एक अस्पष्ट परिदृश्य है जो यहां आया था । 80 संगतता मोड में, यह सफल होगा:

CREATE TABLE dbo.x(y INT);
GO
CREATE TRIGGER tx ON dbo.x
FOR UPDATE, UPDATE
------------^^^^^^ notice the redundant UPDATE
AS PRINT 1;

90 संगतता और उच्चतर में, यह अब नहीं रह गया है, और इसके बजाय आपको निम्न त्रुटि संदेश मिलता है:

Msg 1034, स्तर 15, राज्य 1, प्रक्रिया tx
सिंटैक्स त्रुटि: ट्रिगर घोषणा में "UPDATE" कार्रवाई के डुप्लिकेट विनिर्देश।


धुरी / UNPIVOT

सिंटैक्स के कुछ रूप 80 के तहत काम नहीं करेंगे (लेकिन 90+ में ठीक काम करते हैं):

SELECT col1, col2
FROM dbo.t1
UNPIVOT (value FOR col3 IN ([x],[y])) AS p;

यह प्रदान करता है:

संदेश 156, स्तर 15, राज्य 1
'के लिए' कीवर्ड के पास गलत सिंटैक्स।

कुछ वर्कअराउंड के लिए, सहित CROSS APPLY, इन उत्तरों को देखें ।


नए अंतर्निहित कार्य

TRY_CONVERT()अनुकूलता स्तर <110 के साथ डेटाबेस में नए कार्यों का उपयोग करने का प्रयास करें । वे बस वहाँ बिल्कुल पहचाने नहीं जाते हैं।

SELECT TRY_CONVERT(INT, 1);

नतीजा:

Msg 195, स्तर 15, राज्य 10
'TRY_CONVERT' एक मान्यता प्राप्त अंतर्निहित फ़ंक्शन नाम नहीं है।


सिफ़ारिश करना

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


1
जाहिर है कि यह मेरा एक बेहतर जवाब है!
मैक्स वेरनॉन

इस विस्तृत जवाब के लिए बहुत बहुत धन्यवाद, हारून! और मेरी कई वर्तनी की गलतियों को ठीक करने के लिए।
सुप्लेक्स

1
SQL सर्वर 2014 संगतता नोट यहां पाए जाते हैं: msdn.microsoft.com/en-us/library/bb510680(v=sql.120).aspx
Josh Gallagher

9

संगतता स्तर केवल SQL सर्वर के पुराने संस्करण से नियंत्रित माइग्रेशन की अनुमति देने के लिए मौजूद हैं। सुसंगत स्तर 90 नई सुविधाओं का उपयोग नहीं करता है, इसका मतलब है कि डेटाबेस के कुछ पहलुओं को उसी तरह से बनाए रखा जाता है जो SQL Server 2005 के साथ संगत है।

अधिक जानकारी के लिए http://msdn.microsoft.com/en-us/library/bb510680.aspx देखें ।

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