with primary index create autoincrement sqlite

index - SQLite add Primary Key



sqlite primary key autoincrement (10)

Creé una tabla en Sqlite usando la sintaxis CREATE TABLE AS para crear una tabla basada en una instrucción SELECT . Ahora esta tabla no tiene clave principal, pero me gustaría agregar una.

Ejecutando ALTER TABLE table_name ADD PRIMARY KEY(col1, col2,...) da un error de sintaxis "near PRIMARY"

¿Hay alguna forma de agregar una clave principal durante la creación de la tabla o después en Sqlite?

EDITAR: Por "durante la creación" quiero decir durante la creación con CREATE TABLE AS .


Creo que agregar un índice en esa columna puede tener el mismo efecto.


De acuerdo con los docs sqlite sobre la creación de tabla, el uso de create table como select produce una nueva tabla sin restricciones y sin clave principal.

Sin embargo, la documentación también dice que las claves primarias y los índices únicos son lógicamente equivalentes ( consulte la sección de restricciones ):

En la mayoría de los casos, las restricciones UNIQUE y PRIMARY KEY se implementan al crear un índice único en la base de datos. (Las excepciones son INTEGER PRIMARY KEY y PRIMARY KEYs en tablas SIN ROWID.) Por lo tanto, los siguientes esquemas son lógicamente equivalentes:

CREATE TABLE t1(a, b UNIQUE); CREATE TABLE t1(a, b PRIMARY KEY); CREATE TABLE t1(a, b); CREATE UNIQUE INDEX t1b ON t1(b);

Por lo tanto, incluso si no puede modificar la definición de su tabla a través de la sintaxis SQL alter, puede obtener el mismo efecto de clave principal mediante el uso de un índice único.

Además, cualquier tabla (excepto las creadas sin la sintaxis rowid) tiene una columna entera interna conocida como "rowid". De acuerdo con los documentos, puede usar esta columna interna para recuperar / modificar tablas de registros.


No puede modificar las tablas de SQLite de forma significativa después de que se hayan creado. La solución sugerida es crear una nueva tabla con los requisitos correctos y copiar sus datos en ella, luego soltar la tabla anterior.

aquí está la documentación oficial sobre esto: http://sqlite.org/faq.html#q11


Puedes hacerlo así:

CREATE TABLE mytable ( field1 text, field2 text, field3 integer, PRIMARY KEY (field1, field2) );


Siempre que use CREATE TABLE , si está creando la clave principal en un solo campo , puede usar:

CREATE TABLE mytable ( field1 TEXT, field2 INTEGER PRIMARY KEY, field3 BLOB, );

Con CREATE TABLE , también puede usar siempre el siguiente enfoque para crear una clave principal en uno o varios campos :

CREATE TABLE mytable ( field1 TEXT, field2 INTEGER, field3 BLOB, PRIMARY KEY (field2, field1) );

Referencia: http://www.sqlite.org/lang_createtable.html

Esta respuesta no aborda la alteración de la tabla.


Traté de agregar la clave primaria después cambiando la tabla sqlite_master directamente. Este truco parece funcionar. Es una solución de hackeo, por supuesto.

En resumen: cree un índice regular (único) en la tabla, luego haga que el esquema sea editable y cambie el nombre del índice al formulario reservado por sqlite para identificar un índice de clave principal (es decir, sqlite_autoindex_XXX_1, donde XXX es el nombre de la tabla) y establecer la cadena sql en NULL. Por fin cambiar la definición de la tabla en sí. One pittfal: sqlite no ve el cambio en el nombre del índice hasta que se vuelva a abrir la base de datos. Esto parece un error, pero no grave (incluso sin volver a abrir la base de datos, todavía puede usarlo).

Supongamos que la tabla se ve así:

CREATE TABLE tab1(i INTEGER, j INTEGER, t TEXT);

Entonces hice lo siguiente:

BEGIN; CREATE INDEX pk_tab1 ON tab1(i,j); pragma writable_schema=1; UPDATE sqlite_master SET name=''sqlite_autoindex_tab1_1'',sql=null WHERE name=''pk_tab1''; UPDATE sqlite_master SET sql=''CREATE TABLE tab1(i integer,j integer,t text,primary key(i,j))'' WHERE name=''tab1''; COMMIT;

Algunas pruebas (en shell sqlite):

sqlite> explain query plan select * from tab1 order by i,j; 0|0|0|SCAN TABLE tab1 USING INDEX sqlite_autoindex_tab1_1 sqlite> drop index sqlite_autoindex_tab1_1; Error: index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped


Tuve el mismo problema y la mejor solución que encontré es crear primero la tabla que define la clave principal y luego usar insertar en la declaración.

CREATE TABLE mytable ( field1 INTEGER PRIMARY KEY, field2 TEXT ); INSERT INTO mytable SELECT field1, field2 FROM anothertable;


Utilicé la sintaxis CREATE TABLE AS para unir varias columnas y encontré el mismo problema. Aquí hay un AppleScript que escribí para acelerar el proceso.

set databasePath to "~/Documents/Databases/example.db" set tableOne to "separate" -- Table from which you are pulling data set tableTwo to "merged" -- Table you are creating set {tempCol, tempColEntry, permColEntry} to {{}, {}, {}} set permCol to {"id integer primary key"} -- Columns are created from single items AND from the last item of a list -- {{"a", "b", "c"}, "d", "e"} Columns "a" and "b" will be merged into a new column "c". tableTwo will have columns "c", "d", "e" set nonCoal to {"City", "Contact", "Names", {"Address 1", "Address", "address one", "Address1", "Text4", "Address 1"}, {"E-Mail", "E-Mail Address", "Email", "Email Address", "EmailAddress", "Email"}, {"Zip", "Zip Code", "ZipCode", "Zip"}, {"Telephone", "BusinessPhone", "Phone", "Work Phone", "Telephone"}, {"St", "State", "State"}, {"Salutation", "Mr/Ms", "Mr/s", "Salutations", "Sautation", "Salutation"}} -- Build the COALESCE statements repeat with h from 1 to count of nonCoal set aColumn to item h of nonCoal if class of aColumn is not list then if (count of words of aColumn) > 1 then set aColumn to quote & aColumn & quote set end of tempCol to aColumn set end of permCol to aColumn else set coalEntry to {} repeat with i from 1 to count of aColumn set coalCol to item i of aColumn as string if (count of words of coalCol) > 1 then set coalCol to quote & coalCol & quote if i = 1 then set end of coalEntry to "TRIM(COALESCE(" & coalCol & ", '''') || /" /" || " else if i < ((count of aColumn) - 1) then set end of coalEntry to "COALESCE(" & coalCol & ", '''') || /" /" || " else if i = ((count of aColumn) - 1) then set as_Col to item (i + 1) of aColumn as string if (count of words of as_Col) > 1 then set as_Col to quote & as_Col & quote set end of coalEntry to ("COALESCE(" & coalCol & ", '''')) AS " & as_Col) & "" set end of permCol to as_Col end if end repeat set end of tempCol to (coalEntry as string) end if end repeat -- Since there are ", '''' within the COALESCE statement, you can''t use "TID" and "as string" to convert tempCol and permCol for entry into sqlite3. I rebuild the lists in the next block. repeat with j from 1 to count of tempCol if j < (count of tempCol) then set end of tempColEntry to item j of tempCol & ", " set end of permColEntry to item j of permCol & ", " else set end of tempColEntry to item j of tempCol set end of permColEntry to item j of permCol end if end repeat set end of permColEntry to ", " & item (j + 1) of permCol set permColEntry to (permColEntry as string) set tempColEntry to (tempColEntry as string) -- Create the new table with an "id integer primary key" column set createTable to "create table " & tableTwo & " (" & permColEntry & "); " do shell script "sqlite3 " & databasePath & space & quoted form of createTable -- Create a temporary table and then populate the permanent table set createTemp to "create temp table placeholder as select " & tempColEntry & " from " & tableOne & "; " & "insert into " & tableTwo & " select Null, * from placeholder;" do shell script "sqlite3 " & databasePath & space & quoted form of createTemp --export the new table as a .csv file do shell script "sqlite3 -header -column -csv " & databasePath & " /"select * from " & tableTwo & " ; /"> ~/" & tableTwo & ".csv"


Introducción

Esto se basa en Java de Android y es un buen ejemplo de cómo cambiar la base de datos sin molestar a los fanáticos / clientes de la aplicación. Esto se basa en la idea de la página de preguntas frecuentes de SQLite http://sqlite.org/faq.html#q11

El problema

No me di cuenta de que necesito establecer un row_number o record_id para eliminar un solo artículo comprado en un recibo, y al mismo tiempo el número de código de barras del artículo me engañó y me hizo pensar que era la clave para eliminar ese artículo. Estoy guardando los detalles de un recibo en la tabla código de barra de recibo. Dejarlo sin un record_id puede significar borrar todos los registros del mismo ítem en un recibo si utilicé el código de barras del ítem como la clave.

darse cuenta

Por favor comprenda que esto es un copiar y pegar de mi código. Estoy trabajando en el momento de escribir esto. Úselo solo como ejemplo, copiar y pegar al azar no lo ayudará. Modifique esto primero según sus necesidades

Además, por favor no olvide leer los comentarios en el código.

El código

Use esto como un método en su clase para verificar primero si falta la columna que desea agregar. Hacemos esto solo para no repetir el proceso de alterar la tabla receipt_barcode. Solo menciónalo como parte de tu clase. En el siguiente paso, verá cómo lo usaremos.

public boolean is_column_exists(SQLiteDatabase mDatabase , String table_name, String column_name) { //checks if table_name has column_name Cursor cursor = mDatabase.rawQuery("pragma table_info("+table_name+")",null); while (cursor.moveToNext()){ if (cursor.getString(cursor.getColumnIndex("name")).equalsIgnoreCase(column_name)) return true; } return false; }

Luego, se usa el siguiente código para crear la tabla código de barra de recibo si ya NO sale para los usuarios de su aplicación por primera vez. Y tenga en cuenta el "SI NO EXISTE" en el código. Tiene importancia.

//mDatabase should be defined as a Class member (global variable) //for ease of access : //SQLiteDatabse mDatabase=SQLiteDatabase.openOrCreateDatabase(dbfile_path, null); creation_query = " CREATE TABLE if not exists receipt_barcode ( "; creation_query += "/n record_id INTEGER PRIMARY KEY AUTOINCREMENT,"; creation_query += "/n rcpt_id INT( 11 ) NOT NULL,"; creation_query += "/n barcode VARCHAR( 255 ) NOT NULL ,"; creation_query += "/n barcode_price VARCHAR( 255 ) DEFAULT (0),"; creation_query += "/n PRIMARY KEY ( record_id ) );"; mDatabase.execSQL(creation_query); //This is where the important part comes in regarding the question in this page: //adding the missing primary key record_id in table receipt_barcode for older versions if (!is_column_exists(mDatabase, "receipt_barcode","record_id")){ mDatabase.beginTransaction(); try{ Log.e("record_id", "creating"); creation_query="CREATE TEMPORARY TABLE t1_backup("; creation_query+="record_id INTEGER PRIMARY KEY AUTOINCREMENT,"; creation_query+="rcpt_id INT( 11 ) NOT NULL,"; creation_query+="barcode VARCHAR( 255 ) NOT NULL ,"; creation_query+="barcode_price VARCHAR( 255 ) NOT NULL DEFAULT (0) );"; mDatabase.execSQL(creation_query); creation_query="INSERT INTO t1_backup(rcpt_id,barcode,barcode_price) SELECT rcpt_id,barcode,barcode_price FROM receipt_barcode;"; mDatabase.execSQL(creation_query); creation_query="DROP TABLE receipt_barcode;"; mDatabase.execSQL(creation_query); creation_query="CREATE TABLE receipt_barcode ("; creation_query+="record_id INTEGER PRIMARY KEY AUTOINCREMENT,"; creation_query+="rcpt_id INT( 11 ) NOT NULL,"; creation_query+="barcode VARCHAR( 255 ) NOT NULL ,"; creation_query+="barcode_price VARCHAR( 255 ) NOT NULL DEFAULT (0) );"; mDatabase.execSQL(creation_query); creation_query="INSERT INTO receipt_barcode(record_id,rcpt_id,barcode,barcode_price) SELECT record_id,rcpt_id,barcode,barcode_price FROM t1_backup;"; mDatabase.execSQL(creation_query); creation_query="DROP TABLE t1_backup;"; mDatabase.execSQL(creation_query); mdb.setTransactionSuccessful(); } catch (Exception exception ){ Log.e("table receipt_bracode", "Table receipt_barcode did not get a primary key (record_id"); exception.printStackTrace(); } finally { mDatabase.endTransaction(); }


sqlite> create table t(id int, col2 varchar(32), col3 varchar(8)); sqlite> insert into t values(1, ''he'', ''ha''); sqlite> sqlite> create table t2(id int primary key, col2 varchar(32), col3 varchar(8)); sqlite> insert into t2 select * from t; sqlite> .schema CREATE TABLE t(id int, col2 varchar(32), col3 varchar(8)); CREATE TABLE t2(id int primary key, col2 varchar(32), col3 varchar(8)); sqlite> drop table t; sqlite> alter table t2 rename to t; sqlite> .schema CREATE TABLE IF NOT EXISTS "t"(id int primary key, col2 varchar(32), col3 varchar(8)); sqlite>