यदि कॉलम मौजूद है और उसमें से चयन नहीं हुआ है, तो मैं यह देखने के लिए CASE कथन का उपयोग क्यों नहीं कर सकता / सकती?


17

ऐसा कुछ काम क्यों नहीं करता है?

SELECT
CASE 
WHEN NULLIF(COL_LENGTH('Customers', 'Somecol'), '') IS NULL THEN NULL
ELSE Somecol
END AS MyTest
FROM Customers;

मैं अभी जाँच कर रहा हूँ कि क्या स्तंभ मौजूद है, हालाँकि, SQL सर्वर शिकायत करता है कि Somecolवह मौजूद नहीं है। क्या एकल कथन में इसका कोई विकल्प है?


3
क्या आपके पास एक उदाहरण है कि आप ऐसा क्यों करना चाहते हैं? मैं समझ नहीं पा रहा हूं कि आप ऐसा क्‍वेरी क्‍यों लिखना चाहते हैं जो उस कॉलम से चयन करने का प्रयास करता है जो मौजूद नहीं हो सकता है।
मार्क सिंकिनसन

4
SQL सर्वर मूल्यांकन करता है कि आपके स्टेटमेंट सिंटैक्स सही है, इसे निष्पादित करने से पहले। इसलिए संदर्भित सभी कॉलम तालिकाओं में मौजूद होने चाहिए, भले ही वे एक CASEबयान के भीतर लिपटे हों ।
मार्क सिनकिंसन

@MarkSinkinson: नामों को सिंटैक्स के बाद चेक किया जाता है , लेकिन हाँ, SQL सर्वर वास्तव में बैच चलाने से पहले करता है।
एंड्री एम

1
से चयन करना INFORMATION_SCHEMAवर्कअराउंड के रूप में काम कर सकता है।
ब्रिलियन्ड

जवाबों:


43

निम्न क्वेरी में के रूप में एक ही विचार का उपयोग करता है इस अद्भुत जवाब द्वारा ypercube :

SELECT x.*
FROM (SELECT NULL AS SomeCol) AS dummy
CROSS APPLY
(
  SELECT
    ID,
    SomeCol AS MyTest
  FROM dbo.Customers
) AS x;

यह इस तरह काम करता है:

  • अगर dbo.Customersनाम का कॉलम है SomeCol, तो इस SomeColतरह SomeCol AS MyTestसे हल करेगा dbo.Customers.SomeCol;

  • यदि तालिका में ऐसा कोई कॉलम नहीं है, तो संदर्भ अभी भी मान्य होगा, क्योंकि अब इसे इस रूप में हल किया जाएगा dummy.SomeCol: dummyकॉलम को उस संदर्भ में संदर्भित किया जा सकता है।

आप इस तरह से कई "अतिरिक्त" कॉलम निर्दिष्ट कर सकते हैं। इस तरह के स्तंभों के लिए तालिका उपनाम का उपयोग करने के लिए चाल नहीं है (जो कि ज्यादातर स्थितियों में एक frowned पर अभ्यास है, लेकिन इस मामले में तालिका उपनाम को छोड़ना आपको समस्या को हल करने में मदद करता है)।

यदि तालिका में शामिल होने के लिए उपयोग किया जाता है और दूसरी तालिका का अपना है SomeCol, तो आपको ट्रिक को काम करने के लिए इसे जोड़ने में उपयोग करने से पहले उपरोक्त क्वेरी के रूप में उपरोक्त क्वेरी का उपयोग करना होगा।

SELECT ...
FROM
(
  SELECT x.*
  FROM (SELECT NULL AS SomeCol) AS dummy
  CROSS APPLY (
    SELECT
      ID,
      SomeCol AS MyTest
    FROM dbo.Customers
  ) AS x
) AS cust
INNER JOIN ...
;

1
मुझे आश्चर्य है कि अगर एसक्यूएल संकलक सिर्फ एक छोटा सा जटिल है। सुपर कूल आप क्या कर सकते हैं।
मैक्स वर्नोन

9

ऐसा करने का एक तरीका स्तंभों के अस्तित्व की जांच करना है, फिर उस स्तंभ मौजूद है या नहीं, इसके आधार पर डायनामिक एसक्यूएल का निर्माण करें।

डायनेमिक SQL के बिना, SQL सर्वर मूल्यांकन करने का प्रयास करेगा कि क्या कॉलम विद्यमान होने से पहले भी मौजूद है या नहीं, जिसके परिणामस्वरूप त्रुटि हुई है।

हालाँकि, इसका मतलब है कि आपके पास भविष्य में लिखने और संभावित रूप से बदलने के लिए 2 प्रश्न होंगे। लेकिन मेरा मानना ​​है कि आपको उन SELECTस्तंभों पर बयानों को लक्षित करना चाहिए जो मौजूद नहीं हो सकते हैं।

declare @SQL varchar(max)

If exists (select 1 from sys.columns where Name = N'NameOfColumn' and object_id=object_id(N'yourTableName'))
begin
set @SQL = 'select ID, NameOfColumn from yourTableName'
exec(@sql)
end
else
begin
Print 'Column does not exist'
end

हां, समझ में आता है, हालांकि, एक ही बयान में होना चाहिए। अंततः, मैं शायद कुछ मैजिक सिस्टम फ़ंक्शन की तलाश कर रहा हूं जो मौजूद नहीं है।
कार्सन रिंके

4

आप स्तंभ में हो सकने वाले स्तंभों को क्वेरी करने के लिए कुछ XML का उपयोग कर सकते हैं ।

एक क्रॉस आवेदन में प्रत्येक कॉलम से एक XML बनाएँ और values()फ़ंक्शन का उपयोग करके मान निकालें ।

इस क्वेरी में ID ज्ञात है इसलिए इसे सीधे टेबल से प्राप्त करें। Col1 और Col2 वहाँ हो सकता है या नहीं तो उन्हें XML का उपयोग कर प्राप्त करें।

select T.ID,
       TX.X.value('(Col1/text())[1]', 'int') as Col1,
       TX.X.value('(Col2/text())[1]', 'int') as Col2
from T
  cross apply (select T.* for xml path(''), type) as TX(X)

एसक्यूएल फिडल


-1

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

इसके लिए विशेष रूप से पूछने के साथ 'परेशानी' है - आप जिस परेशानी का सामना कर रहे हैं। सामान्य तौर पर, यदि कोई NULL मान आपको समस्याएँ देता है ... तो अस्तित्व को सत्यापित करने का दूसरा तरीका खोजें। यह सर्वर को परेशान करने के बिना करने का एक तरीका है।

SELECT COUNT(*) FROM sys.columns WHERE sys.columns.name = 'FarmID'

1
यह sysobjectsजाँचने के लिए कि आपकी तालिका में विशेष कॉलम में ऐसा कॉलम क्यों नहीं है?
ypercube y

हां ... मैंने उल्लेख किया है कि आप कर सकते हैं ... आप जिस विशेष तालिका के बारे में क्वेरी कर रहे हैं, उस पर भी आप ऐसा ही कर सकते हैं ... मैंने COUNT का उपयोग करने के लिए सामान्य प्रारूप दिखाया क्योंकि COUNT शून्य है और जब मुझे लगता है कि मुझे लगता है कि चाहिए उल्लेख है कि आप इसे एक चर में भी असाइन कर सकते हैं। (उदाहरण के लिए सेक्शन (*) myVarName… के रूप में चुनें)
जिंज़ई

1
मैं यह नहीं देख सकता कि यह मार्क की क्वेरी से बेहतर कैसे होगा। SELECT 1 ...कोई त्रुटि नहीं करता है।
ypercube y

मैंने यह नहीं कहा कि यह बेहतर था, लेकिन यह उसी परिणाम को प्राप्त करने के लिए बहुत सरल तरीका है। चयन 1 में त्रुटि नहीं हो सकती है, लेकिन यह COUNT जैसी ही बात नहीं है। सही रिटर्न का चयन करें ... भले ही यह पूर्ण हो। COUNT को केवल एक नंबर वापस करना है। यह तरीका और तेज़ होगा और मैंने उल्लेख किया कि बाद में गिनती का उपयोग किया जा सकता है।
जिनजई

अगर आपको गिनती ठीक है। लेकिन EXISTS (SELECT ...)आमतौर पर की तुलना में तेजी से है (SELECT COUNT(*) ...), अन्य तरीके से नहीं।
ypercube y

-3

अगर मैंने इसे सही ढंग से समझा ...

आप क्वेरी का उपयोग नीचे की तरह कुछ कर सकते हैं और गिनती के आधार पर कार्य कर सकते हैं ... यदि गिनती> 1 है, तो इसका मतलब है कि आपके पास उस तालिका में कॉल है, और गिनती = 0 है तो आपके पास उस कॉल में नहीं है तालिका

सेलेक्ट काउंट (*)
FROM INFORMATION_SCHEMA.COLUMNS में जहां COLUMN_NAME IN ('Id')
और TABLE_SCHEMA = 'dbo' और TABLE_NAME = 'UserBase';


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