Câu trả lời:
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.
PRAGMA foreign_keys = ON;
(xem sqlite.org/forignkeys.html#fk_enable )
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)
SELECT * FROM mytable
?
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.
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'
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;
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 SELECT
truy 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 temptable
hoặc RENAME table
hoặ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.
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.