code

SQLite에 존재하지 않는 경우 ALTER TABLE ADD COLUMN

codestyles 2020. 10. 19. 08:05
반응형

SQLite에 존재하지 않는 경우 ALTER TABLE ADD COLUMN


최근에 기존 SQLite 데이터베이스 테이블 몇 개에 열을 추가해야했습니다. 이것은 ALTER TABLE ADD COLUMN. 물론 테이블이 이미 변경된 경우에는 그대로 두어야합니다. 불행하게도, SQLite는은 지원하지 않습니다 IF NOT EXISTS에 절을 ALTER TABLE.

현재 해결 방법은 이 Python 예제 와 마찬가지로 ALTER TABLE 문을 실행하고 "중복 된 열 이름"오류를 무시하는 것입니다 (그러나 C ++에서는).

그러나 데이터베이스 스키마를 설정하는 일반적인 접근 방식은 또는 명령 줄 도구를 사용하여 실행할 수있는 CREATE TABLE IF NOT EXISTSCREATE INDEX IF NOT EXISTS문을 포함하는 .sql 스크립트를 사용 sqlite3_exec하는 것 sqlite3입니다. ALTER TABLE이 스크립트 파일을 넣을 수 없습니다. 그 문이 실패하면 그 이후의 어떤 것도 실행되지 않기 때문입니다.

테이블 정의를 한곳에두고 .sql과 .cpp 파일로 나누지 않고 싶습니다. ALTER TABLE ADD COLUMN IF NOT EXISTS순수한 SQLite SQL에서 해결 방법을 작성하는 방법이 있습니까?


99 % 순수한 SQL 방법이 있습니다. 아이디어는 스키마를 버전 화하는 것입니다. 두 가지 방법으로이 작업을 수행 할 수 있습니다.

  • 'user_version'pragma 명령 ( PRAGMA user_version)을 사용하여 데이터베이스 스키마 버전에 대한 증분 번호를 저장합니다.

  • 고유 한 정의 된 테이블에 버전 번호를 저장합니다.

이러한 방식으로 소프트웨어가 시작될 때 데이터베이스 스키마를 확인하고 필요한 경우 ALTER TABLE쿼리를 실행 한 다음 저장된 버전을 증가시킬 수 있습니다. 특히 데이터베이스가 수년에 걸쳐 몇 번 증가하고 변경되는 경우 다양한 업데이트를 "블라인드"로 시도하는 것보다 훨씬 낫습니다.


한 가지 해결 방법은 열을 생성하고 열이 이미 존재하는 경우 발생하는 예외 / 오류를 포착하는 것입니다. 여러 열을 추가 할 때 하나의 중복으로 인해 다른 열이 생성되는 것을 방지하지 않도록 별도의 ALTER TABLE 문에 추가합니다.

sqlite가-NET , 우리는 다음과 같이했다. 중복 된 sqlite 오류를 다른 sqlite 오류와 구별 할 수 없기 때문에 완벽하지 않습니다.

Dictionary<string, string> columnNameToAddColumnSql = new Dictionary<string, string>
{
    {
        "Column1",
        "ALTER TABLE MyTable ADD COLUMN Column1 INTEGER"
    },
    {
        "Column2",
        "ALTER TABLE MyTable ADD COLUMN Column2 TEXT"
    }
};

foreach (var pair in columnNameToAddColumnSql)
{
    string columnName = pair.Key;
    string sql = pair.Value;

    try
    {
        this.DB.ExecuteNonQuery(sql);
    }
    catch (System.Data.SQLite.SQLiteException e)
    {
        _log.Warn(e, string.Format("Failed to create column [{0}]. Most likely it already exists, which is fine.", columnName));
    }
}

SQLite는 또한 "table_info"라는 pragma 문을 지원합니다.이 구문은 열 이름 (및 열에 대한 기타 정보)이있는 테이블의 열당 한 행을 반환합니다. 쿼리에서이를 사용하여 누락 된 열을 확인하고 존재하지 않는 경우 테이블을 변경할 수 있습니다.

PRAGMA table_info(foo_table_name)

http://www.sqlite.org/pragma.html#pragma_table_info


DB 업그레이드 문에서이 작업을 수행하는 경우 가장 간단한 방법은 이미 존재할 수있는 필드를 추가하려고 할 때 throw되는 예외를 포착하는 것입니다.

try {
   db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN foo TEXT default null");
} catch (SQLiteException ex) {
   Log.w(TAG, "Altering " + TABLE_NAME + ": " + ex.getMessage());
}

threre는 PRAGMA의 방법으로 table_info (table_name)이며 테이블의 모든 정보를 반환합니다.

다음은 열이 있는지 여부를 확인하는 데 사용하는 방법입니다.

    public boolean isColumnExists (String table, String column) {
         boolean isExists = false
         Cursor cursor;
         try {           
            cursor = db.rawQuery("PRAGMA table_info("+ table +")", null);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    String name = cursor.getString(cursor.getColumnIndex("name"));
                    if (column.equalsIgnoreCase(name)) {
                        isExists = true;
                        break;
                    }
                }
            }

         } finally {
            if (cursor != null && !cursor.isClose()) 
               cursor.close();
         }
         return isExists;
    }

루프를 사용하지 않고이 쿼리를 사용할 수도 있습니다.

cursor = db.rawQuery("PRAGMA table_info("+ table +") where name = " + column, null);

In case you're having this problem in flex/adobe air and find yourself here first, i've found a solution, and have posted it on a related question: ADD COLUMN to sqlite db IF NOT EXISTS - flex/air sqlite?

My comment here: https://stackoverflow.com/a/24928437/2678219


I took the answer above in C#/.Net, and rewrote it for Qt/C++, not to much changed, but I wanted to leave it here for anyone in the future looking for a C++'ish' answer.

    bool MainWindow::isColumnExisting(QString &table, QString &columnName){

    QSqlQuery q;

    try {
        if(q.exec("PRAGMA table_info("+ table +")"))
            while (q.next()) {
                QString name = q.value("name").toString();     
                if (columnName.toLower() == name.toLower())
                    return true;
            }

    } catch(exception){
        return false;
    }
    return false;
}

You can alternatively use the CASE-WHEN TSQL statement in combination with pragma_table_info to know if a column exists:

select case(CNT) 
    WHEN 0 then printf('not found')
    WHEN 1 then printf('found')
    END
FROM (SELECT COUNT(*) AS CNT FROM pragma_table_info('myTableName') WHERE name='columnToCheck') 

참고URL : https://stackoverflow.com/questions/3604310/alter-table-add-column-if-not-exists-in-sqlite

반응형