सभी टेबल कमांड को ड्रॉप करें


86

SQLite में सभी तालिकाओं को छोड़ने की आज्ञा क्या है?

इसी तरह मैं सभी अनुक्रमों को छोड़ना चाहूंगा।

जवाबों:


86

मुझे नहीं लगता कि आप एक हिट में सभी तालिकाओं को गिरा सकते हैं, लेकिन आप कमांड प्राप्त करने के लिए निम्न कार्य कर सकते हैं:

select 'drop table ' || name || ';' from sqlite_master
    where type = 'table';

इसका आउटपुट एक स्क्रिप्ट है जो आपके लिए तालिकाओं को छोड़ देगा। अनुक्रमित के लिए, बस तालिका को सूचकांक के साथ बदलें।

आप whereअनुभाग में अन्य खंडों का उपयोग कर सकते हैं कि कौन सी टेबल या इंडेक्स चुने गए हैं (जैसे कि and name glob 'pax_*'"pax_" से शुरू होने वाले लोगों के लिए "")।

आप इस स्क्रिप्ट के निर्माण को साधारण bash (या cmd.exe) स्क्रिप्ट में चलाने के साथ जोड़ सकते हैं ताकि चलाने के लिए केवल एक ही आदेश हो।

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


धन्यवाद। बहुत ही अजीब बात है कि कोई सरल आदेश नहीं है, बल्कि इस हैक किए गए SQL क्वेरी है।
alamodey

7
खैर, एक खाली साइक्लाइट डेटाबेस प्राप्त करने का सबसे आसान तरीका केवल फ़ाइल को हटाना है, और फिर इसे कनेक्ट करना है ..
जॉन फूह

2
इसलिए मेरा अंतिम पैराग्राफ, @ जेएफ।
paxdiablo

एक तालिका से जुड़े ट्रिगर क्या होता है?
आरडीएस

@, जब आप कोई तालिका छोड़ते हैं, तो सभी ट्रिगर फ़ॉट हो जाते हैं और साथ ही हटा दिए जाते हैं। यह थोड़ा समझ में आता है जब वे संभवत: आग नहीं लगा सकते हैं (जैसा कि टेबल अब मौजूद नहीं है)।
paxdiablo

83

हालांकि यह सही है कि कोई DROP ALL TABLES कमांड नहीं है, आप निम्न सेट का उपयोग कर सकते हैं।

नोट: इन आदेशों में आपके डेटाबेस को भ्रष्ट करने की क्षमता है, इसलिए सुनिश्चित करें कि आपके पास एक बैकअप है

PRAGMA writable_schema = 1;
delete from sqlite_master where type in ('table', 'index', 'trigger');
PRAGMA writable_schema = 0;

आप तब के साथ हटाए गए स्थान को पुनर्प्राप्त करना चाहते हैं

VACUUM;

और यह सुनिश्चित करने के लिए एक अच्छा परीक्षण कि सब कुछ ठीक है

PRAGMA INTEGRITY_CHECK;

1
कैसे उन्हें onUpgrade () में निष्पादित करने के लिए ??
अज़ी_

केवल DDL निष्पादित करें, यह पर्याप्त है
नूह

किसी अन्य कारण से किसी अन्य व्यक्ति के पास यह सवाल है, तो उपरोक्त टाइटेनियम मोबाइल के डेटाबेस एपीआई में सभी तालिकाओं को छोड़ने का काम करता है।
रिले डेटन

2
अविश्वसनीय रूप से चतुर। हमारे घरेलू वृद्धिशील उन्नयन प्रणाली केवल संस्करणों की तुलना करने वाली लिपियों को निष्पादित कर सकती है, इस चाल को इसके लिए किसी भी सुधार की आवश्यकता नहीं है :)
इवान जी।

3
ध्यान दें: यह अजीब "डेटाबेस फ़ाइल विकृत है" मुद्दों को डेटाबेस को साफ करने के लिए एक दूसरे प्रयास पर दे सकता है (कम से कम नवीनतम साइक्लाइट के साथ), लेकिन लगता है कि यदि आप किसी चीज का उपयोग करते हैं तो यह त्रुटिपूर्ण रूप से काम करता है delete from sqlite_master where type in ('table', 'index', 'trigger')
mlvljr

36
rm db/development.sqlite3

हां, यह डेटाबेस को हटाता है, लेकिन टेबल के अलावा साइक्लाइट में कोई दूसरी चीज हो सकती है; विवरण के लिए मेरा पूरा उत्तर देखें
नोह

9
यदि डेटाबेस में कई कनेक्शन खुले हैं, तो यह काम नहीं करेगा। एक * निक्स पर जो सिर्फ नाम हटा देगा, और कनेक्शन अनाम डेटाबेस फ़ाइल के साथ काम करना जारी रखेगा जब तक कि वे अपने हैंडल को बंद नहीं करते हैं। यदि इरादे स्कीमा को फिर से लिखना है (सभी तालिकाओं को छोड़ दें, नई तालिकाएं बनाएं) तो आप मुश्किल में पड़ जाएंगे।
जर्बलो

3
यह स्वीकृत उत्तर नहीं होना चाहिए, क्योंकि इसने डेटाबेस को हटा दिया, जिसमें सभी संग्रहीत कार्यविधियाँ, ट्रिगर आदि शामिल हैं, न कि केवल टेबल।
शौक़ीन

2
मेरा मानना ​​है कि यह उत्तर उस प्रश्न का उत्तर देता है जिसका मतलब पोस्टर से पूछना है, जो है: "मैं आसानी से अपने एसक्यूएल डेटाबेस के साथ खरोंच से कैसे शुरू करूं?" किसी को संभवतः अधिक स्पष्ट होने के लिए प्रश्न को संपादित करना चाहिए ... यदि यह संभव है।
१०:१५ पर एरिकोस

22

मुझे SQLite और Android के साथ भी यही समस्या थी। यहाँ मेरा समाधान है:

List<String> tables = new ArrayList<String>();
Cursor cursor = db.rawQuery("SELECT * FROM sqlite_master WHERE type='table';", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    String tableName = cursor.getString(1);
    if (!tableName.equals("android_metadata") &&
            !tableName.equals("sqlite_sequence"))
        tables.add(tableName);
    cursor.moveToNext();
}
cursor.close();

for(String tableName:tables) {
    db.execSQL("DROP TABLE IF EXISTS " + tableName);
}

4

मैं अन्य उत्तरों को जोड़ना चाहूंगा जिसमें ड्रापिंग टेबल शामिल है और फाइल को डिलीट नहीं करना है, ताकि आप delete from sqlite_sequenceऑटो-इन्क्रीमेंट अनुक्रम को रीसेट करने के लिए भी निष्पादित कर सकें ।


4

Pysqlite का उपयोग करना:

tables = list(cur.execute("select name from sqlite_master where type is 'table'"))

cur.executescript(';'.join(["drop table if exists %s" %i for i in tables]))

3

एक बार जब आप सभी तालिकाओं को गिरा देते हैं (और जब तालिका जाती है तो अनुक्रमणिका गायब हो जाएगी) तब SQLite डेटाबेस में कुछ भी नहीं बचा है जहां तक ​​मुझे पता है, हालांकि फ़ाइल को हटना प्रतीत नहीं होता है (एक त्वरित परीक्षण से मैंने अभी किया था )।

तो फ़ाइल को हटाना सबसे तेज़ प्रतीत होगा - इसे तब ही पुनः बनाया जाना चाहिए जब आपका ऐप db फ़ाइल तक पहुँचने का प्रयास करे।


1
फ़ाइल सिकुड़ती नहीं है क्योंकि यह वैसा काम नहीं है जैसा कि sqlite काम करता है - यह केवल OS पर डिस्क स्थान लौटाएगा यदि आप फ़ाइल को वैक्यूम करते हैं (मूल रूप से इसे स्क्रैच से फिर से बनाएँ)। तब तक, फ़ाइल पुन: प्रयोज्य स्थान से भरी होती है।
paxdiablo

हाँ। इसलिए सभी तालिकाओं को छोड़ने और वैक्यूम करने से समझ में आएगा कि आपके पास फाइल डिलीट / विशेषाधिकार बनाने की सुविधा नहीं थी, या कुछ अजीब बहु-उपयोगकर्ता स्थिति थी। नहीं तो बस बात को हटा दें?
माइक वुडहाउस

2

एंड्रॉइड में मेरे पास यह मुद्दा था और मैंने इसे पश्चिम के समान एक विधि लिखा था।

क्योंकि मैंने AUTOINCREMENTअपनी मेजों में प्राथमिक कुंजियों का उपयोग किया था, इसलिए एक तालिका थी sqlite_sequence। जब रुटीन उस टेबल को गिराने की कोशिश करता तो SQLite क्रैश हो जाता। मैं अपवाद भी नहीं पकड़ सका। Https://www.sqlite.org/fileformat.html#internal_schema_objects को देखते हुए , मैंने जाना कि इन आंतरिक स्कीमा तालिकाओं में से कई ऐसे हो सकते हैं जिन्हें मैं छोड़ना नहीं चाहता था। दस्तावेज में कहा गया है कि इन तालिकाओं में से किसी का भी नाम sqlite_ से शुरू हुआ है इसलिए मैंने यह तरीका लिखा है

private void dropAllUserTables(SQLiteDatabase db) {
    Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
    //noinspection TryFinallyCanBeTryWithResources not available with API < 19
    try {
        List<String> tables = new ArrayList<>(cursor.getCount());

        while (cursor.moveToNext()) {
            tables.add(cursor.getString(0));
        }

        for (String table : tables) {
            if (table.startsWith("sqlite_")) {
                continue;
            }
            db.execSQL("DROP TABLE IF EXISTS " + table);
            Log.v(LOG_TAG, "Dropped table " + table);
        }
    } finally {
        cursor.close();
    }
}

1

मैं यह नहीं कह सकता कि यह सबसे अधिक बुलेटप्रूफ या पोर्टेबल समाधान है, लेकिन यह मेरी परीक्षण लिपियों के लिए काम करता है:

.output /tmp/temp_drop_tables.sql
select 'drop table ' || name || ';' from sqlite_master where type = 'table';
.output stdout
.read /tmp/temp_drop_tables.sql
.system rm /tmp/temp_drop_tables.sql

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


0

या शेल प्रॉम्प्ट पर, केवल दो लाइनों में, बिना नाम वाली अस्थायी फ़ाइल के बिना, $ db को SQLite डेटाबेस नाम मानना:

echo "SELECT 'DROP TABLE ' || name ||';' FROM sqlite_master WHERE type = 'table';" |
    sqlite3 -readonly "$db" | sqlite3 "$db"

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