Insertar nueva columna en la tabla en sqlite?

354

Tengo una tabla con columnas name, qty, rate. Ahora necesito agregar una nueva columna COLNewentre las columnas namey qty. ¿Cómo agrego una nueva columna entre dos columnas?

Ensayador
fuente

Respuestas:

677

Tienes dos opciones. Primero, simplemente puede agregar una nueva columna con lo siguiente:

ALTER TABLE {tableName} ADD COLUMN COLNew {type};

En segundo lugar, y más complicado, pero en realidad pondría la columna donde lo desea, sería cambiar el nombre de la tabla:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Luego cree la nueva tabla con la columna que falta:

CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);

Y llenarlo con los datos antiguos:

INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;

Luego elimine la tabla anterior:

DROP TABLE TempOldTable;

Preferiría mucho la segunda opción, ya que te permitirá cambiar el nombre de todo por completo si es necesario.

Raceimaztion
fuente
27
Iría por la primera opción, y usaría la opción predeterminada fuera de la opción de secuencia ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Más importante: (pensando en por qué querría ordenar las columnas ...) use en cada acción de registro (como insertar o agregar) siempre los nombres de las columnas, de esta manera, nunca obtendrá errores en algún lugar de su código después de alterar la tabla.
michel.iamit
55
Por cierto: el valor predeterminado no se puede agregar en ALTER TABLE para algunos tipos de campo: sqlite.org/lang_altertable.html
michel.iamit el
99
no olvides volver a crear índices
Jan Turo T
55
necesitará recrear disparadores también
Christopher K.
77
No olvide posibles infracciones de restricciones causadas por claves externas: "... pero puede invocar acciones de claves externas o infracciones de restricciones". (ver sqlite.org/foreignkeys.html#fk_schemacommands ); como solución alternativa, puede deshabilitar las claves externas mientras tanto: PRAGMA foreign_keys = ON;(consulte sqlite.org/foreignkeys.html#fk_enable )
Trinimon el
112

No agrega columnas entre otras columnas en SQL, solo las agrega. Donde se colocan depende totalmente del DBMS. El lugar correcto para asegurarse de que las columnas salgan en el orden correcto es cuando las coloque select.

En otras palabras, si los quiere en el orden {name,colnew,qty,rate}, use:

select name, colnew, qty, rate from ...

Con SQLite, debe usar alter table, un ejemplo es:

alter table mytable add column colnew char(50)
paxdiablo
fuente
2
SELECT * FROM mytable?
EML
¿Cuál es el valor predeterminado establecido si no lo especificamos en las filas existentes de la nueva columna?
Jacob
12
Hay muy pocos casos de uso en los que debería hacerlo select *. A veces es útil para programas que desean hacer un descubrimiento de tablas pero, para la gran mayoría de los usos, debe especificar explícitamente lo que desea y, por lo tanto, el orden en que lo desea.
paxdiablo
44
Es una locura que esta no sea la "respuesta aceptada". La pregunta original en sí demuestra una completa falta de comprensión de cómo funciona un RDBMS.
Vada Poché
12

Puedes agregar una nueva columna con la consulta

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Pero se agregará al final, no entre las columnas existentes.

Mudassir
fuente
11

SQLite tiene un soporte ALTER TABLE limitado que puede usar para agregar una columna al final de una tabla o para cambiar el nombre de una tabla.

Si desea realizar cambios más complejos en la estructura de una tabla, deberá volver a crear la tabla. Puede guardar los datos existentes en una tabla temporal, descartar la tabla anterior, crear la nueva tabla y luego volver a copiar los datos de la tabla temporal.

Por ejemplo, suponga que tiene una tabla llamada "t1" con los nombres de las columnas "a" y "c" y que desea insertar la columna "b" de esta tabla. Los siguientes pasos ilustran cómo se podría hacer esto:

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

Ahora está listo para insertar sus nuevos datos de esta manera:

UPDATE t1 SET b='blah' WHERE a='key'
CJH
fuente
En mis pruebas, la línea INSERT INTO t1 SELECT a,c FROM t1_backup;causa el error: "la tabla t1 tiene 3 columnas pero se proporcionaron 2 valores: INSERTAR EN t1 SELECCIONE a, c DESDE t1_backup;". La línea correcta debería serINSERT INTO t1 (a,c) SELECT a,c FROM t1_backup;
JnLlnd
5
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};

Esta actualización es necesaria para manejar el valor nulo, ingresando un valor predeterminado según lo requiera. Como en su caso, debe llamar a la SELECTconsulta y obtendrá el orden de las columnas, como ya dijo paxdiablo :

SELECT name, colnew, qty, rate FROM{tablename}

y en mi opinión, el nombre de su columna para obtener el valor del cursor:

private static final String ColNew="ColNew";
String val=cursor.getString(cursor.getColumnIndex(ColNew));

así que si el índice cambia, su aplicación no enfrentará ningún problema.

Esta es la forma segura en el sentido de que, de lo contrario, si está utilizando CREATE temptableo RENAME tableo CREATE, habría una alta probabilidad de pérdida de datos si no se maneja con cuidado, por ejemplo, en el caso de que sus transacciones ocurran mientras la batería se está agotando.

Naval Kishor Jha
fuente
4

Estaba enfrentando el mismo problema y el segundo método propuesto en la respuesta aceptada, como se señaló en los comentarios, puede ser problemático cuando se trata de claves externas.

Mi solución es exportar la base de datos a un archivo sql asegurándome de que las instrucciones INSERT incluyan nombres de columna. Lo hago usando DB Browser para SQLite que tiene una característica útil para eso. Después de eso, solo tiene que editar la instrucción de creación de tabla e insertar la nueva columna donde lo desee y volver a crear la base de datos.

En * nix like systems es solo algo en la línea de

cat db.sql | sqlite3 database.db

No sé qué tan factible es esto con bases de datos muy grandes, pero funcionó en mi caso.

Hirabayashi Taro
fuente