SQLite添加主键

Jac*_*nds 96 sqlite

我使用CREATE TABLE AS语法在Sqlite 中创建了一个基于SELECT语句创建表的表.现在这个表没有主键,但我想添加一个.

执行ALTER TABLE table_name ADD PRIMARY KEY(col1, col2,...)给出语法错误"near PRIMARY"

有没有办法在表创建期间或之后在Sqlite中添加主键?

编辑:"在创作过程中"我的意思是在创作过程中CREATE TABLE AS.

Nat*_*ley 120

创建后,您无法以任何重要方式修改SQLite表.接受的建议解决方案是创建一个具有正确要求的新表并将数据复制到其中,然后删除旧表.

这是关于此的官方文档:http://sqlite.org/faq.html#q11

  • 此链接(http://www.sqlite.org/omitted.html)解释了更详细省略的内容. (6认同)
  • 奇怪的是,你不能在创建表后添加 PK,但你可以添加索引(`CREATE UNIQUE INDEX pkName ON tableName(columnName)`),而像 MS SQL 的 SMO 这样的数据库框架实际上_make_你在表创建后添加 PK创建了! (2认同)

Acu*_*nus 30

只要您使用CREATE TABLE,如果您在单个字段上创建主键,则可以使用:

CREATE TABLE mytable (
field1 TEXT,
field2 INTEGER PRIMARY KEY,
field3 BLOB,
);
Run Code Online (Sandbox Code Playgroud)

使用CREATE TABLE,您还可以始终使用以下方法在一个或多个字段上创建主键:

CREATE TABLE mytable (
field1 TEXT,
field2 INTEGER,
field3 BLOB,
PRIMARY KEY (field2, field1)
);
Run Code Online (Sandbox Code Playgroud)

参考:http://www.sqlite.org/lang_createtable.html

这个答案没有解决表格的变化.


小智 10

我之后尝试通过直接更改sqlite_master表来添加主键.这个技巧似乎有效.当然这是一个黑客的解决方案.

简而言之:在表上创建一个常规(唯一)索引,然后使模式可写并将索引的名称更改为sqlite保留的形式以标识主键索引(即sqlite_autoindex_XXX_1,其中XXX是表名)并将sql字符串设置为NULL.最后更改表定义本身.一个pittfal:在重新打开数据库之前,sqlite看不到索引名称的更改.这似乎是一个错误,但不是一个严重的错误(即使没有重新打开数据库,你仍然可以使用它).

假设表格如下:

CREATE TABLE tab1(i INTEGER, j INTEGER, t TEXT);
Run Code Online (Sandbox Code Playgroud)

然后我做了以下事情:

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;
Run Code Online (Sandbox Code Playgroud)

一些测试(在sqlite shell中):

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    
Run Code Online (Sandbox Code Playgroud)

  • 只是警告你可以(据我所知)使你的整个数据库无法访问,如果你做错了.我正在玩,我不小心错过了第二次更新查询中的WHERE子句.SQLite不喜欢这样:P (2认同)

Car*_*Way 7

根据有关表创建的sqlite 文档,使用create table作为select会生成一个没有约束且没有主键的新表.

但是,文档还说主键和唯一索引在逻辑上是等效的(请参阅约束部分):

在大多数情况下,UNIQUE和PRIMARY KEY约束是通过在数据库中创建唯一索引来实现的.(例外是关于WITHOUT ROWID表的INTEGER PRIMARY KEY和PRIMARY KEY.)因此,以下模式在逻辑上是等价的:

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); 
Run Code Online (Sandbox Code Playgroud)

因此,即使您无法通过SQL alter语法更改表定义,也可以通过使用唯一索引获得相同的主键效果.

此外,任何表(除了那些没有rowid语法创建的表)都有一个内部整数列,称为"rowid".根据文档,您可以使用此内部列来检索/修改记录表.


Nic*_*kis 5

你可以这样做:

CREATE TABLE mytable (
field1 text,
field2 text,
field3 integer,
PRIMARY KEY (field1, field2)
);
Run Code Online (Sandbox Code Playgroud)