Chèn cột mới vào bảng trong sqlite?


354

Tôi có một bảng với các cột name, qty, rate. Bây giờ tôi cần thêm một cột mới COLNewở giữa nameqtycác cột. Làm cách nào để thêm một cột mới vào giữa hai cột?

Câu trả lời:


677

Bạn có hai lựa chọn. Trước tiên, bạn có thể chỉ cần thêm một cột mới với các mục sau:

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

Thứ hai, và phức tạp hơn, nhưng thực sự sẽ đặt cột nơi bạn muốn, sẽ đổi tên bảng:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Sau đó tạo bảng mới với cột bị thiếu:

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

Và điền dữ liệu cũ vào:

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

Sau đó xóa bảng cũ:

DROP TABLE TempOldTable;

Tôi rất thích tùy chọn thứ hai, vì nó sẽ cho phép bạn đổi tên hoàn toàn mọi thứ nếu cần.


26
Tôi sẽ chọn tùy chọn đầu tiên và sử dụng tùy chọn mặc định trong tùy chọn secend ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Quan trọng hơn: (nghĩ về lý do tại sao bạn muốn đặt hàng các cột ..) sử dụng trong mọi hành động ghi (như chèn hoặc thêm) luôn luôn là tên cột, theo cách này, bạn sẽ không bao giờ gặp lỗi nào đó trong mã của mình sau khi thay đổi bảng.
michel.iamit

5
Nhân tiện: không thể thêm giá trị mặc định trong ALTER TABLE cho một số trường: sqlite.org/lang_altertable.html
michel.iamit

9
đừng quên tạo lại các chỉ mục
Jan Turoň

5
bạn cũng sẽ cần phải tạo lại các trình kích hoạt
Christopher K.

7
Đừng quên các vi phạm ràng buộc tiềm ẩn do khóa ngoại gây ra: "... nhưng có thể gọi các hành động khóa ngoại hoặc vi phạm ràng buộc." (xem sqlite.org/forignkeys.html#fk_schemacommands ); như một cách giải quyết, bạn có thể vô hiệu hóa các khóa ngoại trong khi đó: PRAGMA foreign_keys = ON;(xem sqlite.org/forignkeys.html#fk_enable )
Trinimon

112

Bạn không thêm các cột giữa các cột khác trong SQL, bạn chỉ cần thêm chúng. Nơi họ đặt hoàn toàn phụ thuộc vào DBMS. Vị trí thích hợp để đảm bảo rằng các cột đi ra theo đúng thứ tự là khi bạn select.

Nói cách khác, nếu bạn muốn chúng theo thứ tự {name,colnew,qty,rate}, bạn sử dụng:

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

Với SQLite, bạn cần sử dụng alter table, một ví dụ là:

alter table mytable add column colnew char(50)

2
SELECT * FROM mytable?
EML

Giá trị mặc định được đặt là gì nếu chúng ta không chỉ định nó trong các hàng hiện có của cột mới?
Jacob

12
Có rất ít trường hợp sử dụng mà bạn nên làm select *ở tất cả. Đôi khi, nó rất hữu ích cho các chương trình muốn khám phá các bảng nhưng, trong phần lớn các mục đích sử dụng, bạn nên xác định rõ ràng những gì bạn muốn và từ đó theo thứ tự bạn muốn.
paxdiablo

4
Thật điên rồ khi đây không phải là "câu trả lời được chấp nhận". Bản thân câu hỏi ban đầu thể hiện sự thiếu hiểu biết hoàn toàn về cách RDBMS hoạt động.
Vada Poché

12

Bạn có thể thêm cột mới với truy vấn

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Nhưng nó sẽ được thêm vào cuối, không phải ở giữa các cột hiện có.


11

SQLite đã giới hạn hỗ trợ ALTER TABLE mà bạn có thể sử dụng để thêm một cột vào cuối bảng hoặc để thay đổi tên của bảng.

Nếu bạn muốn thực hiện các thay đổi phức tạp hơn trong cấu trúc của bảng, bạn sẽ phải tạo lại bảng. Bạn có thể lưu dữ liệu hiện có vào một bảng tạm thời, bỏ bảng cũ, tạo bảng mới, sau đó sao chép dữ liệu trở lại từ bảng tạm thời.

Ví dụ: giả sử bạn có một bảng có tên "t1" với các tên cột "a" và "c" và bạn muốn chèn cột "b" từ bảng này. Các bước sau minh họa cách thực hiện điều này:

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;

Bây giờ bạn đã sẵn sàng để chèn dữ liệu mới của mình như vậy:

UPDATE t1 SET b='blah' WHERE a='key'

Trong các thử nghiệm của tôi, dòng INSERT INTO t1 SELECT a,c FROM t1_backup;gây ra lỗi: "bảng t1 có 3 cột nhưng 2 giá trị được cung cấp: INSERT INTO t1 CHỌN a, c TỪ t1_backup;". Dòng chính xác phải làINSERT 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};

Bản cập nhật này là bắt buộc để xử lý giá trị null, nhập giá trị mặc định theo yêu cầu của bạn. Như trong trường hợp của bạn, bạn cần gọi SELECTtruy vấn và bạn sẽ nhận được thứ tự các cột, như paxdiablo đã nói:

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

và theo tôi, tên cột của bạn để lấy giá trị từ con trỏ:

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

Vì vậy, nếu chỉ số thay đổi, ứng dụng của bạn sẽ không gặp phải bất kỳ vấn đề nào.

Đây là cách an toàn theo nghĩa khác, nếu bạn đang sử dụng CREATE temptablehoặc RENAME tablehoặc CREATE, sẽ có khả năng mất dữ liệu cao nếu không được xử lý cẩn thận, ví dụ trong trường hợp giao dịch của bạn xảy ra trong khi hết pin.


4

Tôi đã phải đối mặt với cùng một vấn đề và phương pháp thứ hai được đề xuất trong câu trả lời được chấp nhận, như đã lưu ý trong các bình luận, có thể có vấn đề khi xử lý các khóa ngoại.

Cách giải quyết của tôi là xuất cơ sở dữ liệu sang tệp sql để đảm bảo rằng các câu lệnh INSERT bao gồm tên cột. Tôi làm điều đó bằng DB Browser cho SQLite có một tính năng tiện dụng cho việc đó. Sau đó, bạn chỉ cần chỉnh sửa câu lệnh tạo bảng và chèn cột mới vào nơi bạn muốn và tạo lại db.

Trong * nix như các hệ thống chỉ là một cái gì đó dọc theo dòng

cat db.sql | sqlite3 database.db

Tôi không biết làm thế nào khả thi với cơ sở dữ liệu rất lớn, nhưng nó đã hoạt động trong trường hợp của tôi.

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.