Khóa chính Sqlite trên nhiều cột


Câu trả lời:


805

Theo tài liệu , nó

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

3
Vâng, điều này là đúng, nhưng theo tài liệu, TẠO BẢNG một cái gì đó (cột1 PRIMARY KEY, cột2 PRIMARY KEY); nên có thể là tốt, nhưng nó không phải là.
Yar

6
@Yar Các tài liệu nói rằng "Nếu có nhiều hơn một mệnh đề PRIMARY KEY trong một câu lệnh CREATE TABLE, thì đó là một lỗi." Có, sơ đồ đường sắt cũng có thể chỉ ra rằng nó hợp lệ, nhưng văn bản dưới đây làm rõ rằng nó không phải.
Brian Campbell

10
Hãy nhớ thêm phần PRIMARY KEY (cột1, cột2) ở cuối như trong câu trả lời này. Nếu bạn cố gắng thêm nó sau định nghĩa cột2, bạn sẽ gặp lỗi cú pháp .
vovahost 7/2/2015

159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

Không phải khóa chính áp đặt KHÔNG phải là NULL?
pratnala

23
@pratnala Trong SQL tiêu chuẩn, vâng. Trong SQLite, NULLđược phép trong các khóa chính. Câu trả lời này nhấn mạnh rằng nếu bạn muốn hành vi chuẩn hơn, bạn cần thêm NOT NULLchính mình. Câu trả lời của tôi chỉ là cú pháp rất cơ bản cho khóa chính nhiều cột.
Brian Campbell

42

Đúng. Nhưng hãy nhớ rằng khóa chính như vậy cho phép NULLcác giá trị trong cả hai cột nhiều lần.

Tạo một bảng như vậy:

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

Bây giờ điều này hoạt động mà không có bất kỳ cảnh báo:

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

Có bất kỳ tài liệu tham khảo cho lý do của hành vi như vậy? Điều gì sẽ là một cách tốt để kết xuất một số hàng trong cơ sở dữ liệu và vẫn loại bỏ các bản sao, ngay cả khi chúng có chứa NULL?
Pastafarianist 04/11/2015

4
@Pastafarianist sqlite.org/lang_createtable.html - "Theo tiêu chuẩn SQL, PRIMARY KEY phải luôn ngụ ý KHÔNG NULL. Thật không may, do một lỗi trong một số phiên bản đầu tiên, đây không phải là trường hợp trong SQLite. [...] NULL các giá trị được coi là khác biệt với tất cả các giá trị khác, bao gồm các NULL khác. "
Không thể tin được vào ngày

Có, trong SQL NULL luôn so sánh sai. Do đó, lý thuyết quan hệ đặc biệt loại trừ NULL là giá trị của bất kỳ thành phần quan trọng nào. SQLite, tuy nhiên, là thực hành quan hệ. Có vẻ như các tác giả đã chọn cho phép thực tế cho phép nhiều khóa nhưng không "bằng nhau". Rõ ràng không nên cho phép NULL làm giá trị chính.
Holdenweb

31

Căn bản :

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

Nếu các cột của bạn là khóa ngoại của các bảng khác (trường hợp phổ biến):

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
);

14

Các trường khóa chính phải được khai báo là không null (đây không phải là tiêu chuẩn vì định nghĩa của khóa chính là nó phải là duy nhất và không phải là null). Nhưng dưới đây là một cách thực hành tốt cho tất cả các khóa chính nhiều cột trong bất kỳ DBMS nào.

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

11

Kể từ phiên bản 3.8.2 của SQLite, một thay thế cho thông số kỹ thuật KHÔNG NULL rõ ràng là thông số kỹ thuật "KHÔNG CÓ ROWID": [ 1 ]

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

Các bảng "KHÔNG CÓ ROWID" có lợi thế hiệu quả tiềm năng, do đó, một giải pháp thay thế ít dài hơn để xem xét là:

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

Ví dụ: tại dấu nhắc sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2


Đối với bất cứ ai đọc điều này ngày nay: WITHOUT ROWIDcó ý nghĩa bổ sung, và nó không nên được sử dụng như là một thay thế cho việc viết NOT NULLbên cạnh khóa chính của bạn.
Shadowtalker


2

PRIMARY KEY (id, name)không làm việc cho tôi. Thêm một ràng buộc đã làm công việc thay thế.

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


1

Đoạn mã sau tạo một bảng có 2 cột làm khóa chính trong SQLite.

GIẢI PHÁP:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.