इसलिए, मैं यह महसूस करने के बाद त्रुटि को पुन: उत्पन्न करने में सक्षम था कि CAST
स्थानीय रूप से किया जा रहा है, दूरस्थ उदाहरण पर नहीं। मैंने पहले इसे ठीक करने की उम्मीद में SP3 तक जाने की सिफारिश की थी (आंशिक रूप से SP3 पर त्रुटि को पुन: पेश करने में सक्षम नहीं होने के कारण, और आंशिक रूप से इसकी परवाह किए बिना एक अच्छा विचार होने के कारण)। हालांकि, अब जब मैं त्रुटि को पुन: उत्पन्न कर सकता हूं, तो यह स्पष्ट है कि एसपी 3 तक बढ़ रहा है, जबकि अभी भी शायद एक अच्छा विचार है, इसे ठीक करने वाला नहीं है। और मैंने SQL Server 2008 R2 RTM और 2014 SP1 में त्रुटि (तीनों मामलों में "लूप-बैक" स्थानीय लिंक्ड सर्वर का उपयोग करके) भी पुन: उत्पन्न किया।
ऐसा लगता है कि इस समस्या के साथ क्या करना है जहां क्वेरी निष्पादित हो रही है, या कम से कम जहां इसका हिस्सा निष्पादित हो रहा है। मैं यह कहता हूं क्योंकि मैं CAST
काम करने के लिए ऑपरेशन करने में सक्षम था , लेकिन केवल एक स्थानीय डीबी ऑब्जेक्ट के संदर्भ को शामिल करके:
SELECT rmt.*, CAST(NULL AS UNIQUEIDENTIFIER) AS [GUID]
FROM [Local].[database_name].[dbo].[table_name] rmt
CROSS JOIN (SELECT TOP (1) 1 FROM [sys].[data_spaces]) tmp(dummy);
जो वास्तव में काम करता है। लेकिन मूल त्रुटि निम्नलिखित है:
SELECT rmt.*, CAST(NULL AS UNIQUEIDENTIFIER) AS [GUID]
FROM [Local].[database_name].[dbo].[table_name] rmt
CROSS JOIN (VALUES (1)) tmp(dummy);
मैं अनुमान लगा रहा हूं कि जब कोई स्थानीय संदर्भ नहीं होते हैं, तो पूरी क्वेरी को निष्पादित करने के लिए रिमोट सिस्टम पर भेज दिया जाता है, और किसी कारण से NULL
इसे परिवर्तित नहीं किया जा सकता है UNIQUEIDENTIFIER
, या शायद NULL
OLE DB ड्राइवर द्वारा गलत तरीके से अनुवाद किया जा रहा है।
मेरे द्वारा किए गए परीक्षण के आधार पर, यह एक बग प्रतीत होगा, लेकिन मुझे यकीन नहीं है कि बग SQL सर्वर या SQL सर्वर मूल क्लाइंट / OLEDB ड्राइवर के भीतर है। हालांकि, रूपांतरण त्रुटि OLEDB चालक के भीतर होती है, और इसलिए जरूरी से परिवर्तित करने की कोई समस्या नहीं है INT
करने के लिए UNIQUEIDENTIFIER
ड्राइवर के बाद से (जिस रूपांतरण एसक्यूएल सर्वर में अनुमति नहीं है) एसक्यूएल सर्वर का उपयोग नहीं कर रहा है, रूपांतरण (एसक्यूएल सर्वर भी नहीं है ऐसा करने के लिए परिवर्तित INT
करने की अनुमति दें DATE
, फिर भी OLEDB ड्राइवर को सफलतापूर्वक संभालता है, जैसा कि परीक्षणों में से एक में दिखाया गया है)।
मैंने तीन परीक्षण चलाए। सफल होने वाले दो लोगों के लिए, मैंने एक्सएमएल निष्पादन योजनाओं को देखा जो दूर से निष्पादित की जाने वाली क्वेरी को दिखाते हैं। तीनों के लिए, मैंने SQL Profiler के माध्यम से किसी भी अपवाद या OLEDB घटनाओं पर कब्जा कर लिया:
आयोजन:
- त्रुटियां और चेतावनी
- ध्यान
- अपवाद
- निष्पादन चेतावनी
- उपयोगकर्ता त्रुटि संदेश
- OLEDB
- TSQL
- सभी को छोड़कर :
- एसक्यूएल: StmtRecompile
- XQuery स्टेटिक प्रकार
कॉलम फ़िल्टर:
- आवेदन का नाम
- नहीं पसंद % Intellisense%
- SPID
जाँच
परीक्षण 1
CAST(NULL AS UNIQUEIDENTIFIER)
यह काम करता है
SELECT TOP (2) CAST(NULL AS UNIQUEIDENTIFIER) AS [Something]
, (SELECT COUNT(*) FROM sys.[data_spaces]) AS [lcl]
FROM [Local].[TEMPTEST].[sys].[objects] rmt;
XML निष्पादन योजना का प्रासंगिक भाग:
<DefinedValue>
<ColumnReference Column="Expr1002" />
<ScalarOperator ScalarString="NULL">
<Const ConstValue="NULL" />
</ScalarOperator>
</DefinedValue>
...
<RemoteQuery RemoteSource="Local" RemoteQuery=
"SELECT 1 FROM "TEMPTEST"."sys"."objects" "Tbl1001""
/>
परीक्षण २
CAST(NULL AS UNIQUEIDENTIFIER)
वह विफल रहता है
SELECT TOP (2) CAST(NULL AS UNIQUEIDENTIFIER) AS [Something]
-- , (SELECT COUNT(*) FROM sys.[data_spaces]) AS [lcl]
FROM [Local].[TEMPTEST].[sys].[objects] rmt;
(ध्यान दें: मैंने वहां उपशम रखा था, टिप्पणी की, ताकि जब मैं XML ट्रेस फ़ाइलों की तुलना में यह एक कम अंतर हो जाए)
परीक्षण ३
CAST(NULL AS DATE)
यह काम करता है
SELECT TOP (2) CAST(NULL AS DATE) AS [Something]
-- , (SELECT COUNT(*) FROM sys.[data_spaces]) AS [lcl]
FROM [Local].[TEMPTEST].[sys].[objects] rmt;
(ध्यान दें: मैंने वहां उपशम रखा था, टिप्पणी की, ताकि जब मैं XML ट्रेस फ़ाइलों की तुलना में यह एक कम अंतर हो जाए)
XML निष्पादन योजना का प्रासंगिक भाग:
<DefinedValue>
<ColumnReference Column="Expr1002" />
<ScalarOperator ScalarString="[Expr1002]">
<Identifier>
<ColumnReference Column="Expr1002" />
</Identifier>
</ScalarOperator>
</DefinedValue>
...
<RemoteQuery RemoteSource="Local" RemoteQuery=
"SELECT TOP (2) NULL "Expr1002" FROM "TEMPTEST"."sys"."objects" "Tbl1001""
/>
यदि आप टेस्ट # 3 को देखते हैं, तो यह SELECT TOP (2) NULL
"रिमोट" सिस्टम पर कर रहा है। SQL Profiler ट्रेस दिखाता है कि इस दूरस्थ क्षेत्र का डेटाटाइप वास्तव में है INT
। ट्रेस यह भी दर्शाता है कि ग्राहक की ओर का क्षेत्र (यानी जहां मैं क्वेरी चला रहा हूं) DATE
अपेक्षा के अनुरूप है। से रूपांतरण INT
करने के लिए DATE
, जो कुछ एसक्यूएल सर्वर में एक त्रुटि प्राप्त होगी, OLEDB चालक के भीतर बस ठीक काम करता है। दूरस्थ मान है NULL
, इसलिए इसे सीधे लौटा दिया जाता है, इसलिए <ColumnReference Column="Expr1002" />
।
यदि आप टेस्ट # 1 को देखते हैं, तो यह SELECT 1
"रिमोट" सिस्टम पर कर रहा है। SQL Profiler ट्रेस दिखाता है कि वास्तव में इस दूरस्थ क्षेत्र का डेटाटाइप है INT
। ट्रेस यह भी दर्शाता है कि ग्राहक की ओर का क्षेत्र (अर्थात जहाँ से मैं क्वेरी चला रहा हूँ) GUID
अपेक्षित है। से रूपांतरण INT
करने के लिए GUID
(याद रखें, इस ड्राइवर के भीतर किया जाता है, और OLEDB यह कॉल "GUID"), जो कुछ एसक्यूएल सर्वर में एक त्रुटि प्राप्त होगी, OLEDB चालक के भीतर बस ठीक काम करता है। दूरस्थ मूल्य नहीं है NULL
, इसलिए इसे शाब्दिक रूप से बदल दिया जाता है NULL
, इसलिए <Const ConstValue="NULL" />
।
टेस्ट # 2 विफल रहता है, इसलिए कोई निष्पादन योजना नहीं है। हालाँकि, यह "रिमोट" सिस्टम को सफलतापूर्वक क्वेरी करता है, लेकिन परिणाम सेट को वापस नहीं कर सकता। SQL Profiler ने जिस क्वेरी पर कब्जा किया है वह है:
SELECT TOP (2) NULL "Expr1002" FROM "TEMPTEST"."sys"."objects" "Tbl1001"
यह वही सटीक प्रश्न है जो टेस्ट # 1 में किया जा रहा है, फिर भी यहाँ यह विफल हो रहा है। अन्य मामूली अंतर हैं, लेकिन मैं OLEDB संचार की पूरी तरह से व्याख्या नहीं कर सकता। हालाँकि, दूरस्थ क्षेत्र अभी भी INT
(wType = 3 = adInteger / four-byte हस्ताक्षरित पूर्णांक / DBTYPE_I4) के रूप में दिखा रहा है, जबकि "क्लाइंट" फ़ील्ड अभी भी GUID
(wType = 72 = adGIDID / विश्वव्यापी विशिष्ट पहचानकर्ता / DBTYPE_GUID) के रूप में दिखाई दे रहा है। OLE DB प्रलेखन GUID डेटा प्रकार रूपांतरण , DBDATE डेटा प्रकार रूपांतरण , और I4 डेटा प्रकार रूपांतरण के रूप में ज्यादा मदद नहीं करता है कि I4 से या तो GUID या DBDATE में कनवर्ट करना असमर्थित है, फिर भी DATE
क्वेरी काम करती है।
तीन परीक्षणों के लिए ट्रेस एक्सएमएल फाइलें पेस्टबिन पर स्थित हैं। यदि आप इस बात का विवरण देखना चाहते हैं कि प्रत्येक परीक्षण दूसरों से कहां भिन्न है, तो आप उन्हें स्थानीय रूप से सहेज सकते हैं और फिर उन पर "अंतर" कर सकते हैं। फाइलें हैं:
- NullGuidSuccess.xml
- NullGuidError.xml
- NullDateSuccess.xml
फलस्वरूप?
इसके बारे में क्या करना है? संभवतः सिर्फ काम-आस-पास मैंने शीर्ष खंड में उल्लेख किया है, यह देखते हुए कि एसक्यूएल नेटिव क्लाइंट - SQLNCLI11
- को एसक्यूएल सर्वर २०१२ के रूप में दर्शाया गया है। एसक्यूएल सर्वर नेटिव क्लाइंट के विषय पर अधिकांश एमएसडीएन पृष्ठों में निम्नलिखित सूचना है। शीर्ष:
चेतावनी
SQL सर्वर 2012 से परे SQL सर्वर नेटिव क्लाइंट (SNAC) समर्थित नहीं है। नए विकास कार्यों में SNAC का उपयोग करने से बचें, और वर्तमान में इसका उपयोग करने वाले अनुप्रयोगों को संशोधित करने की योजना बनाएं। एसक्यूएल सर्वर के लिए Microsoft ODBC ड्राइवर Microsoft SQL सर्वर और Microsoft Azure एसक्यूएल डाटाबेस करने के लिए Windows से देशी कनेक्टिविटी प्रदान करता है।
अधिक जानकारी के लिए, कृपया देखें:
ODBC ??
मैंने एक ODBC लिंक किया हुआ सर्वर सेट किया है:
EXEC master.dbo.sp_addlinkedserver
@server = N'LocalODBC',
@srvproduct=N'{my_server_name}',
@provider=N'MSDASQL',
@provstr=N'Driver={SQL Server};Server=(local);Trusted_Connection=Yes;';
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname=N'LocalODBC',
@useself=N'True',
@locallogin=NULL,
@rmtuser=NULL,
@rmtpassword=NULL;
और फिर कोशिश की:
SELECT CAST(NULL AS UNIQUEIDENTIFIER) AS [Something]
FROM [LocalODBC].[tempdb].[sys].[objects] rmt;
और निम्न त्रुटि प्राप्त हुई:
OLE DB प्रदाता "MSDASQL" लिंक किए गए सर्वर "LocalODBC" के लिए संदेश "अनुरोधित रूपांतरण समर्थित नहीं है।"।
Msg 7341, स्तर 16, राज्य 2, पंक्ति 53
स्तंभ की वर्तमान पंक्ति मान नहीं प्राप्त कर सकते हैं "(उपयोगकर्ता द्वारा उत्पन्न अभिव्यक्ति) .Expr1002" OLE DB प्रदाता "MSDASQL" से लिंक किए गए सर्वर "LocalODBC" के लिए।
पुनश्च
जैसा कि यह दूरस्थ और स्थानीय सर्वरों के बीच GUID को परिवहन करने से संबंधित है, गैर-पूर्ण मानों को एक विशेष वाक्यविन्यास के माध्यम से नियंत्रित किया जाता है। जब मैंने भाग लिया तो मैंने SQL Profiler ट्रेस में निम्नलिखित OLE DB इवेंट जानकारी देखी CAST(0x00 AS UNIQUEIDENTIFIER)
:
<RemoteQuery RemoteSource="Local" RemoteQuery=
"SELECT {guid'00000000-0000-0000-0000-000000000000'} "Expr1002" FROM "TEMPTEST"."sys"."objects" "Tbl1001""
/>
पी पी एस
मैंने OPENQUERY
निम्नलिखित प्रश्न के माध्यम से भी परीक्षण किया :
SELECT TOP (2) CAST(NULL AS UNIQUEIDENTIFIER) AS [Something]
--, (SELECT COUNT(*) FROM sys.[data_spaces]) AS [lcl]
FROM OPENQUERY([Local], N'SELECT 705 AS [dummy] FROM [TEMPTEST].[sys].[objects];') rmt;
और यह स्थानीय वस्तु संदर्भ के बिना भी सफल रहा। SQL Profiler ट्रेस XML फ़ाइल को PasteBin पर पोस्ट किया गया है:
NullGuidSuccessOPENQUERY.xml
एक्सएमएल निष्पादन योजना एक NULL
स्थिर का उपयोग करके दिखाती है , जैसा कि टेस्ट # 1 में है।