এসকিউএল টেবিল থেকে কলাম মুছুন


114

আমার একটি সমস্যা আছে: আমার এসকিউএল ডাটাবেস থেকে আমার একটি কলাম মুছতে হবে। আমি এই ক্যোয়ারী লিখেছি

alter table table_name drop column column_name 

কিন্তু এটা কাজ করে না. আমাকে সাহায্য করুন.

উত্তর:


207

থেকে: http://www.sqlite.org/faq.html :

(১১) আমি কীভাবে এসকিউএলাইটে বিদ্যমান সারণী থেকে কলামগুলি যুক্ত করব বা মুছব।

এসকিউএলাইটে অল্টার টেবল সমর্থন সীমিত রয়েছে যা আপনি কোনও টেবিলের শেষে একটি কলাম যুক্ত করতে বা কোনও টেবিলের নাম পরিবর্তন করতে পারেন। আপনি যদি কোনও টেবিলের কাঠামোর আরও জটিল পরিবর্তন করতে চান তবে আপনাকে টেবিলটি পুনরায় তৈরি করতে হবে। আপনি অস্থায়ী টেবিলটিতে বিদ্যমান ডেটা সংরক্ষণ করতে পারেন, পুরানো টেবিলটি ফেলে দিতে পারেন, নতুন টেবিলটি তৈরি করতে পারেন, তারপরে অস্থায়ী সারণী থেকে ডেটাটি অনুলিপি করতে পারেন।

উদাহরণস্বরূপ, ধরুন আপনার কাছে "t1" নামের একটি সারণী রয়েছে যার সাথে কলামের নাম "এ", "বি" এবং "সি" রয়েছে এবং আপনি এই টেবিল থেকে "গ" কলামটি মুছতে চান। নিম্নলিখিত পদক্ষেপগুলি কীভাবে এটি করা যেতে পারে তা চিত্রিত করে:

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
+ সবসময় এসকিউএল ডকুমেন্টেশন পড়ুন। আপনি ত্রুটিগুলি পেয়ে গেলে আপনি এসকিউএল ব্যাকরণে অনেকগুলি সীমাবদ্ধতা এবং পার্থক্য লক্ষ্য করবেন। এসকিউএল ডকুমেন্টেশন খুব সহজে বোঝা যায়। এটি সম্পর্কে চিন্তা করবেন না।
আহমেটবি - গুগল

2
সুরক্ষার জন্য কলামগুলি সরিয়ে নেওয়ার পরে আপনাকে ভ্যাকিউম কমান্ডটি করাতে হবে; ভ্যাকুয়ামিং ছাড়াই ডাটাবেস ফাইলটিতে এখনও মুছে ফেলা কলামগুলির ডেটা থাকে।
jj1bdx

@ jj1bdx আমি মনে করি না এটিতে এখনও ডেটা রয়েছে তবে "অব্যবহৃত ডিস্কের স্থানটি একটি অভ্যন্তরীণ" ফ্রি-লিস্ট "এ যুক্ত হয় এবং পরের বার আপনি ডেটা timeোকানোর সময় পুনরায় ব্যবহার করা হয় The ডিস্কের স্থানটি হারাতে পারেনি তবে তাও নয় অপারেটিং সিস্টেমে ফিরে এসেছিল। " হিসাবে sqlite3 ওয়েবসাইট থেকে উদ্ধৃত।
গিলহর্ম সালোম

আমি এক লেনদেন একাধিক কলাম সরানো ব্যবহৃত হিসাবে এই শুধুমাত্র যখন আমি মুছে কাজ TEMPORARYথেকে CREATE TABLE
এফিমার

Qt এর QSqlQuery ব্যবহার করে আমার প্রয়োগ রয়েছে: gist.github.com/ephemerr/568d0d41bc389ec78f9fb7d1f015a82a
এফিমার

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
নোট করুন যে এটি প্রাথমিক কী সংরক্ষণ করে না এবং স্ক্লাইটটি প্রাথমিক কী যুক্ত করতে পরিবর্তনীয় টেবিলগুলিকে সমর্থন করে না। তাই যদি প্রাথমিক কীটি গুরুত্বপূর্ণ হয় তবে এটি আপনার ব্যবহার করা উচিত নয়
টিম

2
এটি নালও সংরক্ষণ করে না।
ফিউচারশকে

গৃহীত উত্তর ভাল কাজ করে। আপনি যখন টেবিলটি তৈরি করেন তখন আপনাকে ডেটা প্রকারগুলি নির্দিষ্ট করার কথা। দীর্ঘশ্বাস.
জন লর্ড

8

এই বিকল্পটি কেবল তখনই কাজ করে যদি আপনি এসকিউএলাইটের জন্য ডিবি ব্রাউজারের মতো ডিবি ব্রাউজারে ডিবি খুলতে পারেন ।

এসকিউলাইটের জন্য ডিবি ব্রাউজারে:

  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

এসকিউএলাইট 3 সি ++ এর জন্য:

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

যদি কারও কাছে (প্রায়) ব্যবহারের জন্য প্রস্তুত পিএইচপি ফাংশন প্রয়োজন হয় তবে নিম্নলিখিত এই উত্তরের উপর ভিত্তি করে :

/**
 * 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

কেবল যদি এটি আমার মতো কাউকে সহায়তা করতে পারে।

অফিসিয়াল ওয়েবসাইট এবং স্বীকৃত উত্তরের উপর ভিত্তি করে আমি সি # ব্যবহার করে একটি কোড তৈরি করেছি যা System.Data.SQLite নুগেট প্যাকেজ ব্যবহার করে ।

এই কোডটি প্রাথমিক কী এবং বিদেশী কী সংরক্ষণ করে ।

সি # তে কোড:

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.