SQLite에 존재하지 않는 경우 ALTER TABLE ADD COLUMN
최근에 기존 SQLite 데이터베이스 테이블 몇 개에 열을 추가해야했습니다. 이것은 ALTER TABLE ADD COLUMN. 물론 테이블이 이미 변경된 경우에는 그대로 두어야합니다. 불행하게도, SQLite는은 지원하지 않습니다 IF NOT EXISTS에 절을 ALTER TABLE.
현재 해결 방법은 이 Python 예제 와 마찬가지로 ALTER TABLE 문을 실행하고 "중복 된 열 이름"오류를 무시하는 것입니다 (그러나 C ++에서는).
그러나 데이터베이스 스키마를 설정하는 일반적인 접근 방식은 또는 명령 줄 도구를 사용하여 실행할 수있는 CREATE TABLE IF NOT EXISTS및 CREATE 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
'code' 카테고리의 다른 글
| Func 및 Action에 해당하는 Java의 기능 (0) | 2020.10.19 |
|---|---|
| Jersey, Apache Wink 및 JBoss RESTEasy 중에서 선택하는 방법은 무엇입니까? (0) | 2020.10.19 |
| Powershell : 스크립트에 오류가 표시되지 않도록하려면 어떻게해야합니까? (0) | 2020.10.19 |
| Dapper 쿼리에 대한 인수를 동적으로 만드는 방법 (0) | 2020.10.19 |
| var없이 객체 분해 (0) | 2020.10.19 |