2009-06-03 23 views
86

मैंने SELECT कथन के आधार पर तालिका बनाने के लिए CREATE TABLE AS वाक्यविन्यास का उपयोग कर स्क्लाइट में एक तालिका बनाई है। अब इस तालिका में कोई प्राथमिक कुंजी नहीं है लेकिन मैं एक जोड़ना चाहता हूं।SQLite प्राथमिक कुंजी जोड़ें

निष्पादित ALTER TABLE table_name ADD PRIMARY KEY(col1, col2,...) में सिंटेक्स त्रुटि देता है "के पास प्राथमिक"

वहाँ एक प्राथमिक कुंजी या तो तालिका निर्माण के दौरान या बाद में SQLite में जोड़ने के लिए एक तरीका है?

संपादित करें: "सृजन के दौरान" मेरा मतलब CREATE TABLE AS के साथ सृजन के दौरान है।

+0

आप डेटाबेस संपादित करने के लिए किसी भी डीबी ब्राउज़र का उपयोग कर सकते हैं। वे टेबल को हटा रहे हैं और बना रहे हैं। लेकिन हम इसके बारे में परेशान नहीं करना चाहते हैं। आप यहां से किसी भी ओएस के लिए डीबी ब्राउज़र डाउनलोड कर सकते हैं http://sqlitebrowser.org/ – vichu

उत्तर

110

आप किसी भी महत्वपूर्ण रास्ते में SQLite टेबल संशोधित नहीं कर सकते बाद वे बनाए गए हैं। स्वीकृत सुझाया गया समाधान सही आवश्यकताओं के साथ एक नई तालिका बनाना है और इसमें अपना डेटा कॉपी करना है, फिर पुरानी तालिका छोड़ दें।

यहां इस बारे में आधिकारिक दस्तावेज है: के रूप में आप, CREATE TABLE उपयोग कर रहे हैं यदि आप एक एकल क्षेत्र पर प्राथमिक कुंजी बना रहे हैं तो जब तक http://sqlite.org/faq.html#q11

+5

यह लिंक (http://www.sqlite.org/omitted.html) बताता है कि अधिक विस्तार से क्या छोड़ा गया था। –

+1

लेकिन हम नए कॉलम – umesh

+0

@umesh http://stackoverflow.com/questions/4253804/insert-new-column-into-table-in-sqlite –

5

आप इस तरह यह कर सकते हैं:

CREATE TABLE mytable (
field1 text, 
field2 text, 
field3 integer, 
PRIMARY KEY (field1, field2) 
); 
29

, तो आप उपयोग कर सकते हैं:

CREATE TABLE mytable (
field1 TEXT, 
field2 INTEGER PRIMARY KEY, 
field3 BLOB, 
); 

CREATE TABLE के साथ, आप हमेशा एक या एकाधिक फ़ील्ड:

पर प्राथमिक कुंजी बनाने के लिए निम्न दृष्टिकोण का भी उपयोग कर सकते हैं
CREATE TABLE mytable (
field1 TEXT, 
field2 INTEGER, 
field3 BLOB, 
PRIMARY KEY (field2, field1) 
); 

संदर्भ: http://www.sqlite.org/lang_createtable.html

इस उत्तर तालिका परिवर्तन को संबोधित नहीं करता।

0

मैंने कई स्तंभों को मर्ज करने के लिए CREATE तालिका को वाक्यविन्यास के रूप में उपयोग किया और एक ही समस्या का सामना किया। यहां एक ऐप्पलस्क्रिप्ट है जिसे मैंने प्रक्रिया को गति देने के लिए लिखा था।

set databasePath to "~/Documents/Databases/example.db" 
set tableOne to "separate" -- Table from which you are pulling data 
set tableTwo to "merged" -- Table you are creating 
set {tempCol, tempColEntry, permColEntry} to {{}, {}, {}} 
set permCol to {"id integer primary key"} 

-- Columns are created from single items AND from the last item of a list 
-- {{"a", "b", "c"}, "d", "e"} Columns "a" and "b" will be merged into a new column "c". tableTwo will have columns "c", "d", "e" 

set nonCoal to {"City", "Contact", "Names", {"Address 1", "Address", "address one", "Address1", "Text4", "Address 1"}, {"E-Mail", "E-Mail Address", "Email", "Email Address", "EmailAddress", "Email"}, {"Zip", "Zip Code", "ZipCode", "Zip"}, {"Telephone", "BusinessPhone", "Phone", "Work Phone", "Telephone"}, {"St", "State", "State"}, {"Salutation", "Mr/Ms", "Mr/s", "Salutations", "Sautation", "Salutation"}} 

-- Build the COALESCE statements 
repeat with h from 1 to count of nonCoal 
set aColumn to item h of nonCoal 
if class of aColumn is not list then 
    if (count of words of aColumn) > 1 then set aColumn to quote & aColumn & quote 
    set end of tempCol to aColumn 
    set end of permCol to aColumn 
else 
    set coalEntry to {} 
    repeat with i from 1 to count of aColumn 
     set coalCol to item i of aColumn as string 
     if (count of words of coalCol) > 1 then set coalCol to quote & coalCol & quote 
     if i = 1 then 
      set end of coalEntry to "TRIM(COALESCE(" & coalCol & ", '') || \" \" || " 
     else if i < ((count of aColumn) - 1) then 
      set end of coalEntry to "COALESCE(" & coalCol & ", '') || \" \" || " 
     else if i = ((count of aColumn) - 1) then 
      set as_Col to item (i + 1) of aColumn as string 
      if (count of words of as_Col) > 1 then set as_Col to quote & as_Col & quote 
      set end of coalEntry to ("COALESCE(" & coalCol & ", '')) AS " & as_Col) & "" 
      set end of permCol to as_Col 
     end if 
    end repeat 
    set end of tempCol to (coalEntry as string) 
end if 
end repeat 

-- Since there are ", '' within the COALESCE statement, you can't use "TID" and "as string" to convert tempCol and permCol for entry into sqlite3. I rebuild the lists in the next block. 
repeat with j from 1 to count of tempCol 
if j < (count of tempCol) then 
    set end of tempColEntry to item j of tempCol & ", " 
    set end of permColEntry to item j of permCol & ", " 
else 
    set end of tempColEntry to item j of tempCol 
    set end of permColEntry to item j of permCol 
end if 
end repeat 
set end of permColEntry to ", " & item (j + 1) of permCol 
set permColEntry to (permColEntry as string) 
set tempColEntry to (tempColEntry as string) 

-- Create the new table with an "id integer primary key" column 
set createTable to "create table " & tableTwo & " (" & permColEntry & "); " 
do shell script "sqlite3 " & databasePath & space & quoted form of createTable 

-- Create a temporary table and then populate the permanent table 
set createTemp to "create temp table placeholder as select " & tempColEntry & " from " & tableOne & "; " & "insert into " & tableTwo & " select Null, * from placeholder;" 
do shell script "sqlite3 " & databasePath & space & quoted form of createTemp 

--export the new table as a .csv file 
do shell script "sqlite3 -header -column -csv " & databasePath & " \"select * from " & tableTwo & " ; \"> ~/" & tableTwo & ".csv" 
9

मैंने बाद में sqlite_master तालिका को बदलकर प्राथमिक कुंजी जोड़ने की कोशिश की। यह चाल काम करने लगती है। यह पाठ्यक्रम का एक हैक समाधान है।

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

मान लीजिए तालिका लगता है:

BEGIN; 
CREATE INDEX pk_tab1 ON tab1(i,j); 
pragma writable_schema=1; 
UPDATE sqlite_master SET name='sqlite_autoindex_tab1_1',sql=null WHERE name='pk_tab1'; 
UPDATE sqlite_master SET sql='CREATE TABLE tab1(i integer,j integer,t text,primary key(i,j))' WHERE name='tab1'; 
COMMIT; 

कुछ परीक्षण (SQLite खोल में):

sqlite> explain query plan select * from tab1 order by i,j; 
0|0|0|SCAN TABLE tab1 USING INDEX sqlite_autoindex_tab1_1 
sqlite> drop index sqlite_autoindex_tab1_1; 
Error: index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped  
+1

+1 हैक लेकिन काम करता है! –

+1

यदि आप यह गलत करते हैं तो बस एक चेतावनी जो आप कर सकते हैं (जहां तक ​​मैं कह सकता हूं) अपना संपूर्ण डेटाबेस पहुंच योग्य नहीं बना सकता है। मैं चारों ओर खेल रहा था और मैंने दूसरी अद्यतन क्वेरी में WHERE क्लॉज को गलती से याद किया। SQLite को यह पसंद नहीं आया: पी –

2

परिचय

CREATE TABLE tab1(i INTEGER, j INTEGER, t TEXT); 

तो मैं निम्नलिखित किया

यह एंड्रॉइड के जावा पर आधारित है और यह आपके एप्लिकेशन प्रशंसकों/ग्राहकों को परेशान किए बिना डेटाबेस को बदलने पर एक अच्छा उदाहरण है। यह SQLite FAQ पृष्ठ के विचार पर आधारित है http://sqlite.org/faq.html#q11

समस्या

मैं नोटिस नहीं था कि मैं एक रसीद में एक भी खरीदे गए आइटम को हटाने के लिए एक ROW_NUMBER या record_id निर्धारित करने की आवश्यकता है कि, और कम से उसी समय आइटम बारकोड नंबर ने मुझे उस आइटम को हटाने की कुंजी के रूप में बनाने की सोच में बेवकूफ़ बना दिया। मैं तालिका रसीद_बारकोड में रसीद विवरण सहेज रहा हूं। रिकॉर्ड_आईड के बिना इसे छोड़कर मतलब एक ही आइटम के सभी रिकॉर्ड्स को रसीद में हटाया जा सकता है अगर मैंने आइटम बारकोड को कुंजी के रूप में इस्तेमाल किया।

सूचना

कृपया समझते हैं कि यह मेरा कोड की एक कॉपी-पेस्ट मैं इस लेखन के समय पर काम कर रहा हूँ है। इसे केवल एक उदाहरण के रूप में उपयोग करें, कॉपी-पेस्टिंग यादृच्छिक रूप से आपकी सहायता नहीं करेगा। इसे अपनी आवश्यकताओं के अनुसार पहले संशोधित करें

भी कोड में टिप्पणियां पढ़ने के लिए मत भूलना।

कोड

अपनी कक्षा में एक विधि के रूप में इस का प्रयोग करें 1 स्तंभ आप जोड़ना चाहते हैं याद आ रही है कि क्या जांच करने के लिए। हम टेबल रसीद_बारकोड को बदलने की प्रक्रिया को दोहराने के लिए ऐसा नहीं करते हैं। बस अपनी कक्षा के हिस्से के रूप में इसका जिक्र करें। अगले चरण में आप देखेंगे कि हम इसका उपयोग कैसे करेंगे।

public boolean is_column_exists(SQLiteDatabase mDatabase , String table_name, 
String  column_name) { 
    //checks if table_name has column_name 
    Cursor cursor = mDatabase.rawQuery("pragma table_info("+table_name+")",null); 
    while (cursor.moveToNext()){ 
    if (cursor.getString(cursor.getColumnIndex("name")).equalsIgnoreCase(column_name)) return true; 
    } 
    return false; 
} 

फिर, निम्नलिखित कोड तालिका receipt_barcode बनाने के लिए अगर यह पहले से आपका ऐप्लिकेशन के 1 समय उपयोगकर्ताओं के लिए नहीं बाहर निकलें करता है प्रयोग किया जाता है। और कृपया कोड में "अगर नहीं है" नोटिस करें। यह महत्व है।

//mDatabase should be defined as a Class member (global variable) 
//for ease of access : 
//SQLiteDatabse mDatabase=SQLiteDatabase.openOrCreateDatabase(dbfile_path, null); 
creation_query = " CREATE TABLE if not exists receipt_barcode ("; 
creation_query += "\n record_id  INTEGER PRIMARY KEY AUTOINCREMENT,"; 
creation_query += "\n rcpt_id INT(11)  NOT NULL,"; 
creation_query += "\n barcode VARCHAR(255) NOT NULL ,"; 
creation_query += "\n barcode_price VARCHAR(255) DEFAULT (0),"; 
creation_query += "\n PRIMARY KEY (record_id));"; 
mDatabase.execSQL(creation_query); 

//This is where the important part comes in regarding the question in this page: 

//adding the missing primary key record_id in table receipt_barcode for older versions 
     if (!is_column_exists(mDatabase, "receipt_barcode","record_id")){ 
      mDatabase.beginTransaction(); 
      try{ 
       Log.e("record_id", "creating"); 


       creation_query="CREATE TEMPORARY TABLE t1_backup("; 
       creation_query+="record_id INTEGER  PRIMARY KEY AUTOINCREMENT,"; 
       creation_query+="rcpt_id INT(11)  NOT NULL,"; 
       creation_query+="barcode VARCHAR(255) NOT NULL ,"; 
       creation_query+="barcode_price VARCHAR(255) NOT NULL DEFAULT (0));"; 
       mDatabase.execSQL(creation_query); 

       creation_query="INSERT INTO t1_backup(rcpt_id,barcode,barcode_price) SELECT rcpt_id,barcode,barcode_price FROM receipt_barcode;"; 
       mDatabase.execSQL(creation_query); 

       creation_query="DROP TABLE receipt_barcode;"; 
       mDatabase.execSQL(creation_query); 

       creation_query="CREATE TABLE receipt_barcode ("; 
       creation_query+="record_id INTEGER  PRIMARY KEY AUTOINCREMENT,"; 
       creation_query+="rcpt_id INT(11)  NOT NULL,"; 
       creation_query+="barcode VARCHAR(255) NOT NULL ,"; 
       creation_query+="barcode_price VARCHAR(255) NOT NULL DEFAULT (0));"; 
       mDatabase.execSQL(creation_query); 

       creation_query="INSERT INTO receipt_barcode(record_id,rcpt_id,barcode,barcode_price) SELECT record_id,rcpt_id,barcode,barcode_price FROM t1_backup;"; 
       mDatabase.execSQL(creation_query); 

       creation_query="DROP TABLE t1_backup;"; 
       mDatabase.execSQL(creation_query); 


       mdb.setTransactionSuccessful(); 
      } catch (Exception exception){ 
       Log.e("table receipt_bracode", "Table receipt_barcode did not get a primary key (record_id"); 
       exception.printStackTrace(); 
      } finally { 
       mDatabase.endTransaction(); 
      } 
-1

मुझे लगता है कि उस कॉलम पर एक इंडेक्स जोड़ने से काफी प्रभाव हो सकता है।

0

मुझे एक ही समस्या थी और मुझे मिला सबसे अच्छा समाधान प्राथमिक तालिका को परिभाषित करने वाली तालिका बनाने के लिए और फिर कथन में सम्मिलित करने के लिए है।

CREATE TABLE mytable (
field1 INTEGER PRIMARY KEY, 
field2 TEXT 
); 

INSERT INTO mytable 
SELECT field1, field2 
FROM anothertable; 
5

SQLite docs तालिका निर्माण के बारे में, create table as select का उपयोग कर के अनुसार की कमी के बिना और प्राथमिक कुंजी के बिना एक नई तालिका पैदा करता है।

हालांकि, प्रलेखन भी कहता है कि प्राथमिक कुंजी और अद्वितीय अनुक्रमणिका तार्किक समकक्ष (see constraints section) कर रहे हैं:

ज्यादातर मामलों में, अद्वितीय और प्राथमिक कुंजी की कमी डेटाबेस में एक अद्वितीय सूचकांक बनाने के द्वारा लागू किया जाता है। (अपवाद पूर्णांक प्राथमिक कुंजी और ROWID तालिकाओं के बिना पर प्राथमिक कुँजियों कर रहे हैं।) इसलिए, निम्नलिखित स्कीमा तार्किक बराबर हैं:

CREATE TABLE t1(a, b UNIQUE); 

CREATE TABLE t1(a, b PRIMARY KEY); 

CREATE TABLE t1(a, b); 
CREATE UNIQUE INDEX t1b ON t1(b); 

तो, भले ही आप एसक्यूएल के माध्यम से अपनी मेज परिभाषा को बदल नहीं सकते वाक्य रचना में परिवर्तन, आप एक अद्वितीय सूचकांक के उपयोग के माध्यम से वही प्राथमिक कुंजी प्रभाव प्राप्त कर सकते हैं।

इसके अलावा, कोई भी तालिका (पंक्तिबद्ध वाक्यविन्यास के बिना बनाए गए को छोड़कर) में एक आंतरिक पूर्णांक स्तंभ होता है जिसे "पंक्ति" कहा जाता है। दस्तावेज़ों के अनुसार, आप रिकॉर्ड टेबल को पुनर्प्राप्त/संशोधित करने के लिए इस आंतरिक कॉलम का उपयोग कर सकते हैं।

0
sqlite> create table t(id int, col2 varchar(32), col3 varchar(8)); 
sqlite> insert into t values(1, 'he', 'ha'); 
sqlite> 
sqlite> create table t2(id int primary key, col2 varchar(32), col3 varchar(8)); 
sqlite> insert into t2 select * from t; 
sqlite> .schema 
CREATE TABLE t(id int, col2 varchar(32), col3 varchar(8)); 
CREATE TABLE t2(id int primary key, col2 varchar(32), col3 varchar(8)); 
sqlite> drop table t; 
sqlite> alter table t2 rename to t; 
sqlite> .schema 
CREATE TABLE IF NOT EXISTS "t"(id int primary key, col2 varchar(32), col3 varchar(8)); 
sqlite> 
संबंधित मुद्दे