मैं कुछ SQLite3 तालिकाओं का डेटा कैसे डंप करूं?


182

मैं डेटाबेस के कुछ SQLite3 तालिकाओं (सभी तालिकाओं) का डेटा, और केवल डेटा, स्कीमा नहीं, कैसे डंप करता हूं? डंप एसक्यूएल प्रारूप में होना चाहिए, क्योंकि इसे बाद में आसानी से डेटाबेस में फिर से दर्ज किया जाना चाहिए और कमांड लाइन से किया जाना चाहिए। कुछ इस तरह

sqlite3 db .dump

लेकिन स्कीमा डंप किए बिना और टेबल को डंप करने के लिए चयन करें।


किस प्रारूप में? कुछ भी विशेष रूप से, या आपके बस एक मानव पठनीय बैकअप की तलाश है? कृपया निर्दिष्ट करें।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

1
मैं SQL प्रारूप में डंप करना चाहता हूं, ताकि मैं इसे आसानी से पुनर्स्थापित कर सकूं। मैंने उस जानकारी को मुख्य प्रश्न में जोड़ दिया है।
प्यूपेनो

जवाबों:


214

आप यह नहीं कह रहे हैं कि आप डंप फ़ाइल के साथ क्या करना चाहते हैं।

मैं CSV फ़ाइल प्राप्त करने के लिए निम्नलिखित का उपयोग करूंगा, जिसे मैं लगभग हर चीज में आयात कर सकता हूं

.mode csv 
-- use '.separator SOME_STRING' for something other than a comma.
.headers on 
.out file.csv 
select * from MyTable;

यदि आप एक अलग SQLite डेटाबेस में फिर से लिखना चाहते हैं:

.mode insert <target_table_name>
.out file.sql 
select * from MyTable;

क्या SQL कथन का उपयोग करके प्रोग्रामेटिक रूप से ऐसा करने का कोई तरीका है? मैं देख सकता हूं कि इंटरप्रेटर का उपयोग करके इसे कैसे किया जा सकता है, लेकिन क्या होगा यदि मैं एक स्क्रिप्ट लिखना चाहता हूं?
कोलिफ़र

4
आप अपने बयानों को एक फ़ाइल में रख सकते हैं (जैसे sample.txt) और फिर इसका उपयोग करके आह्वान करें: sqlite3 db.sq3 <
sample.txt

" या .output और आउटपुट के बजाय .once कमांड का उपयोग करें। कंसोल पर वापस जाने से पहले सिंगल नेक्स्ट कमांड के लिए केवल रीडायरेक्ट किया जाएगा। किसी भी तर्क के साथ .output का उपयोग मानक आउटपुट पर फिर से लिखना शुरू करने के लिए नहीं करें। " SQLite डॉक्स
रफिन

156

आप .schema और .dump कमांड के अंतर को प्राप्त कर सकते हैं। उदाहरण के लिए grep के साथ:

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -vx -f schema.sql dump.sql > data.sql

data.sql फ़ाइल में स्कीमा के बिना केवल डेटा होगा, कुछ इस तरह से:

BEGIN TRANSACTION;
INSERT INTO "table1" VALUES ...;
...
INSERT INTO "table2" VALUES ...;
...
COMMIT;

मैं आशान्वित हूं कि इससे आपको सहायता मिलेगी।


5
@anurageldorado यह सादा sql है। बस चलाsqlite3 some.db < data.sql
जेलिफ़िश

कुछ रासन मेरे लिए काम नहीं करते। मुझे उपयोग की आवश्यकता है। sqlite3 storage/db/jobs.s3db .schema jobs > schema.sqlकाम नहीं, लेकिन echo '.schema' jobs | sqlite3 storage/db/jobs.s3db > schema.sqlठीक काम
abkrim

2
यह एक अच्छा समाधान की तरह लग रहा था, लेकिन मेरे मामले में ज्यादातर लाइनें वास्तव में grep द्वारा हटा दी जा रही हैं। .Schema कमांड प्रत्येक टेबल के स्कीमा को कई लाइनों पर उत्पन्न करता है, इसलिए इसमें केवल एक लाइन होती है );, और grep सभी लाइनों को हटा देता है जिसमें grep );का -xविकल्प जोड़कर इस समस्या को हल करता है।
सुंदर

38

सबसे अच्छा तरीका नहीं है, लेकिन पट्टे पर बाहरी उपकरणों की आवश्यकता नहीं है (grep को छोड़कर, जो मानक * वैसे भी * nix बक्से पर है)

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

लेकिन आपको प्रत्येक तालिका के लिए यह कमांड करने की आवश्यकता है, हालांकि आप इसके लिए देख रहे हैं।

ध्यान दें कि इसमें स्कीमा शामिल नहीं है।


1
मैंने इस्तेमाल कियाsqlite3 Database.s3db .dump
जादर डायस

3
अगर उन आवेषणों की मानों में नई रेखाएँ हैं, तो यह टूट जाएगा। बेहतर उपयोग grep -v '^CREATE'अन्य उत्तर में से एक में सुझाव के रूप में
dequis

1
grep -v '^CREATE;यदि CREATEस्टेटमेंट्स में लाइन ब्रेक है (जो वे कभी-कभी करते हैं) का उपयोग करके टूट जाएगा । सर्वश्रेष्ठ, IMO, स्वचालित रूप CREATEसे सभी स्टेटमेंट्स को स्ट्रिप करने के लिए नहीं है , बल्कि मैन्युअल रूप से उन्हें संपादित करता है। बस आपको जो भी टेक्स्ट एडिटर की आवश्यकता है, उसका उपयोग करें CREATEऔर उन स्टेटमेंट को मैन्युअल रूप से खोजें और निकालें। जब तक डेटाबेस विशाल नहीं है (और जब से आप साइक्लाइट का उपयोग कर रहे हैं, मुझे लगता है कि यह नोट है), तब तक यह बहुत आसान है।
डैन जोन्स

लेकिन बनाने के क्रेप विचारों से भी बना लेगा। मैं उसे कैसे निकाल सकता हूं?
सिल्वे 2611

35

आप .dump विशेष कमांड, जैसे एक या एक से अधिक टेबल तर्क निर्दिष्ट कर सकते हैं sqlite3 db ".dump 'table1' 'table2'"


4
जब मैं आपके बताए अनुसार कई तालिका नाम जोड़ता हूं, तो यह मुझे यह आउटपुट देता है: उपयोग: .dump? - संरक्षित-पंक्तिबद्ध? ? तरह-पैटर्न?
एमडब्ल्यू

1
@ mwm मैं उसी समस्या का अवलोकन कर रहा हूं sqlite3 3.31.1 (2020/01/27)बदलाव का है कि बारे में कुछ नहीं कहते हैं। (वैसे, --preserve-rowidsकाम करता है लेकिन बिलकुल भी प्रलेखित नहीं है।)
ynn

11

कोई भी उत्तर जो CREATEलाइनों को बाहर करने के लिए grep का उपयोग करने का सुझाव देता है या आउटपुट INSERTसे लाइनों को हड़पने के लिए sqlite3 $DB .dumpबुरी तरह से विफल हो जाएगा। CREATE TABLEआदेशों प्रति पंक्ति एक स्तंभ सूची (छोड़कर इसलिए CREATEइसके बारे में सब नहीं मिलेगा), और पर मूल्यों INSERTलाइनों एम्बेडेड नई पंक्तियां हो सकता है (ताकि आप सिर्फ आकर्षित नहीं कर सकते हैं INSERTलाइनों)।

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

Sqlite3 संस्करण 3.6.20 पर परीक्षण किया गया।

यदि आप कुछ तालिकाओं को बाहर करना चाहते हैं $(sqlite $DB .tables | grep -v -e one -e two -e three), तो आप उन्हें फ़िल्टर कर सकते हैं , या यदि आप एक विशिष्ट सबसेट प्राप्त करना चाहते हैं, तो उसके साथ प्रतिस्थापित करें one two three


9

पॉल एगन के जवाब में सुधार के रूप में, इसे निम्न प्रकार से पूरा किया जा सकता है:

sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'

--or--

sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'

निश्चित रूप से, चेतावनी यह है कि आपको grep स्थापित करना होगा।


1
मैं यह पसंद है। एक अतिरिक्त बोनस के रूप में, यह तब भी काम करता है जब आपके पास एक डंप की गई एसक्यूएल फाइल चारों ओर लटकी हो, बस cat database.sql | grep '^INSERT' > database_inserts.sql(स्कीमा के लिए एक ही हो, इसके साथ बदलेंgrep '^CREATE'
trisweb

2
@trisweb, निश्चित रूप से आपका मतलब है grep '^INSERT' < database.sql > database_inserts.sqlकि वह बहुत ही शानदार catहै
सेबस्टियन

1
इसके बारे में बहुत कुछ नहीं। catमूल रूप से निष्पादित करने के लिए कोई लागत नहीं आती है और उत्पादन के लिए इनपुट की श्रृंखला अधिक स्पष्ट करता है। बेशक, आप भी लिख सकते हैं < database.sql grep '^INSERT' ...लेकिन एक स्पष्ट पाइप को पढ़ना बहुत आसान है।
14:15

1
जब मैं आपके बताए अनुसार कई तालिका नाम जोड़ता हूं, तो यह मुझे यह आउटपुट देता है: उपयोग: .dump? - संरक्षित-पंक्तिबद्ध? ? तरह-पैटर्न?
एमडब्ल्यू

-1: क्री के साथ लाइनों के लिए खोज एक बेकार विचार है। लगभग हर दृश्य या ट्रिगर विशेष रूप से, यदि इसमें टिप्पणियां शामिल हैं, तो एक से अधिक लाइन की आवश्यकता होती है।
छत

6

पायथन या जावा या किसी भी उच्च स्तरीय भाषा में .dump काम नहीं करता है। हमें CSV में रूपांतरण को हाथ से कोड करने की आवश्यकता है। मैं एक पायथन उदाहरण देता हूं। अन्य, उदाहरण की सराहना की जाएगी:

from os import path   
import csv 

def convert_to_csv(directory, db_name):
    conn = sqlite3.connect(path.join(directory, db_name + '.db'))
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
    tables = cursor.fetchall()
    for table in tables:
        table = table[0]
        cursor.execute('SELECT * FROM ' + table)
        column_names = [column_name[0] for column_name in cursor.description]
        with open(path.join(directory, table + '.csv'), 'w') as csv_file:
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow(column_names)
            while True:
                try:
                    csv_writer.writerow(cursor.fetchone())
                except csv.Error:
                    break

यदि आपके पास 'पैनल डेटा' है, तो दूसरे शब्दों में आईडी के साथ कई व्यक्तिगत प्रविष्टियाँ इसे लुक के साथ जोड़ देती हैं और इससे सारांश आँकड़े भी आ जाते हैं:

        if 'id' in column_names:
            with open(path.join(directory, table + '_aggregate.csv'), 'w') as csv_file:
                csv_writer = csv.writer(csv_file)
                column_names.remove('id')
                column_names.remove('round')
                sum_string = ','.join('sum(%s)' % item for item in column_names)
                cursor.execute('SELECT round, ' + sum_string +' FROM ' + table + ' GROUP BY round;')
                csv_writer.writerow(['round'] + column_names)
                while True:
                    try:
                        csv_writer.writerow(cursor.fetchone())
                    except csv.Error:
                        break 

4

SQLite के लिए कमांड लाइन शेल के लिए SQLite प्रलेखन के अनुसार, आप CSV के रूप में एक SQLite टेबल (या एक टेबल का हिस्सा) निर्यात कर सकते हैं, बस "मोड" को "सीएसवी" सेट करके और फिर वांछित पंक्तियों को निकालने के लिए एक क्वेरी चलाएँ। टेबल:

sqlite> .header on
sqlite> .mode csv
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .exit

फिर एक SQLite तालिका में CSV (अल्पविराम से अलग किए गए मान) डेटा आयात करने के लिए ".import" कमांड का उपयोग करें:

sqlite> .mode csv
sqlite> .import C:/work/dataout.csv tab1
sqlite> .exit

कृपया विचार करने के लिए दो मामलों के बारे में आगे के दस्तावेज पढ़ें: (1) टेबल "टैब 1" पहले से मौजूद नहीं है और (2) टेबल "टैब 1" पहले से मौजूद है।


3

स्कीमा भागों को छोड़कर, sqlite3 db डंप कोड को लेने के लिए सबसे अच्छी विधि होगी।

उदाहरण छद्म कोड:

SELECT 'INSERT INTO ' || tableName || ' VALUES( ' || 
  {for each value} ' quote(' || value || ')'     (+ commas until final)
|| ')' FROM 'tableName' ORDER BY rowid DESC

देखें: src/shell.c:838 (वास्तविक कोड के लिए sqlite-3.5.9)

तुम भी बस उस खोल को ले सकते हैं और स्कीमा भागों को टिप्पणी कर सकते हैं और उसका उपयोग कर सकते हैं।


3

अन्य संभावित समाधानों की समीक्षा

केवल INSERTs शामिल करें

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

लागू करना आसान है लेकिन यह विफल हो जाएगा यदि आपके किसी भी कॉलम में नई लाइनें शामिल हैं

SQLite डालने मोड

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

यह एक अच्छा और अनुकूलन योग्य समाधान है, लेकिन यह काम नहीं करता है यदि आपके कॉलम में स्थानिक में 'ज्योमेट्री' टाइप जैसी वस्तुएं हैं

स्कीमा के साथ डंप मुश्किल

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -v -f schema.sql dump > data.sql

यकीन नहीं क्यों, लेकिन मेरे लिए काम नहीं कर रहा है

एक और (नया) संभव समाधान

संभवतः इस सवाल का कोई सबसे अच्छा जवाब नहीं है, लेकिन जो मेरे लिए काम कर रहा है, वह इस बात को ध्यान में रख रहा है कि इस तरह के एक्सप्रेशन के साथ कॉलम वैल्यू में नई लाइनें हो

grep -Pzo "(?s)^INSERT.*\);[ \t]*$"

तालिकाओं का चयन करने के लिए डंप किया जाना चाहिए .dumpतालिका नामों से मेल करने के लिए एक LIKE तर्क मानता है, लेकिन अगर यह पर्याप्त नहीं है तो एक सरल स्क्रिप्ट बेहतर विकल्प है

TABLES='table1 table2 table3'

echo '' > /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 database.db3 | grep -Pzo "(?s)^INSERT.*?\);$" >> /tmp/backup.sql
done

या, विदेशी चाबियों का सम्मान करने और केवल एक लेनदेन में सभी डंप को अलग करने के लिए कुछ और विस्तृत

TABLES='table1 table2 table3'

echo 'BEGIN TRANSACTION;' > /tmp/backup.sql
echo '' >> /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 $1 | grep -Pzo "(?s)^INSERT.*?\);$" | grep -v -e 'PRAGMA foreign_keys=OFF;' -e 'BEGIN TRANSACTION;' -e 'COMMIT;' >> /tmp/backup.sql
done

echo '' >> /tmp/backup.sql
echo 'COMMIT;' >> /tmp/backup.sql

इस बात का ध्यान रखें कि अगर );किसी भी कॉलम में कोई स्ट्रिंग मौजूद है तो grep एक्सप्रेशन फेल हो जाएगा

इसे पुनर्स्थापित करने के लिए (पहले से बनाई गई तालिकाओं वाले डेटाबेस में)

sqlite3 -bail database.db3 < /tmp/backup.sql

2

यह संस्करण आवेषण के अंदर नईलाइन्स के साथ अच्छी तरह से काम करता है:

sqlite3 database.sqlite3 .dump | grep -v '^CREATE'

अभ्यास में उन सभी लाइनों को शामिल नहीं किया गया है CREATEजिनके साथ नई लाइनें शामिल होने की संभावना कम है


0

मुंहतोड़ जवाब के साथ निकटतम होना चाहिए, फिर भी यह मेरे मामले के लिए काम नहीं करता है। एक सम्मिलित क्वेरी बीच में ही टूट गई और निर्यात रुक गया। निश्चित नहीं है कि इसका क्या कारण है। हालाँकि यह ठीक काम करता है .dump

अंत में मैंने एसक्यूएल से उत्पन्न विभाजन के लिए एक उपकरण लिखा .dump:

https://github.com/motherapp/sqlite_sql_parser/


-3

आप प्रत्येक फ़ील्ड के बाद csv डालने के लिए तालिकाओं पर एक चयन कर सकते हैं, या एक GUI उपकरण का उपयोग करके सभी डेटा को वापस कर सकते हैं और इसे एक csv पर सहेज सकते हैं।


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