【问题标题】:Sqlite primary key on multiple columns多列上的 Sqlite 主键
【发布时间】:2010-10-18 14:15:22
【问题描述】:

在 SQLITE 中为多于 1 列指定主键的语法是什么?

【问题讨论】:

标签: sqlite primary-key ddl composite-primary-key


【解决方案1】:

根据documentation,是

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);

【讨论】:

  • 嗯,这是正确的,但根据文档,CREATE TABLE 东西(column1 PRIMARY KEY,column2 PRIMARY KEY);应该也是可能的,但事实并非如此。
  • @Yar 文档说“如果在单个 CREATE TABLE 语句中有多个 PRIMARY KEY 子句,这是一个错误。”是的,铁路图也可能表明这也是有效的,但下面的文字说明它不是。
  • 记得在最后添加 PRIMARY KEY(column1, column2) 部分,就像在这个答案中一样。如果您尝试在 column2 定义之后添加它,您将收到 语法错误
【解决方案2】:
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

【讨论】:

  • 主键不强制非空吗?
  • @pratnala 在标准 SQL 中,是的。在 SQLite 中,主键中允许使用 NULL。这个答案强调,如果你想要更标准的行为,你需要自己添加NOT NULL。我的答案只是多列主键的基本语法。
【解决方案3】:

是的。但请记住,这样的主键允许在两列中多次使用 NULL 值。

这样创建一个表:

    sqlite> CREATE TABLE something (
column1, column2, value, PRIMARY KEY (column1, column2));

现在它可以在没有任何警告的情况下工作:

sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> select * from something;
NULL|NULL|bla-bla
NULL|NULL|bla-bla

【讨论】:

  • 有没有提到这种行为的原因?什么是在数据库中转储多行并仍然删除重复项的好方法,即使它们包含NULL
  • @Pastafarianist sqlite.org/lang_createtable.html - “根据 SQL 标准,PRIMARY KEY 应始终暗示 NOT NULL。不幸的是,由于某些早期版本中的错误,SQLite 中并非如此。[。 ..] NULL 值被认为与所有其他值不同,包括其他 NULL。"
  • 是的,在 SQL 中,NULL 总是比较假。正因为如此,关系理论明确排除了 NULL 作为任何关键组件的值。然而,SQLite 是关系实践。似乎作者选择务实地允许多个但不是“相等”的键。显然,最好不要让 NULL 作为键值。
【解决方案4】:

基本:

CREATE TABLE table1 (
    columnA INTEGER NOT NULL,
    columnB INTEGER NOT NULL,
    PRIMARY KEY (columnA, columnB)
);

如果你的列是其他表的外键(常见情况):

CREATE TABLE table1 (
    table2_id INTEGER NOT NULL,
    table3_id INTEGER NOT NULL,
    FOREIGN KEY (table2_id) REFERENCES table2(id),
    FOREIGN KEY (table3_id) REFERENCES table3(id),
    PRIMARY KEY (table2_id, table3_id)
);

CREATE TABLE table2 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

CREATE TABLE table3 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

【讨论】:

    【解决方案5】:

    主键字段应声明为非空(这是非标准的定义 主键的主要特点是它必须是唯一的并且不能为空)。但下面是一个很好的做法 任何 DBMS 中的所有多列主键。

    create table foo
    (
      fooint integer not null
      ,foobar string not null
      ,fooval real
      ,primary key (fooint, foobar)
    )
    ;
    

    【讨论】:

      【解决方案6】:

      从 SQLite 版本 3.8.2 开始,显式 NOT NULL 规范的替代方案是“WITHOUT ROWID”规范:[1]

      NOT NULL is enforced on every column of the PRIMARY KEY
      in a WITHOUT ROWID table.
      

      “WITHOUT ROWID”表具有潜在的效率优势,因此要考虑的不太冗长的替代方案是:

      CREATE TABLE t (
        c1, 
        c2, 
        c3, 
        PRIMARY KEY (c1, c2)
       ) WITHOUT ROWID;
      

      例如,在 sqlite3 提示符下: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2

      【讨论】:

      • 对于现在阅读本文的任何人:WITHOUT ROWID 具有其他含义,不应将其用作在主键旁边写 NOT NULL 的替代方法。
      【解决方案7】:

      以下代码在 SQLite 中创建一个以 2 列作为主键的表。

      解决方案:

      CREATE TABLE IF NOT EXISTS users (
          id TEXT NOT NULL, 
          name TEXT NOT NULL, 
          pet_name TEXT, 
          PRIMARY KEY (id, name)
      )
      

      【讨论】:

        【解决方案8】:

        另外,您还可以将两列主键设为unique自动递增键设为primary。就像这样:https://stackoverflow.com/a/6157337

        【讨论】:

        • 这正是我想要的。谢谢!
        【解决方案9】:

        PRIMARY KEY (id, name) 对我不起作用。添加约束代替了这项工作。

        CREATE TABLE IF NOT EXISTS customer (
            id INTEGER, name TEXT,
            user INTEGER,
            CONSTRAINT PK_CUSTOMER PRIMARY KEY (user, id)
        )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-18
          • 1970-01-01
          • 2011-06-29
          • 2011-03-04
          相关资源
          最近更新 更多