ALTER TABLE ADD COLUMN SI NO EXISTE en SQLite

Recientemente hemos tenido la necesidad de agregar columnas a algunas de nuestras tablas de bases de datos SQLite existentes. Esto se puede hacer con ALTER TABLE ADD COLUMN . Por supuesto, si la tabla ya ha sido modificada, queremos dejarlo en paz. Desafortunadamente, SQLite no admite una cláusula IF NOT EXISTS en ALTER TABLE .

Nuestra solución actual es ejecutar la instrucción ALTER TABLE e ignorar cualquier error de “nombre de columna duplicado”, al igual que este ejemplo de Python (pero en C ++).

Sin embargo, nuestro enfoque habitual para configurar esquemas de bases de datos es tener un script .sql que contenga instrucciones CREATE TABLE IF NOT EXISTS y CREATE INDEX IF NOT EXISTS , que se pueden ejecutar utilizando sqlite3_exec o la herramienta de línea de comandos sqlite3 . No podemos poner ALTER TABLE en estos archivos de script porque si esa sentencia falla, no se ejecutará nada después de ella.

Quiero tener las definiciones de tabla en un lugar y no dividir entre los archivos .sql y .cpp. ¿Hay alguna manera de escribir una solución alternativa ALTER TABLE ADD COLUMN IF NOT EXISTS en SQLite SQL puro?

Tengo un 99% de método SQL puro. La idea es versionar su esquema. Puede hacer esto de dos maneras:

  • Utilice el comando pragma ‘user_version’ ( PRAGMA user_version ) para almacenar un número incremental para su versión de esquema de base de datos.

  • Almacene su número de versión en su propia tabla definida.

De esta forma, cuando se inicia el software, puede verificar el esquema de la base de datos y, si es necesario, ejecutar su consulta ALTER TABLE , y luego incrementar la versión almacenada. Esto es mucho mejor que intentar varias actualizaciones “a ciegas”, especialmente si su base de datos crece y cambia varias veces a lo largo de los años.

SQLite también admite una instrucción pragma llamada “table_info” que devuelve una fila por columna en una tabla con el nombre de la columna (y otra información sobre la columna). Puede usar esto en una consulta para verificar la columna que falta, y si no está presente, alterar la tabla.

 PRAGMA table_info(foo_table_name) 

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

Una solución es simplemente crear las columnas y detectar la excepción / error que surge si la columna ya existe. Cuando agregue varias columnas, agréguelas en declaraciones ALTER TABLE separadas para que un duplicado no impida que se creen las otras.

Con sqlite-net , hicimos algo como esto. No es perfecto, ya que no podemos distinguir los errores duplicados de sqlite de otros errores de sqlite.

 Dictionary columnNameToAddColumnSql = new Dictionary { { "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)); } } 

threre es un método de PRAGMA es table_info (table_name), devuelve toda la información de la tabla.

Aquí está la implementación de cómo usarlo para la columna de verificación existe o no,

 public boolean isColumnExists (String table, String column) { Cursor 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)) { return true; } } } return false; } 

Si está haciendo esto en una statement de actualización de base de datos, quizás la forma más sencilla sea capturar la excepción lanzada si está intentando agregar un campo que ya existe.

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

En caso de que tenga este problema en flex / adobe air y se encuentre aquí primero, he encontrado una solución y la he publicado en una pregunta relacionada: AGREGUE COLUMNA a sqlite db SI NO EXISTE – flex / air sqlite?

Mi comentario aquí: https://stackoverflow.com/a/24928437/2678219