क्या वस्तु के नामों को रेखांकित करने के लिए MS-SQL पर कोई (छिपा हुआ) अंतर्निहित कार्य है?


12

कभी-कभी हम अपने कुछ डेटाबेस में ऑब्जेक्ट नाम (पहचानकर्ता) स्टोर करते हैं, उदाहरण के लिए कुछ पैरामीटर टेबल में। क्योंकि मैं '=' ​​या 'LIKE' तुलना संचालकों का उपयोग करके इन तालिकाओं से रिकॉर्ड का चयन करता हूं, मुझे इन नामों को हमेशा ब्रैकेट के साथ या उसके बिना संग्रहीत करने का ध्यान रखना चाहिए ।

IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = '[TABLE_NAME]';

या

IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = 'TABLE_NAME';

हालाँकि MS-SQL के कुछ कार्य हैं जहाँ आप OBJECT_ID () फ़ंक्शन के उदाहरण के लिए या बिना ब्रैकेट के ऑब्जेक्ट ऑब्जेक्ट का उपयोग कर सकते हैं। मैंने dbfiddle.uk पर एक न्यूनतम उदाहरण स्थापित किया है ।

CREATE TABLE TEST
(
    ID     INT IDENTITY(1,1) PRIMARY KEY,
    OBJECT sysname NOT NULL
);
GO

INSERT INTO TEST VALUES ('[obj1]'),('obj2'),('obj3'),('[obj4]');
GO

अब मैं जाँचने के लिए OBJECT_ID () का उपयोग कर सकता हूं कि क्या तालिका परीक्षण इस तरह से मौजूद है:

IF OBJECT_ID('TEST') IS NOT NULL
BEGIN
    SELECT 'TEST EXISTS.' OBJECT_ID;
END
GO

| OBJECT_ID    |
| :----------- |
| TEST EXISTS. |

IF OBJECT_ID('[TEST]') IS NOT NULL
BEGIN
    SELECT '[TEST] EXISTS.' OBJECT_ID;
END
GO

| OBJECT_ID      |
| :------------- |
| [TEST] EXISTS. |

इससे कोई फर्क नहीं पड़ता कि मैं पहचानकर्ता परीक्षण को कोष्ठक के साथ या बिना पास करता हूं, तो कोष्ठक को हटाने के लिए पार्सर काफी स्मार्ट है।

खैर, मैं इसे एक स्केलर फ़ंक्शन को जोड़कर अनुकरण कर सकता हूं जो एक स्ट्रिंग से कोष्ठक हटाता है:

CREATE FUNCTION UNQUOTENAME(@TXT NVARCHAR(MAX)) 
RETURNS NVARCHAR(MAX)
AS
    BEGIN
        RETURN IIF(LEFT(@TXT, 1) = N'[' AND RIGHT(@TXT, 1) = N']', 
                   SUBSTRING(@TXT, 2, LEN(@TXT) -  2), 
                   @TXT);
    END;
GO

और फिर इसे इस तरह से उपयोग करें:

SELECT dbo.UNQUOTENAME (N'[FIELD]') NAME1, N'FIELD' NAME2;
GO

NAME1 | NAME2
:---- | :----
FIELD | FIELD

SELECT ID, OBJECT 
FROM   TEST 
WHERE OBJECT LIKE 'obj%';
GO

ID | OBJECT
-: | :-----
 2 | obj2  
 3 | obj3  

SELECT ID, dbo.UNQUOTENAME(OBJECT) 
FROM   TEST 
WHERE  dbo.UNQUOTENAME(OBJECT) LIKE 'obj%';
GO

ID | (No column name)
-: | :---------------
 1 | obj1
 2 | obj2
 3 | obj3
 4 | obj4  

लेकिन मेरा सवाल यह है:

  • क्या कोई छिपी हुई अंतर्निहित फ़ंक्शन है जो टी-एसक्यूएल का उपयोग करके कोष्ठक को हटाती है?

यहाँ dbfiddle

जवाबों:


12

क्या कोई छिपी हुई अंतर्निहित फ़ंक्शन है जो टी-एसक्यूएल का उपयोग करके कोष्ठक को हटाती है?

नहीं , टी-एसक्यूएल का उपयोग नहीं कर रहा है।

OBJECT_IDएक आंतरिक कार्य है। इसे सीधे SQL Server निष्पादन योग्य कोड में लागू किया जाता है, T-SQL में नहीं; और इसे किसी भी T-SQL को कॉल नहीं किया जाता है।

रनटाइम पर, ऑब्जेक्ट आईडी अभिव्यक्ति सेवा कॉलिंग के माध्यम से प्राप्त की जाती है sqlmin!I4ObjIdWstr

कार्यान्वयन तब संदर्भित स्ट्रिंग में किसी ऑब्जेक्ट की आईडी में प्रदान किए गए स्ट्रिंग पैरामीटर (ओं) को हल करने के लिए सभी आवश्यक चरणों से गुजरता है।

पहले चरणों में से एक के माध्यम से स्ट्रिंग में किसी भी सीमांकित पहचानकर्ताओं के साथ काम करना शामिल है sqlmin!CbParseQuotesW। एक संकीर्ण अर्थ में, वह कोड फ़ंक्शन है जिसका आप उल्लेख कर रहे हैं, लेकिन यह सीधे टी-एसक्यूएल से सुलभ नहीं है। इसमें निम्नलिखित कोड शामिल हैं:

cmp     r9d,22h
je      sqlmin!CbParseQuotesW+0x185
cmp     r9d,2Eh
je      sqlmin!CbParseQuotesW+0x139
cmp     r9d,5Bh
je      sqlmin!CbParseQuotesW+0xfe
cmp     r9d,5Dh
je      sqlmin!CbParseQuotesW+0xda

... जो पात्रों को संभालने के लिए परीक्षण हैं:

  • हेक्स 22 = डिक 34 "
  • हेक्स 2 ई = डेसीक 46 = .
  • हेक्स 5 बी = डीआईसी 91 = [
  • हेक्स 5 डी = 93 डी = ]

आईडी में मापदंडों को हल करने की बाकी प्रक्रिया में निम्नलिखित शामिल हैं:

  • एक स्वचालित रीड-ओनली लेनदेन शुरू करना
  • डेटाबेस आवश्यकताओं की जाँच करना
  • नाम पैरामीटर के लिए संभावित मैचों के माध्यम से परिवर्तन (सही टकराव का उपयोग करके)
    • प्रदत्त डेटाबेस नाम (या वर्तमान संदर्भ डेटाबेस) में
    • आपूर्ति किए गए स्कीमा नाम (या sys , या उपयोगकर्ता का डिफ़ॉल्ट स्कीमा आदि) में
  • आवश्यक मेटाडेटा ताले लेना
  • एक मैच के लिए मेटाडेटा कैश से परामर्श करना
  • यदि आवश्यक हो तो मेटाडेटा को कैश में लाना
  • अनुमतियों की जाँच (ऑब्जेक्ट आईडी तक पहुँचने के लिए)
  • पहली मिलान की गई वस्तु (यदि कोई हो) की आईडी लौटा देना

साइड नोट पर, प्रश्न में कोड:

IF OBJECT_ID('TEST') IS NOT NULL

... केवल तालिकाओं के लिए नहीं दिखता है। इसके लिए दूसरे फंक्शन पैरामीटर का उपयोग करना होगा। इसके अलावा, यह केवल TEST नाम की किसी स्कीमा-स्कॉप्ड ऑब्जेक्ट के लिए दिखता है - इसलिए BananaSchema.TEST नाम का एक दृश्य, उदाहरण के लिए मेल खाएगा। एक बेहतर अभिव्यक्ति होगी:

IF OBJECT_ID(N'dbo.TEST', N'U') IS NOT NULL

संबंधित प्रश्न और एक:


18

कभी-कभी हम अपने कुछ डेटाबेस में वस्तुओं के नाम संग्रहीत करते हैं

मुझे इस नाम को हमेशा कोष्ठक के साथ या बिना संगृहीत करने का ध्यान रखना चाहिए।

एक "ऑब्जेक्ट नाम" को तकनीकी रूप से एक पहचानकर्ता कहा जाता है । कुछ संदर्भों में एक पहचानकर्ता TSQL कोड [और] या "और" से घिरा हुआ दिखाई देगा। ये वर्ण पहचानकर्ता का हिस्सा नहीं हैं, और आपको उन्हें कभी भी संग्रहीत नहीं करना चाहिए।

इसके बजाय पहचानकर्ता को एक nvarchar (128) (या sysname) के रूप में संग्रहीत करें, और QUOTENAME फ़ंक्शन का उपयोग करके रनटाइम पर सीमांकक जोड़ें ।

QUOTENAME का उल्टा होता है PARSENAME , जो बहु-भाग नाम नेविगेट करने के लिए अतिरिक्त क्षमता है।

ध्यान दें कि QUOTENAME का एक वैकल्पिक दूसरा पैरामीटर है, और यदि आप उस पैरामीटर के लिए एक एकल उद्धरण वर्ण निर्दिष्ट करते हैं, तो QUOTENAME एक मान्य सीमांकित पहचानकर्ता अभिव्यक्ति नहीं बनाता है। यह एक varchar शाब्दिक अभिव्यक्ति का उत्सर्जन करता है।


7

SQL सर्वर में स्पष्ट रूप से कुछ आंतरिक होता है जो स्ट्रिप्स [square brackets](या अन्य पहचानकर्ता, जैसे "double quotes") होता है।

जब आप की तरह एक तालिका बनाने [dbo].[foo], आप ठीक है, केवल fooमें जमा हो जाता है sys.tablesऔर sys.objects, और कोई शिकायत है कि स्कीमा है [dbo](वर्ग कोष्ठक के साथ) नहीं मिला था।

लेकिन यह कोड के लिए होता है CREATE TABLE। वे इस्तेमाल कर रहे होंगे PARSENAME(), जैसा कि डेविड ने बताया। डिबगर को हुक करना निश्चित रूप से संकेत कर सकता है, लेकिन क्या इससे कोई फर्क पड़ता है?

आप कहीं और देख सकते हैं कि वे क्या कर रहे हैं, और sys.sp_renameवास्तव में उपज PARSENAME()का उपयोग किया जाता है:

select @UnqualOldName = parsename(@objname, 1),
        @QualName1 = parsename(@objname, 2),
        @QualName2 = parsename(@objname, 3),
        @QualName3 = parsename(@objname, 4)

लेकिन फिर, मुझे यकीन नहीं है कि मैं समझता हूं कि आप कभी-कभी केवल वर्ग कोष्ठक को क्यों हटाना चाहते हैं।

मेरे लिए, व्यक्तिगत रूप से, मेरे कोड का एक बड़ा प्रतिशत व्यापक दर्शकों के लिए लिखा गया है, जो उन वातावरण में कोड का उपयोग करेंगे, जहां मुझे कोई ज्ञान या नियंत्रण नहीं है कि वे असुरक्षित पहचानकर्ता का उपयोग कर रहे हैं या नहीं। इसलिए मेरे पास हमेशा है और हमेशा (और पसंद) कोड लिखेंगे जो QUOTENAME()स्क्रिप्ट उत्पन्न करने के लिए उपयोग करता है जिसमें किसी भी प्रकार का पहचानकर्ता शामिल होता है।

मेरे पास हर समय चौकोर कोष्ठक होंगे, उन्हें दूर ले जाने और एक बार काटे जाने की आवश्यकता होने पर।


2
@McNets - ऐसे मामलों की ऋणात्मक संख्या के लिए जहां यह उपयोगी हो सकता है जबकि मैं अन्य चीजों पर ध्यान केंद्रित करता हूं। आप आसानी से मौजूदा स्ट्रिंग फ़ंक्शंस का उपयोग करने के लिए अग्रणी और अनुगामी से अलग कर सकते हैं [और ]किसी भी के ]]साथ प्रतिस्थापित कर सकते हैं]
मार्टिन स्मिथ

-6

जब वर्ग कोष्ठक की आवश्यकता होती है - यह इसलिए है क्योंकि आपका पहचानकर्ता पहले से ही एक आरक्षित कीवर्ड है। मनमाने ढंग से उनका उपयोग करना न केवल आवश्यक है, बल्कि यह बहुत भ्रम पैदा करता है जैसा कि आप देख सकते हैं।

मेरी राय में, पहली जगह में आरक्षित पहचानकर्ताओं का उपयोग करने से बचने का सबसे अच्छा तरीका है।

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