SQLite 데이터베이스 테이블에서 열의 이름을 바꾸려면 어떻게합니까?


296

SQLite 데이터베이스의 일부 테이블에서 몇 개의 열의 이름을 바꿔야합니다. 나는 이전에 stackoverflow에 대해 비슷한 질문 을 받았지만 일반적으로 SQL에 대한 것이었고 SQLite의 경우는 언급되지 않았습니다.

ALTER TABLE에 대한 SQLite 문서에서 "쉽게"그러한 일을 할 수 없다는 것을 모았습니다 (즉, 단일 ALTER TABLE 문).

누군가 SQLite로 그러한 일을하는 일반적인 SQL 방법을 알고 궁금했습니다.


sqlite를위한 db 브라우저를 사용하면 쉽게 할 수있다
Matt G

1
이 답변을 승인 된 것으로 표시하십시오. stackoverflow.com/a/52346199/124486
Evan Carroll

답변:


66

이것은 2018-09-15 (3.25.0)로 수정되었습니다.

ALTER TABLE명령을 향상시킵니다 .

  • table을 사용하여 ALTER TABLE테이블 내에서 열 이름 바꾸기에 대한 지원을 추가하십시오 RENAME COLUMN oldname TO newname.
  • 테이블 이름 바꾸기 기능을 수정하여 트리거 및보기에서 이름이 바뀐 테이블에 대한 참조도 업데이트합니다.

아래에 문서화 된 새 구문을 찾을 수 있습니다 ALTER TABLE

RENAME COLUMN TO구문은 table-name 테이블의 column-name을 new-column-name으로 변경합니다. 열 이름은 테이블 정의 자체와 열을 참조하는 모든 인덱스, 트리거 및보기 내에서 변경됩니다. 열 이름 변경으로 인해 트리거 또는 뷰에서 의미 상 모호성이 RENAME COLUMN발생하면 오류와 함께 실패하고 변경 사항이 적용되지 않습니다.

여기에 이미지 설명을 입력하십시오 이미지 출처 : https://www.sqlite.org/images/syntax/alter-table-stmt.gif

예:

CREATE TABLE tab AS SELECT 1 AS c;

SELECT * FROM tab;

ALTER TABLE tab RENAME COLUMN c to c_new;

SELECT * FROM tab;

db-fiddle.com 데모


안드로이드 지원

작성 당시 Android API 27은 SQLite 패키지 버전 3.19를 사용하고 있습니다.

Android가 현재 사용하고 있으며이 업데이트가 SQLite 버전 3.25.0에서 제공되고 있음을 기반으로 Android에 대한 지원이 추가되기 전에 약간의 대기 시간 (약 API 33)이 있다고 말하고 싶습니다.

그럼에도 불구하고 API 33보다 오래된 버전을 지원해야하는 경우에는이를 사용할 수 없습니다.


8
Android 마이그레이션을 구현하고 있지만 불행히도 IntelliJ는 유효한 SQL 명령이 아니라는 경고를 표시합니다. database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount"). COLUM 이 빨간색으로 강조 표시되고 TO가 'COLUMN'을 (를) 얻었습니다 . 불행히도 Android는 여전히 SQLite 버전 3.19 에 있으므로 이것이 작동하지 않습니다.
Adam Hurwitz

1
편집 : system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q1 에서 1.0.109.x)가 실제로 SQLite 3.24 및 System.Data.SQLite를 사용하고 있음을 발견했습니다 . SQLite 3.25를 사용하면 이번 달에 관련이 있습니다.
rychlmoj

1
참고로 불행히도 이것은 아직 안드로이드의 SQLite 라이브러리에 의해 구현되지 않았습니다 . 잘만되면 그들은 곧 업데이트 될 것이다.
Adam Hurwitz '12

3
다른 사람들이 희망을 갖지 못하도록 Android 지원 섹션을 추가했습니다. Android 27의 현재 SQLite 3.19 사용에 따라이 기능이 Android에 추가되기 전에 대략 API 33까지 기다려야하며 최신 버전에서만 지원됩니다. 한숨.
Joshua Pinter

1
@JoshuaPinter 답변을 연장해 주셔서 감사합니다.
Lukasz Szozda

448

테이블이 있고 "colb"의 이름을 "col_b"로 바꿔야한다고 가정하십시오.

먼저 이전 테이블의 이름을 바꿉니다.

ALTER TABLE orig_table_name RENAME TO tmp_table_name;

그런 다음 이전 테이블을 기반으로하지만 업데이트 된 열 이름을 사용하여 새 테이블을 만듭니다.

CREATE TABLE orig_table_name (
  col_a INT
, col_b INT
);

그런 다음 원래 테이블에서 내용을 복사하십시오.

INSERT INTO orig_table_name(col_a, col_b)
SELECT col_a, colb
FROM tmp_table_name;

마지막으로 이전 테이블을 삭제하십시오.

DROP TABLE tmp_table_name;

A의 모든 포장 BEGIN TRANSACTION;및 것은 COMMIT;도 아마 좋은 아이디어이다.


51
그리고 당신의 색인을 잊지 마십시오.
Tom Mayfield

11
매우 중요한 것은 위의 예제 코드에 트랜잭션이 없다는 것입니다. 이름 바꾸기가 성공적으로 완료되거나 전혀 완료되지 않도록 모든 것을 BEGIN / END (또는 ROLLBACK)로 랩핑해야합니다.
Roger Binns

4
안드로이드에서 이것을하고 싶은 사람은 SQLiteDatabase.beginTransaction ()을
bmaupin

7
답변의 코드에는 인덱스를 복사하는 것이 없습니다. 빈 테이블을 작성하고 데이터를 테이블에 넣으면 구조와 데이터 만 복사됩니다. 메타 데이터 (인디 케이트, 외래 키, 제약 조건 등)를 원할 경우, 대체 테이블에서이를 생성하기 위해 명령문을 발행해야합니다.
Tom Mayfield

17
SQLite의 .schema명령은 CREATE TABLE기존 테이블을 만드는 명령문 을 표시하는 데 편리 합니다. 출력을 가져 와서 필요에 따라 수정 한 후 실행하여 새 테이블을 작성할 수 있습니다. 이 명령은 또한 CREATE INDEX색인을 작성 하는 데 필요한 명령을 보여줍니다.이 명령은 Thomas의 관심사를 다루어야합니다. 물론 변경하기 전에이 명령을 실행하십시오.
Mike DeSimone

56

파고 들자, SQLite 용 DB 브라우저 라는이 다중 플랫폼 (Linux | Mac | Windows) 그래픽 도구 가 실제로 매우 사용자 친화적 인 방식으로 열 이름을 바꿀 수 있음을 발견했습니다!

편집 | 테이블 수정 | 테이블 | 필드 편집 클릭 클릭! 짜잔!

그러나 누군가 프로그램 방식으로 공유하고 싶다면 기꺼이 알고 싶습니다.


1
같은 작업을 수행 하는 Firefox 애드온 도 있습니다. 이름을 바꾸려는 열을 마우스 오른쪽 버튼으로 클릭하고 "열 편집"을 선택하십시오.
Jacob Hacker

1
openSUSE에서도 패키지로 제공됩니다. software.opensuse.org/package/sqlitebrowser

투표가 너무 이상합니다. 우리는 여기서 프로그래밍에 대해 이야기하고 있습니다 (코드). 왜이 답변을 여기에 게시 했습니까?
user25

2
내 질문에 코드 로이 작업을 수행하는 방법에 대한 언급은 없습니다. 방금 SQLite DB에서 열의 이름을 바꾸는 방법을 알고 싶었습니다.
joce February

@joce 사랑해 !!! (형제처럼) 필드를 바꾸게 했어요. MS Access 테이블을 SQLite로 내 보냈고 필드 중 하나 앞에 3YearLetterSent라는 숫자가있었습니다. Visual Studio는 테이블에서 클래스를 만들었지 만 필드 이름 앞에 "3"숫자를 넣었습니다. 나는 이것을 알았고, 단지 보지 않았습니다.
JustJohn

53

ALTER COLUMN이없는 것이 사실이지만 열 이름 만 바꾸거나 NOT NULL 제약 조건을 삭제하거나 데이터 형식을 변경하려는 경우 다음 명령 집합을 사용할 수 있습니다.

참고 :이 명령은 데이터베이스를 손상시킬 수 있으므로 백업이 있는지 확인하십시오.

PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;

변경 사항을 스키마에 다시로드하려면 연결을 닫았다가 다시 열거 나 데이터베이스를 정리해야합니다.

예를 들면 다음과 같습니다.

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
Error: BOOKS.publication_date may not be NULL  
sqlite> PRAGMA writable_schema = 1; 
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';  
sqlite> PRAGMA writable_schema = 0;  
sqlite> .q  

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
sqlite> .q  

참조 :


pragma writable_schema
이 pragma가 설정되면 일반 UPDATE, INSERT 및 DELETE 문을 사용하여 데이터베이스를 변경할 수있는 SQLITE_MASTER 테이블. 경고 :이 pragma를 잘못 사용하면 데이터베이스 파일이 쉽게 손상 될 수 있습니다.

alter table
SQLite는 ALTER TABLE의 제한된 하위 집합을 지원합니다. SQLite의 ALTER TABLE 명령을 사용하면 테이블 이름을 바꾸거나 기존 테이블에 새 열을 추가 할 수 있습니다. 열 이름을 바꾸거나 열을 제거하거나 테이블에서 제약 조건을 추가하거나 제거 할 수 없습니다.

ALTER TABLE SYNTAX


3
위험하지만 여전히 가장 간단한 대답 imo입니다.
Tek

2
매우 빠릅니다. 위험 은 "먼저 백업을해야합니다"라는 의미입니다.
Noah

6
sqlite 파일 형식은 매우 간단하므로이 작업이 유효합니다. 파일 형식에는 테이블에 대한 두 가지 정보 세트 만 있습니다. 실제 텍스트 인 일반 CREATE TABLE 명령과 CREATE 명령의 필드 순서대로 값이 나타나는 행. sqlite 코드가 데이터베이스를 열면 각 CREATE 명령을 구문 분석하고 열 정보를 메모리에 동적으로 빌드합니다. 따라서 유형이나 제약 조건을 변경하더라도 동일한 수의 열로 끝나는 방식으로 CREATE 명령을 변경하는 명령이 작동합니다.
Thomas Tempelmann

3
@ThomasTempelmann 그러나 쿼리 집합이 제약 조건이 있다고 가정하기 때문에 데이터 집합에서 충족되지 않은 제약 조건을 추가하면 문제가 발생합니다.
fuz

2
@ThomasTempelmann 제약 조건 제거 는 항상 좋습니다. 제약 조건을 모든 행에서 만족하지만 확인해야 할 경우 제약 조건을 추가하는 것이 좋습니다.
fuz

18

최근에는 SQLite3 에서 colunms id, lon, lat으로 points 포인트 라는 테이블을 사용 하여이 작업을 수행해야했습니다 . 잘못, 테이블을 가져올 때 lon 열에 저장된 위도의 값 과 그 반대 의 값은 해당 열의 이름을 바꾸는 것이 분명합니다. 트릭은 다음과 같습니다.

create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;

나는 이것이 당신에게 도움이되기를 바랍니다!


이 방법은 PK 값을 적절하게 복사하지 않고 숨겨진 rowid 열을 자동으로 만듭니다. 반드시 문제는 아니지만 그것이 문제가 되었기 때문에 지적하고 싶었습니다.
TPoschel

4
"업데이트 포인트 SET lon = lat, lat = lon;"을 수행하는 것이 쉽지 않습니까?
kstep

1
이 답변은 올바른 순서로 프로세스를 수행합니다. 먼저 임시 테이블을 만들고 채우고 원본을 삭제하십시오 .
Xeoncross

14

sqlite 문서 인용 :

SQLite는 ALTER TABLE의 제한된 하위 집합을 지원합니다. SQLite의 ALTER TABLE 명령을 사용하면 테이블 이름을 바꾸거나 기존 테이블에 새 열을 추가 할 수 있습니다. 열의 이름을 바꾸거나 열을 제거하거나 테이블에서 제한 조건을 추가 또는 제거 할 수 없습니다.

물론 할 수있는 일은 새 레이아웃으로 SELECT * FROM old_table새 테이블을 만들고받는 값으로 새 테이블을 채우는 것입니다.


7

우선, 이것은 놀랍게도 나를 놀라게하는 것들 중 하나입니다. 열의 이름을 바꾸려면 완전히 새로운 테이블을 만들고 이전 테이블의 데이터를 새 테이블로 복사해야합니다 ...

SQLite 작업을 수행하기 위해 방문한 GUI는 Base 입니다. 실행 된 모든 명령을 보여주는 멋진 로그 창이 있습니다. Base를 통해 열의 이름을 바꾸면 필요한 명령으로 로그 창이 채워집니다.

기본 로그 창

그런 다음 필요한 곳에 쉽게 복사하여 붙여 넣을 수 있습니다. 저에게는 ActiveAndroid 마이그레이션 파일이 있습니다. 또한 복사 된 데이터에는 타임 스탬프 등이 아닌 SQLite 명령 만 포함되어 있습니다.

바라건대, 그것은 사람들의 시간을 절약 해줍니다.


참고로 ActiveAndroid 사용하는 경우 ActiveAndroid가 자체적으로 처리 하므로 and 및 행을 생략 할 수 있습니다. BEGIN TRANSACTION;COMMIT;
Joshua Pinter

6

사례 1 : SQLite 3.25.0+

SQLite 버전 3.25.0 만 열 이름 바꾸기를 지원합니다. 장치가이 요구 사항을 충족하면 문제가 매우 간단합니다. 아래 쿼리는 문제를 해결합니다.

ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";

사례 2 : SQLite 이전 버전

약간 까다로울 수있는 결과를 얻으려면 다른 접근법을 따라야합니다.

예를 들어 다음과 같은 테이블이있는 경우

CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)

그리고 열 이름을 변경하려면 Location

1 단계 : 원래 테이블 이름을 바꿉니다.

ALTER TABLE student RENAME TO student_temp;

2 단계 : 이제 student올바른 열 이름 으로 새 테이블 을 만듭니다 .

CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)

3 단계 : 원래 테이블에서 새 테이블로 데이터를 복사하십시오.

INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;

참고 : 위 명령은 모두 한 줄이어야합니다.

4 단계 : 원본 테이블을 삭제합니다.

DROP TABLE student_temp;

이 네 단계를 통해 SQLite 테이블을 수동으로 변경할 수 있습니다. 새 테이블에서 인덱스, 뷰어 또는 트리거도 다시 작성해야합니다.


1
어떻게 API 레벨 28 사용하고 안드로이드 스튜디오에서 3.29.0에 sqllite 데이터베이스 버전을 업그레이드
Nathani 소프트웨어

SQLite 버전은 앱이 작동하는 장치에 의해 정의됩니다. 장치에 따라 다릅니다.
Febin Mathew

1
오래된 sqlite를 사용하는 사람들에게는 위의 네 단계를 권장하지 않습니다. sqlite.org/lang_altertable.html 의 "주의"섹션을 참조하십시오 .
Jeff

3

테이블 열 <id>를 <_id>로 변경

 String LastId = "id";

    database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
    +"("
            + PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
            + PhraseContract.COLUMN_PHRASE + " text ,"
            + PhraseContract.COLUMN_ORDER  + " text ,"
            + PhraseContract.COLUMN_FROM_A_LANG + " text"
    +")"
    );
    database.execSQL("INSERT INTO " +
            PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
            " SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
            " FROM " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");

3

원하는 열 이름으로 새 열을 작성하십시오 (COLNew).

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

이전 열 COLOld의 내용을 새 열 COLNew에 복사하십시오.

INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}

참고 : 위 줄에는 괄호가 필요합니다.


2

앞에서 언급했듯이 SQLite Database Browser 도구가 있습니다. 이 도구는 사용자 또는 응용 프로그램이 수행 한 모든 작업을 기록합니다. 이 작업을 한 번 수행하고 응용 프로그램 로그를 보면 관련 코드가 표시됩니다. 쿼리를 복사하고 필요에 따라 붙여 넣습니다. 나를 위해 일했다. 도움이 되었기를 바랍니다


2

공식 문서에서

디스크 내용에 영향을 미치지 않는 일부 변경 사항 에는 더 간단하고 빠른 절차 를 선택적으로 사용할 수 있습니다. 다음의 간단한 절차는 CHECK 또는 FOREIGN KEY 또는 NOT NULL 제약 조건 제거, 열 이름 바꾸기 또는 열의 기본값 추가 또는 제거 또는 변경에 적합합니다.

  1. 거래를 시작하십시오.

  2. PRAGMA schema_version을 실행하여 현재 스키마 버전 번호를 판별하십시오. 이 번호는 아래 6 단계에 필요합니다.

  3. PRAGMA writable_schema = ON을 사용하여 스키마 편집을 활성화하십시오.

  4. UPDATE 문을 실행하여 sqlite_master 테이블에서 테이블 X의 정의를 변경하십시오. UPDATE sqlite_master SET sql = ... WHERE type = 'table'AND name = 'X';

    주의 : sqlite_master 테이블을 이와 같이 변경하면 변경에 구문 오류가 포함 된 경우 데이터베이스가 손상되어 읽을 수 없게됩니다. 중요한 데이터가 포함 된 데이터베이스에서 UPDATE 문을 사용하기 전에 별도의 빈 데이터베이스에서 UPDATE 문을 신중하게 테스트하는 것이 좋습니다.

  5. 테이블 X에 대한 변경 사항이 다른 테이블 또는 인덱스에 영향을 미치거나 트리거가 스키마 내의 뷰인 경우 UPDATE 문을 실행하여 다른 테이블 인덱스 및 뷰도 수정하십시오. 예를 들어 열 이름이 변경되면 해당 열을 참조하는 모든 FOREIGN KEY 제약 조건, 트리거, 인덱스 및 뷰를 수정해야합니다.

    주의 : sqlite_master 테이블을 이와 같이 변경하면 변경 사항에 오류가있는 경우 데이터베이스가 손상되어 읽을 수 없게됩니다. 중요한 데이터가 포함 된 데이터베이스에서 사용하기 전에 별도의 테스트 데이터베이스에서이 전체 프로 시저를주의 깊게 테스트하거나이 절차를 실행하기 전에 중요한 데이터베이스의 백업 사본을 만드십시오.

  6. PRAGMA schema_version = X를 사용하여 스키마 버전 번호를 늘리십시오. 여기서 X는 위의 2 단계에서 찾은 이전 스키마 버전 번호보다 하나 더 많습니다.

  7. PRAGMA writable_schema = OFF를 사용하여 스키마 편집을 비활성화하십시오.

  8. (선택 사항) PRAGMA integrity_check를 실행하여 스키마 변경 사항이 데이터베이스를 손상시키지 않았는지 확인하십시오.

  9. 위의 1 단계에서 시작된 트랜잭션을 커미트하십시오.


PRAGMA integrity_check는 스키마의 오류를 선택하지 않습니다.
Graymatter

그리고 그 문제는 무엇입니까?
모하마드 야히아

1

한 가지 옵션은 핀치 작업이 필요하고 초기 열이 기본값으로 작성된 경우 원하는 새 열을 작성하고 내용을 복사하고 기본적으로 이전 열을 "버림"하는 것입니다. 존재하지만 사용하거나 업데이트하지는 않습니다.)

전의:

alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically

이것은 열 뒤에 남습니다 (그리고 NOT NULL로 작성되었지만 기본값이 없으면 열을 무시하는 미래의 삽입은 실패 할 수 있습니다). 단지 테이블 인 경우 트레이드 오프가 허용 될 수 있습니다. 그렇지 않으면 여기에 언급 된 다른 답변 중 하나 또는 열의 이름을 바꿀 수있는 다른 데이터베이스를 사용하십시오.



-3

sqlite3 yourdb .dump> /tmp/db.txt
편집 /tmp/db.txt 편집 행에서 열 이름 변경
sqlite2 yourdb2 </tmp/db.txt
mv / move yourdb2 yourdb


3
당신은 어떤 정보도 제공하지 않습니다. 당신은 그것이 작동 할 것이라고 생각하는 이유 또는 그것을 실행할 때 일어날 것으로 예상되는 것에 대한 추가 정보없이 많은 코드 / 지시 사항을 뱉습니다.
RGLSV
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.