SQLite तालिका से कॉलम हटाएं


114

मुझे एक समस्या है: मुझे अपने SQLite डेटाबेस से एक कॉलम को हटाने की आवश्यकता है। मैंने यह क्वेरी लिखी है

alter table table_name drop column column_name 

लेकिन यह काम नहीं करता है। क्रिप्या मेरि सहायता करे।

जवाबों:


207

प्रेषक: http://www.sqlite.org/faq.html :

(11) मैं SQLite में मौजूदा तालिका से कॉलम कैसे जोड़ूं या हटाऊं।

SQLite में ALTER TABLE सपोर्ट सीमित है जिसका उपयोग आप टेबल के अंत में कॉलम जोड़ने के लिए या टेबल का नाम बदलने के लिए कर सकते हैं। यदि आप किसी तालिका की संरचना में अधिक जटिल परिवर्तन करना चाहते हैं, तो आपको तालिका को फिर से बनाना होगा। आप मौजूदा डेटा को एक अस्थायी तालिका में सहेज सकते हैं, पुरानी तालिका को गिरा सकते हैं, नई तालिका बना सकते हैं, फिर अस्थायी तालिका से डेटा को वापस कॉपी कर सकते हैं।

उदाहरण के लिए, मान लें कि आपके पास कॉलम नाम "a", "b", और "c" के साथ "t1" नाम है और आप इस तालिका से कॉलम "c" हटाना चाहते हैं। निम्नलिखित चरण यह बताते हैं कि यह कैसे किया जा सकता है:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;

8
+ हमेशा SQLite प्रलेखन पढ़ें। जब आपको त्रुटियाँ मिलती हैं, तो आपको SQL व्याकरण में बहुत सी सीमाएँ और अंतर दिखाई देंगे। SQLite प्रलेखन समझने में बहुत आसान है। इसके बारे में चिंता मत करो।
अहमतबी - गूगल

2
सुरक्षा के लिए कॉलम हटाने के बाद आपको VACUUM कमांड निष्पादित करने की आवश्यकता है; वैक्यूम किए बिना, डेटाबेस फ़ाइल में अभी भी हटाए गए कॉलम का डेटा शामिल है।
jj1bdx

@ jj1bdx मुझे नहीं लगता कि इसमें अभी भी डेटा है, लेकिन "अप्रयुक्त डिस्क स्थान को आंतरिक" फ्री-लिस्ट "में जोड़ा जाता है और जब आप डेटा डालते हैं तो अगली बार पुन: उपयोग किया जाता है। डिस्क स्थान नहीं खोया है। लेकिन न तो यह है। ऑपरेटिंग सिस्टम पर लौट आए। " sqlite3 वेबसाइट से उद्धृत।
गिलहर्मे सालोमे

जैसा कि मैंने एक लेन-देन में कई स्तंभ निष्कासन का उपयोग किया है, यह केवल तभी काम करता है जब मुझे हटा दिया TEMPORARYजाता है CREATE TABLE
पंचांग

Qt के QSqlQuery का उपयोग करके मेरा कार्यान्वयन है: gist.github.com/ephemerr/568d0d41bc389ec78f9fb7d1f015a82a
ephemerr

56

बैकअप तालिका को छोड़ने के बजाय, इसे नाम बदलें ...

BEGIN TRANSACTION;
CREATE TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
ALTER TABLE t1_backup RENAME TO t1;
COMMIT;

6
यह तब काम नहीं करेगा जब आपके पास फोरजी की से जुड़ी हो t1
पंचांग

39

सरलता के लिए, चयन कथन से बैकअप तालिका क्यों नहीं बनाई गई?

CREATE TABLE t1_backup AS SELECT a, b FROM t1;
DROP TABLE t1;
ALTER TABLE t1_backup RENAME TO t1;

3
यह दृष्टिकोण डेटा प्रकार के कॉलम को संरक्षित करने के लिए लगता है, जबकि स्वीकृत उत्तर की तरह कुछ परिणाम सभी कॉलमों के प्रकार के होते हैं TEXT
उवे कीम

2
इन बयानों को लेनदेन में भी लपेटा जाना चाहिए।
जॉर्ज शॉली

10
ध्यान दें कि यह प्राथमिक कुंजी को संरक्षित नहीं करता है और sqlite प्राथमिक कुंजी को जोड़ने के लिए परिवर्तन तालिकाओं का समर्थन नहीं करता है। इसलिए यदि प्राथमिक कुंजी महत्वपूर्ण है, तो यह वह नहीं है
टिम

2
यह भी NULL को संरक्षित नहीं करता है।
FutureShocked

स्वीकृत उत्तर ठीक काम करता है। आप तालिका बनाते समय डेटा प्रकार निर्दिष्ट करने वाले होते हैं। आह।
जॉन लॉर्ड

8

यह विकल्प केवल तभी काम करता है जब आप DB ब्राउजर जैसे DB ब्राउजर को SQLite में DB खोल सकते हैं ।

SQLite के लिए DB ब्राउज़र में:

  1. टैब पर जाएं, "डेटाबेस स्ट्रक्चर"
  2. आप तालिका का चयन करें संशोधित तालिका चुनें (सिर्फ टैब के नीचे)
  3. वह कॉलम चुनें जिसे आप हटाना चाहते हैं
  4. निकालें फ़ील्ड पर क्लिक करें और ठीक पर क्लिक करें

3

=> निम्नलिखित क्वेरी के साथ सीधे एक नई तालिका बनाएँ:

CREATE TABLE table_name (Column_1 TEXT,Column_2 TEXT);

=> अब निम्नलिखित क्वेरी के साथ मौजूदा_टेबल से तालिका_नाम में डेटा डालें:

INSERT INTO table_name (Column_1,Column_2) FROM existing_table;

=> अब क्वेरी को फ़ॉलो करके मौजूदा_टेबल को छोड़ दें:

DROP TABLE existing_table;

1

SQLite3 c ++ के लिए:

void GetTableColNames( tstring sTableName , std::vector<tstring> *pvsCols )
{
    UASSERT(pvsCols);

    CppSQLite3Table table1;

    tstring sDML = StringOps::std_sprintf(_T("SELECT * FROM %s") , sTableName.c_str() );



    table1 = getTable( StringOps::tstringToUTF8string(sDML).c_str() );

    for ( int nCol = 0 ; nCol < table1.numFields() ; nCol++ )
    {
        const char* pch1 = table1.fieldName(nCol);  

        pvsCols->push_back( StringOps::UTF8charTo_tstring(pch1));
    }
}


bool ColExists( tstring sColName )
{
    bool bColExists = true;

    try
    {
        tstring sQuery = StringOps::std_sprintf(_T("SELECT %s FROM MyOriginalTable LIMIT 1;") , sColName.c_str() );

        ShowVerbalMessages(false);

        CppSQLite3Query q = execQuery( StringOps::tstringTo_stdString(sQuery).c_str() );

        ShowVerbalMessages(true);
    }
    catch (CppSQLite3Exception& e)
    {
        bColExists = false;
    }

    return bColExists;
}

void DeleteColumns( std::vector<tstring> *pvsColsToDelete )
{
    UASSERT(pvsColsToDelete);

    execDML( StringOps::tstringTo_stdString(_T("begin transaction;")).c_str() );


    std::vector<tstring> vsCols;
    GetTableColNames( _T("MyOriginalTable") , &vsCols );


    CreateFields( _T("TempTable1") , false );

    tstring sFieldNamesSeperatedByCommas;

    for ( int nCol = 0 ; nCol < vsCols.size() ; nCol++ )
    {

        tstring sColNameCurr = vsCols.at(nCol);

        bool bUseCol = true;

        for ( int nColsToDelete = 0; nColsToDelete < pvsColsToDelete->size() ; nColsToDelete++ )
        {
            if ( pvsColsToDelete->at(nColsToDelete) == sColNameCurr )
            {
                bUseCol = false;
                break;
            }
        }

        if ( bUseCol )
            sFieldNamesSeperatedByCommas+= (sColNameCurr + _T(","));

    }

    if ( sFieldNamesSeperatedByCommas.at( int(sFieldNamesSeperatedByCommas.size()) - 1) == _T(','))
        sFieldNamesSeperatedByCommas.erase( int(sFieldNamesSeperatedByCommas.size()) - 1 );

    tstring sDML;


    sDML = StringOps::std_sprintf(_T("insert into TempTable1 SELECT %s FROM MyOriginalTable;\n") , sFieldNamesSeperatedByCommas.c_str() );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );

    sDML = StringOps::std_sprintf(_T("ALTER TABLE MyOriginalTable RENAME TO MyOriginalTable_old\n") );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );

    sDML = StringOps::std_sprintf(_T("ALTER TABLE TempTable1 RENAME TO MyOriginalTable\n") );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );


    sDML = ( _T("DROP TABLE MyOriginalTable_old;") );   
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );


    execDML( StringOps::tstringTo_stdString(_T("commit transaction;")).c_str() );   
}

1

मैंने एक पायथन फ़ंक्शन बनाया है जहां आप तर्क के रूप में हटाने के लिए तालिका और कॉलम दर्ज करते हैं:

def removeColumn(table, column):
    columns = []
    for row in c.execute('PRAGMA table_info(' + table + ')'):
        columns.append(row[1])
    columns.remove(column)
    columns = str(columns)
    columns = columns.replace("[", "(")
    columns = columns.replace("]", ")")
    for i in ["\'", "(", ")"]:
        columns = columns.replace(i, "")
    c.execute('CREATE TABLE temptable AS SELECT ' + columns + ' FROM ' + table)
    c.execute('DROP TABLE ' + table)
    c.execute('ALTER TABLE temptable RENAME TO ' + table)
    conn.commit()

डूडा और मेबीगेटग्यूय के उत्तरों के बारे में जानकारी के अनुसार यदि टेबल पर कोई विदेशी कुंजी है तो यह काम नहीं करेगा, लेकिन इसे कोड की 2 पंक्तियों के साथ तय किया जा सकता है (एक नई तालिका बनाना और न केवल अस्थायी तालिका का नाम बदलना)


सी क्या है? कोन है? यह उत्तर अज्ञात प्रकार के लाभकारी चरों की बहुत अधिक धारणा बनाता है।
इवान कैस्टेलानोस

0

यदि किसी को PHP फ़ंक्शन के लिए (लगभग) रेडी-टू-यूज़ उपयोग की आवश्यकता है, तो इस उत्तर पर आधारित है :

/**
 * Remove a column from a table.
 * 
 * @param string $tableName The table to remove the column from.
 * @param string $columnName The column to remove from the table.
 */
public function DropTableColumn($tableName, $columnName)
{
    // --
    // Determine all columns except the one to remove.

    $columnNames = array();

    $statement = $pdo->prepare("PRAGMA table_info($tableName);");
    $statement->execute(array());
    $rows = $statement->fetchAll(PDO::FETCH_OBJ);

    $hasColumn = false;

    foreach ($rows as $row)
    {
        if(strtolower($row->name) !== strtolower($columnName))
        {
            array_push($columnNames, $row->name);
        }
        else
        {
            $hasColumn = true;
        }
    }

    // Column does not exist in table, no need to do anything.
    if ( !$hasColumn ) return;

    // --
    // Actually execute the SQL.

    $columns = implode('`,`', $columnNames);

    $statement = $pdo->exec(
       "CREATE TABLE `t1_backup` AS SELECT `$columns` FROM `$tableName`;
        DROP TABLE `$tableName`;
        ALTER TABLE `t1_backup` RENAME TO `$tableName`;");
}

अन्य उत्तरों के विपरीत, इस दृष्टिकोण में प्रयुक्त एसक्यूएल डेटा प्रकार के कॉलम को संरक्षित करने के लिए लगता है, जबकि स्वीकृत उत्तर की तरह कुछ परिणाम सभी कॉलमों के प्रकार के होते हैं TEXT

अपडेट 1:

उपयोग की गई एसक्यूएल में खामी है कि autoincrementकॉलम संरक्षित नहीं हैं।


0

बस अगर यह मेरे जैसे किसी की मदद कर सकता है।

आधिकारिक वेबसाइट और स्वीकृत उत्तर के आधार पर , मैंने C # का उपयोग करके एक कोड बनाया, जो System.Data.SQLite NuGet पैकेज का उपयोग करता है ।

यह कोड प्राथमिक कुंजी और विदेशी कुंजी को भी संरक्षित करता है ।

CODE में C #:

void RemoveColumnFromSqlite (string tableName, string columnToRemove) {
 try {
    var mSqliteDbConnection = new SQLiteConnection ("Data Source=db_folder\\MySqliteBasedApp.db;Version=3;Page Size=1024;");
    mSqliteDbConnection.Open ();             
    // Reads all columns definitions from table
    List<string> columnDefinition = new List<string> ();
    var mSql = $"SELECT type, sql FROM sqlite_master WHERE tbl_name='{tableName}'";
    var mSqliteCommand = new SQLiteCommand (mSql, mSqliteDbConnection);
    string sqlScript = "";
    using (mSqliteReader = mSqliteCommand.ExecuteReader ()) {
       while (mSqliteReader.Read ()) {
          sqlScript = mSqliteReader["sql"].ToString ();
          break;
       }
    }
    if (!string.IsNullOrEmpty (sqlScript)) {
       // Gets string within first '(' and last ')' characters
       int firstIndex = sqlScript.IndexOf ("(");
       int lastIndex = sqlScript.LastIndexOf (")");
       if (firstIndex >= 0 && lastIndex <= sqlScript.Length - 1) {
          sqlScript = sqlScript.Substring (firstIndex, lastIndex - firstIndex + 1);
       }
       string[] scriptParts = sqlScript.Split (new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
       foreach (string s in scriptParts) {
          if (!s.Contains (columnToRemove)) {
             columnDefinition.Add (s);
          }
       }
    }
    string columnDefinitionString = string.Join (",", columnDefinition);
    // Reads all columns from table
    List<string> columns = new List<string> ();
    mSql = $"PRAGMA table_info({tableName})";
    mSqliteCommand = new SQLiteCommand (mSql, mSqliteDbConnection);
    using (mSqliteReader = mSqliteCommand.ExecuteReader ()) {
       while (mSqliteReader.Read ()) columns.Add (mSqliteReader["name"].ToString ());
    }
    columns.Remove (columnToRemove);
    string columnString = string.Join (",", columns);
    mSql = "PRAGMA foreign_keys=OFF";
    mSqliteCommand = new SQLiteCommand (mSql, mSqliteDbConnection);
    int n = mSqliteCommand.ExecuteNonQuery ();
    // Removes a column from the table
    using (SQLiteTransaction tr = mSqliteDbConnection.BeginTransaction ()) {
       using (SQLiteCommand cmd = mSqliteDbConnection.CreateCommand ()) {
          cmd.Transaction = tr;
          string query = $"CREATE TEMPORARY TABLE {tableName}_backup {columnDefinitionString}";
          cmd.CommandText = query;
          cmd.ExecuteNonQuery ();
          cmd.CommandText = $"INSERT INTO {tableName}_backup SELECT {columnString} FROM {tableName}";
          cmd.ExecuteNonQuery ();
          cmd.CommandText = $"DROP TABLE {tableName}";
          cmd.ExecuteNonQuery ();
          cmd.CommandText = $"CREATE TABLE {tableName} {columnDefinitionString}";
          cmd.ExecuteNonQuery ();
          cmd.CommandText = $"INSERT INTO {tableName} SELECT {columnString} FROM {tableName}_backup;";
          cmd.ExecuteNonQuery ();
          cmd.CommandText = $"DROP TABLE {tableName}_backup";
          cmd.ExecuteNonQuery ();
       }
       tr.Commit ();
    }
    mSql = "PRAGMA foreign_keys=ON";
    mSqliteCommand = new SQLiteCommand (mSql, mSqliteDbConnection);
    n = mSqliteCommand.ExecuteNonQuery ();
 } catch (Exception ex) {
    HandleExceptions (ex);
 }
}

0
PRAGMA foreign_keys=off;

BEGIN TRANSACTION;

ALTER TABLE table1 RENAME TO _table1_old;

CREATE TABLE table1 (
( column1 datatype [ NULL | NOT NULL ],
  column2 datatype [ NULL | NOT NULL ],
  ...
);

INSERT INTO table1 (column1, column2, ... column_n)
  SELECT column1, column2, ... column_n
  FROM _table1_old;

COMMIT;

PRAGMA foreign_keys=on;

अधिक जानकारी के लिए: https://www.techonthenet.com/sqlite/tables/alter_table.php

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