सवाल जांचें कि कोई SQL तालिका मौजूद है या नहीं


यह जांचने का सबसे अच्छा तरीका क्या है कि किसी डेटाबेस में एसक्यूएल डेटाबेस में एक तालिका स्वतंत्र रूप से मौजूद है या नहीं?

मेरे द्वारा लाया गया:

   bool exists;
   const string sqlStatement = @"SELECT COUNT(*) FROM my_table";

   try
    {
       using (OdbcCommand cmd = new OdbcCommand(sqlStatement, myOdbcConnection))
       {
            cmd.ExecuteScalar();
            exists = true;
       }
    }
    catch
    {
        exists = false;
    }

क्या ऐसा करने के लिए इससे अच्छा तरीका है? डेटाबेस से कनेक्शन विफल होने पर यह विधि काम नहीं करेगी। मुझे Sybase, SQL सर्वर, ओरेकल के लिए तरीके मिल गए हैं लेकिन कुछ भी नहीं जो सभी डेटाबेस के लिए काम करता है।


38
2018-01-21 08:48


मूल


"चयन 1 से" का उपयोग करने का एक बेहतर तरीका होगा tbl जहां 1 = 0 "इस तरह यह संसाधन उपभोग के रूप में नहीं होगा। - Alex Shnayder


जवाब:


bool exists;

try
{
    // ANSI SQL way.  Works in PostgreSQL, MSSQL, MySQL.  
    var cmd = new OdbcCommand(
      "select case when exists((select * from information_schema.tables where table_name = '" + tableName + "')) then 1 else 0 end");

    exists = (int)cmd.ExecuteScalar() == 1;
}
catch
{
    try
    {
        // Other RDBMS.  Graceful degradation
        exists = true;
        var cmdOthers = new OdbcCommand("select 1 from " + tableName + " where 1 = 0");
        cmdOthers.ExecuteNonQuery();
    }
    catch
    {
        exists = false;
    }
}

59
2018-01-21 09:03



यह लिंक देखें msdn.microsoft.com/en-us/library/ms186778.aspx एसक्यूएल-सर्वर में info_schema पर अधिक जानकारी के लिए। - GvS
-1 मुझसे यह MySQL में काम नहीं करता है। Coz, यह किसी भी डेटाबेस में 'tableName' नाम की एक तालिका है, तो यह सच हो जाता है। मैंने इसका परीक्षण MySQL 5.1 + Navicat8 के साथ किया है। - anonymous
@ जेएमएसए: क्षमा करें, मैं schema_name (डेटाबेस नाम फ़ील्ड) शामिल करना भूल गया। select * from information_schema.tables where schema_name = 'yourDatabaseNameHere' and table_name = 'yourTableNameHere। कृपया डाउनवोट पूर्ववत करें - Michael Buen
यह या तो काम नहीं करेगा। Coz, Navicat दिखा रहा है कि, 'info_schema.tables'-table में 'schema_name' नाम का कोई फ़ील्ड नहीं है। 'Table_schema' नामक एक फ़ील्ड है और उस क्षेत्र में प्रत्येक पंक्ति में शून्य डाली गई है। - anonymous
@ जेएमएसए: क्या यह मेरी गलती होगी यदि कोई निश्चित डेटाबेस एएनएसआई एसक्यूएल-अनुरूप नहीं है? शायद आपको समाधान का योगदान करना चाहिए, और अचानक अचानक डाउनवॉटिंग नहीं करना चाहिए क्योंकि मेरा जवाब सभी डेटाबेस को कवर नहीं करता है - Michael Buen


मुझे नहीं लगता कि एक सामान्य तरीका मौजूद है जो सभी डेटाबेस के लिए काम करता है, क्योंकि यह कुछ विशिष्ट है जो कि डीबी कैसे बनाया गया है इस पर निर्भर करता है।

लेकिन, आप एक विशिष्ट क्वेरी का उपयोग करके ऐसा क्यों करना चाहते हैं? क्या आप कार्यान्वयन को उस चीज़ से दूर नहीं कर सकते जो आप करना चाहते हैं? मेरा मतलब है: क्यों एक सामान्य इंटरफेस नहीं बनाते, जो कि दूसरों के बीच है, उदाहरण के लिए 'टेबलएक्सिस्ट्स (स्ट्रिंग टैबब्लैम)' नामक एक विधि। फिर, प्रत्येक डीबीएमएस के लिए जिसे आप समर्थन देना चाहते हैं, आप एक वर्ग बनाते हैं जो इस इंटरफ़ेस को लागू करता है, और TableExists विधि में, आप इस डीबीएमएस के लिए विशिष्ट तर्क लिखते हैं।
SQLServer कार्यान्वयन में तब एक क्वेरी होगी जो sysobjects से पूछताछ करेगी।

आपके आवेदन में, आपके पास एक फैक्ट्री क्लास हो सकती है जो किसी दिए गए संदर्भ के लिए सही कार्यान्वयन बनाती है, और फिर आप टेबलएक्सिस्ट्स विधि को कॉल करते हैं।

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

IMyInterface foo = MyFactory.CreateMyInterface (SupportedDbms.SqlServer);

if( foo.TableExists ("mytable") )
...

मुझे लगता है कि मुझे यह करना चाहिए।


10
2018-01-21 08:57



इस तरह हम अपने मुख्य आवेदन में ऐसा करते हैं। हालांकि, क्या होगा यदि आपके पास अभी एक ओडीबीसी कनेक्शन है और यह नहीं पता कि इसके पीछे डेटाबेस क्या है? - Carra
मेरा अनुभव बताता है कि यह एक गलत तरीका है! दुर्भाग्यवश, आपको संभवतः शून्य प्रदर्शन मिलेगा - abatishchev
@abtischev - क्या आप अधिक विस्तार से जा सकते हैं? - MPritchard


यदि आप डेटाबेस स्वतंत्रता की कोशिश कर रहे हैं तो आपको न्यूनतम मानक मानना ​​होगा। आईआईआरसी एएनएसआई INFORMATION_SCHEMA ओडीबीसी अनुरूपता के लिए विचारों की आवश्यकता है, ताकि आप उनके खिलाफ पूछ सकें:

select count (*) 
  from information_schema.tables 
 where table_name = 'foobar'

यह देखते हुए कि आप ओडीबीसी का उपयोग कर रहे हैं, आप विभिन्न का भी उपयोग कर सकते हैं ओडीबीसी एपीआई कॉल इस मेटाडेटा को पुनः प्राप्त करने के लिए भी।

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

उपरोक्त यह है कि आपको अपने एप्लिकेशन के लिए सबसे कम आम denominator खोजने की आवश्यकता है (जो एसक्यूएल की तुलना में काफी कठिन है) या एक मंच-निर्भर अनुभाग का निर्माण करें जहां गैर-पोर्टेबल कार्यों को प्रति-प्लेटफ़ॉर्म पर प्लग किया जा सके आधार।


9
2018-01-21 10:25



फिर, यदि मैं आपकी पोस्ट को सही ढंग से समझता हूं, तो कुछ मानक के अनुसार प्रत्येक डीबीएमएस में INFORMATION_SCHEMA दृश्य होना चाहिए? - Frederik Gheysels
मेरा मानना ​​है कि ANFORMATION_SCHEMA विचारों को एएनएसआई एसक्यूएल-9 2 मानक के अनुपालन के लिए आवश्यक है। हालांकि, डीबीएमएस विक्रेता अनुपालन के अपने दावों में एएनएसआई एसक्यूएल मानकों के साथ थोड़ा तेज़ और ढीला खेलते हैं। - ConcernedOfTunbridgeWells


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

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

SELECT 1 FROM my_table WHERE 1=2

4
2018-01-21 09:05





मैं निष्पादित करने से बचूंगा select count(x) from xxxxxx क्योंकि डीबीएमएस वास्तव में आगे बढ़ेगा और ऐसा करेगा जो बड़ी तालिका के लिए कुछ समय ले सकता है।

इसके बजाए बस तैयार करना ए select * from mysterytableक्वेरी। अगर रहस्यमय अस्तित्व में नहीं है तो तैयार विफल हो जाएगा। वास्तव में तैयार कथन निष्पादित करने की कोई आवश्यकता नहीं है।


4
2018-01-21 10:04



मुझे ओडीबीसी के बारे में पता नहीं है, लेकिन ओडीकल पर जेडीबीसी का उपयोग करके आप एक बयान तैयार कर सकते हैं जो इसे चलाने पर पूरी तरह विफल हो जाएगा। - Mr. Shiny and New 安宇
हां - लेकिन वह केवल तभी दिखाना चाहता है जब तालिका मौजूद है जो तैयार करेगी। विशेष रूप से यदि यह आसान है "????? से चुनें * जो केवल तभी विफल हो सकता है ??? अस्तित्व में नहीं है। - James Anderson
मुझे सच में संदेह है कि "गिनती का चयन करें (*)" (जहां कोई खंड नहीं है) एक बड़ी मेज के लिए लंबा समय लगेगा - मुझे लगता है कि सभी डेटाबेस आंतरिक डेटाबेस / इंडेक्स / कैश में पंक्ति गणना स्टोर करते हैं, इसलिए यह केवल एक ही होगा देखो। इसलिए तालिका के आकार की क्वेरी के समय तक कोई प्रासंगिकता नहीं होगी। - David_001
@ डेविड - डीबीएमएस पर निर्भर करता है लेकिन अधिकांश सटीक पंक्ति गणना नहीं रखते हैं और वास्तव में पंक्तियों (या कम से कम पीके इंडेक्स में प्रविष्टियों) की गणना करेंगे। यदि आप इसके बारे में सोचते हैं कि "गिनती" को बनाए रखने के बीच ट्रेडऑफ जो प्रत्येक सम्मिलन या हटाए गए बनाम विवाद के लिए विवाद का एक बिंदु होगा, तो कॉम्पैप्रिटिवली दुर्लभ चयन कथन को अनुकूलित करना एक अच्छा है। - James Anderson
हाँ, आप सही हैं, मेरी टिप्पणी को अनदेखा करें ... - David_001


मेरे काम पर वर्तमान परियोजना में मुझे 'डेटा एजेंट' लिखना होगा जो कई डेटाबेस प्रकारों का समर्थन करेगा।

इसलिए मैंने आगे करने का फैसला किया: वर्चुअल विधियों का उपयोग करके आधार (डेटाबेस स्वतंत्र) कार्यक्षमता के साथ एक बेस क्लास लिखें और उप-वर्गों में सभी डेटाबेस-विशिष्ट क्षणों को ओवरराइड करें


2
2018-01-21 09:27



निश्चित रूप से ऐसा करने का तरीका, हां। - Nyerguds


निम्नलिखित मेरे लिए अच्छा काम करता है ...

private bool TableExists(SqlConnection conn, string database, string name)
{
    string strCmd = null;
    SqlCommand sqlCmd = null;

    try
    {
        strCmd = "select case when exists((select '['+SCHEMA_NAME(schema_id)+'].['+name+']' As name FROM [" + database + "].sys.tables WHERE name = '" + name + "')) then 1 else 0 end";
        sqlCmd = new SqlCommand(strCmd, conn);

        return (int)sqlCmd.ExecuteScalar() == 1;
    }
    catch { return false; }
}

1
2017-12-14 18:40





यदि आप कोशिश-पकड़ समाधान से बचना चाहते हैं, तो मैं sys.tables का उपयोग करके इस विधि का सुझाव दे रहा हूं

private bool IsTableExisting(string table)
    {
        string command = $"select * from sys.tables";
        using (SqlConnection con = new SqlConnection(Constr))
        using (SqlCommand com = new SqlCommand(command, con))
        {
            SqlDataReader reader = com.ExecuteReader();
            while (reader.Read())
            {
                if (reader.GetString(0).ToLower() == table.ToLower())
                    return true;
            }
            reader.Close();
        }
        return false;
    }

1
2017-09-11 08:54





बहुत आसान

use YOUR_DATABASE --OPTIONAL
SELECT count(*) as Exist from INFORMATION_SCHEMA.TABLES where table_name = 'YOUR_TABLE_NAME'

अगर जवाब 1 है, तो एक टेबल है। अगर उत्तर 0 है, तो कोई टेबल नहीं है।


0
2017-12-29 19:54